miriad-viz 0.13.13 → 0.14.0

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.
@@ -0,0 +1,23 @@
1
+ // src/cli/guided/resolve-audio-dir.ts
2
+ import { existsSync, readdirSync } from "fs";
3
+ import { resolve } from "path";
4
+ var AUDIO_EXTENSIONS = /\.(mp3|wav|ogg|m4a)$/i;
5
+ function hasAudioFiles(dir) {
6
+ if (!existsSync(dir)) return false;
7
+ try {
8
+ return readdirSync(dir).some((f) => AUDIO_EXTENSIONS.test(f));
9
+ } catch {
10
+ return false;
11
+ }
12
+ }
13
+ function resolveAudioDir(projectDir) {
14
+ const primary = resolve(projectDir, "audio");
15
+ const fallback = resolve(projectDir, "data", "audio");
16
+ if (hasAudioFiles(primary)) return primary;
17
+ if (existsSync(fallback)) return fallback;
18
+ return primary;
19
+ }
20
+
21
+ export {
22
+ resolveAudioDir
23
+ };
package/dist-cli/index.js CHANGED
@@ -1,3 +1,6 @@
1
+ import {
2
+ resolveAudioDir
3
+ } from "./chunk-KP27GWEA.js";
1
4
  import {
2
5
  canSync,
3
6
  getBoardSyncConfig,
@@ -979,6 +982,7 @@ function computeNext(progress, existingFiles, logTails, flags = {}, dataSummary,
979
982
  }
980
983
  if (step === "voices") {
981
984
  const VOICE_AUDIO_PREFIX = "audio/";
985
+ const VOICE_AUDIO_PREFIX_ALT = "data/audio/";
982
986
  if (flags["skip-audio"]) {
983
987
  progress.steps.voices = {
984
988
  status: "complete",
@@ -995,7 +999,7 @@ function computeNext(progress, existingFiles, logTails, flags = {}, dataSummary,
995
999
  }
996
1000
  if (flags["voices-approved"]) {
997
1001
  const audioFiles = existingFiles.filter(
998
- (f) => f.startsWith(VOICE_AUDIO_PREFIX) && f.endsWith(".mp3")
1002
+ (f) => (f.startsWith(VOICE_AUDIO_PREFIX) || f.startsWith(VOICE_AUDIO_PREFIX_ALT)) && f.endsWith(".mp3")
999
1003
  );
1000
1004
  if (audioFiles.length === 0) {
1001
1005
  output.push(
@@ -1025,7 +1029,7 @@ function computeNext(progress, existingFiles, logTails, flags = {}, dataSummary,
1025
1029
  }
1026
1030
  if (state.status === "in_progress") {
1027
1031
  const audioFiles = existingFiles.filter(
1028
- (f) => f.startsWith(VOICE_AUDIO_PREFIX) && f.endsWith(".mp3")
1032
+ (f) => (f.startsWith(VOICE_AUDIO_PREFIX) || f.startsWith(VOICE_AUDIO_PREFIX_ALT)) && f.endsWith(".mp3")
1029
1033
  );
1030
1034
  if (audioFiles.length > 0) {
1031
1035
  output.push("", `\u{1F3B5} Voice clips found (${audioFiles.length}):`);
@@ -1629,6 +1633,7 @@ function gatherAudioFiles(projectDir) {
1629
1633
  }
1630
1634
  };
1631
1635
  scanDir("audio/", "audio/");
1636
+ scanDir("data/audio/", "data/audio/");
1632
1637
  scanDir(AUDIO_DIR_PREFIX, AUDIO_DIR_PREFIX);
1633
1638
  return files;
1634
1639
  }
@@ -1982,7 +1987,7 @@ async function main() {
1982
1987
  }
1983
1988
  const { runTransform } = await import("./transform-J2AY7XRX.js");
1984
1989
  await runTransform({ projectDir, progress });
1985
- const { runPreview: runPreview2 } = await import("./preview-7JHBZRU5.js");
1990
+ const { runPreview: runPreview2 } = await import("./preview-A6V36JCT.js");
1986
1991
  await runPreview2({ projectDir, progress, port, noOpen: flags["no-open"] === true });
1987
1992
  break;
1988
1993
  }
@@ -2002,17 +2007,17 @@ async function main() {
2002
2007
  }
2003
2008
  const { runTransform } = await import("./transform-J2AY7XRX.js");
2004
2009
  await runTransform({ projectDir, progress });
2005
- const { runPreview: runPreview2 } = await import("./preview-7JHBZRU5.js");
2010
+ const { runPreview: runPreview2 } = await import("./preview-A6V36JCT.js");
2006
2011
  await runPreview2({ projectDir, progress, port, noOpen: flags["no-open"] === true });
2007
2012
  break;
2008
2013
  }
2009
- const { runPreview } = await import("./preview-7JHBZRU5.js");
2014
+ const { runPreview } = await import("./preview-A6V36JCT.js");
2010
2015
  await runPreview({ projectDir, progress, port, noOpen: flags["no-open"] === true });
2011
2016
  break;
2012
2017
  }
2013
2018
  case "render": {
2014
2019
  const { projectDir, progress } = requireProject();
2015
- const { runRender } = await import("./render-B6PFEJXP.js");
2020
+ const { runRender } = await import("./render-ZNTHZCGP.js");
2016
2021
  await runRender({ projectDir, progress, draft: flags.draft === true });
2017
2022
  break;
2018
2023
  }
@@ -2049,7 +2054,7 @@ async function main() {
2049
2054
  \u2717 Invalid script.json: ${message}`);
2050
2055
  process.exit(1);
2051
2056
  }
2052
- const audioDir = resolve3(projectDir, "audio");
2057
+ const audioDir = resolveAudioDir(projectDir);
2053
2058
  let clipDurations;
2054
2059
  try {
2055
2060
  clipDurations = readAudioDurations(audioDir);
@@ -2113,7 +2118,7 @@ async function main() {
2113
2118
  \u2717 Invalid script.json: ${message}`);
2114
2119
  process.exit(1);
2115
2120
  }
2116
- const audioDir = resolve3(projectDir, "audio");
2121
+ const audioDir = resolveAudioDir(projectDir);
2117
2122
  let clipDurations;
2118
2123
  try {
2119
2124
  clipDurations = readAudioDurations(audioDir);
@@ -2240,5 +2245,6 @@ main().catch((err) => {
2240
2245
  process.exit(1);
2241
2246
  });
2242
2247
  export {
2248
+ gatherAudioFiles,
2243
2249
  gatherDensityData
2244
2250
  };
@@ -2,6 +2,9 @@ import {
2
2
  resolvePackageRoot,
3
3
  scaffoldTemplate
4
4
  } from "./chunk-XI2U2ON3.js";
5
+ import {
6
+ resolveAudioDir
7
+ } from "./chunk-KP27GWEA.js";
5
8
  import {
6
9
  markComplete,
7
10
  writeProgress
@@ -74,7 +77,7 @@ async function runPreview(options) {
74
77
  return;
75
78
  }
76
79
  }
77
- const audioDir = resolve(projectDir, "audio");
80
+ const audioDir = resolveAudioDir(projectDir);
78
81
  const dataDir = resolve(projectDir, progress.project.dataDir);
79
82
  const copyResult = copyPreviewAssets({ outputDir: outDir, dataDir, audioDir, viewerDir });
80
83
  if (copyResult.copiedVizData) {
@@ -1,3 +1,6 @@
1
+ import {
2
+ resolveAudioDir
3
+ } from "./chunk-KP27GWEA.js";
1
4
  import {
2
5
  canSync,
3
6
  getBoardSyncConfig,
@@ -12,7 +15,14 @@ import {
12
15
 
13
16
  // src/cli/guided/steps/render.ts
14
17
  import { execSync } from "child_process";
15
- import { copyFileSync, existsSync, mkdirSync, readFileSync, readdirSync } from "fs";
18
+ import {
19
+ copyFileSync,
20
+ existsSync,
21
+ mkdirSync,
22
+ readFileSync,
23
+ readdirSync,
24
+ writeFileSync
25
+ } from "fs";
16
26
  import { resolve } from "path";
17
27
 
18
28
  // src/audio/manifest.ts
@@ -224,6 +234,76 @@ function validateAudioManifest(manifest) {
224
234
  }
225
235
  return { valid: errors.length === 0, errors };
226
236
  }
237
+ function resolveAudioManifestForRemotion(v2, timing, options) {
238
+ const fps = options?.fps ?? 30;
239
+ const lineById = /* @__PURE__ */ new Map();
240
+ for (const line of timing.lines) {
241
+ lineById.set(line.id, line);
242
+ }
243
+ const dialog = timing.lines.map((line) => ({
244
+ id: line.id,
245
+ file: line.audioFile,
246
+ speaker: line.speaker,
247
+ text: line.text,
248
+ startSec: line.startSec,
249
+ durationSec: line.durationSec,
250
+ style: line.style
251
+ }));
252
+ const sfx = v2.sfx.map((raw) => {
253
+ let startSec;
254
+ if (raw.atLine != null) {
255
+ const refLine = lineById.get(raw.atLine);
256
+ if (refLine == null) {
257
+ throw new Error(`SFX "${raw.id}": atLine "${raw.atLine}" not found in timing.json lines`);
258
+ }
259
+ startSec = refLine.startSec + (raw.offsetSec ?? 0);
260
+ } else {
261
+ startSec = raw.startSec ?? 0;
262
+ }
263
+ const resolved = {
264
+ id: raw.id,
265
+ file: raw.file,
266
+ startSec
267
+ };
268
+ if (raw.volume != null) resolved.volume = raw.volume;
269
+ if (raw.note != null) resolved.note = raw.note;
270
+ return resolved;
271
+ });
272
+ const music = v2.music.map((raw) => {
273
+ let startSec;
274
+ if (raw.fromLine != null) {
275
+ const refLine = lineById.get(raw.fromLine);
276
+ if (refLine == null) {
277
+ throw new Error(
278
+ `Music "${raw.id}": fromLine "${raw.fromLine}" not found in timing.json lines`
279
+ );
280
+ }
281
+ startSec = refLine.startSec;
282
+ } else {
283
+ startSec = raw.startSec;
284
+ }
285
+ const resolved = {
286
+ id: raw.id,
287
+ file: raw.file,
288
+ startSec,
289
+ durationSec: raw.durationSec,
290
+ volume: raw.volume
291
+ };
292
+ if (raw.fadeInSec != null) resolved.fadeInSec = raw.fadeInSec;
293
+ if (raw.fadeOutSec != null) resolved.fadeOutSec = raw.fadeOutSec;
294
+ if (raw.duckTo != null) resolved.duckTo = raw.duckTo;
295
+ return resolved;
296
+ });
297
+ return {
298
+ version: 1,
299
+ fps,
300
+ totalDurationSec: timing.totalDurationSec,
301
+ dialog,
302
+ music,
303
+ sfx,
304
+ overlays: []
305
+ };
306
+ }
227
307
 
228
308
  // src/cli/guided/steps/render.ts
229
309
  function needsInstall(remotionDir) {
@@ -267,7 +347,7 @@ async function runRender(options) {
267
347
  mkdirSync(remotionDataDir, { recursive: true });
268
348
  copyFileSync(vizDataPath, resolve(remotionDataDir, "viz-data.json"));
269
349
  console.log(" \u2713 Copied viz-data.json to remotion/public/data/");
270
- const sourceAudioDir = resolve(projectDir, "audio");
350
+ const sourceAudioDir = resolveAudioDir(projectDir);
271
351
  const remotionAudioDir = resolve(remotionDir, "public", "audio");
272
352
  const sourceAudioFiles = getAudioFiles(sourceAudioDir);
273
353
  if (sourceAudioFiles.length > 0) {
@@ -280,6 +360,35 @@ async function runRender(options) {
280
360
  copyFileSync(sourceManifest, resolve(remotionAudioDir, "audio-manifest.json"));
281
361
  }
282
362
  console.log(` \u2713 Copied ${sourceAudioFiles.length} audio file(s) to remotion/public/audio/`);
363
+ const copiedManifestPath = resolve(remotionAudioDir, "audio-manifest.json");
364
+ if (existsSync(copiedManifestPath)) {
365
+ try {
366
+ const rawManifest = JSON.parse(readFileSync(copiedManifestPath, "utf-8"));
367
+ if (rawManifest?.version === 2) {
368
+ const dataDir = resolve(projectDir, progress.project.dataDir);
369
+ const timingFromOutput = resolve(outDir, "timing.json");
370
+ const timingFromData = resolve(dataDir, "timing.json");
371
+ const timingPath = existsSync(timingFromOutput) ? timingFromOutput : existsSync(timingFromData) ? timingFromData : null;
372
+ if (timingPath) {
373
+ const timing = JSON.parse(readFileSync(timingPath, "utf-8"));
374
+ const resolved = resolveAudioManifestForRemotion(rawManifest, timing);
375
+ writeFileSync(copiedManifestPath, `${JSON.stringify(resolved, null, 2)}
376
+ `);
377
+ console.log(
378
+ ` \u2713 Resolved v2 manifest \u2192 v1: ${resolved.dialog.length} dialog, ${resolved.music.length} music, ${resolved.sfx.length} sfx`
379
+ );
380
+ } else {
381
+ console.warn(
382
+ " \u26A0\uFE0F v2 audio manifest found but no timing.json \u2014 cannot resolve dialog timing."
383
+ );
384
+ console.warn(" Run the viz-timing step first to generate timing.json.");
385
+ }
386
+ }
387
+ } catch (err) {
388
+ const message = err instanceof Error ? err.message : String(err);
389
+ console.warn(` \u26A0\uFE0F Could not resolve v2 manifest: ${message}`);
390
+ }
391
+ }
283
392
  }
284
393
  const audioDir = remotionAudioDir;
285
394
  const audioFiles = getAudioFiles(audioDir);
@@ -295,7 +404,7 @@ async function runRender(options) {
295
404
  const validation = validateAudioManifest(manifest);
296
405
  if (validation.valid) {
297
406
  console.log(
298
- ` \u2713 Audio manifest valid: ${manifest.totalDurationSec}s, ${manifest.dialog.length} dialog, ${manifest.music.length} music, ${manifest.sfx.length} sfx`
407
+ ` \u2713 Audio manifest valid: ${manifest.totalDurationSec ?? "?"}s, ${(manifest.dialog ?? []).length} dialog, ${(manifest.music ?? []).length} music, ${(manifest.sfx ?? []).length} sfx`
299
408
  );
300
409
  } else {
301
410
  console.warn(" \u26A0\uFE0F Audio manifest has validation errors:");
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/transform/transform-raw.ts","../src/transform/transform-curation.ts","../src/types/script.ts","../src/types/pacing.ts","../src/types/timing.ts","../src/audio/manifest.ts"],"names":["z"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Transform source data → RawData (Contract A).\n *\n * Pure function. Deterministic. No side effects.\n * Maps existing JSON files to the generic RawData contract.\n */\n\nimport type {\n RawAgent,\n RawArtifact,\n RawCommit,\n RawData,\n RawMessage,\n RawPR,\n} from '../types/raw-data.js';\nimport type {\n SourceArtifactData,\n SourceBeamEvent,\n SourceCommit,\n SourceMessage,\n SourceMessageEvent,\n SourcePR,\n SourcePRAgentMap,\n SourceRetroPageData,\n SourceTimelineEvents,\n TransformSources,\n} from './source-types.js';\n\n/**\n * Infer a RawAgent role from a freeform role string (e.g. from teamAssembly).\n *\n * Checks for known keywords in the string (case-insensitive).\n * Order matters — more specific matches first (e.g. \"eng-lead\" matches \"lead\").\n * Falls back to 'builder' as the safest default (most common role).\n */\nexport function inferRole(roleString: string): RawAgent['role'] {\n const s = roleString.toLowerCase();\n if (s.includes('human') || s === 'user') return 'human';\n if (s.includes('lead')) return 'lead';\n if (s.includes('pm')) return 'pm';\n if (s.includes('tester') || s.includes('qa')) return 'tester';\n if (s.includes('reviewer') || s.includes('review')) return 'reviewer';\n if (s.includes('auditor') || s.includes('audit')) return 'auditor';\n if (s.includes('challenger') || s.includes('challenge')) return 'challenger';\n if (s.includes('scout')) return 'scout';\n if (s.includes('ideation')) return 'ideation';\n if (s.includes('research')) return 'researcher';\n if (s.includes('builder') || s.includes('build')) return 'builder';\n return 'builder'; // safe default — most common role\n}\n\n/**\n * Transform all source data into RawData.\n * This is the main entry point for the extraction layer.\n */\nexport function transformToRawData(sources: TransformSources): RawData {\n // First agent from teamAssembly is the default for unattributed items\n const defaultAgent = sources.retroPageData.teamAssembly[0]?.agent.replace('@', '') ?? 'unknown';\n\n return {\n project: {\n name: sources.retroPageData.meta.title,\n description: sources.retroPageData.meta.subtitle,\n },\n agents: transformAgents(\n sources.retroPageData,\n sources.chatActivity.agentTotals,\n sources.timelineEvents,\n undefined,\n sources.messages,\n ),\n commits: transformCommits(sources.commits, sources.prAgentMap, defaultAgent),\n prs: transformPRs(sources.prs, sources.prAgentMap),\n messages: transformMessages(sources.timelineEvents, sources.messages),\n artifacts: sources.artifactData\n ? transformArtifacts(\n sources.artifactData,\n sources.retroPageData,\n sources.prs,\n sources.prAgentMap,\n )\n : [],\n };\n}\n\n/**\n * Build a map of agent → earliest message timestamp from timeline events.\n * Only counts messages where the agent is the sender (not just mentioned).\n */\nfunction buildFirstMessageTimeMap(timelineEvents?: SourceTimelineEvents): Map<string, number> {\n const map = new Map<string, number>();\n if (!timelineEvents) return map;\n\n for (const evt of timelineEvents.events) {\n if (evt.type !== 'message' && evt.type !== 'beam') continue;\n const sender = (evt as SourceMessageEvent | SourceBeamEvent).from;\n const ts = new Date(evt.t).getTime();\n const existing = map.get(sender);\n if (existing === undefined || ts < existing) {\n map.set(sender, ts);\n }\n }\n\n return map;\n}\n\n/**\n * Build RawAgent[] from team assembly data + chat activity.\n *\n * joinedAt resolution priority:\n * 1. First message timestamp from timeline events (most accurate)\n * 2. teamAssembly join time (curated/scaffold fallback)\n * 3. Project start date (last resort)\n *\n * Role resolution priority:\n * 1. Explicit `agentRoles` override (if provided)\n * 2. Inferred from teamAssembly `role` field (e.g. \"eng-lead\" → \"lead\")\n * 3. Default: 'builder' (most common role, safe fallback)\n *\n * Never throws on unknown agents — always infers or defaults.\n */\nexport function transformAgents(\n retroData: SourceRetroPageData,\n agentTotals: Record<string, number>,\n timelineEvents?: SourceTimelineEvents,\n agentRoles?: Record<string, string>,\n messages?: SourceMessage[],\n): RawAgent[] {\n const agents: RawAgent[] = [];\n const seen = new Set<string>();\n\n // Build first-message-time lookup from timeline events\n const firstMessageTime = buildFirstMessageTimeMap(timelineEvents);\n\n // Build a lookup from teamAssembly role fields for agents not in override\n const assemblyRoles = new Map<string, string>();\n for (const entry of retroData.teamAssembly) {\n const id = entry.agent.replace('@', '');\n assemblyRoles.set(id, entry.role);\n }\n\n /** Resolve role for an agent: override → teamAssembly inference → default */\n function resolveRole(id: string): RawAgent['role'] {\n // 1. Explicit override\n if (agentRoles?.[id]) {\n return inferRole(agentRoles[id]);\n }\n // 2. Infer from teamAssembly role field\n const assemblyRole = assemblyRoles.get(id);\n if (assemblyRole) {\n return inferRole(assemblyRole);\n }\n // 3. Default\n return 'builder';\n }\n\n /** Resolve joinedAt: earliest of (first message, teamAssembly time), or startDate */\n function resolveJoinedAt(id: string, assemblyTime?: number): number {\n const msgTime = firstMessageTime.get(id);\n // Use earliest available timestamp — agent was present from whichever came first\n if (msgTime !== undefined && assemblyTime !== undefined) {\n return Math.min(msgTime, assemblyTime);\n }\n if (msgTime !== undefined) return msgTime;\n if (assemblyTime !== undefined) return assemblyTime;\n // Last resort: project start date\n return new Date(retroData.meta.startDate).getTime();\n }\n\n // Primary source: team assembly (has join times)\n for (const entry of retroData.teamAssembly) {\n const id = entry.agent.replace('@', '');\n if (seen.has(id)) continue;\n seen.add(id);\n\n agents.push({\n id,\n role: resolveRole(id),\n joinedAt: resolveJoinedAt(id, new Date(entry.time).getTime()),\n });\n }\n\n // Catch any agents in chat activity not in team assembly\n for (const id of Object.keys(agentTotals)) {\n if (seen.has(id)) continue;\n agents.push({\n id,\n role: resolveRole(id),\n joinedAt: resolveJoinedAt(id),\n });\n seen.add(id);\n }\n\n // Detect human users from message senderType.\n // Two phases: (1) add unseen human senders, (2) upgrade already-seen\n // agents to role: 'human'. Phase 2 is needed because users like @snorre\n // appear in agentTotals (they send messages) and get role: 'builder'\n // before the senderType check — see PR #640 review by @check.\n if (messages) {\n const humanSenders = new Set<string>();\n for (const msg of messages) {\n if (msg.senderType === 'user') humanSenders.add(msg.sender);\n }\n\n // Phase 1: add unseen human senders\n for (const id of humanSenders) {\n if (!seen.has(id)) {\n seen.add(id);\n agents.push({\n id,\n role: 'human',\n joinedAt: resolveJoinedAt(id),\n });\n }\n }\n\n // Phase 2: upgrade already-seen agents to human\n for (const agent of agents) {\n if (humanSenders.has(agent.id)) {\n agent.role = 'human';\n }\n }\n }\n\n return agents;\n}\n\n/**\n * Transform git commits → RawCommit[].\n * Cross-references pr-agent-map for attribution.\n *\n * @param defaultAgent - Fallback agent for commits with no PR reference\n * (typically the first agent from teamAssembly/roster)\n */\nexport function transformCommits(\n commits: SourceCommit[],\n prAgentMap: SourcePRAgentMap,\n defaultAgent = 'unknown',\n): RawCommit[] {\n return commits.map((c) => {\n const agent = resolveCommitAgent(c, prAgentMap, defaultAgent);\n\n return {\n sha: c.hash,\n timestamp: new Date(c.date).getTime(),\n agent,\n message: c.subject,\n filesChanged: c.files.length,\n insertions: c.totalInsertions,\n deletions: c.totalDeletions,\n prNumber: c.prNumber ?? undefined,\n };\n });\n}\n\n/**\n * Resolve which agent authored a commit.\n * Strategy chain:\n * 1. prNumber field → pr-agent-map lookup\n * 2. \"Merge pull request #N\" in subject → pr-agent-map lookup\n * 3. \"(#N)\" suffix in subject → pr-agent-map lookup\n * 4. Fallback to defaultAgent (first agent from roster/teamAssembly)\n */\nexport function resolveCommitAgent(\n commit: SourceCommit,\n prAgentMap: SourcePRAgentMap,\n defaultAgent = 'unknown',\n): string {\n // Strategy 1: direct prNumber field\n if (commit.prNumber != null) {\n const agent = prAgentMap[String(commit.prNumber)];\n if (agent) return agent;\n }\n\n // Strategy 2: \"Merge pull request #N\" pattern\n const mergeMatch = commit.subject.match(/^Merge pull request #(\\d+)/);\n if (mergeMatch) {\n const agent = prAgentMap[mergeMatch[1]];\n if (agent) return agent;\n }\n\n // Strategy 3: \"(#N)\" suffix pattern\n const suffixMatch = commit.subject.match(/\\(#(\\d+)\\)\\s*$/);\n if (suffixMatch) {\n const agent = prAgentMap[suffixMatch[1]];\n if (agent) return agent;\n }\n\n // Fallback: first agent from roster (caller provides)\n return defaultAgent;\n}\n\n/**\n * Transform PR details → RawPR[].\n * Cross-references pr-agent-map for attribution.\n */\nexport function transformPRs(prs: SourcePR[], prAgentMap: SourcePRAgentMap): RawPR[] {\n return prs.map((pr) => {\n const agent = prAgentMap[String(pr.number)] ?? 'unknown';\n\n return {\n number: pr.number,\n title: pr.title,\n agent,\n createdAt: new Date(pr.createdAt).getTime(),\n mergedAt: pr.mergedAt ? new Date(pr.mergedAt).getTime() : null,\n additions: pr.additions,\n deletions: pr.deletions,\n branch: pr.headRefName,\n };\n });\n}\n\n/**\n * Infer artifact type from slug or file path.\n *\n * Handles both platforms:\n * - Redux: file paths with extensions (\"/specs/auth.md\", \"plan/task-X1Y2\")\n * - Cast: artifact slugs (\"spec-auth\", \"screenshot-login\", \"qa-review\")\n *\n * Redux patterns are checked first (more specific), cast patterns as fallback.\n */\nexport function inferArtifactType(slug: string): RawArtifact['type'] {\n // --- Redux: plan item prefixes ---\n if (slug.startsWith('plan/task-')) return 'task';\n if (slug.startsWith('plan/spec-')) return 'doc';\n\n // --- Extension-based (works for both platforms, but primarily redux file paths) ---\n const ext = slug.split('.').pop()?.toLowerCase();\n if (ext && ['ts', 'tsx', 'js', 'jsx', 'py', 'rs', 'go', 'sh'].includes(ext)) return 'code';\n if (ext && ['png', 'jpg', 'jpeg', 'svg', 'gif', 'webp', 'ico'].includes(ext)) return 'asset';\n if (ext && ['md', 'txt', 'json', 'yaml', 'yml', 'toml'].includes(ext)) return 'doc';\n\n // --- Redux: path-based patterns ---\n if (slug.includes('/specs/') || slug.includes('/spec/')) return 'doc';\n if (slug.includes('/assets/') || slug.includes('/images/')) return 'asset';\n\n // --- Cast: existing slug patterns (backward compat) ---\n if (slug.includes('.app.')) return 'code';\n if (slug.includes('screenshot') || slug.includes('qa-')) return 'asset';\n if (slug.includes('decision')) return 'decision';\n if (slug.includes('task') || slug.includes('phase-')) return 'task';\n if (slug.startsWith('spec-') || slug.startsWith('spec')) return 'doc';\n if (slug.includes('concept')) return 'doc';\n\n return 'doc';\n}\n\n/**\n * Resolve artifact agent from source data.\n *\n * Priority:\n * 1. Explicit `createdBy` from the artifact record (Miriad API provides this)\n * 2. PR number in slug → pr-agent-map lookup\n * 3. Configurable default (first agent from roster, typically the lead)\n */\nexport function resolveArtifactAgent(\n slug: string,\n prAgentMap: SourcePRAgentMap,\n createdBy: string | undefined,\n defaultAgent: string,\n): string {\n // 1. Explicit creator from source data\n if (createdBy) return createdBy;\n\n // 2. PR reference in slug → agent map\n const prMatch = slug.match(/#?(\\d+)/);\n if (prMatch) {\n const agent = prAgentMap[prMatch[1]];\n if (agent) return agent;\n }\n\n // 3. Default (first agent from roster)\n return defaultAgent;\n}\n\n/** Category name → artifact type */\nconst CATEGORY_TYPE_MAP: Record<string, RawArtifact['type']> = {\n qaScreenshots: 'asset',\n transitionSpecs: 'doc',\n transitionConcepts: 'doc',\n scenes: 'doc',\n vizConcepts: 'code',\n teamPrinciples: 'doc',\n retroData: 'doc',\n decisions: 'decision',\n};\n\n/**\n * Distribute N artifacts within time boundaries, clustered around\n * PR timestamps when available for realistic density.\n */\nexport function distributeTimestamps(\n count: number,\n bounds: { start: number; end: number },\n prTimestamps: number[],\n): number[] {\n const phasePRTimes = prTimestamps.filter((t) => t >= bounds.start && t <= bounds.end);\n const timestamps: number[] = [];\n\n for (let i = 0; i < count; i++) {\n let timestamp: number;\n if (phasePRTimes.length > 0) {\n const prIdx = i % phasePRTimes.length;\n timestamp = phasePRTimes[prIdx] + i * 60000;\n } else {\n const fraction = count > 1 ? i / (count - 1) : 0.5;\n timestamp = bounds.start + fraction * (bounds.end - bounds.start);\n }\n timestamps.push(Math.round(Math.max(bounds.start, Math.min(bounds.end, timestamp))));\n }\n\n return timestamps;\n}\n\n/**\n * Build a type distribution from category data.\n *\n * Each category maps to a type. We build a weighted list so bulk\n * artifacts can be assigned types proportional to category counts.\n * Returns entries sorted by count descending for deterministic assignment.\n *\n * Agent assignment is NOT done here — it's handled by the caller using\n * round-robin over the known agent list (from teamAssembly).\n */\nexport function buildCategoryDistribution(\n categories: SourceArtifactData['categories'],\n): Array<{ type: RawArtifact['type']; weight: number }> {\n const entries: Array<{ type: RawArtifact['type']; count: number }> = [];\n let total = 0;\n\n for (const [categoryName, categoryData] of Object.entries(categories)) {\n if (categoryData.count === 0) continue;\n entries.push({\n type: CATEGORY_TYPE_MAP[categoryName] ?? 'doc',\n count: categoryData.count,\n });\n total += categoryData.count;\n }\n\n if (total === 0) return [{ type: 'doc', weight: 1 }];\n\n return entries\n .sort((a, b) => b.count - a.count)\n .map((e) => ({ type: e.type, weight: e.count / total }));\n}\n\n/**\n * Build a slug → createdBy lookup from SourceArtifactData category items.\n * Items can be plain strings (no creator info) or objects with optional createdBy.\n */\nfunction buildCreatedByLookup(categories: SourceArtifactData['categories']): Map<string, string> {\n const lookup = new Map<string, string>();\n for (const categoryData of Object.values(categories)) {\n for (const item of categoryData.items ?? []) {\n if (typeof item === 'object' && item.createdBy) {\n lookup.set(item.slug, item.createdBy);\n }\n }\n }\n return lookup;\n}\n\n/**\n * Transform artifact-data.json → RawArtifact[].\n *\n * Uses phase `count` fields for correct per-phase density. Each phase\n * specifies how many artifacts were created during that time window:\n * Phase 1: 5, Phase 2: 45, Phase 3: 80, Phase 4: 120, Phase 5: 60 = 310\n *\n * Within each phase:\n * 1. Curated slugs get their own entries with createdBy from source data\n * 2. Remaining count filled with generated artifacts using category\n * type proportions and round-robin agent assignment\n * 3. All timestamps distributed within phase boundaries, clustered\n * around PR activity\n */\nexport function transformArtifacts(\n artifactData: SourceArtifactData,\n retroData: SourceRetroPageData,\n prs: SourcePR[],\n prAgentMap: SourcePRAgentMap,\n): RawArtifact[] {\n const artifacts: RawArtifact[] = [];\n\n // Build agent list from teamAssembly for round-robin and default\n const agentIds = retroData.teamAssembly.map((e) => e.agent.replace('@', ''));\n const defaultAgent = agentIds[0] ?? 'unknown';\n\n const phaseBoundaries = retroData.phases.map((p) => ({\n start: new Date(p.start).getTime(),\n end: new Date(p.end).getTime(),\n }));\n\n const prTimestamps = prs.map((pr) => new Date(pr.createdAt).getTime()).sort((a, b) => a - b);\n const distribution = buildCategoryDistribution(artifactData.categories);\n const createdByLookup = buildCreatedByLookup(artifactData.categories);\n\n let phaseIndex = 0;\n let globalBulkIndex = 0;\n\n for (const [_phaseName, phaseData] of Object.entries(artifactData.phases)) {\n if (phaseIndex >= phaseBoundaries.length) break;\n const bounds = phaseBoundaries[phaseIndex];\n phaseIndex++;\n\n const totalCount = phaseData.count;\n const slugs = phaseData.artifacts;\n const bulkCount = Math.max(0, totalCount - slugs.length);\n\n // All artifacts in this phase share one timestamp distribution\n const timestamps = distributeTimestamps(totalCount, bounds, prTimestamps);\n\n // ── Curated slugs first ──────────────────────────────────────────────\n let tsIdx = 0;\n for (const slug of slugs) {\n artifacts.push({\n slug,\n type: inferArtifactType(slug),\n createdAt: timestamps[tsIdx],\n updatedAt: timestamps[tsIdx],\n agent: resolveArtifactAgent(slug, prAgentMap, createdByLookup.get(slug), defaultAgent),\n });\n tsIdx++;\n }\n\n // ── Bulk artifacts fill remaining count ───────────────────────────────\n // Assign type by walking through the weighted distribution.\n // Assign agent by round-robin over the known agent list.\n let distIdx = 0;\n let distBudget = Math.round(distribution[0].weight * bulkCount);\n\n for (let i = 0; i < bulkCount; i++) {\n // Advance to next distribution bucket when current is exhausted\n while (distBudget <= 0 && distIdx < distribution.length - 1) {\n distIdx++;\n distBudget = Math.round(distribution[distIdx].weight * bulkCount);\n }\n distBudget--;\n\n const entry = distribution[distIdx];\n // Round-robin agent assignment across the roster\n const agent =\n agentIds.length > 0 ? agentIds[globalBulkIndex % agentIds.length] : defaultAgent;\n artifacts.push({\n slug: `phase${phaseIndex}-${entry.type}-${String(globalBulkIndex + 1).padStart(3, '0')}`,\n type: entry.type,\n createdAt: timestamps[tsIdx],\n updatedAt: timestamps[tsIdx],\n agent,\n });\n tsIdx++;\n globalBulkIndex++;\n }\n }\n\n artifacts.sort((a, b) => a.createdAt - b.createdAt);\n\n return artifacts;\n}\n\n/**\n * Transform curated timeline events into chat pills for the viewer.\n *\n * Chat pills come ONLY from timeline-events.json (curated).\n * Raw messages (messages-viz.json) are NEVER a source for chat pills —\n * they exist only for the agent to read during curation and for the\n * density table's \"Msgs\" column.\n *\n * Single source of truth: the curated file.\n */\nexport function transformMessages(\n timelineEvents: SourceTimelineEvents,\n rawMessages?: SourceMessage[],\n): RawMessage[] {\n // Curated events (timeline-events.json) → chat pills (labeled bubbles)\n const curatedMessages = timelineEvents.events\n .filter(\n (e): e is SourceMessageEvent | SourceBeamEvent => e.type === 'message' || e.type === 'beam',\n )\n .map((evt, i) => ({\n id: `curated-${String(i).padStart(4, '0')}`,\n timestamp: new Date(evt.t).getTime(),\n sender: evt.from,\n mentions: [evt.to],\n }));\n\n // Raw messages (messages-viz.json / messages-full.json) → beam channels + particles\n const rawMsgs: RawMessage[] = (rawMessages ?? []).map((msg, i) => ({\n id: msg.id || `raw-${String(i).padStart(4, '0')}`,\n timestamp: new Date(msg.timestamp).getTime(),\n sender: msg.sender,\n mentions: msg.mentions,\n }));\n\n // Merge: raw messages provide beam/particle density, curated provide labeled pills.\n // Deduplicate by timestamp+sender to avoid double-counting when a raw message\n // was also curated as a chat pill.\n const seen = new Set(rawMsgs.map((m) => `${m.timestamp}:${m.sender}`));\n const uniqueCurated = curatedMessages.filter((m) => !seen.has(`${m.timestamp}:${m.sender}`));\n\n return [...rawMsgs, ...uniqueCurated];\n}\n","/**\n * Transform source data → CurationData (editorial content).\n *\n * Pure function. Deterministic. No side effects.\n * Maps curated board artifacts to the CurationData contract.\n */\n\nimport type {\n CurationData,\n CurationMilestone,\n CurationNarrationEntry,\n CurationPhase,\n CurationQuote,\n CurationTrustKeyframe,\n} from '../types/raw-data.js';\nimport type {\n SourceRetroPageData,\n SourceRetroPageQuotes,\n TransformSources,\n} from './source-types.js';\n\n/**\n * Transform curated source data into CurationData.\n * This is the main entry point for the curation layer.\n */\nexport function transformToCurationData(sources: TransformSources): CurationData {\n const narration = transformNarration(sources.retroPageData);\n const meta = sources.retroPageData.meta;\n\n // Thread curated timeline bounds from meta.startDate/endDate\n const curatedStartMs = meta?.startDate ? new Date(meta.startDate).getTime() : undefined;\n const curatedEndMs = meta?.endDate ? new Date(meta.endDate).getTime() : undefined;\n\n return {\n phases: transformPhases(sources.retroPageData),\n quotes: transformQuotes(sources.retroPageData, sources.retroPageQuotes),\n milestones: transformMilestones(sources.retroPageData),\n trustKeyframes: transformTrustKeyframes(sources.retroPageData),\n ...(narration.length > 0 ? { editorialNarration: narration } : {}),\n ...(curatedStartMs && !Number.isNaN(curatedStartMs) ? { curatedStartMs } : {}),\n ...(curatedEndMs && !Number.isNaN(curatedEndMs) ? { curatedEndMs } : {}),\n };\n}\n\n/**\n * Transform phase definitions from retro-page-data.\n * Phases have hand-curated boundaries, names, and descriptions.\n */\nexport function transformPhases(retroData: SourceRetroPageData): CurationPhase[] {\n return retroData.phases.map((p) => ({\n id: p.id,\n name: p.name || p.label || '',\n startTime: new Date(p.start || p.startTime || '').getTime(),\n endTime: new Date(p.end || p.endTime || '').getTime(),\n }));\n}\n\n/**\n * Transform milestones from retro-page-data.\n * Each milestone is cross-referenced to its containing phase.\n */\nexport function transformMilestones(retroData: SourceRetroPageData): CurationMilestone[] {\n const phases = retroData.phases;\n\n return retroData.milestones.map((m) => {\n const milestoneTime = new Date(m.time).getTime();\n const phase = findPhaseForTimestamp(milestoneTime, phases);\n\n return {\n label: m.label,\n timestamp: milestoneTime,\n phase: phase?.id ?? 'unknown',\n };\n });\n}\n\n/**\n * Map mood category to mood string for quotes from retroPageData.\n */\nconst CATEGORY_MOOD: Record<string, string> = {\n theGood: 'good',\n theBad: 'bad',\n theUgly: 'angry',\n theFunny: 'good',\n};\n\n/**\n * Map mood category to mood string for quotes from retroPageQuotes.\n */\nconst ADDITION_MOOD: Record<string, string> = {\n good: 'good',\n bad: 'bad',\n ugly: 'angry',\n};\n\n/**\n * Transform quotes from both curated sources.\n * Merges retro-page-data quotes (theGood/theBad/theUgly/theFunny) with\n * retro-page-quotes additions (good/bad/ugly). Parses informal timestamps,\n * strips @ prefix from speakers, and cross-references to phases.\n * Sorted by timestamp.\n */\nexport function transformQuotes(\n retroData: SourceRetroPageData,\n retroQuotes: SourceRetroPageQuotes,\n): CurationQuote[] {\n const phases = retroData.phases;\n const quotes: CurationQuote[] = [];\n\n // Derive reference year from first phase start date (for informal timestamp parsing)\n const firstPhaseStart = phases[0]?.start;\n const referenceYear = firstPhaseStart\n ? new Date(firstPhaseStart).getUTCFullYear()\n : new Date().getUTCFullYear();\n\n // Source 1: retroPageData.quotes (theGood, theBad, theUgly, theFunny)\n for (const [category, entries] of Object.entries(retroData.quotes)) {\n if (!Array.isArray(entries)) continue; // skip _comment and other non-quote fields\n const mood = CATEGORY_MOOD[category] ?? 'good';\n for (const entry of entries) {\n const timestamp = parseInformalTimestamp(entry.time, referenceYear);\n if (timestamp == null) continue;\n const phase = findPhaseForTimestamp(timestamp, phases);\n quotes.push({\n text: entry.text,\n speaker: entry.author.replace(/^@/, ''),\n timestamp,\n phase: phase?.id ?? 'unknown',\n mood,\n });\n }\n }\n\n // Source 2: retroPageQuotes (good, bad, ugly)\n for (const [category, entries] of Object.entries(retroQuotes)) {\n if (!Array.isArray(entries)) continue; // skip _comment and other non-quote fields\n const mood = ADDITION_MOOD[category] ?? 'good';\n for (const entry of entries) {\n const timestamp = parseInformalTimestamp(entry.timestamp, referenceYear);\n if (timestamp == null) continue;\n const phase = findPhaseForTimestamp(timestamp, phases);\n quotes.push({\n text: entry.text,\n speaker: entry.author.replace(/^@/, ''),\n timestamp,\n phase: phase?.id ?? 'unknown',\n mood,\n });\n }\n }\n\n // Sort chronologically\n quotes.sort((a, b) => a.timestamp - b.timestamp);\n return quotes;\n}\n\n/**\n * Transform trust arc keyframes from retro-page-data.\n * Source levels are 0-100 integers; we normalize to 0-1.\n * Sorted by timestamp for interpolation.\n */\nexport function transformTrustKeyframes(retroData: SourceRetroPageData): CurationTrustKeyframe[] {\n if (!retroData.trustArc || retroData.trustArc.length === 0) return [];\n\n return retroData.trustArc\n .map((entry) => ({\n timestamp: new Date(entry.time).getTime(),\n level: entry.level / 100, // normalize 0-100 → 0-1\n label: entry.label,\n }))\n .sort((a, b) => a.timestamp - b.timestamp);\n}\n\n/** Month abbreviation → 0-based index */\nconst MONTH_ABBREVS: Record<string, number> = {\n jan: 0,\n feb: 1,\n mar: 2,\n apr: 3,\n may: 4,\n jun: 5,\n jul: 6,\n aug: 7,\n sep: 8,\n oct: 9,\n nov: 10,\n dec: 11,\n};\n\n/**\n * Transform editorial narration entries from retro-page-data.\n * Each entry has an ISO timestamp, phase title, color, text, and type.\n * Returns empty array if no narration is present in the source data.\n */\nexport function transformNarration(retroData: SourceRetroPageData): CurationNarrationEntry[] {\n if (!retroData.editorialNarration || retroData.editorialNarration.length === 0) return [];\n\n return retroData.editorialNarration\n .map((entry) => ({\n timestamp: new Date(entry.time).getTime(),\n phaseTitle: entry.phaseTitle,\n phaseColor: entry.phaseColor,\n text: entry.text,\n type: entry.type,\n }))\n .sort((a, b) => a.timestamp - b.timestamp);\n}\n\n/**\n * Parse informal timestamp strings like \"Feb 10 21:18\", \"Dec 31 (early)\", \"Jan 2 ~23:00\".\n * Accepts any 3-letter month abbreviation.\n *\n * @param timeStr - Informal timestamp (e.g., \"Feb 10 21:18\", \"Dec 31\")\n * @param referenceYear - Year to use (e.g., 2025). Required — no hardcoded default.\n * For projects spanning Dec→Jan, callers should handle year rollover.\n * @returns Unix ms or null if unparseable.\n */\nexport function parseInformalTimestamp(\n timeStr: string | undefined | null,\n referenceYear: number,\n): number | null {\n if (!timeStr) return null;\n\n // Try ISO 8601 first (scaffold generates ISO timestamps)\n const isoDate = new Date(timeStr);\n if (!Number.isNaN(isoDate.getTime()) && timeStr.includes('-')) {\n return isoDate.getTime();\n }\n\n // Strip tildes and parenthetical notes\n const cleaned = timeStr\n .replace(/~/g, '')\n .replace(/\\(.*?\\)/g, '')\n .trim();\n\n // Match \"Mon DD HH:MM\" or \"Mon DD\" (3-letter month abbreviation)\n const match = cleaned.match(/([A-Za-z]{3})\\s+(\\d{1,2})(?:\\s+(\\d{1,2}):(\\d{2}))?/);\n if (!match) return null;\n\n const monthIdx = MONTH_ABBREVS[match[1].toLowerCase()];\n if (monthIdx === undefined) return null;\n\n const day = Number.parseInt(match[2], 10);\n const hour = match[3] ? Number.parseInt(match[3], 10) : 12; // default to noon if no time\n const minute = match[4] ? Number.parseInt(match[4], 10) : 0;\n\n const date = new Date(Date.UTC(referenceYear, monthIdx, day, hour, minute, 0));\n return date.getTime();\n}\n\n/**\n * Find which phase a timestamp falls within.\n * First tries exact range match. If no phase contains the timestamp\n * (e.g., it falls in a gap between phases), falls back to the nearest\n * phase by distance to its start/end boundaries.\n *\n * Returns undefined only when phases array is empty.\n */\nexport function findPhaseForTimestamp(\n timestamp: number,\n phases: SourceRetroPageData['phases'],\n): SourceRetroPageData['phases'][number] | undefined {\n if (phases.length === 0) return undefined;\n\n // Try exact range match first\n const exact = phases.find((p) => {\n const start = new Date(p.start || p.startTime || '').getTime();\n const end = new Date(p.end || p.endTime || '').getTime();\n return timestamp >= start && timestamp <= end;\n });\n if (exact) return exact;\n\n // Fallback: find nearest phase by distance to boundaries\n let nearest: SourceRetroPageData['phases'][number] | undefined;\n let minDistance = Number.POSITIVE_INFINITY;\n\n for (const p of phases) {\n const start = new Date(p.start || p.startTime || '').getTime();\n const end = new Date(p.end || p.endTime || '').getTime();\n const distance = Math.min(Math.abs(timestamp - start), Math.abs(timestamp - end));\n if (distance < minDistance) {\n minDistance = distance;\n nearest = p;\n }\n }\n\n return nearest;\n}\n","/**\n * ScriptFile — the authoring contract for Step 2 (Script Writing).\n *\n * WHY: The script is the creative foundation. An agent writes this file\n * to define the narrative structure: who speaks, what they say, and in\n * what style. Every downstream file (pacing, timing) derives from this.\n *\n * The agent creates this from scratch in Step 2, guided by extracted data\n * (event density, agent activity, phases). The human reviews and approves.\n */\n\nimport { z } from 'zod';\n\n// --- Zod schemas (source of truth) ---\n\nexport const ScriptLineSchema = z.object({\n /** Unique identifier for this line (e.g., 'narrator-01', 'lead-03') */\n id: z.string().min(1),\n /** Who speaks this line (e.g., 'narrator', 'lead', 'snorre') */\n speaker: z.string().min(1),\n /** The spoken text */\n text: z.string().min(1),\n /** Rendering style: narrator voice (cursive) or agent quote (normal) */\n style: z.enum(['narrator', 'quote']),\n /** Optional phase this line belongs to (for grouping in the viz) */\n phaseId: z.string().optional(),\n});\n\nexport const ScriptFileSchema = z\n .object({\n /** Schema version — always 1 for now */\n version: z.literal(1),\n /** Ordered list of script lines */\n lines: z.array(ScriptLineSchema).min(1),\n })\n .superRefine((data, ctx) => {\n // Enforce unique line IDs\n const ids = new Set<string>();\n for (let i = 0; i < data.lines.length; i++) {\n const id = data.lines[i].id;\n if (ids.has(id)) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: `Duplicate line ID: \"${id}\" (line index ${i})`,\n path: ['lines', i, 'id'],\n });\n }\n ids.add(id);\n }\n });\n\n// --- TypeScript types (inferred from schemas) ---\n\nexport type ScriptLine = z.infer<typeof ScriptLineSchema>;\nexport type ScriptFile = z.infer<typeof ScriptFileSchema>;\n\n// --- Normalization ---\n\n/**\n * Auto-populate missing fields so a minimal script.json passes ScriptFileSchema.\n *\n * - If `version` is missing, defaults to `1`.\n * - If `style` is missing on a line, infers from speaker:\n * `speaker === 'narrator'` → `'narrator'`, otherwise → `'quote'`.\n *\n * Returns a new object (does not mutate the input).\n */\nexport function normalizeScript(raw: Record<string, unknown>): Record<string, unknown> {\n const out: Record<string, unknown> = { ...raw };\n\n if (out.version === undefined) {\n out.version = 1;\n }\n\n if (Array.isArray(out.lines)) {\n out.lines = (out.lines as Record<string, unknown>[]).map((line) => {\n if (line === null || typeof line !== 'object') return line;\n const l = { ...line };\n if (!l.style && typeof l.speaker === 'string') {\n l.style = l.speaker === 'narrator' ? 'narrator' : 'quote';\n }\n return l;\n });\n }\n\n return out;\n}\n","/**\n * PacingFile — the agent-facing timing contract for Step 4 (Viz Timing).\n *\n * WHY: The pacing file is what the agent edits to control how fast the viz\n * moves during each narration line. scaffold-pacing generates it from\n * script.json + audio clip durations. The agent then annotates 4 optional\n * fields per line: pauseAfter, vizSpeed, gapVizSpeed, note.\n *\n * Design: Approach A (Annotated Script) — mirrors the script with timing\n * annotations. Text + clip durations inline. Defaults handle 80% of lines.\n * No cascading edits (unlike start-time approaches).\n *\n * vizSpeed definition: multiplier on project-time-per-second.\n * 2.0 = viz moves 2x faster = LESS screen time for that period.\n * 0.5 = viz moves 2x slower = MORE screen time for that period.\n */\n\nimport { z } from 'zod';\n\n// --- Zod schemas (source of truth) ---\n\nexport const PacingLineSchema = z.object({\n /** Line ID — must match script.json line ID */\n id: z.string().min(1),\n /** Text from script (read-only, for context while editing pacing) */\n text: z.string().min(1),\n /** Audio clip duration in seconds (measured from file, read-only) */\n clipDuration: z.number().positive(),\n /** Silence after this line in seconds (overrides defaultPauseSec) */\n pauseAfter: z.number().nonnegative().optional(),\n /** Viz speed multiplier DURING this clip's audio. >1 = faster, <1 = slower */\n vizSpeed: z.number().positive().optional(),\n /** Viz speed multiplier DURING the pause after this clip (defaults to defaultVizSpeed) */\n gapVizSpeed: z.number().positive().optional(),\n /** Agent's reasoning for pacing choices (human reads during review) */\n note: z.string().optional(),\n});\n\nexport const PacingFileSchema = z\n .object({\n /** Schema version — always 1 for now */\n version: z.literal(1),\n /** Seconds of viz playback before first narration line */\n leadInSec: z.number().nonnegative().optional(),\n /** Seconds of viz playback after last narration line */\n tailOutSec: z.number().nonnegative().optional(),\n /** Default pause between lines in seconds (used when pauseAfter not set) */\n defaultPauseSec: z.number().nonnegative(),\n /** Default viz speed multiplier (used when vizSpeed/gapVizSpeed not set) */\n defaultVizSpeed: z.number().positive(),\n /** Ordered list of pacing lines — must match script.json order */\n lines: z.array(PacingLineSchema).min(1),\n })\n .superRefine((data, ctx) => {\n // Enforce unique line IDs\n const ids = new Set<string>();\n for (let i = 0; i < data.lines.length; i++) {\n const id = data.lines[i].id;\n if (ids.has(id)) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: `Duplicate line ID: \"${id}\" (line index ${i})`,\n path: ['lines', i, 'id'],\n });\n }\n ids.add(id);\n }\n });\n\n// --- TypeScript types (inferred from schemas) ---\n\nexport type PacingLine = z.infer<typeof PacingLineSchema>;\nexport type PacingFile = z.infer<typeof PacingFileSchema>;\n","/**\n * TimingFile — the engine-facing contract produced by generateTiming().\n *\n * WHY: This is the fully-resolved timing data that the transform layer reads\n * to produce narration entries with precise progress mapping. All fields are\n * required — no defaults, no optionals (except phase). generateTiming()\n * resolves all defaults from PacingFile and computes progress values.\n *\n * The transform layer validates this on read (belt-and-suspenders with\n * generateTiming's validation on write). If this file is corrupt, the\n * pipeline fails fast with a clear error.\n */\n\nimport { z } from 'zod';\n\n// --- Zod schemas (source of truth) ---\n\nexport const TimedLineSchema = z\n .object({\n /** Line ID — matches script.json and pacing.json */\n id: z.string().min(1),\n /** Speaker identifier (e.g., 'narrator', 'lead', 'snorre') */\n speaker: z.string().min(1),\n /** The spoken text */\n text: z.string().min(1),\n /** Rendering style: narrator voice (cursive) or agent quote (normal) */\n style: z.enum(['narrator', 'quote']),\n /** Wall-clock start time in seconds from video start */\n startSec: z.number().nonnegative(),\n /** Audio clip duration in seconds */\n durationSec: z.number().positive(),\n /** Pause after this line in seconds (resolved from defaults) */\n pauseAfterSec: z.number().nonnegative(),\n /** Audio file path relative to audio directory (e.g., 'narrator-01.mp3') */\n audioFile: z.string().min(1),\n /** Viz progress at clip start [0, 1] */\n progressStart: z.number().min(0).max(1),\n /** Viz progress at clip end [0, 1] */\n progressEnd: z.number().min(0).max(1),\n /** Viz speed multiplier during this clip */\n vizSpeed: z.number().positive(),\n /** Viz speed multiplier during the pause after this clip */\n gapVizSpeed: z.number().positive(),\n /** Phase this line belongs to (optional) */\n phase: z.string().optional(),\n })\n .refine((line) => line.progressStart <= line.progressEnd, {\n message: 'progressStart must be <= progressEnd',\n path: ['progressStart'],\n });\n\nexport const TimingFileSchema = z\n .object({\n /** Schema version — always 1 for now */\n version: z.literal(1),\n /** Total video duration in seconds */\n totalDurationSec: z.number().positive(),\n /** Ordered list of timed lines — fully resolved, all fields required */\n lines: z.array(TimedLineSchema).min(1),\n })\n .superRefine((data, ctx) => {\n // Enforce unique line IDs\n const ids = new Set<string>();\n for (let i = 0; i < data.lines.length; i++) {\n const id = data.lines[i].id;\n if (ids.has(id)) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: `Duplicate line ID: \"${id}\" (line index ${i})`,\n path: ['lines', i, 'id'],\n });\n }\n ids.add(id);\n }\n });\n\n// --- TypeScript types (inferred from schemas) ---\n\nexport type TimedLine = z.infer<typeof TimedLineSchema>;\nexport type TimingFile = z.infer<typeof TimingFileSchema>;\n","/**\n * Audio manifest schema — the contract between audio generation and Remotion consumption.\n * Lives at: remotion/public/audio/audio-manifest.json\n *\n * @module audio/manifest\n */\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface AudioManifest {\n version: 1;\n fps: number;\n totalDurationSec: number;\n\n /** Per-beat voice clips */\n dialog: DialogBeat[];\n /** Background music tracks */\n music: MusicTrack[];\n /** One-shot sound effects */\n sfx: SfxPlacement[];\n /** Text overlays (title cards, labels, data accents) */\n overlays: TextOverlay[];\n}\n\n/**\n * v2 audio manifest — SFX + music only.\n * Dialog comes from timing.json (generated in Step 4).\n * No overlays section.\n */\nexport interface AudioManifestV2 {\n version: 2;\n /** Background music tracks */\n music: MusicTrack[];\n /** One-shot sound effects */\n sfx: SfxPlacement[];\n}\n\n/** Union of all manifest versions */\nexport type AudioManifestAny = AudioManifest | AudioManifestV2;\n\nexport interface DialogBeat {\n id: string;\n file: string;\n speaker: string;\n text: string;\n startSec: number;\n durationSec: number;\n volume?: number;\n style?: 'quote' | 'narrator' | 'text-card';\n}\n\nexport interface MusicTrack {\n id: string;\n file: string;\n startSec: number;\n durationSec: number;\n volume: number;\n fadeInSec?: number;\n fadeOutSec?: number;\n duckTo?: number;\n}\n\nexport interface SfxPlacement {\n id: string;\n file: string;\n startSec: number;\n volume?: number;\n note?: string;\n}\n\nexport interface TextOverlay {\n id: string;\n type: 'title-card' | 'speaker-label' | 'data-accent' | 'chapter';\n text: string;\n startSec: number;\n durationSec: number;\n style?: {\n fontSize?: number;\n color?: string;\n position?: 'center' | 'bottom-left' | 'bottom-right' | 'top';\n typingSpeed?: number | null;\n };\n}\n\n// ---------------------------------------------------------------------------\n// Validation\n// ---------------------------------------------------------------------------\n\nexport interface ValidationResult {\n valid: boolean;\n errors: string[];\n}\n\n/**\n * Validate an AudioManifest for structural correctness.\n *\n * Checks:\n * - Required top-level fields (version, fps, totalDurationSec)\n * - Dialog beats within totalDurationSec, no same-speaker overlap\n * - Music tracks within totalDurationSec, volume 0-1\n * - SFX placements within totalDurationSec\n * - Overlay timing within totalDurationSec\n * - File paths are relative strings (no absolute paths)\n * - Volume values in 0-1 range\n */\nexport function validateAudioManifest(manifest: unknown): ValidationResult {\n const errors: string[] = [];\n\n if (manifest == null || typeof manifest !== 'object') {\n return { valid: false, errors: ['Manifest must be a non-null object'] };\n }\n\n const m = manifest as Record<string, unknown>;\n\n // --- Required top-level fields ---\n const version = m.version;\n if (version !== 1 && version !== 2) {\n errors.push(`version must be 1 or 2, got ${JSON.stringify(version)}`);\n }\n\n // v1 requires fps and totalDurationSec; v2 does not\n if (version === 1) {\n if (typeof m.fps !== 'number' || m.fps <= 0) {\n errors.push(`fps must be a positive number, got ${JSON.stringify(m.fps)}`);\n }\n if (typeof m.totalDurationSec !== 'number' || m.totalDurationSec <= 0) {\n errors.push(\n `totalDurationSec must be a positive number, got ${JSON.stringify(m.totalDurationSec)}`,\n );\n }\n }\n\n const totalDur = typeof m.totalDurationSec === 'number' ? m.totalDurationSec : 0;\n\n // --- Arrays: v1 requires all four, v2 requires sfx + music only ---\n if (version === 1) {\n if (!Array.isArray(m.dialog)) {\n errors.push('dialog must be an array');\n }\n if (!Array.isArray(m.overlays)) {\n errors.push('overlays must be an array');\n }\n }\n if (!Array.isArray(m.music)) {\n errors.push('music must be an array');\n }\n if (!Array.isArray(m.sfx)) {\n errors.push('sfx must be an array');\n }\n\n // Bail early if arrays are missing — can't validate contents\n if (errors.length > 0) {\n return { valid: false, errors };\n }\n\n const dialog = (Array.isArray(m.dialog) ? m.dialog : []) as DialogBeat[];\n const music = m.music as MusicTrack[];\n const sfx = m.sfx as SfxPlacement[];\n const overlays = (Array.isArray(m.overlays) ? m.overlays : []) as TextOverlay[];\n\n // --- Shared helpers ---\n function checkFilePath(file: unknown, context: string): void {\n if (typeof file !== 'string' || file.length === 0) {\n errors.push(`${context}: file must be a non-empty string`);\n } else if (file.startsWith('/') || file.startsWith('\\\\')) {\n errors.push(`${context}: file must be a relative path, got \"${file}\"`);\n }\n }\n\n function checkVolume(vol: unknown, context: string, required: boolean): void {\n if (vol == null) {\n if (required) errors.push(`${context}: volume is required`);\n return;\n }\n if (typeof vol !== 'number' || vol < 0 || vol > 1) {\n errors.push(`${context}: volume must be 0-1, got ${JSON.stringify(vol)}`);\n }\n }\n\n function checkTimingWithin(startSec: unknown, durationSec: unknown, context: string): void {\n if (typeof startSec !== 'number' || startSec < 0) {\n errors.push(\n `${context}: startSec must be a non-negative number, got ${JSON.stringify(startSec)}`,\n );\n return;\n }\n if (typeof durationSec === 'number') {\n if (durationSec < 0) {\n errors.push(`${context}: durationSec must be non-negative, got ${durationSec}`);\n }\n // Only check bounds when totalDurationSec is known (v1 manifests)\n if (totalDur > 0 && startSec + durationSec > totalDur) {\n errors.push(\n `${context}: startSec (${startSec}) + durationSec (${durationSec}) = ${startSec + durationSec} exceeds totalDurationSec (${totalDur})`,\n );\n }\n }\n }\n\n // --- Dialog beats ---\n const ids = new Set<string>();\n for (let i = 0; i < dialog.length; i++) {\n const b = dialog[i];\n const ctx = `dialog[${i}] (${b.id ?? 'no id'})`;\n\n if (typeof b.id !== 'string' || b.id.length === 0) {\n errors.push(`${ctx}: id must be a non-empty string`);\n } else if (ids.has(b.id)) {\n errors.push(`${ctx}: duplicate id \"${b.id}\"`);\n } else {\n ids.add(b.id);\n }\n\n checkFilePath(b.file, ctx);\n\n if (typeof b.speaker !== 'string' || b.speaker.length === 0) {\n errors.push(`${ctx}: speaker must be a non-empty string`);\n }\n if (typeof b.text !== 'string') {\n errors.push(`${ctx}: text must be a string`);\n }\n if (typeof b.durationSec !== 'number' || b.durationSec <= 0) {\n errors.push(\n `${ctx}: durationSec must be a positive number, got ${JSON.stringify(b.durationSec)}`,\n );\n }\n\n checkTimingWithin(b.startSec, b.durationSec, ctx);\n checkVolume(b.volume, ctx, false);\n\n if (\n b.style !== undefined &&\n b.style !== 'quote' &&\n b.style !== 'narrator' &&\n b.style !== 'text-card'\n ) {\n errors.push(`${ctx}: style must be 'quote', 'narrator', or 'text-card', got \"${b.style}\"`);\n }\n }\n\n // --- Same-speaker overlap check ---\n const bySpeaker = new Map<string, DialogBeat[]>();\n for (const b of dialog) {\n if (typeof b.speaker !== 'string') continue;\n const list = bySpeaker.get(b.speaker) ?? [];\n list.push(b);\n bySpeaker.set(b.speaker, list);\n }\n for (const [speaker, beats] of bySpeaker) {\n const sorted = [...beats].sort((a, b) => a.startSec - b.startSec);\n for (let i = 1; i < sorted.length; i++) {\n const prev = sorted[i - 1];\n const curr = sorted[i];\n const prevEnd = prev.startSec + prev.durationSec;\n if (prevEnd > curr.startSec) {\n errors.push(\n `dialog overlap for speaker \"${speaker}\": \"${prev.id}\" ends at ${prevEnd}s but \"${curr.id}\" starts at ${curr.startSec}s`,\n );\n }\n }\n }\n\n // --- Music tracks ---\n for (let i = 0; i < music.length; i++) {\n const t = music[i];\n const ctx = `music[${i}] (${t.id ?? 'no id'})`;\n\n if (typeof t.id !== 'string' || t.id.length === 0) {\n errors.push(`${ctx}: id must be a non-empty string`);\n }\n checkFilePath(t.file, ctx);\n checkTimingWithin(t.startSec, t.durationSec, ctx);\n checkVolume(t.volume, ctx, true);\n\n if (t.fadeInSec != null && (typeof t.fadeInSec !== 'number' || t.fadeInSec < 0)) {\n errors.push(`${ctx}: fadeInSec must be a non-negative number`);\n }\n if (t.fadeOutSec != null && (typeof t.fadeOutSec !== 'number' || t.fadeOutSec < 0)) {\n errors.push(`${ctx}: fadeOutSec must be a non-negative number`);\n }\n if (t.duckTo != null) {\n if (typeof t.duckTo !== 'number' || t.duckTo < 0 || t.duckTo > 1) {\n errors.push(`${ctx}: duckTo must be 0-1, got ${JSON.stringify(t.duckTo)}`);\n }\n }\n }\n\n // --- SFX placements ---\n for (let i = 0; i < sfx.length; i++) {\n const s = sfx[i];\n const ctx = `sfx[${i}] (${s.id ?? 'no id'})`;\n\n if (typeof s.id !== 'string' || s.id.length === 0) {\n errors.push(`${ctx}: id must be a non-empty string`);\n }\n checkFilePath(s.file, ctx);\n if (typeof s.startSec !== 'number' || s.startSec < 0) {\n errors.push(\n `${ctx}: startSec must be a non-negative number, got ${JSON.stringify(s.startSec)}`,\n );\n }\n if (totalDur > 0 && s.startSec > totalDur) {\n errors.push(`${ctx}: startSec (${s.startSec}) exceeds totalDurationSec (${totalDur})`);\n }\n checkVolume(s.volume, ctx, false);\n }\n\n // --- Text overlays ---\n const validOverlayTypes = new Set(['title-card', 'speaker-label', 'data-accent', 'chapter']);\n const validPositions = new Set(['center', 'bottom-left', 'bottom-right', 'top']);\n for (let i = 0; i < overlays.length; i++) {\n const o = overlays[i];\n const ctx = `overlays[${i}] (${o.id ?? 'no id'})`;\n\n if (typeof o.id !== 'string' || o.id.length === 0) {\n errors.push(`${ctx}: id must be a non-empty string`);\n }\n if (!validOverlayTypes.has(o.type)) {\n errors.push(\n `${ctx}: type must be one of ${[...validOverlayTypes].join(', ')}, got \"${o.type}\"`,\n );\n }\n if (typeof o.text !== 'string' || o.text.length === 0) {\n errors.push(`${ctx}: text must be a non-empty string`);\n }\n if (typeof o.durationSec !== 'number' || o.durationSec <= 0) {\n errors.push(\n `${ctx}: durationSec must be a positive number, got ${JSON.stringify(o.durationSec)}`,\n );\n }\n checkTimingWithin(o.startSec, o.durationSec, ctx);\n\n if (o.style != null) {\n if (typeof o.style !== 'object') {\n errors.push(`${ctx}: style must be an object`);\n } else {\n if (\n o.style.fontSize != null &&\n (typeof o.style.fontSize !== 'number' || o.style.fontSize <= 0)\n ) {\n errors.push(`${ctx}: style.fontSize must be a positive number`);\n }\n if (o.style.color != null && typeof o.style.color !== 'string') {\n errors.push(`${ctx}: style.color must be a string`);\n }\n if (o.style.position != null && !validPositions.has(o.style.position)) {\n errors.push(\n `${ctx}: style.position must be one of ${[...validPositions].join(', ')}, got \"${o.style.position}\"`,\n );\n }\n if (\n o.style.typingSpeed !== undefined &&\n o.style.typingSpeed !== null &&\n (typeof o.style.typingSpeed !== 'number' || o.style.typingSpeed <= 0)\n ) {\n errors.push(`${ctx}: style.typingSpeed must be a positive number or null`);\n }\n }\n }\n }\n\n return { valid: errors.length === 0, errors };\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Compute total duration from manifest content.\n * Returns max(endTime) across all tracks + 2s padding.\n * Useful for agents building the manifest before totalDurationSec is known.\n */\nexport function computeTotalDuration(\n manifest: Pick<AudioManifest, 'dialog' | 'music' | 'sfx' | 'overlays'>,\n): number {\n let maxEnd = 0;\n\n for (const b of manifest.dialog) {\n maxEnd = Math.max(maxEnd, b.startSec + b.durationSec);\n }\n for (const t of manifest.music) {\n maxEnd = Math.max(maxEnd, t.startSec + t.durationSec);\n }\n for (const s of manifest.sfx) {\n // SFX don't have durationSec — use startSec only\n maxEnd = Math.max(maxEnd, s.startSec);\n }\n for (const o of manifest.overlays) {\n maxEnd = Math.max(maxEnd, o.startSec + o.durationSec);\n }\n\n return maxEnd + 2;\n}\n"]}
1
+ {"version":3,"sources":["../src/transform/transform-raw.ts","../src/transform/transform-curation.ts","../src/types/script.ts","../src/types/pacing.ts","../src/types/timing.ts","../src/audio/manifest.ts"],"names":["z"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Transform source data → RawData (Contract A).\n *\n * Pure function. Deterministic. No side effects.\n * Maps existing JSON files to the generic RawData contract.\n */\n\nimport type {\n RawAgent,\n RawArtifact,\n RawCommit,\n RawData,\n RawMessage,\n RawPR,\n} from '../types/raw-data.js';\nimport type {\n SourceArtifactData,\n SourceBeamEvent,\n SourceCommit,\n SourceMessage,\n SourceMessageEvent,\n SourcePR,\n SourcePRAgentMap,\n SourceRetroPageData,\n SourceTimelineEvents,\n TransformSources,\n} from './source-types.js';\n\n/**\n * Infer a RawAgent role from a freeform role string (e.g. from teamAssembly).\n *\n * Checks for known keywords in the string (case-insensitive).\n * Order matters — more specific matches first (e.g. \"eng-lead\" matches \"lead\").\n * Falls back to 'builder' as the safest default (most common role).\n */\nexport function inferRole(roleString: string): RawAgent['role'] {\n const s = roleString.toLowerCase();\n if (s.includes('human') || s === 'user') return 'human';\n if (s.includes('lead')) return 'lead';\n if (s.includes('pm')) return 'pm';\n if (s.includes('tester') || s.includes('qa')) return 'tester';\n if (s.includes('reviewer') || s.includes('review')) return 'reviewer';\n if (s.includes('auditor') || s.includes('audit')) return 'auditor';\n if (s.includes('challenger') || s.includes('challenge')) return 'challenger';\n if (s.includes('scout')) return 'scout';\n if (s.includes('ideation')) return 'ideation';\n if (s.includes('research')) return 'researcher';\n if (s.includes('builder') || s.includes('build')) return 'builder';\n return 'builder'; // safe default — most common role\n}\n\n/**\n * Transform all source data into RawData.\n * This is the main entry point for the extraction layer.\n */\nexport function transformToRawData(sources: TransformSources): RawData {\n // First agent from teamAssembly is the default for unattributed items\n const defaultAgent = sources.retroPageData.teamAssembly[0]?.agent.replace('@', '') ?? 'unknown';\n\n return {\n project: {\n name: sources.retroPageData.meta.title,\n description: sources.retroPageData.meta.subtitle,\n },\n agents: transformAgents(\n sources.retroPageData,\n sources.chatActivity.agentTotals,\n sources.timelineEvents,\n undefined,\n sources.messages,\n ),\n commits: transformCommits(sources.commits, sources.prAgentMap, defaultAgent),\n prs: transformPRs(sources.prs, sources.prAgentMap),\n messages: transformMessages(sources.timelineEvents, sources.messages),\n artifacts: sources.artifactData\n ? transformArtifacts(\n sources.artifactData,\n sources.retroPageData,\n sources.prs,\n sources.prAgentMap,\n )\n : [],\n };\n}\n\n/**\n * Build a map of agent → earliest message timestamp from timeline events.\n * Only counts messages where the agent is the sender (not just mentioned).\n */\nfunction buildFirstMessageTimeMap(timelineEvents?: SourceTimelineEvents): Map<string, number> {\n const map = new Map<string, number>();\n if (!timelineEvents) return map;\n\n for (const evt of timelineEvents.events) {\n if (evt.type !== 'message' && evt.type !== 'beam') continue;\n const sender = (evt as SourceMessageEvent | SourceBeamEvent).from;\n const ts = new Date(evt.t).getTime();\n const existing = map.get(sender);\n if (existing === undefined || ts < existing) {\n map.set(sender, ts);\n }\n }\n\n return map;\n}\n\n/**\n * Build RawAgent[] from team assembly data + chat activity.\n *\n * joinedAt resolution priority:\n * 1. First message timestamp from timeline events (most accurate)\n * 2. teamAssembly join time (curated/scaffold fallback)\n * 3. Project start date (last resort)\n *\n * Role resolution priority:\n * 1. Explicit `agentRoles` override (if provided)\n * 2. Inferred from teamAssembly `role` field (e.g. \"eng-lead\" → \"lead\")\n * 3. Default: 'builder' (most common role, safe fallback)\n *\n * Never throws on unknown agents — always infers or defaults.\n */\nexport function transformAgents(\n retroData: SourceRetroPageData,\n agentTotals: Record<string, number>,\n timelineEvents?: SourceTimelineEvents,\n agentRoles?: Record<string, string>,\n messages?: SourceMessage[],\n): RawAgent[] {\n const agents: RawAgent[] = [];\n const seen = new Set<string>();\n\n // Build first-message-time lookup from timeline events\n const firstMessageTime = buildFirstMessageTimeMap(timelineEvents);\n\n // Build a lookup from teamAssembly role fields for agents not in override\n const assemblyRoles = new Map<string, string>();\n for (const entry of retroData.teamAssembly) {\n const id = entry.agent.replace('@', '');\n assemblyRoles.set(id, entry.role);\n }\n\n /** Resolve role for an agent: override → teamAssembly inference → default */\n function resolveRole(id: string): RawAgent['role'] {\n // 1. Explicit override\n if (agentRoles?.[id]) {\n return inferRole(agentRoles[id]);\n }\n // 2. Infer from teamAssembly role field\n const assemblyRole = assemblyRoles.get(id);\n if (assemblyRole) {\n return inferRole(assemblyRole);\n }\n // 3. Default\n return 'builder';\n }\n\n /** Resolve joinedAt: earliest of (first message, teamAssembly time), or startDate */\n function resolveJoinedAt(id: string, assemblyTime?: number): number {\n const msgTime = firstMessageTime.get(id);\n // Use earliest available timestamp — agent was present from whichever came first\n if (msgTime !== undefined && assemblyTime !== undefined) {\n return Math.min(msgTime, assemblyTime);\n }\n if (msgTime !== undefined) return msgTime;\n if (assemblyTime !== undefined) return assemblyTime;\n // Last resort: project start date\n return new Date(retroData.meta.startDate).getTime();\n }\n\n // Primary source: team assembly (has join times)\n for (const entry of retroData.teamAssembly) {\n const id = entry.agent.replace('@', '');\n if (seen.has(id)) continue;\n seen.add(id);\n\n agents.push({\n id,\n role: resolveRole(id),\n joinedAt: resolveJoinedAt(id, new Date(entry.time).getTime()),\n });\n }\n\n // Catch any agents in chat activity not in team assembly\n for (const id of Object.keys(agentTotals)) {\n if (seen.has(id)) continue;\n agents.push({\n id,\n role: resolveRole(id),\n joinedAt: resolveJoinedAt(id),\n });\n seen.add(id);\n }\n\n // Detect human users from message senderType.\n // Two phases: (1) add unseen human senders, (2) upgrade already-seen\n // agents to role: 'human'. Phase 2 is needed because users like @snorre\n // appear in agentTotals (they send messages) and get role: 'builder'\n // before the senderType check — see PR #640 review by @check.\n if (messages) {\n const humanSenders = new Set<string>();\n for (const msg of messages) {\n if (msg.senderType === 'user') humanSenders.add(msg.sender);\n }\n\n // Phase 1: add unseen human senders\n for (const id of humanSenders) {\n if (!seen.has(id)) {\n seen.add(id);\n agents.push({\n id,\n role: 'human',\n joinedAt: resolveJoinedAt(id),\n });\n }\n }\n\n // Phase 2: upgrade already-seen agents to human\n for (const agent of agents) {\n if (humanSenders.has(agent.id)) {\n agent.role = 'human';\n }\n }\n }\n\n return agents;\n}\n\n/**\n * Transform git commits → RawCommit[].\n * Cross-references pr-agent-map for attribution.\n *\n * @param defaultAgent - Fallback agent for commits with no PR reference\n * (typically the first agent from teamAssembly/roster)\n */\nexport function transformCommits(\n commits: SourceCommit[],\n prAgentMap: SourcePRAgentMap,\n defaultAgent = 'unknown',\n): RawCommit[] {\n return commits.map((c) => {\n const agent = resolveCommitAgent(c, prAgentMap, defaultAgent);\n\n return {\n sha: c.hash,\n timestamp: new Date(c.date).getTime(),\n agent,\n message: c.subject,\n filesChanged: c.files.length,\n insertions: c.totalInsertions,\n deletions: c.totalDeletions,\n prNumber: c.prNumber ?? undefined,\n };\n });\n}\n\n/**\n * Resolve which agent authored a commit.\n * Strategy chain:\n * 1. prNumber field → pr-agent-map lookup\n * 2. \"Merge pull request #N\" in subject → pr-agent-map lookup\n * 3. \"(#N)\" suffix in subject → pr-agent-map lookup\n * 4. Fallback to defaultAgent (first agent from roster/teamAssembly)\n */\nexport function resolveCommitAgent(\n commit: SourceCommit,\n prAgentMap: SourcePRAgentMap,\n defaultAgent = 'unknown',\n): string {\n // Strategy 1: direct prNumber field\n if (commit.prNumber != null) {\n const agent = prAgentMap[String(commit.prNumber)];\n if (agent) return agent;\n }\n\n // Strategy 2: \"Merge pull request #N\" pattern\n const mergeMatch = commit.subject.match(/^Merge pull request #(\\d+)/);\n if (mergeMatch) {\n const agent = prAgentMap[mergeMatch[1]];\n if (agent) return agent;\n }\n\n // Strategy 3: \"(#N)\" suffix pattern\n const suffixMatch = commit.subject.match(/\\(#(\\d+)\\)\\s*$/);\n if (suffixMatch) {\n const agent = prAgentMap[suffixMatch[1]];\n if (agent) return agent;\n }\n\n // Fallback: first agent from roster (caller provides)\n return defaultAgent;\n}\n\n/**\n * Transform PR details → RawPR[].\n * Cross-references pr-agent-map for attribution.\n */\nexport function transformPRs(prs: SourcePR[], prAgentMap: SourcePRAgentMap): RawPR[] {\n return prs.map((pr) => {\n const agent = prAgentMap[String(pr.number)] ?? 'unknown';\n\n return {\n number: pr.number,\n title: pr.title,\n agent,\n createdAt: new Date(pr.createdAt).getTime(),\n mergedAt: pr.mergedAt ? new Date(pr.mergedAt).getTime() : null,\n additions: pr.additions,\n deletions: pr.deletions,\n branch: pr.headRefName,\n };\n });\n}\n\n/**\n * Infer artifact type from slug or file path.\n *\n * Handles both platforms:\n * - Redux: file paths with extensions (\"/specs/auth.md\", \"plan/task-X1Y2\")\n * - Cast: artifact slugs (\"spec-auth\", \"screenshot-login\", \"qa-review\")\n *\n * Redux patterns are checked first (more specific), cast patterns as fallback.\n */\nexport function inferArtifactType(slug: string): RawArtifact['type'] {\n // --- Redux: plan item prefixes ---\n if (slug.startsWith('plan/task-')) return 'task';\n if (slug.startsWith('plan/spec-')) return 'doc';\n\n // --- Extension-based (works for both platforms, but primarily redux file paths) ---\n const ext = slug.split('.').pop()?.toLowerCase();\n if (ext && ['ts', 'tsx', 'js', 'jsx', 'py', 'rs', 'go', 'sh'].includes(ext)) return 'code';\n if (ext && ['png', 'jpg', 'jpeg', 'svg', 'gif', 'webp', 'ico'].includes(ext)) return 'asset';\n if (ext && ['md', 'txt', 'json', 'yaml', 'yml', 'toml'].includes(ext)) return 'doc';\n\n // --- Redux: path-based patterns ---\n if (slug.includes('/specs/') || slug.includes('/spec/')) return 'doc';\n if (slug.includes('/assets/') || slug.includes('/images/')) return 'asset';\n\n // --- Cast: existing slug patterns (backward compat) ---\n if (slug.includes('.app.')) return 'code';\n if (slug.includes('screenshot') || slug.includes('qa-')) return 'asset';\n if (slug.includes('decision')) return 'decision';\n if (slug.includes('task') || slug.includes('phase-')) return 'task';\n if (slug.startsWith('spec-') || slug.startsWith('spec')) return 'doc';\n if (slug.includes('concept')) return 'doc';\n\n return 'doc';\n}\n\n/**\n * Resolve artifact agent from source data.\n *\n * Priority:\n * 1. Explicit `createdBy` from the artifact record (Miriad API provides this)\n * 2. PR number in slug → pr-agent-map lookup\n * 3. Configurable default (first agent from roster, typically the lead)\n */\nexport function resolveArtifactAgent(\n slug: string,\n prAgentMap: SourcePRAgentMap,\n createdBy: string | undefined,\n defaultAgent: string,\n): string {\n // 1. Explicit creator from source data\n if (createdBy) return createdBy;\n\n // 2. PR reference in slug → agent map\n const prMatch = slug.match(/#?(\\d+)/);\n if (prMatch) {\n const agent = prAgentMap[prMatch[1]];\n if (agent) return agent;\n }\n\n // 3. Default (first agent from roster)\n return defaultAgent;\n}\n\n/** Category name → artifact type */\nconst CATEGORY_TYPE_MAP: Record<string, RawArtifact['type']> = {\n qaScreenshots: 'asset',\n transitionSpecs: 'doc',\n transitionConcepts: 'doc',\n scenes: 'doc',\n vizConcepts: 'code',\n teamPrinciples: 'doc',\n retroData: 'doc',\n decisions: 'decision',\n};\n\n/**\n * Distribute N artifacts within time boundaries, clustered around\n * PR timestamps when available for realistic density.\n */\nexport function distributeTimestamps(\n count: number,\n bounds: { start: number; end: number },\n prTimestamps: number[],\n): number[] {\n const phasePRTimes = prTimestamps.filter((t) => t >= bounds.start && t <= bounds.end);\n const timestamps: number[] = [];\n\n for (let i = 0; i < count; i++) {\n let timestamp: number;\n if (phasePRTimes.length > 0) {\n const prIdx = i % phasePRTimes.length;\n timestamp = phasePRTimes[prIdx] + i * 60000;\n } else {\n const fraction = count > 1 ? i / (count - 1) : 0.5;\n timestamp = bounds.start + fraction * (bounds.end - bounds.start);\n }\n timestamps.push(Math.round(Math.max(bounds.start, Math.min(bounds.end, timestamp))));\n }\n\n return timestamps;\n}\n\n/**\n * Build a type distribution from category data.\n *\n * Each category maps to a type. We build a weighted list so bulk\n * artifacts can be assigned types proportional to category counts.\n * Returns entries sorted by count descending for deterministic assignment.\n *\n * Agent assignment is NOT done here — it's handled by the caller using\n * round-robin over the known agent list (from teamAssembly).\n */\nexport function buildCategoryDistribution(\n categories: SourceArtifactData['categories'],\n): Array<{ type: RawArtifact['type']; weight: number }> {\n const entries: Array<{ type: RawArtifact['type']; count: number }> = [];\n let total = 0;\n\n for (const [categoryName, categoryData] of Object.entries(categories)) {\n if (categoryData.count === 0) continue;\n entries.push({\n type: CATEGORY_TYPE_MAP[categoryName] ?? 'doc',\n count: categoryData.count,\n });\n total += categoryData.count;\n }\n\n if (total === 0) return [{ type: 'doc', weight: 1 }];\n\n return entries\n .sort((a, b) => b.count - a.count)\n .map((e) => ({ type: e.type, weight: e.count / total }));\n}\n\n/**\n * Build a slug → createdBy lookup from SourceArtifactData category items.\n * Items can be plain strings (no creator info) or objects with optional createdBy.\n */\nfunction buildCreatedByLookup(categories: SourceArtifactData['categories']): Map<string, string> {\n const lookup = new Map<string, string>();\n for (const categoryData of Object.values(categories)) {\n for (const item of categoryData.items ?? []) {\n if (typeof item === 'object' && item.createdBy) {\n lookup.set(item.slug, item.createdBy);\n }\n }\n }\n return lookup;\n}\n\n/**\n * Transform artifact-data.json → RawArtifact[].\n *\n * Uses phase `count` fields for correct per-phase density. Each phase\n * specifies how many artifacts were created during that time window:\n * Phase 1: 5, Phase 2: 45, Phase 3: 80, Phase 4: 120, Phase 5: 60 = 310\n *\n * Within each phase:\n * 1. Curated slugs get their own entries with createdBy from source data\n * 2. Remaining count filled with generated artifacts using category\n * type proportions and round-robin agent assignment\n * 3. All timestamps distributed within phase boundaries, clustered\n * around PR activity\n */\nexport function transformArtifacts(\n artifactData: SourceArtifactData,\n retroData: SourceRetroPageData,\n prs: SourcePR[],\n prAgentMap: SourcePRAgentMap,\n): RawArtifact[] {\n const artifacts: RawArtifact[] = [];\n\n // Build agent list from teamAssembly for round-robin and default\n const agentIds = retroData.teamAssembly.map((e) => e.agent.replace('@', ''));\n const defaultAgent = agentIds[0] ?? 'unknown';\n\n const phaseBoundaries = retroData.phases.map((p) => ({\n start: new Date(p.start).getTime(),\n end: new Date(p.end).getTime(),\n }));\n\n const prTimestamps = prs.map((pr) => new Date(pr.createdAt).getTime()).sort((a, b) => a - b);\n const distribution = buildCategoryDistribution(artifactData.categories);\n const createdByLookup = buildCreatedByLookup(artifactData.categories);\n\n let phaseIndex = 0;\n let globalBulkIndex = 0;\n\n for (const [_phaseName, phaseData] of Object.entries(artifactData.phases)) {\n if (phaseIndex >= phaseBoundaries.length) break;\n const bounds = phaseBoundaries[phaseIndex];\n phaseIndex++;\n\n const totalCount = phaseData.count;\n const slugs = phaseData.artifacts;\n const bulkCount = Math.max(0, totalCount - slugs.length);\n\n // All artifacts in this phase share one timestamp distribution\n const timestamps = distributeTimestamps(totalCount, bounds, prTimestamps);\n\n // ── Curated slugs first ──────────────────────────────────────────────\n let tsIdx = 0;\n for (const slug of slugs) {\n artifacts.push({\n slug,\n type: inferArtifactType(slug),\n createdAt: timestamps[tsIdx],\n updatedAt: timestamps[tsIdx],\n agent: resolveArtifactAgent(slug, prAgentMap, createdByLookup.get(slug), defaultAgent),\n });\n tsIdx++;\n }\n\n // ── Bulk artifacts fill remaining count ───────────────────────────────\n // Assign type by walking through the weighted distribution.\n // Assign agent by round-robin over the known agent list.\n let distIdx = 0;\n let distBudget = Math.round(distribution[0].weight * bulkCount);\n\n for (let i = 0; i < bulkCount; i++) {\n // Advance to next distribution bucket when current is exhausted\n while (distBudget <= 0 && distIdx < distribution.length - 1) {\n distIdx++;\n distBudget = Math.round(distribution[distIdx].weight * bulkCount);\n }\n distBudget--;\n\n const entry = distribution[distIdx];\n // Round-robin agent assignment across the roster\n const agent =\n agentIds.length > 0 ? agentIds[globalBulkIndex % agentIds.length] : defaultAgent;\n artifacts.push({\n slug: `phase${phaseIndex}-${entry.type}-${String(globalBulkIndex + 1).padStart(3, '0')}`,\n type: entry.type,\n createdAt: timestamps[tsIdx],\n updatedAt: timestamps[tsIdx],\n agent,\n });\n tsIdx++;\n globalBulkIndex++;\n }\n }\n\n artifacts.sort((a, b) => a.createdAt - b.createdAt);\n\n return artifacts;\n}\n\n/**\n * Transform curated timeline events into chat pills for the viewer.\n *\n * Chat pills come ONLY from timeline-events.json (curated).\n * Raw messages (messages-viz.json) are NEVER a source for chat pills —\n * they exist only for the agent to read during curation and for the\n * density table's \"Msgs\" column.\n *\n * Single source of truth: the curated file.\n */\nexport function transformMessages(\n timelineEvents: SourceTimelineEvents,\n rawMessages?: SourceMessage[],\n): RawMessage[] {\n // Curated events (timeline-events.json) → chat pills (labeled bubbles)\n const curatedMessages = timelineEvents.events\n .filter(\n (e): e is SourceMessageEvent | SourceBeamEvent => e.type === 'message' || e.type === 'beam',\n )\n .map((evt, i) => ({\n id: `curated-${String(i).padStart(4, '0')}`,\n timestamp: new Date(evt.t).getTime(),\n sender: evt.from,\n mentions: [evt.to],\n }));\n\n // Raw messages (messages-viz.json / messages-full.json) → beam channels + particles\n const rawMsgs: RawMessage[] = (rawMessages ?? []).map((msg, i) => ({\n id: msg.id || `raw-${String(i).padStart(4, '0')}`,\n timestamp: new Date(msg.timestamp).getTime(),\n sender: msg.sender,\n mentions: msg.mentions,\n }));\n\n // Merge: raw messages provide beam/particle density, curated provide labeled pills.\n // Deduplicate by timestamp+sender to avoid double-counting when a raw message\n // was also curated as a chat pill.\n const seen = new Set(rawMsgs.map((m) => `${m.timestamp}:${m.sender}`));\n const uniqueCurated = curatedMessages.filter((m) => !seen.has(`${m.timestamp}:${m.sender}`));\n\n return [...rawMsgs, ...uniqueCurated];\n}\n","/**\n * Transform source data → CurationData (editorial content).\n *\n * Pure function. Deterministic. No side effects.\n * Maps curated board artifacts to the CurationData contract.\n */\n\nimport type {\n CurationData,\n CurationMilestone,\n CurationNarrationEntry,\n CurationPhase,\n CurationQuote,\n CurationTrustKeyframe,\n} from '../types/raw-data.js';\nimport type {\n SourceRetroPageData,\n SourceRetroPageQuotes,\n TransformSources,\n} from './source-types.js';\n\n/**\n * Transform curated source data into CurationData.\n * This is the main entry point for the curation layer.\n */\nexport function transformToCurationData(sources: TransformSources): CurationData {\n const narration = transformNarration(sources.retroPageData);\n const meta = sources.retroPageData.meta;\n\n // Thread curated timeline bounds from meta.startDate/endDate\n const curatedStartMs = meta?.startDate ? new Date(meta.startDate).getTime() : undefined;\n const curatedEndMs = meta?.endDate ? new Date(meta.endDate).getTime() : undefined;\n\n return {\n phases: transformPhases(sources.retroPageData),\n quotes: transformQuotes(sources.retroPageData, sources.retroPageQuotes),\n milestones: transformMilestones(sources.retroPageData),\n trustKeyframes: transformTrustKeyframes(sources.retroPageData),\n ...(narration.length > 0 ? { editorialNarration: narration } : {}),\n ...(curatedStartMs && !Number.isNaN(curatedStartMs) ? { curatedStartMs } : {}),\n ...(curatedEndMs && !Number.isNaN(curatedEndMs) ? { curatedEndMs } : {}),\n };\n}\n\n/**\n * Transform phase definitions from retro-page-data.\n * Phases have hand-curated boundaries, names, and descriptions.\n */\nexport function transformPhases(retroData: SourceRetroPageData): CurationPhase[] {\n return retroData.phases.map((p) => ({\n id: p.id,\n name: p.name || p.label || '',\n startTime: new Date(p.start || p.startTime || '').getTime(),\n endTime: new Date(p.end || p.endTime || '').getTime(),\n }));\n}\n\n/**\n * Transform milestones from retro-page-data.\n * Each milestone is cross-referenced to its containing phase.\n */\nexport function transformMilestones(retroData: SourceRetroPageData): CurationMilestone[] {\n const phases = retroData.phases;\n\n return retroData.milestones.map((m) => {\n const milestoneTime = new Date(m.time).getTime();\n const phase = findPhaseForTimestamp(milestoneTime, phases);\n\n return {\n label: m.label,\n timestamp: milestoneTime,\n phase: phase?.id ?? 'unknown',\n };\n });\n}\n\n/**\n * Map mood category to mood string for quotes from retroPageData.\n */\nconst CATEGORY_MOOD: Record<string, string> = {\n theGood: 'good',\n theBad: 'bad',\n theUgly: 'angry',\n theFunny: 'good',\n};\n\n/**\n * Map mood category to mood string for quotes from retroPageQuotes.\n */\nconst ADDITION_MOOD: Record<string, string> = {\n good: 'good',\n bad: 'bad',\n ugly: 'angry',\n};\n\n/**\n * Transform quotes from both curated sources.\n * Merges retro-page-data quotes (theGood/theBad/theUgly/theFunny) with\n * retro-page-quotes additions (good/bad/ugly). Parses informal timestamps,\n * strips @ prefix from speakers, and cross-references to phases.\n * Sorted by timestamp.\n */\nexport function transformQuotes(\n retroData: SourceRetroPageData,\n retroQuotes: SourceRetroPageQuotes,\n): CurationQuote[] {\n const phases = retroData.phases;\n const quotes: CurationQuote[] = [];\n\n // Derive reference year from first phase start date (for informal timestamp parsing)\n const firstPhaseStart = phases[0]?.start;\n const referenceYear = firstPhaseStart\n ? new Date(firstPhaseStart).getUTCFullYear()\n : new Date().getUTCFullYear();\n\n // Source 1: retroPageData.quotes (theGood, theBad, theUgly, theFunny)\n for (const [category, entries] of Object.entries(retroData.quotes)) {\n if (!Array.isArray(entries)) continue; // skip _comment and other non-quote fields\n const mood = CATEGORY_MOOD[category] ?? 'good';\n for (const entry of entries) {\n const timestamp = parseInformalTimestamp(entry.time, referenceYear);\n if (timestamp == null) continue;\n const phase = findPhaseForTimestamp(timestamp, phases);\n quotes.push({\n text: entry.text,\n speaker: entry.author.replace(/^@/, ''),\n timestamp,\n phase: phase?.id ?? 'unknown',\n mood,\n });\n }\n }\n\n // Source 2: retroPageQuotes (good, bad, ugly)\n for (const [category, entries] of Object.entries(retroQuotes)) {\n if (!Array.isArray(entries)) continue; // skip _comment and other non-quote fields\n const mood = ADDITION_MOOD[category] ?? 'good';\n for (const entry of entries) {\n const timestamp = parseInformalTimestamp(entry.timestamp, referenceYear);\n if (timestamp == null) continue;\n const phase = findPhaseForTimestamp(timestamp, phases);\n quotes.push({\n text: entry.text,\n speaker: entry.author.replace(/^@/, ''),\n timestamp,\n phase: phase?.id ?? 'unknown',\n mood,\n });\n }\n }\n\n // Sort chronologically\n quotes.sort((a, b) => a.timestamp - b.timestamp);\n return quotes;\n}\n\n/**\n * Transform trust arc keyframes from retro-page-data.\n * Source levels are 0-100 integers; we normalize to 0-1.\n * Sorted by timestamp for interpolation.\n */\nexport function transformTrustKeyframes(retroData: SourceRetroPageData): CurationTrustKeyframe[] {\n if (!retroData.trustArc || retroData.trustArc.length === 0) return [];\n\n return retroData.trustArc\n .map((entry) => ({\n timestamp: new Date(entry.time).getTime(),\n level: entry.level / 100, // normalize 0-100 → 0-1\n label: entry.label,\n }))\n .sort((a, b) => a.timestamp - b.timestamp);\n}\n\n/** Month abbreviation → 0-based index */\nconst MONTH_ABBREVS: Record<string, number> = {\n jan: 0,\n feb: 1,\n mar: 2,\n apr: 3,\n may: 4,\n jun: 5,\n jul: 6,\n aug: 7,\n sep: 8,\n oct: 9,\n nov: 10,\n dec: 11,\n};\n\n/**\n * Transform editorial narration entries from retro-page-data.\n * Each entry has an ISO timestamp, phase title, color, text, and type.\n * Returns empty array if no narration is present in the source data.\n */\nexport function transformNarration(retroData: SourceRetroPageData): CurationNarrationEntry[] {\n if (!retroData.editorialNarration || retroData.editorialNarration.length === 0) return [];\n\n return retroData.editorialNarration\n .map((entry) => ({\n timestamp: new Date(entry.time).getTime(),\n phaseTitle: entry.phaseTitle,\n phaseColor: entry.phaseColor,\n text: entry.text,\n type: entry.type,\n }))\n .sort((a, b) => a.timestamp - b.timestamp);\n}\n\n/**\n * Parse informal timestamp strings like \"Feb 10 21:18\", \"Dec 31 (early)\", \"Jan 2 ~23:00\".\n * Accepts any 3-letter month abbreviation.\n *\n * @param timeStr - Informal timestamp (e.g., \"Feb 10 21:18\", \"Dec 31\")\n * @param referenceYear - Year to use (e.g., 2025). Required — no hardcoded default.\n * For projects spanning Dec→Jan, callers should handle year rollover.\n * @returns Unix ms or null if unparseable.\n */\nexport function parseInformalTimestamp(\n timeStr: string | undefined | null,\n referenceYear: number,\n): number | null {\n if (!timeStr) return null;\n\n // Try ISO 8601 first (scaffold generates ISO timestamps)\n const isoDate = new Date(timeStr);\n if (!Number.isNaN(isoDate.getTime()) && timeStr.includes('-')) {\n return isoDate.getTime();\n }\n\n // Strip tildes and parenthetical notes\n const cleaned = timeStr\n .replace(/~/g, '')\n .replace(/\\(.*?\\)/g, '')\n .trim();\n\n // Match \"Mon DD HH:MM\" or \"Mon DD\" (3-letter month abbreviation)\n const match = cleaned.match(/([A-Za-z]{3})\\s+(\\d{1,2})(?:\\s+(\\d{1,2}):(\\d{2}))?/);\n if (!match) return null;\n\n const monthIdx = MONTH_ABBREVS[match[1].toLowerCase()];\n if (monthIdx === undefined) return null;\n\n const day = Number.parseInt(match[2], 10);\n const hour = match[3] ? Number.parseInt(match[3], 10) : 12; // default to noon if no time\n const minute = match[4] ? Number.parseInt(match[4], 10) : 0;\n\n const date = new Date(Date.UTC(referenceYear, monthIdx, day, hour, minute, 0));\n return date.getTime();\n}\n\n/**\n * Find which phase a timestamp falls within.\n * First tries exact range match. If no phase contains the timestamp\n * (e.g., it falls in a gap between phases), falls back to the nearest\n * phase by distance to its start/end boundaries.\n *\n * Returns undefined only when phases array is empty.\n */\nexport function findPhaseForTimestamp(\n timestamp: number,\n phases: SourceRetroPageData['phases'],\n): SourceRetroPageData['phases'][number] | undefined {\n if (phases.length === 0) return undefined;\n\n // Try exact range match first\n const exact = phases.find((p) => {\n const start = new Date(p.start || p.startTime || '').getTime();\n const end = new Date(p.end || p.endTime || '').getTime();\n return timestamp >= start && timestamp <= end;\n });\n if (exact) return exact;\n\n // Fallback: find nearest phase by distance to boundaries\n let nearest: SourceRetroPageData['phases'][number] | undefined;\n let minDistance = Number.POSITIVE_INFINITY;\n\n for (const p of phases) {\n const start = new Date(p.start || p.startTime || '').getTime();\n const end = new Date(p.end || p.endTime || '').getTime();\n const distance = Math.min(Math.abs(timestamp - start), Math.abs(timestamp - end));\n if (distance < minDistance) {\n minDistance = distance;\n nearest = p;\n }\n }\n\n return nearest;\n}\n","/**\n * ScriptFile — the authoring contract for Step 2 (Script Writing).\n *\n * WHY: The script is the creative foundation. An agent writes this file\n * to define the narrative structure: who speaks, what they say, and in\n * what style. Every downstream file (pacing, timing) derives from this.\n *\n * The agent creates this from scratch in Step 2, guided by extracted data\n * (event density, agent activity, phases). The human reviews and approves.\n */\n\nimport { z } from 'zod';\n\n// --- Zod schemas (source of truth) ---\n\nexport const ScriptLineSchema = z.object({\n /** Unique identifier for this line (e.g., 'narrator-01', 'lead-03') */\n id: z.string().min(1),\n /** Who speaks this line (e.g., 'narrator', 'lead', 'snorre') */\n speaker: z.string().min(1),\n /** The spoken text */\n text: z.string().min(1),\n /** Rendering style: narrator voice (cursive) or agent quote (normal) */\n style: z.enum(['narrator', 'quote']),\n /** Optional phase this line belongs to (for grouping in the viz) */\n phaseId: z.string().optional(),\n});\n\nexport const ScriptFileSchema = z\n .object({\n /** Schema version — always 1 for now */\n version: z.literal(1),\n /** Ordered list of script lines */\n lines: z.array(ScriptLineSchema).min(1),\n })\n .superRefine((data, ctx) => {\n // Enforce unique line IDs\n const ids = new Set<string>();\n for (let i = 0; i < data.lines.length; i++) {\n const id = data.lines[i].id;\n if (ids.has(id)) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: `Duplicate line ID: \"${id}\" (line index ${i})`,\n path: ['lines', i, 'id'],\n });\n }\n ids.add(id);\n }\n });\n\n// --- TypeScript types (inferred from schemas) ---\n\nexport type ScriptLine = z.infer<typeof ScriptLineSchema>;\nexport type ScriptFile = z.infer<typeof ScriptFileSchema>;\n\n// --- Normalization ---\n\n/**\n * Auto-populate missing fields so a minimal script.json passes ScriptFileSchema.\n *\n * - If `version` is missing, defaults to `1`.\n * - If `style` is missing on a line, infers from speaker:\n * `speaker === 'narrator'` → `'narrator'`, otherwise → `'quote'`.\n *\n * Returns a new object (does not mutate the input).\n */\nexport function normalizeScript(raw: Record<string, unknown>): Record<string, unknown> {\n const out: Record<string, unknown> = { ...raw };\n\n if (out.version === undefined) {\n out.version = 1;\n }\n\n if (Array.isArray(out.lines)) {\n out.lines = (out.lines as Record<string, unknown>[]).map((line) => {\n if (line === null || typeof line !== 'object') return line;\n const l = { ...line };\n if (!l.style && typeof l.speaker === 'string') {\n l.style = l.speaker === 'narrator' ? 'narrator' : 'quote';\n }\n return l;\n });\n }\n\n return out;\n}\n","/**\n * PacingFile — the agent-facing timing contract for Step 4 (Viz Timing).\n *\n * WHY: The pacing file is what the agent edits to control how fast the viz\n * moves during each narration line. scaffold-pacing generates it from\n * script.json + audio clip durations. The agent then annotates 4 optional\n * fields per line: pauseAfter, vizSpeed, gapVizSpeed, note.\n *\n * Design: Approach A (Annotated Script) — mirrors the script with timing\n * annotations. Text + clip durations inline. Defaults handle 80% of lines.\n * No cascading edits (unlike start-time approaches).\n *\n * vizSpeed definition: multiplier on project-time-per-second.\n * 2.0 = viz moves 2x faster = LESS screen time for that period.\n * 0.5 = viz moves 2x slower = MORE screen time for that period.\n */\n\nimport { z } from 'zod';\n\n// --- Zod schemas (source of truth) ---\n\nexport const PacingLineSchema = z.object({\n /** Line ID — must match script.json line ID */\n id: z.string().min(1),\n /** Text from script (read-only, for context while editing pacing) */\n text: z.string().min(1),\n /** Audio clip duration in seconds (measured from file, read-only) */\n clipDuration: z.number().positive(),\n /** Silence after this line in seconds (overrides defaultPauseSec) */\n pauseAfter: z.number().nonnegative().optional(),\n /** Viz speed multiplier DURING this clip's audio. >1 = faster, <1 = slower */\n vizSpeed: z.number().positive().optional(),\n /** Viz speed multiplier DURING the pause after this clip (defaults to defaultVizSpeed) */\n gapVizSpeed: z.number().positive().optional(),\n /** Agent's reasoning for pacing choices (human reads during review) */\n note: z.string().optional(),\n});\n\nexport const PacingFileSchema = z\n .object({\n /** Schema version — always 1 for now */\n version: z.literal(1),\n /** Seconds of viz playback before first narration line */\n leadInSec: z.number().nonnegative().optional(),\n /** Seconds of viz playback after last narration line */\n tailOutSec: z.number().nonnegative().optional(),\n /** Default pause between lines in seconds (used when pauseAfter not set) */\n defaultPauseSec: z.number().nonnegative(),\n /** Default viz speed multiplier (used when vizSpeed/gapVizSpeed not set) */\n defaultVizSpeed: z.number().positive(),\n /** Ordered list of pacing lines — must match script.json order */\n lines: z.array(PacingLineSchema).min(1),\n })\n .superRefine((data, ctx) => {\n // Enforce unique line IDs\n const ids = new Set<string>();\n for (let i = 0; i < data.lines.length; i++) {\n const id = data.lines[i].id;\n if (ids.has(id)) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: `Duplicate line ID: \"${id}\" (line index ${i})`,\n path: ['lines', i, 'id'],\n });\n }\n ids.add(id);\n }\n });\n\n// --- TypeScript types (inferred from schemas) ---\n\nexport type PacingLine = z.infer<typeof PacingLineSchema>;\nexport type PacingFile = z.infer<typeof PacingFileSchema>;\n","/**\n * TimingFile — the engine-facing contract produced by generateTiming().\n *\n * WHY: This is the fully-resolved timing data that the transform layer reads\n * to produce narration entries with precise progress mapping. All fields are\n * required — no defaults, no optionals (except phase). generateTiming()\n * resolves all defaults from PacingFile and computes progress values.\n *\n * The transform layer validates this on read (belt-and-suspenders with\n * generateTiming's validation on write). If this file is corrupt, the\n * pipeline fails fast with a clear error.\n */\n\nimport { z } from 'zod';\n\n// --- Zod schemas (source of truth) ---\n\nexport const TimedLineSchema = z\n .object({\n /** Line ID — matches script.json and pacing.json */\n id: z.string().min(1),\n /** Speaker identifier (e.g., 'narrator', 'lead', 'snorre') */\n speaker: z.string().min(1),\n /** The spoken text */\n text: z.string().min(1),\n /** Rendering style: narrator voice (cursive) or agent quote (normal) */\n style: z.enum(['narrator', 'quote']),\n /** Wall-clock start time in seconds from video start */\n startSec: z.number().nonnegative(),\n /** Audio clip duration in seconds */\n durationSec: z.number().positive(),\n /** Pause after this line in seconds (resolved from defaults) */\n pauseAfterSec: z.number().nonnegative(),\n /** Audio file path relative to audio directory (e.g., 'narrator-01.mp3') */\n audioFile: z.string().min(1),\n /** Viz progress at clip start [0, 1] */\n progressStart: z.number().min(0).max(1),\n /** Viz progress at clip end [0, 1] */\n progressEnd: z.number().min(0).max(1),\n /** Viz speed multiplier during this clip */\n vizSpeed: z.number().positive(),\n /** Viz speed multiplier during the pause after this clip */\n gapVizSpeed: z.number().positive(),\n /** Phase this line belongs to (optional) */\n phase: z.string().optional(),\n })\n .refine((line) => line.progressStart <= line.progressEnd, {\n message: 'progressStart must be <= progressEnd',\n path: ['progressStart'],\n });\n\nexport const TimingFileSchema = z\n .object({\n /** Schema version — always 1 for now */\n version: z.literal(1),\n /** Total video duration in seconds */\n totalDurationSec: z.number().positive(),\n /** Ordered list of timed lines — fully resolved, all fields required */\n lines: z.array(TimedLineSchema).min(1),\n })\n .superRefine((data, ctx) => {\n // Enforce unique line IDs\n const ids = new Set<string>();\n for (let i = 0; i < data.lines.length; i++) {\n const id = data.lines[i].id;\n if (ids.has(id)) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: `Duplicate line ID: \"${id}\" (line index ${i})`,\n path: ['lines', i, 'id'],\n });\n }\n ids.add(id);\n }\n });\n\n// --- TypeScript types (inferred from schemas) ---\n\nexport type TimedLine = z.infer<typeof TimedLineSchema>;\nexport type TimingFile = z.infer<typeof TimingFileSchema>;\n","/**\n * Audio manifest schema — the contract between audio generation and Remotion consumption.\n * Lives at: remotion/public/audio/audio-manifest.json\n *\n * @module audio/manifest\n */\n\nimport type { TimedLine, TimingFile } from '../types/timing.js';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface AudioManifest {\n version: 1;\n fps: number;\n totalDurationSec: number;\n\n /** Per-beat voice clips */\n dialog: DialogBeat[];\n /** Background music tracks */\n music: MusicTrack[];\n /** One-shot sound effects */\n sfx: SfxPlacement[];\n /** Text overlays (title cards, labels, data accents) */\n overlays: TextOverlay[];\n}\n\n/**\n * v2 audio manifest — SFX + music only.\n * Dialog comes from timing.json (generated in Step 4).\n * No overlays section.\n */\nexport interface AudioManifestV2 {\n version: 2;\n /** Background music tracks */\n music: MusicTrack[];\n /** One-shot sound effects */\n sfx: SfxPlacement[];\n}\n\n/** Union of all manifest versions */\nexport type AudioManifestAny = AudioManifest | AudioManifestV2;\n\nexport interface DialogBeat {\n id: string;\n file: string;\n speaker: string;\n text: string;\n startSec: number;\n durationSec: number;\n volume?: number;\n style?: 'quote' | 'narrator' | 'text-card';\n}\n\nexport interface MusicTrack {\n id: string;\n file: string;\n startSec: number;\n durationSec: number;\n volume: number;\n fadeInSec?: number;\n fadeOutSec?: number;\n duckTo?: number;\n}\n\nexport interface SfxPlacement {\n id: string;\n file: string;\n startSec: number;\n volume?: number;\n note?: string;\n}\n\nexport interface TextOverlay {\n id: string;\n type: 'title-card' | 'speaker-label' | 'data-accent' | 'chapter';\n text: string;\n startSec: number;\n durationSec: number;\n style?: {\n fontSize?: number;\n color?: string;\n position?: 'center' | 'bottom-left' | 'bottom-right' | 'top';\n typingSpeed?: number | null;\n };\n}\n\n// ---------------------------------------------------------------------------\n// Validation\n// ---------------------------------------------------------------------------\n\nexport interface ValidationResult {\n valid: boolean;\n errors: string[];\n}\n\n/**\n * Validate an AudioManifest for structural correctness.\n *\n * Checks:\n * - Required top-level fields (version, fps, totalDurationSec)\n * - Dialog beats within totalDurationSec, no same-speaker overlap\n * - Music tracks within totalDurationSec, volume 0-1\n * - SFX placements within totalDurationSec\n * - Overlay timing within totalDurationSec\n * - File paths are relative strings (no absolute paths)\n * - Volume values in 0-1 range\n */\nexport function validateAudioManifest(manifest: unknown): ValidationResult {\n const errors: string[] = [];\n\n if (manifest == null || typeof manifest !== 'object') {\n return { valid: false, errors: ['Manifest must be a non-null object'] };\n }\n\n const m = manifest as Record<string, unknown>;\n\n // --- Required top-level fields ---\n const version = m.version;\n if (version !== 1 && version !== 2) {\n errors.push(`version must be 1 or 2, got ${JSON.stringify(version)}`);\n }\n\n // v1 requires fps and totalDurationSec; v2 does not\n if (version === 1) {\n if (typeof m.fps !== 'number' || m.fps <= 0) {\n errors.push(`fps must be a positive number, got ${JSON.stringify(m.fps)}`);\n }\n if (typeof m.totalDurationSec !== 'number' || m.totalDurationSec <= 0) {\n errors.push(\n `totalDurationSec must be a positive number, got ${JSON.stringify(m.totalDurationSec)}`,\n );\n }\n }\n\n const totalDur = typeof m.totalDurationSec === 'number' ? m.totalDurationSec : 0;\n\n // --- Arrays: v1 requires all four, v2 requires sfx + music only ---\n if (version === 1) {\n if (!Array.isArray(m.dialog)) {\n errors.push('dialog must be an array');\n }\n if (!Array.isArray(m.overlays)) {\n errors.push('overlays must be an array');\n }\n }\n if (!Array.isArray(m.music)) {\n errors.push('music must be an array');\n }\n if (!Array.isArray(m.sfx)) {\n errors.push('sfx must be an array');\n }\n\n // Bail early if arrays are missing — can't validate contents\n if (errors.length > 0) {\n return { valid: false, errors };\n }\n\n const dialog = (Array.isArray(m.dialog) ? m.dialog : []) as DialogBeat[];\n const music = m.music as MusicTrack[];\n const sfx = m.sfx as SfxPlacement[];\n const overlays = (Array.isArray(m.overlays) ? m.overlays : []) as TextOverlay[];\n\n // --- Shared helpers ---\n function checkFilePath(file: unknown, context: string): void {\n if (typeof file !== 'string' || file.length === 0) {\n errors.push(`${context}: file must be a non-empty string`);\n } else if (file.startsWith('/') || file.startsWith('\\\\')) {\n errors.push(`${context}: file must be a relative path, got \"${file}\"`);\n }\n }\n\n function checkVolume(vol: unknown, context: string, required: boolean): void {\n if (vol == null) {\n if (required) errors.push(`${context}: volume is required`);\n return;\n }\n if (typeof vol !== 'number' || vol < 0 || vol > 1) {\n errors.push(`${context}: volume must be 0-1, got ${JSON.stringify(vol)}`);\n }\n }\n\n function checkTimingWithin(startSec: unknown, durationSec: unknown, context: string): void {\n if (typeof startSec !== 'number' || startSec < 0) {\n errors.push(\n `${context}: startSec must be a non-negative number, got ${JSON.stringify(startSec)}`,\n );\n return;\n }\n if (typeof durationSec === 'number') {\n if (durationSec < 0) {\n errors.push(`${context}: durationSec must be non-negative, got ${durationSec}`);\n }\n // Only check bounds when totalDurationSec is known (v1 manifests)\n if (totalDur > 0 && startSec + durationSec > totalDur) {\n errors.push(\n `${context}: startSec (${startSec}) + durationSec (${durationSec}) = ${startSec + durationSec} exceeds totalDurationSec (${totalDur})`,\n );\n }\n }\n }\n\n // --- Dialog beats ---\n const ids = new Set<string>();\n for (let i = 0; i < dialog.length; i++) {\n const b = dialog[i];\n const ctx = `dialog[${i}] (${b.id ?? 'no id'})`;\n\n if (typeof b.id !== 'string' || b.id.length === 0) {\n errors.push(`${ctx}: id must be a non-empty string`);\n } else if (ids.has(b.id)) {\n errors.push(`${ctx}: duplicate id \"${b.id}\"`);\n } else {\n ids.add(b.id);\n }\n\n checkFilePath(b.file, ctx);\n\n if (typeof b.speaker !== 'string' || b.speaker.length === 0) {\n errors.push(`${ctx}: speaker must be a non-empty string`);\n }\n if (typeof b.text !== 'string') {\n errors.push(`${ctx}: text must be a string`);\n }\n if (typeof b.durationSec !== 'number' || b.durationSec <= 0) {\n errors.push(\n `${ctx}: durationSec must be a positive number, got ${JSON.stringify(b.durationSec)}`,\n );\n }\n\n checkTimingWithin(b.startSec, b.durationSec, ctx);\n checkVolume(b.volume, ctx, false);\n\n if (\n b.style !== undefined &&\n b.style !== 'quote' &&\n b.style !== 'narrator' &&\n b.style !== 'text-card'\n ) {\n errors.push(`${ctx}: style must be 'quote', 'narrator', or 'text-card', got \"${b.style}\"`);\n }\n }\n\n // --- Same-speaker overlap check ---\n const bySpeaker = new Map<string, DialogBeat[]>();\n for (const b of dialog) {\n if (typeof b.speaker !== 'string') continue;\n const list = bySpeaker.get(b.speaker) ?? [];\n list.push(b);\n bySpeaker.set(b.speaker, list);\n }\n for (const [speaker, beats] of bySpeaker) {\n const sorted = [...beats].sort((a, b) => a.startSec - b.startSec);\n for (let i = 1; i < sorted.length; i++) {\n const prev = sorted[i - 1];\n const curr = sorted[i];\n const prevEnd = prev.startSec + prev.durationSec;\n if (prevEnd > curr.startSec) {\n errors.push(\n `dialog overlap for speaker \"${speaker}\": \"${prev.id}\" ends at ${prevEnd}s but \"${curr.id}\" starts at ${curr.startSec}s`,\n );\n }\n }\n }\n\n // --- Music tracks ---\n for (let i = 0; i < music.length; i++) {\n const t = music[i];\n const ctx = `music[${i}] (${t.id ?? 'no id'})`;\n\n if (typeof t.id !== 'string' || t.id.length === 0) {\n errors.push(`${ctx}: id must be a non-empty string`);\n }\n checkFilePath(t.file, ctx);\n checkTimingWithin(t.startSec, t.durationSec, ctx);\n checkVolume(t.volume, ctx, true);\n\n if (t.fadeInSec != null && (typeof t.fadeInSec !== 'number' || t.fadeInSec < 0)) {\n errors.push(`${ctx}: fadeInSec must be a non-negative number`);\n }\n if (t.fadeOutSec != null && (typeof t.fadeOutSec !== 'number' || t.fadeOutSec < 0)) {\n errors.push(`${ctx}: fadeOutSec must be a non-negative number`);\n }\n if (t.duckTo != null) {\n if (typeof t.duckTo !== 'number' || t.duckTo < 0 || t.duckTo > 1) {\n errors.push(`${ctx}: duckTo must be 0-1, got ${JSON.stringify(t.duckTo)}`);\n }\n }\n }\n\n // --- SFX placements ---\n for (let i = 0; i < sfx.length; i++) {\n const s = sfx[i];\n const ctx = `sfx[${i}] (${s.id ?? 'no id'})`;\n\n if (typeof s.id !== 'string' || s.id.length === 0) {\n errors.push(`${ctx}: id must be a non-empty string`);\n }\n checkFilePath(s.file, ctx);\n if (typeof s.startSec !== 'number' || s.startSec < 0) {\n errors.push(\n `${ctx}: startSec must be a non-negative number, got ${JSON.stringify(s.startSec)}`,\n );\n }\n if (totalDur > 0 && s.startSec > totalDur) {\n errors.push(`${ctx}: startSec (${s.startSec}) exceeds totalDurationSec (${totalDur})`);\n }\n checkVolume(s.volume, ctx, false);\n }\n\n // --- Text overlays ---\n const validOverlayTypes = new Set(['title-card', 'speaker-label', 'data-accent', 'chapter']);\n const validPositions = new Set(['center', 'bottom-left', 'bottom-right', 'top']);\n for (let i = 0; i < overlays.length; i++) {\n const o = overlays[i];\n const ctx = `overlays[${i}] (${o.id ?? 'no id'})`;\n\n if (typeof o.id !== 'string' || o.id.length === 0) {\n errors.push(`${ctx}: id must be a non-empty string`);\n }\n if (!validOverlayTypes.has(o.type)) {\n errors.push(\n `${ctx}: type must be one of ${[...validOverlayTypes].join(', ')}, got \"${o.type}\"`,\n );\n }\n if (typeof o.text !== 'string' || o.text.length === 0) {\n errors.push(`${ctx}: text must be a non-empty string`);\n }\n if (typeof o.durationSec !== 'number' || o.durationSec <= 0) {\n errors.push(\n `${ctx}: durationSec must be a positive number, got ${JSON.stringify(o.durationSec)}`,\n );\n }\n checkTimingWithin(o.startSec, o.durationSec, ctx);\n\n if (o.style != null) {\n if (typeof o.style !== 'object') {\n errors.push(`${ctx}: style must be an object`);\n } else {\n if (\n o.style.fontSize != null &&\n (typeof o.style.fontSize !== 'number' || o.style.fontSize <= 0)\n ) {\n errors.push(`${ctx}: style.fontSize must be a positive number`);\n }\n if (o.style.color != null && typeof o.style.color !== 'string') {\n errors.push(`${ctx}: style.color must be a string`);\n }\n if (o.style.position != null && !validPositions.has(o.style.position)) {\n errors.push(\n `${ctx}: style.position must be one of ${[...validPositions].join(', ')}, got \"${o.style.position}\"`,\n );\n }\n if (\n o.style.typingSpeed !== undefined &&\n o.style.typingSpeed !== null &&\n (typeof o.style.typingSpeed !== 'number' || o.style.typingSpeed <= 0)\n ) {\n errors.push(`${ctx}: style.typingSpeed must be a positive number or null`);\n }\n }\n }\n }\n\n return { valid: errors.length === 0, errors };\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Compute total duration from manifest content.\n * Returns max(endTime) across all tracks + 2s padding.\n * Useful for agents building the manifest before totalDurationSec is known.\n */\nexport function computeTotalDuration(\n manifest: Pick<AudioManifest, 'dialog' | 'music' | 'sfx' | 'overlays'>,\n): number {\n let maxEnd = 0;\n\n for (const b of manifest.dialog) {\n maxEnd = Math.max(maxEnd, b.startSec + b.durationSec);\n }\n for (const t of manifest.music) {\n maxEnd = Math.max(maxEnd, t.startSec + t.durationSec);\n }\n for (const s of manifest.sfx) {\n // SFX don't have durationSec — use startSec only\n maxEnd = Math.max(maxEnd, s.startSec);\n }\n for (const o of manifest.overlays) {\n maxEnd = Math.max(maxEnd, o.startSec + o.durationSec);\n }\n\n return maxEnd + 2;\n}\n\n// ---------------------------------------------------------------------------\n// v2 → v1 manifest resolver (Bug #13: audio-narration sync)\n// ---------------------------------------------------------------------------\n\n/**\n * Raw SFX entry from the v2 sound design manifest.\n * May use `atLine` + `offsetSec` instead of absolute `startSec`.\n */\ninterface RawV2Sfx {\n id: string;\n file: string;\n startSec?: number;\n volume?: number;\n note?: string;\n /** Line ID reference — resolved to absolute startSec via timing.json */\n atLine?: string;\n /** Offset from the referenced line's startSec (default: 0) */\n offsetSec?: number;\n}\n\n/**\n * Raw music entry from the v2 sound design manifest.\n * May use `fromLine`/`toLine` instead of absolute `startSec`.\n */\ninterface RawV2Music {\n id: string;\n file: string;\n startSec: number;\n durationSec: number;\n volume: number;\n fadeInSec?: number;\n fadeOutSec?: number;\n duckTo?: number;\n /** Line ID reference — resolved to absolute startSec via timing.json */\n fromLine?: string;\n /** Line ID reference (informational — not used for timing resolution) */\n toLine?: string;\n}\n\n/** Raw v2 manifest input (may contain atLine/fromLine references) */\ninterface RawV2Manifest {\n version: 2;\n sfx: RawV2Sfx[];\n music: RawV2Music[];\n}\n\n/** Options for resolveAudioManifestForRemotion */\ninterface ResolveOptions {\n /** Frames per second (default: 30) */\n fps?: number;\n}\n\n/**\n * Resolve a v2 audio manifest + timing.json into a v1 AudioManifest for Remotion.\n *\n * 1. Builds dialog beats from timing.json lines (each line → DialogBeat)\n * 2. Resolves SFX `atLine` references to absolute `startSec` using timing.json\n * 3. Resolves music `fromLine` references to absolute `startSec` using timing.json\n * 4. Returns a complete v1 AudioManifest ready for Remotion consumption\n *\n * Pure function — no I/O.\n */\nexport function resolveAudioManifestForRemotion(\n v2: RawV2Manifest,\n timing: TimingFile,\n options?: ResolveOptions,\n): AudioManifest {\n const fps = options?.fps ?? 30;\n\n // Build a lookup map: line ID → TimedLine\n const lineById = new Map<string, TimedLine>();\n for (const line of timing.lines) {\n lineById.set(line.id, line);\n }\n\n // 1. Build dialog beats from timing.json lines\n const dialog: DialogBeat[] = timing.lines.map((line) => ({\n id: line.id,\n file: line.audioFile,\n speaker: line.speaker,\n text: line.text,\n startSec: line.startSec,\n durationSec: line.durationSec,\n style: line.style,\n }));\n\n // 2. Resolve SFX: atLine → absolute startSec\n const sfx: SfxPlacement[] = v2.sfx.map((raw) => {\n let startSec: number;\n\n if (raw.atLine != null) {\n const refLine = lineById.get(raw.atLine);\n if (refLine == null) {\n throw new Error(`SFX \"${raw.id}\": atLine \"${raw.atLine}\" not found in timing.json lines`);\n }\n startSec = refLine.startSec + (raw.offsetSec ?? 0);\n } else {\n startSec = raw.startSec ?? 0;\n }\n\n const resolved: SfxPlacement = {\n id: raw.id,\n file: raw.file,\n startSec,\n };\n if (raw.volume != null) resolved.volume = raw.volume;\n if (raw.note != null) resolved.note = raw.note;\n return resolved;\n });\n\n // 3. Resolve music: fromLine → absolute startSec\n const music: MusicTrack[] = v2.music.map((raw) => {\n let startSec: number;\n\n if (raw.fromLine != null) {\n const refLine = lineById.get(raw.fromLine);\n if (refLine == null) {\n throw new Error(\n `Music \"${raw.id}\": fromLine \"${raw.fromLine}\" not found in timing.json lines`,\n );\n }\n startSec = refLine.startSec;\n } else {\n startSec = raw.startSec;\n }\n\n const resolved: MusicTrack = {\n id: raw.id,\n file: raw.file,\n startSec,\n durationSec: raw.durationSec,\n volume: raw.volume,\n };\n if (raw.fadeInSec != null) resolved.fadeInSec = raw.fadeInSec;\n if (raw.fadeOutSec != null) resolved.fadeOutSec = raw.fadeOutSec;\n if (raw.duckTo != null) resolved.duckTo = raw.duckTo;\n return resolved;\n });\n\n // 4. Assemble v1 manifest\n return {\n version: 1,\n fps,\n totalDurationSec: timing.totalDurationSec,\n dialog,\n music,\n sfx,\n overlays: [],\n };\n}\n"]}
@@ -828,6 +828,7 @@ declare function computePRPeakRows(events: VizEvent[]): number;
828
828
  *
829
829
  * @module audio/manifest
830
830
  */
831
+
831
832
  interface AudioManifest {
832
833
  version: 1;
833
834
  fps: number;
@@ -828,6 +828,7 @@ declare function computePRPeakRows(events: VizEvent[]): number;
828
828
  *
829
829
  * @module audio/manifest
830
830
  */
831
+
831
832
  interface AudioManifest {
832
833
  version: 1;
833
834
  fps: number;
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/transform/transform-raw.ts","../src/transform/transform-curation.ts","../src/types/script.ts","../src/types/pacing.ts","../src/types/timing.ts","../src/audio/manifest.ts"],"names":["z"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Transform source data → RawData (Contract A).\n *\n * Pure function. Deterministic. No side effects.\n * Maps existing JSON files to the generic RawData contract.\n */\n\nimport type {\n RawAgent,\n RawArtifact,\n RawCommit,\n RawData,\n RawMessage,\n RawPR,\n} from '../types/raw-data.js';\nimport type {\n SourceArtifactData,\n SourceBeamEvent,\n SourceCommit,\n SourceMessage,\n SourceMessageEvent,\n SourcePR,\n SourcePRAgentMap,\n SourceRetroPageData,\n SourceTimelineEvents,\n TransformSources,\n} from './source-types.js';\n\n/**\n * Infer a RawAgent role from a freeform role string (e.g. from teamAssembly).\n *\n * Checks for known keywords in the string (case-insensitive).\n * Order matters — more specific matches first (e.g. \"eng-lead\" matches \"lead\").\n * Falls back to 'builder' as the safest default (most common role).\n */\nexport function inferRole(roleString: string): RawAgent['role'] {\n const s = roleString.toLowerCase();\n if (s.includes('human') || s === 'user') return 'human';\n if (s.includes('lead')) return 'lead';\n if (s.includes('pm')) return 'pm';\n if (s.includes('tester') || s.includes('qa')) return 'tester';\n if (s.includes('reviewer') || s.includes('review')) return 'reviewer';\n if (s.includes('auditor') || s.includes('audit')) return 'auditor';\n if (s.includes('challenger') || s.includes('challenge')) return 'challenger';\n if (s.includes('scout')) return 'scout';\n if (s.includes('ideation')) return 'ideation';\n if (s.includes('research')) return 'researcher';\n if (s.includes('builder') || s.includes('build')) return 'builder';\n return 'builder'; // safe default — most common role\n}\n\n/**\n * Transform all source data into RawData.\n * This is the main entry point for the extraction layer.\n */\nexport function transformToRawData(sources: TransformSources): RawData {\n // First agent from teamAssembly is the default for unattributed items\n const defaultAgent = sources.retroPageData.teamAssembly[0]?.agent.replace('@', '') ?? 'unknown';\n\n return {\n project: {\n name: sources.retroPageData.meta.title,\n description: sources.retroPageData.meta.subtitle,\n },\n agents: transformAgents(\n sources.retroPageData,\n sources.chatActivity.agentTotals,\n sources.timelineEvents,\n undefined,\n sources.messages,\n ),\n commits: transformCommits(sources.commits, sources.prAgentMap, defaultAgent),\n prs: transformPRs(sources.prs, sources.prAgentMap),\n messages: transformMessages(sources.timelineEvents, sources.messages),\n artifacts: sources.artifactData\n ? transformArtifacts(\n sources.artifactData,\n sources.retroPageData,\n sources.prs,\n sources.prAgentMap,\n )\n : [],\n };\n}\n\n/**\n * Build a map of agent → earliest message timestamp from timeline events.\n * Only counts messages where the agent is the sender (not just mentioned).\n */\nfunction buildFirstMessageTimeMap(timelineEvents?: SourceTimelineEvents): Map<string, number> {\n const map = new Map<string, number>();\n if (!timelineEvents) return map;\n\n for (const evt of timelineEvents.events) {\n if (evt.type !== 'message' && evt.type !== 'beam') continue;\n const sender = (evt as SourceMessageEvent | SourceBeamEvent).from;\n const ts = new Date(evt.t).getTime();\n const existing = map.get(sender);\n if (existing === undefined || ts < existing) {\n map.set(sender, ts);\n }\n }\n\n return map;\n}\n\n/**\n * Build RawAgent[] from team assembly data + chat activity.\n *\n * joinedAt resolution priority:\n * 1. First message timestamp from timeline events (most accurate)\n * 2. teamAssembly join time (curated/scaffold fallback)\n * 3. Project start date (last resort)\n *\n * Role resolution priority:\n * 1. Explicit `agentRoles` override (if provided)\n * 2. Inferred from teamAssembly `role` field (e.g. \"eng-lead\" → \"lead\")\n * 3. Default: 'builder' (most common role, safe fallback)\n *\n * Never throws on unknown agents — always infers or defaults.\n */\nexport function transformAgents(\n retroData: SourceRetroPageData,\n agentTotals: Record<string, number>,\n timelineEvents?: SourceTimelineEvents,\n agentRoles?: Record<string, string>,\n messages?: SourceMessage[],\n): RawAgent[] {\n const agents: RawAgent[] = [];\n const seen = new Set<string>();\n\n // Build first-message-time lookup from timeline events\n const firstMessageTime = buildFirstMessageTimeMap(timelineEvents);\n\n // Build a lookup from teamAssembly role fields for agents not in override\n const assemblyRoles = new Map<string, string>();\n for (const entry of retroData.teamAssembly) {\n const id = entry.agent.replace('@', '');\n assemblyRoles.set(id, entry.role);\n }\n\n /** Resolve role for an agent: override → teamAssembly inference → default */\n function resolveRole(id: string): RawAgent['role'] {\n // 1. Explicit override\n if (agentRoles?.[id]) {\n return inferRole(agentRoles[id]);\n }\n // 2. Infer from teamAssembly role field\n const assemblyRole = assemblyRoles.get(id);\n if (assemblyRole) {\n return inferRole(assemblyRole);\n }\n // 3. Default\n return 'builder';\n }\n\n /** Resolve joinedAt: earliest of (first message, teamAssembly time), or startDate */\n function resolveJoinedAt(id: string, assemblyTime?: number): number {\n const msgTime = firstMessageTime.get(id);\n // Use earliest available timestamp — agent was present from whichever came first\n if (msgTime !== undefined && assemblyTime !== undefined) {\n return Math.min(msgTime, assemblyTime);\n }\n if (msgTime !== undefined) return msgTime;\n if (assemblyTime !== undefined) return assemblyTime;\n // Last resort: project start date\n return new Date(retroData.meta.startDate).getTime();\n }\n\n // Primary source: team assembly (has join times)\n for (const entry of retroData.teamAssembly) {\n const id = entry.agent.replace('@', '');\n if (seen.has(id)) continue;\n seen.add(id);\n\n agents.push({\n id,\n role: resolveRole(id),\n joinedAt: resolveJoinedAt(id, new Date(entry.time).getTime()),\n });\n }\n\n // Catch any agents in chat activity not in team assembly\n for (const id of Object.keys(agentTotals)) {\n if (seen.has(id)) continue;\n agents.push({\n id,\n role: resolveRole(id),\n joinedAt: resolveJoinedAt(id),\n });\n seen.add(id);\n }\n\n // Detect human users from message senderType.\n // Two phases: (1) add unseen human senders, (2) upgrade already-seen\n // agents to role: 'human'. Phase 2 is needed because users like @snorre\n // appear in agentTotals (they send messages) and get role: 'builder'\n // before the senderType check — see PR #640 review by @check.\n if (messages) {\n const humanSenders = new Set<string>();\n for (const msg of messages) {\n if (msg.senderType === 'user') humanSenders.add(msg.sender);\n }\n\n // Phase 1: add unseen human senders\n for (const id of humanSenders) {\n if (!seen.has(id)) {\n seen.add(id);\n agents.push({\n id,\n role: 'human',\n joinedAt: resolveJoinedAt(id),\n });\n }\n }\n\n // Phase 2: upgrade already-seen agents to human\n for (const agent of agents) {\n if (humanSenders.has(agent.id)) {\n agent.role = 'human';\n }\n }\n }\n\n return agents;\n}\n\n/**\n * Transform git commits → RawCommit[].\n * Cross-references pr-agent-map for attribution.\n *\n * @param defaultAgent - Fallback agent for commits with no PR reference\n * (typically the first agent from teamAssembly/roster)\n */\nexport function transformCommits(\n commits: SourceCommit[],\n prAgentMap: SourcePRAgentMap,\n defaultAgent = 'unknown',\n): RawCommit[] {\n return commits.map((c) => {\n const agent = resolveCommitAgent(c, prAgentMap, defaultAgent);\n\n return {\n sha: c.hash,\n timestamp: new Date(c.date).getTime(),\n agent,\n message: c.subject,\n filesChanged: c.files.length,\n insertions: c.totalInsertions,\n deletions: c.totalDeletions,\n prNumber: c.prNumber ?? undefined,\n };\n });\n}\n\n/**\n * Resolve which agent authored a commit.\n * Strategy chain:\n * 1. prNumber field → pr-agent-map lookup\n * 2. \"Merge pull request #N\" in subject → pr-agent-map lookup\n * 3. \"(#N)\" suffix in subject → pr-agent-map lookup\n * 4. Fallback to defaultAgent (first agent from roster/teamAssembly)\n */\nexport function resolveCommitAgent(\n commit: SourceCommit,\n prAgentMap: SourcePRAgentMap,\n defaultAgent = 'unknown',\n): string {\n // Strategy 1: direct prNumber field\n if (commit.prNumber != null) {\n const agent = prAgentMap[String(commit.prNumber)];\n if (agent) return agent;\n }\n\n // Strategy 2: \"Merge pull request #N\" pattern\n const mergeMatch = commit.subject.match(/^Merge pull request #(\\d+)/);\n if (mergeMatch) {\n const agent = prAgentMap[mergeMatch[1]];\n if (agent) return agent;\n }\n\n // Strategy 3: \"(#N)\" suffix pattern\n const suffixMatch = commit.subject.match(/\\(#(\\d+)\\)\\s*$/);\n if (suffixMatch) {\n const agent = prAgentMap[suffixMatch[1]];\n if (agent) return agent;\n }\n\n // Fallback: first agent from roster (caller provides)\n return defaultAgent;\n}\n\n/**\n * Transform PR details → RawPR[].\n * Cross-references pr-agent-map for attribution.\n */\nexport function transformPRs(prs: SourcePR[], prAgentMap: SourcePRAgentMap): RawPR[] {\n return prs.map((pr) => {\n const agent = prAgentMap[String(pr.number)] ?? 'unknown';\n\n return {\n number: pr.number,\n title: pr.title,\n agent,\n createdAt: new Date(pr.createdAt).getTime(),\n mergedAt: pr.mergedAt ? new Date(pr.mergedAt).getTime() : null,\n additions: pr.additions,\n deletions: pr.deletions,\n branch: pr.headRefName,\n };\n });\n}\n\n/**\n * Infer artifact type from slug or file path.\n *\n * Handles both platforms:\n * - Redux: file paths with extensions (\"/specs/auth.md\", \"plan/task-X1Y2\")\n * - Cast: artifact slugs (\"spec-auth\", \"screenshot-login\", \"qa-review\")\n *\n * Redux patterns are checked first (more specific), cast patterns as fallback.\n */\nexport function inferArtifactType(slug: string): RawArtifact['type'] {\n // --- Redux: plan item prefixes ---\n if (slug.startsWith('plan/task-')) return 'task';\n if (slug.startsWith('plan/spec-')) return 'doc';\n\n // --- Extension-based (works for both platforms, but primarily redux file paths) ---\n const ext = slug.split('.').pop()?.toLowerCase();\n if (ext && ['ts', 'tsx', 'js', 'jsx', 'py', 'rs', 'go', 'sh'].includes(ext)) return 'code';\n if (ext && ['png', 'jpg', 'jpeg', 'svg', 'gif', 'webp', 'ico'].includes(ext)) return 'asset';\n if (ext && ['md', 'txt', 'json', 'yaml', 'yml', 'toml'].includes(ext)) return 'doc';\n\n // --- Redux: path-based patterns ---\n if (slug.includes('/specs/') || slug.includes('/spec/')) return 'doc';\n if (slug.includes('/assets/') || slug.includes('/images/')) return 'asset';\n\n // --- Cast: existing slug patterns (backward compat) ---\n if (slug.includes('.app.')) return 'code';\n if (slug.includes('screenshot') || slug.includes('qa-')) return 'asset';\n if (slug.includes('decision')) return 'decision';\n if (slug.includes('task') || slug.includes('phase-')) return 'task';\n if (slug.startsWith('spec-') || slug.startsWith('spec')) return 'doc';\n if (slug.includes('concept')) return 'doc';\n\n return 'doc';\n}\n\n/**\n * Resolve artifact agent from source data.\n *\n * Priority:\n * 1. Explicit `createdBy` from the artifact record (Miriad API provides this)\n * 2. PR number in slug → pr-agent-map lookup\n * 3. Configurable default (first agent from roster, typically the lead)\n */\nexport function resolveArtifactAgent(\n slug: string,\n prAgentMap: SourcePRAgentMap,\n createdBy: string | undefined,\n defaultAgent: string,\n): string {\n // 1. Explicit creator from source data\n if (createdBy) return createdBy;\n\n // 2. PR reference in slug → agent map\n const prMatch = slug.match(/#?(\\d+)/);\n if (prMatch) {\n const agent = prAgentMap[prMatch[1]];\n if (agent) return agent;\n }\n\n // 3. Default (first agent from roster)\n return defaultAgent;\n}\n\n/** Category name → artifact type */\nconst CATEGORY_TYPE_MAP: Record<string, RawArtifact['type']> = {\n qaScreenshots: 'asset',\n transitionSpecs: 'doc',\n transitionConcepts: 'doc',\n scenes: 'doc',\n vizConcepts: 'code',\n teamPrinciples: 'doc',\n retroData: 'doc',\n decisions: 'decision',\n};\n\n/**\n * Distribute N artifacts within time boundaries, clustered around\n * PR timestamps when available for realistic density.\n */\nexport function distributeTimestamps(\n count: number,\n bounds: { start: number; end: number },\n prTimestamps: number[],\n): number[] {\n const phasePRTimes = prTimestamps.filter((t) => t >= bounds.start && t <= bounds.end);\n const timestamps: number[] = [];\n\n for (let i = 0; i < count; i++) {\n let timestamp: number;\n if (phasePRTimes.length > 0) {\n const prIdx = i % phasePRTimes.length;\n timestamp = phasePRTimes[prIdx] + i * 60000;\n } else {\n const fraction = count > 1 ? i / (count - 1) : 0.5;\n timestamp = bounds.start + fraction * (bounds.end - bounds.start);\n }\n timestamps.push(Math.round(Math.max(bounds.start, Math.min(bounds.end, timestamp))));\n }\n\n return timestamps;\n}\n\n/**\n * Build a type distribution from category data.\n *\n * Each category maps to a type. We build a weighted list so bulk\n * artifacts can be assigned types proportional to category counts.\n * Returns entries sorted by count descending for deterministic assignment.\n *\n * Agent assignment is NOT done here — it's handled by the caller using\n * round-robin over the known agent list (from teamAssembly).\n */\nexport function buildCategoryDistribution(\n categories: SourceArtifactData['categories'],\n): Array<{ type: RawArtifact['type']; weight: number }> {\n const entries: Array<{ type: RawArtifact['type']; count: number }> = [];\n let total = 0;\n\n for (const [categoryName, categoryData] of Object.entries(categories)) {\n if (categoryData.count === 0) continue;\n entries.push({\n type: CATEGORY_TYPE_MAP[categoryName] ?? 'doc',\n count: categoryData.count,\n });\n total += categoryData.count;\n }\n\n if (total === 0) return [{ type: 'doc', weight: 1 }];\n\n return entries\n .sort((a, b) => b.count - a.count)\n .map((e) => ({ type: e.type, weight: e.count / total }));\n}\n\n/**\n * Build a slug → createdBy lookup from SourceArtifactData category items.\n * Items can be plain strings (no creator info) or objects with optional createdBy.\n */\nfunction buildCreatedByLookup(categories: SourceArtifactData['categories']): Map<string, string> {\n const lookup = new Map<string, string>();\n for (const categoryData of Object.values(categories)) {\n for (const item of categoryData.items ?? []) {\n if (typeof item === 'object' && item.createdBy) {\n lookup.set(item.slug, item.createdBy);\n }\n }\n }\n return lookup;\n}\n\n/**\n * Transform artifact-data.json → RawArtifact[].\n *\n * Uses phase `count` fields for correct per-phase density. Each phase\n * specifies how many artifacts were created during that time window:\n * Phase 1: 5, Phase 2: 45, Phase 3: 80, Phase 4: 120, Phase 5: 60 = 310\n *\n * Within each phase:\n * 1. Curated slugs get their own entries with createdBy from source data\n * 2. Remaining count filled with generated artifacts using category\n * type proportions and round-robin agent assignment\n * 3. All timestamps distributed within phase boundaries, clustered\n * around PR activity\n */\nexport function transformArtifacts(\n artifactData: SourceArtifactData,\n retroData: SourceRetroPageData,\n prs: SourcePR[],\n prAgentMap: SourcePRAgentMap,\n): RawArtifact[] {\n const artifacts: RawArtifact[] = [];\n\n // Build agent list from teamAssembly for round-robin and default\n const agentIds = retroData.teamAssembly.map((e) => e.agent.replace('@', ''));\n const defaultAgent = agentIds[0] ?? 'unknown';\n\n const phaseBoundaries = retroData.phases.map((p) => ({\n start: new Date(p.start).getTime(),\n end: new Date(p.end).getTime(),\n }));\n\n const prTimestamps = prs.map((pr) => new Date(pr.createdAt).getTime()).sort((a, b) => a - b);\n const distribution = buildCategoryDistribution(artifactData.categories);\n const createdByLookup = buildCreatedByLookup(artifactData.categories);\n\n let phaseIndex = 0;\n let globalBulkIndex = 0;\n\n for (const [_phaseName, phaseData] of Object.entries(artifactData.phases)) {\n if (phaseIndex >= phaseBoundaries.length) break;\n const bounds = phaseBoundaries[phaseIndex];\n phaseIndex++;\n\n const totalCount = phaseData.count;\n const slugs = phaseData.artifacts;\n const bulkCount = Math.max(0, totalCount - slugs.length);\n\n // All artifacts in this phase share one timestamp distribution\n const timestamps = distributeTimestamps(totalCount, bounds, prTimestamps);\n\n // ── Curated slugs first ──────────────────────────────────────────────\n let tsIdx = 0;\n for (const slug of slugs) {\n artifacts.push({\n slug,\n type: inferArtifactType(slug),\n createdAt: timestamps[tsIdx],\n updatedAt: timestamps[tsIdx],\n agent: resolveArtifactAgent(slug, prAgentMap, createdByLookup.get(slug), defaultAgent),\n });\n tsIdx++;\n }\n\n // ── Bulk artifacts fill remaining count ───────────────────────────────\n // Assign type by walking through the weighted distribution.\n // Assign agent by round-robin over the known agent list.\n let distIdx = 0;\n let distBudget = Math.round(distribution[0].weight * bulkCount);\n\n for (let i = 0; i < bulkCount; i++) {\n // Advance to next distribution bucket when current is exhausted\n while (distBudget <= 0 && distIdx < distribution.length - 1) {\n distIdx++;\n distBudget = Math.round(distribution[distIdx].weight * bulkCount);\n }\n distBudget--;\n\n const entry = distribution[distIdx];\n // Round-robin agent assignment across the roster\n const agent =\n agentIds.length > 0 ? agentIds[globalBulkIndex % agentIds.length] : defaultAgent;\n artifacts.push({\n slug: `phase${phaseIndex}-${entry.type}-${String(globalBulkIndex + 1).padStart(3, '0')}`,\n type: entry.type,\n createdAt: timestamps[tsIdx],\n updatedAt: timestamps[tsIdx],\n agent,\n });\n tsIdx++;\n globalBulkIndex++;\n }\n }\n\n artifacts.sort((a, b) => a.createdAt - b.createdAt);\n\n return artifacts;\n}\n\n/**\n * Transform curated timeline events into chat pills for the viewer.\n *\n * Chat pills come ONLY from timeline-events.json (curated).\n * Raw messages (messages-viz.json) are NEVER a source for chat pills —\n * they exist only for the agent to read during curation and for the\n * density table's \"Msgs\" column.\n *\n * Single source of truth: the curated file.\n */\nexport function transformMessages(\n timelineEvents: SourceTimelineEvents,\n rawMessages?: SourceMessage[],\n): RawMessage[] {\n // Curated events (timeline-events.json) → chat pills (labeled bubbles)\n const curatedMessages = timelineEvents.events\n .filter(\n (e): e is SourceMessageEvent | SourceBeamEvent => e.type === 'message' || e.type === 'beam',\n )\n .map((evt, i) => ({\n id: `curated-${String(i).padStart(4, '0')}`,\n timestamp: new Date(evt.t).getTime(),\n sender: evt.from,\n mentions: [evt.to],\n }));\n\n // Raw messages (messages-viz.json / messages-full.json) → beam channels + particles\n const rawMsgs: RawMessage[] = (rawMessages ?? []).map((msg, i) => ({\n id: msg.id || `raw-${String(i).padStart(4, '0')}`,\n timestamp: new Date(msg.timestamp).getTime(),\n sender: msg.sender,\n mentions: msg.mentions,\n }));\n\n // Merge: raw messages provide beam/particle density, curated provide labeled pills.\n // Deduplicate by timestamp+sender to avoid double-counting when a raw message\n // was also curated as a chat pill.\n const seen = new Set(rawMsgs.map((m) => `${m.timestamp}:${m.sender}`));\n const uniqueCurated = curatedMessages.filter((m) => !seen.has(`${m.timestamp}:${m.sender}`));\n\n return [...rawMsgs, ...uniqueCurated];\n}\n","/**\n * Transform source data → CurationData (editorial content).\n *\n * Pure function. Deterministic. No side effects.\n * Maps curated board artifacts to the CurationData contract.\n */\n\nimport type {\n CurationData,\n CurationMilestone,\n CurationNarrationEntry,\n CurationPhase,\n CurationQuote,\n CurationTrustKeyframe,\n} from '../types/raw-data.js';\nimport type {\n SourceRetroPageData,\n SourceRetroPageQuotes,\n TransformSources,\n} from './source-types.js';\n\n/**\n * Transform curated source data into CurationData.\n * This is the main entry point for the curation layer.\n */\nexport function transformToCurationData(sources: TransformSources): CurationData {\n const narration = transformNarration(sources.retroPageData);\n const meta = sources.retroPageData.meta;\n\n // Thread curated timeline bounds from meta.startDate/endDate\n const curatedStartMs = meta?.startDate ? new Date(meta.startDate).getTime() : undefined;\n const curatedEndMs = meta?.endDate ? new Date(meta.endDate).getTime() : undefined;\n\n return {\n phases: transformPhases(sources.retroPageData),\n quotes: transformQuotes(sources.retroPageData, sources.retroPageQuotes),\n milestones: transformMilestones(sources.retroPageData),\n trustKeyframes: transformTrustKeyframes(sources.retroPageData),\n ...(narration.length > 0 ? { editorialNarration: narration } : {}),\n ...(curatedStartMs && !Number.isNaN(curatedStartMs) ? { curatedStartMs } : {}),\n ...(curatedEndMs && !Number.isNaN(curatedEndMs) ? { curatedEndMs } : {}),\n };\n}\n\n/**\n * Transform phase definitions from retro-page-data.\n * Phases have hand-curated boundaries, names, and descriptions.\n */\nexport function transformPhases(retroData: SourceRetroPageData): CurationPhase[] {\n return retroData.phases.map((p) => ({\n id: p.id,\n name: p.name || p.label || '',\n startTime: new Date(p.start || p.startTime || '').getTime(),\n endTime: new Date(p.end || p.endTime || '').getTime(),\n }));\n}\n\n/**\n * Transform milestones from retro-page-data.\n * Each milestone is cross-referenced to its containing phase.\n */\nexport function transformMilestones(retroData: SourceRetroPageData): CurationMilestone[] {\n const phases = retroData.phases;\n\n return retroData.milestones.map((m) => {\n const milestoneTime = new Date(m.time).getTime();\n const phase = findPhaseForTimestamp(milestoneTime, phases);\n\n return {\n label: m.label,\n timestamp: milestoneTime,\n phase: phase?.id ?? 'unknown',\n };\n });\n}\n\n/**\n * Map mood category to mood string for quotes from retroPageData.\n */\nconst CATEGORY_MOOD: Record<string, string> = {\n theGood: 'good',\n theBad: 'bad',\n theUgly: 'angry',\n theFunny: 'good',\n};\n\n/**\n * Map mood category to mood string for quotes from retroPageQuotes.\n */\nconst ADDITION_MOOD: Record<string, string> = {\n good: 'good',\n bad: 'bad',\n ugly: 'angry',\n};\n\n/**\n * Transform quotes from both curated sources.\n * Merges retro-page-data quotes (theGood/theBad/theUgly/theFunny) with\n * retro-page-quotes additions (good/bad/ugly). Parses informal timestamps,\n * strips @ prefix from speakers, and cross-references to phases.\n * Sorted by timestamp.\n */\nexport function transformQuotes(\n retroData: SourceRetroPageData,\n retroQuotes: SourceRetroPageQuotes,\n): CurationQuote[] {\n const phases = retroData.phases;\n const quotes: CurationQuote[] = [];\n\n // Derive reference year from first phase start date (for informal timestamp parsing)\n const firstPhaseStart = phases[0]?.start;\n const referenceYear = firstPhaseStart\n ? new Date(firstPhaseStart).getUTCFullYear()\n : new Date().getUTCFullYear();\n\n // Source 1: retroPageData.quotes (theGood, theBad, theUgly, theFunny)\n for (const [category, entries] of Object.entries(retroData.quotes)) {\n if (!Array.isArray(entries)) continue; // skip _comment and other non-quote fields\n const mood = CATEGORY_MOOD[category] ?? 'good';\n for (const entry of entries) {\n const timestamp = parseInformalTimestamp(entry.time, referenceYear);\n if (timestamp == null) continue;\n const phase = findPhaseForTimestamp(timestamp, phases);\n quotes.push({\n text: entry.text,\n speaker: entry.author.replace(/^@/, ''),\n timestamp,\n phase: phase?.id ?? 'unknown',\n mood,\n });\n }\n }\n\n // Source 2: retroPageQuotes (good, bad, ugly)\n for (const [category, entries] of Object.entries(retroQuotes)) {\n if (!Array.isArray(entries)) continue; // skip _comment and other non-quote fields\n const mood = ADDITION_MOOD[category] ?? 'good';\n for (const entry of entries) {\n const timestamp = parseInformalTimestamp(entry.timestamp, referenceYear);\n if (timestamp == null) continue;\n const phase = findPhaseForTimestamp(timestamp, phases);\n quotes.push({\n text: entry.text,\n speaker: entry.author.replace(/^@/, ''),\n timestamp,\n phase: phase?.id ?? 'unknown',\n mood,\n });\n }\n }\n\n // Sort chronologically\n quotes.sort((a, b) => a.timestamp - b.timestamp);\n return quotes;\n}\n\n/**\n * Transform trust arc keyframes from retro-page-data.\n * Source levels are 0-100 integers; we normalize to 0-1.\n * Sorted by timestamp for interpolation.\n */\nexport function transformTrustKeyframes(retroData: SourceRetroPageData): CurationTrustKeyframe[] {\n if (!retroData.trustArc || retroData.trustArc.length === 0) return [];\n\n return retroData.trustArc\n .map((entry) => ({\n timestamp: new Date(entry.time).getTime(),\n level: entry.level / 100, // normalize 0-100 → 0-1\n label: entry.label,\n }))\n .sort((a, b) => a.timestamp - b.timestamp);\n}\n\n/** Month abbreviation → 0-based index */\nconst MONTH_ABBREVS: Record<string, number> = {\n jan: 0,\n feb: 1,\n mar: 2,\n apr: 3,\n may: 4,\n jun: 5,\n jul: 6,\n aug: 7,\n sep: 8,\n oct: 9,\n nov: 10,\n dec: 11,\n};\n\n/**\n * Transform editorial narration entries from retro-page-data.\n * Each entry has an ISO timestamp, phase title, color, text, and type.\n * Returns empty array if no narration is present in the source data.\n */\nexport function transformNarration(retroData: SourceRetroPageData): CurationNarrationEntry[] {\n if (!retroData.editorialNarration || retroData.editorialNarration.length === 0) return [];\n\n return retroData.editorialNarration\n .map((entry) => ({\n timestamp: new Date(entry.time).getTime(),\n phaseTitle: entry.phaseTitle,\n phaseColor: entry.phaseColor,\n text: entry.text,\n type: entry.type,\n }))\n .sort((a, b) => a.timestamp - b.timestamp);\n}\n\n/**\n * Parse informal timestamp strings like \"Feb 10 21:18\", \"Dec 31 (early)\", \"Jan 2 ~23:00\".\n * Accepts any 3-letter month abbreviation.\n *\n * @param timeStr - Informal timestamp (e.g., \"Feb 10 21:18\", \"Dec 31\")\n * @param referenceYear - Year to use (e.g., 2025). Required — no hardcoded default.\n * For projects spanning Dec→Jan, callers should handle year rollover.\n * @returns Unix ms or null if unparseable.\n */\nexport function parseInformalTimestamp(\n timeStr: string | undefined | null,\n referenceYear: number,\n): number | null {\n if (!timeStr) return null;\n\n // Try ISO 8601 first (scaffold generates ISO timestamps)\n const isoDate = new Date(timeStr);\n if (!Number.isNaN(isoDate.getTime()) && timeStr.includes('-')) {\n return isoDate.getTime();\n }\n\n // Strip tildes and parenthetical notes\n const cleaned = timeStr\n .replace(/~/g, '')\n .replace(/\\(.*?\\)/g, '')\n .trim();\n\n // Match \"Mon DD HH:MM\" or \"Mon DD\" (3-letter month abbreviation)\n const match = cleaned.match(/([A-Za-z]{3})\\s+(\\d{1,2})(?:\\s+(\\d{1,2}):(\\d{2}))?/);\n if (!match) return null;\n\n const monthIdx = MONTH_ABBREVS[match[1].toLowerCase()];\n if (monthIdx === undefined) return null;\n\n const day = Number.parseInt(match[2], 10);\n const hour = match[3] ? Number.parseInt(match[3], 10) : 12; // default to noon if no time\n const minute = match[4] ? Number.parseInt(match[4], 10) : 0;\n\n const date = new Date(Date.UTC(referenceYear, monthIdx, day, hour, minute, 0));\n return date.getTime();\n}\n\n/**\n * Find which phase a timestamp falls within.\n * First tries exact range match. If no phase contains the timestamp\n * (e.g., it falls in a gap between phases), falls back to the nearest\n * phase by distance to its start/end boundaries.\n *\n * Returns undefined only when phases array is empty.\n */\nexport function findPhaseForTimestamp(\n timestamp: number,\n phases: SourceRetroPageData['phases'],\n): SourceRetroPageData['phases'][number] | undefined {\n if (phases.length === 0) return undefined;\n\n // Try exact range match first\n const exact = phases.find((p) => {\n const start = new Date(p.start || p.startTime || '').getTime();\n const end = new Date(p.end || p.endTime || '').getTime();\n return timestamp >= start && timestamp <= end;\n });\n if (exact) return exact;\n\n // Fallback: find nearest phase by distance to boundaries\n let nearest: SourceRetroPageData['phases'][number] | undefined;\n let minDistance = Number.POSITIVE_INFINITY;\n\n for (const p of phases) {\n const start = new Date(p.start || p.startTime || '').getTime();\n const end = new Date(p.end || p.endTime || '').getTime();\n const distance = Math.min(Math.abs(timestamp - start), Math.abs(timestamp - end));\n if (distance < minDistance) {\n minDistance = distance;\n nearest = p;\n }\n }\n\n return nearest;\n}\n","/**\n * ScriptFile — the authoring contract for Step 2 (Script Writing).\n *\n * WHY: The script is the creative foundation. An agent writes this file\n * to define the narrative structure: who speaks, what they say, and in\n * what style. Every downstream file (pacing, timing) derives from this.\n *\n * The agent creates this from scratch in Step 2, guided by extracted data\n * (event density, agent activity, phases). The human reviews and approves.\n */\n\nimport { z } from 'zod';\n\n// --- Zod schemas (source of truth) ---\n\nexport const ScriptLineSchema = z.object({\n /** Unique identifier for this line (e.g., 'narrator-01', 'lead-03') */\n id: z.string().min(1),\n /** Who speaks this line (e.g., 'narrator', 'lead', 'snorre') */\n speaker: z.string().min(1),\n /** The spoken text */\n text: z.string().min(1),\n /** Rendering style: narrator voice (cursive) or agent quote (normal) */\n style: z.enum(['narrator', 'quote']),\n /** Optional phase this line belongs to (for grouping in the viz) */\n phaseId: z.string().optional(),\n});\n\nexport const ScriptFileSchema = z\n .object({\n /** Schema version — always 1 for now */\n version: z.literal(1),\n /** Ordered list of script lines */\n lines: z.array(ScriptLineSchema).min(1),\n })\n .superRefine((data, ctx) => {\n // Enforce unique line IDs\n const ids = new Set<string>();\n for (let i = 0; i < data.lines.length; i++) {\n const id = data.lines[i].id;\n if (ids.has(id)) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: `Duplicate line ID: \"${id}\" (line index ${i})`,\n path: ['lines', i, 'id'],\n });\n }\n ids.add(id);\n }\n });\n\n// --- TypeScript types (inferred from schemas) ---\n\nexport type ScriptLine = z.infer<typeof ScriptLineSchema>;\nexport type ScriptFile = z.infer<typeof ScriptFileSchema>;\n\n// --- Normalization ---\n\n/**\n * Auto-populate missing fields so a minimal script.json passes ScriptFileSchema.\n *\n * - If `version` is missing, defaults to `1`.\n * - If `style` is missing on a line, infers from speaker:\n * `speaker === 'narrator'` → `'narrator'`, otherwise → `'quote'`.\n *\n * Returns a new object (does not mutate the input).\n */\nexport function normalizeScript(raw: Record<string, unknown>): Record<string, unknown> {\n const out: Record<string, unknown> = { ...raw };\n\n if (out.version === undefined) {\n out.version = 1;\n }\n\n if (Array.isArray(out.lines)) {\n out.lines = (out.lines as Record<string, unknown>[]).map((line) => {\n if (line === null || typeof line !== 'object') return line;\n const l = { ...line };\n if (!l.style && typeof l.speaker === 'string') {\n l.style = l.speaker === 'narrator' ? 'narrator' : 'quote';\n }\n return l;\n });\n }\n\n return out;\n}\n","/**\n * PacingFile — the agent-facing timing contract for Step 4 (Viz Timing).\n *\n * WHY: The pacing file is what the agent edits to control how fast the viz\n * moves during each narration line. scaffold-pacing generates it from\n * script.json + audio clip durations. The agent then annotates 4 optional\n * fields per line: pauseAfter, vizSpeed, gapVizSpeed, note.\n *\n * Design: Approach A (Annotated Script) — mirrors the script with timing\n * annotations. Text + clip durations inline. Defaults handle 80% of lines.\n * No cascading edits (unlike start-time approaches).\n *\n * vizSpeed definition: multiplier on project-time-per-second.\n * 2.0 = viz moves 2x faster = LESS screen time for that period.\n * 0.5 = viz moves 2x slower = MORE screen time for that period.\n */\n\nimport { z } from 'zod';\n\n// --- Zod schemas (source of truth) ---\n\nexport const PacingLineSchema = z.object({\n /** Line ID — must match script.json line ID */\n id: z.string().min(1),\n /** Text from script (read-only, for context while editing pacing) */\n text: z.string().min(1),\n /** Audio clip duration in seconds (measured from file, read-only) */\n clipDuration: z.number().positive(),\n /** Silence after this line in seconds (overrides defaultPauseSec) */\n pauseAfter: z.number().nonnegative().optional(),\n /** Viz speed multiplier DURING this clip's audio. >1 = faster, <1 = slower */\n vizSpeed: z.number().positive().optional(),\n /** Viz speed multiplier DURING the pause after this clip (defaults to defaultVizSpeed) */\n gapVizSpeed: z.number().positive().optional(),\n /** Agent's reasoning for pacing choices (human reads during review) */\n note: z.string().optional(),\n});\n\nexport const PacingFileSchema = z\n .object({\n /** Schema version — always 1 for now */\n version: z.literal(1),\n /** Seconds of viz playback before first narration line */\n leadInSec: z.number().nonnegative().optional(),\n /** Seconds of viz playback after last narration line */\n tailOutSec: z.number().nonnegative().optional(),\n /** Default pause between lines in seconds (used when pauseAfter not set) */\n defaultPauseSec: z.number().nonnegative(),\n /** Default viz speed multiplier (used when vizSpeed/gapVizSpeed not set) */\n defaultVizSpeed: z.number().positive(),\n /** Ordered list of pacing lines — must match script.json order */\n lines: z.array(PacingLineSchema).min(1),\n })\n .superRefine((data, ctx) => {\n // Enforce unique line IDs\n const ids = new Set<string>();\n for (let i = 0; i < data.lines.length; i++) {\n const id = data.lines[i].id;\n if (ids.has(id)) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: `Duplicate line ID: \"${id}\" (line index ${i})`,\n path: ['lines', i, 'id'],\n });\n }\n ids.add(id);\n }\n });\n\n// --- TypeScript types (inferred from schemas) ---\n\nexport type PacingLine = z.infer<typeof PacingLineSchema>;\nexport type PacingFile = z.infer<typeof PacingFileSchema>;\n","/**\n * TimingFile — the engine-facing contract produced by generateTiming().\n *\n * WHY: This is the fully-resolved timing data that the transform layer reads\n * to produce narration entries with precise progress mapping. All fields are\n * required — no defaults, no optionals (except phase). generateTiming()\n * resolves all defaults from PacingFile and computes progress values.\n *\n * The transform layer validates this on read (belt-and-suspenders with\n * generateTiming's validation on write). If this file is corrupt, the\n * pipeline fails fast with a clear error.\n */\n\nimport { z } from 'zod';\n\n// --- Zod schemas (source of truth) ---\n\nexport const TimedLineSchema = z\n .object({\n /** Line ID — matches script.json and pacing.json */\n id: z.string().min(1),\n /** Speaker identifier (e.g., 'narrator', 'lead', 'snorre') */\n speaker: z.string().min(1),\n /** The spoken text */\n text: z.string().min(1),\n /** Rendering style: narrator voice (cursive) or agent quote (normal) */\n style: z.enum(['narrator', 'quote']),\n /** Wall-clock start time in seconds from video start */\n startSec: z.number().nonnegative(),\n /** Audio clip duration in seconds */\n durationSec: z.number().positive(),\n /** Pause after this line in seconds (resolved from defaults) */\n pauseAfterSec: z.number().nonnegative(),\n /** Audio file path relative to audio directory (e.g., 'narrator-01.mp3') */\n audioFile: z.string().min(1),\n /** Viz progress at clip start [0, 1] */\n progressStart: z.number().min(0).max(1),\n /** Viz progress at clip end [0, 1] */\n progressEnd: z.number().min(0).max(1),\n /** Viz speed multiplier during this clip */\n vizSpeed: z.number().positive(),\n /** Viz speed multiplier during the pause after this clip */\n gapVizSpeed: z.number().positive(),\n /** Phase this line belongs to (optional) */\n phase: z.string().optional(),\n })\n .refine((line) => line.progressStart <= line.progressEnd, {\n message: 'progressStart must be <= progressEnd',\n path: ['progressStart'],\n });\n\nexport const TimingFileSchema = z\n .object({\n /** Schema version — always 1 for now */\n version: z.literal(1),\n /** Total video duration in seconds */\n totalDurationSec: z.number().positive(),\n /** Ordered list of timed lines — fully resolved, all fields required */\n lines: z.array(TimedLineSchema).min(1),\n })\n .superRefine((data, ctx) => {\n // Enforce unique line IDs\n const ids = new Set<string>();\n for (let i = 0; i < data.lines.length; i++) {\n const id = data.lines[i].id;\n if (ids.has(id)) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: `Duplicate line ID: \"${id}\" (line index ${i})`,\n path: ['lines', i, 'id'],\n });\n }\n ids.add(id);\n }\n });\n\n// --- TypeScript types (inferred from schemas) ---\n\nexport type TimedLine = z.infer<typeof TimedLineSchema>;\nexport type TimingFile = z.infer<typeof TimingFileSchema>;\n","/**\n * Audio manifest schema — the contract between audio generation and Remotion consumption.\n * Lives at: remotion/public/audio/audio-manifest.json\n *\n * @module audio/manifest\n */\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface AudioManifest {\n version: 1;\n fps: number;\n totalDurationSec: number;\n\n /** Per-beat voice clips */\n dialog: DialogBeat[];\n /** Background music tracks */\n music: MusicTrack[];\n /** One-shot sound effects */\n sfx: SfxPlacement[];\n /** Text overlays (title cards, labels, data accents) */\n overlays: TextOverlay[];\n}\n\n/**\n * v2 audio manifest — SFX + music only.\n * Dialog comes from timing.json (generated in Step 4).\n * No overlays section.\n */\nexport interface AudioManifestV2 {\n version: 2;\n /** Background music tracks */\n music: MusicTrack[];\n /** One-shot sound effects */\n sfx: SfxPlacement[];\n}\n\n/** Union of all manifest versions */\nexport type AudioManifestAny = AudioManifest | AudioManifestV2;\n\nexport interface DialogBeat {\n id: string;\n file: string;\n speaker: string;\n text: string;\n startSec: number;\n durationSec: number;\n volume?: number;\n style?: 'quote' | 'narrator' | 'text-card';\n}\n\nexport interface MusicTrack {\n id: string;\n file: string;\n startSec: number;\n durationSec: number;\n volume: number;\n fadeInSec?: number;\n fadeOutSec?: number;\n duckTo?: number;\n}\n\nexport interface SfxPlacement {\n id: string;\n file: string;\n startSec: number;\n volume?: number;\n note?: string;\n}\n\nexport interface TextOverlay {\n id: string;\n type: 'title-card' | 'speaker-label' | 'data-accent' | 'chapter';\n text: string;\n startSec: number;\n durationSec: number;\n style?: {\n fontSize?: number;\n color?: string;\n position?: 'center' | 'bottom-left' | 'bottom-right' | 'top';\n typingSpeed?: number | null;\n };\n}\n\n// ---------------------------------------------------------------------------\n// Validation\n// ---------------------------------------------------------------------------\n\nexport interface ValidationResult {\n valid: boolean;\n errors: string[];\n}\n\n/**\n * Validate an AudioManifest for structural correctness.\n *\n * Checks:\n * - Required top-level fields (version, fps, totalDurationSec)\n * - Dialog beats within totalDurationSec, no same-speaker overlap\n * - Music tracks within totalDurationSec, volume 0-1\n * - SFX placements within totalDurationSec\n * - Overlay timing within totalDurationSec\n * - File paths are relative strings (no absolute paths)\n * - Volume values in 0-1 range\n */\nexport function validateAudioManifest(manifest: unknown): ValidationResult {\n const errors: string[] = [];\n\n if (manifest == null || typeof manifest !== 'object') {\n return { valid: false, errors: ['Manifest must be a non-null object'] };\n }\n\n const m = manifest as Record<string, unknown>;\n\n // --- Required top-level fields ---\n const version = m.version;\n if (version !== 1 && version !== 2) {\n errors.push(`version must be 1 or 2, got ${JSON.stringify(version)}`);\n }\n\n // v1 requires fps and totalDurationSec; v2 does not\n if (version === 1) {\n if (typeof m.fps !== 'number' || m.fps <= 0) {\n errors.push(`fps must be a positive number, got ${JSON.stringify(m.fps)}`);\n }\n if (typeof m.totalDurationSec !== 'number' || m.totalDurationSec <= 0) {\n errors.push(\n `totalDurationSec must be a positive number, got ${JSON.stringify(m.totalDurationSec)}`,\n );\n }\n }\n\n const totalDur = typeof m.totalDurationSec === 'number' ? m.totalDurationSec : 0;\n\n // --- Arrays: v1 requires all four, v2 requires sfx + music only ---\n if (version === 1) {\n if (!Array.isArray(m.dialog)) {\n errors.push('dialog must be an array');\n }\n if (!Array.isArray(m.overlays)) {\n errors.push('overlays must be an array');\n }\n }\n if (!Array.isArray(m.music)) {\n errors.push('music must be an array');\n }\n if (!Array.isArray(m.sfx)) {\n errors.push('sfx must be an array');\n }\n\n // Bail early if arrays are missing — can't validate contents\n if (errors.length > 0) {\n return { valid: false, errors };\n }\n\n const dialog = (Array.isArray(m.dialog) ? m.dialog : []) as DialogBeat[];\n const music = m.music as MusicTrack[];\n const sfx = m.sfx as SfxPlacement[];\n const overlays = (Array.isArray(m.overlays) ? m.overlays : []) as TextOverlay[];\n\n // --- Shared helpers ---\n function checkFilePath(file: unknown, context: string): void {\n if (typeof file !== 'string' || file.length === 0) {\n errors.push(`${context}: file must be a non-empty string`);\n } else if (file.startsWith('/') || file.startsWith('\\\\')) {\n errors.push(`${context}: file must be a relative path, got \"${file}\"`);\n }\n }\n\n function checkVolume(vol: unknown, context: string, required: boolean): void {\n if (vol == null) {\n if (required) errors.push(`${context}: volume is required`);\n return;\n }\n if (typeof vol !== 'number' || vol < 0 || vol > 1) {\n errors.push(`${context}: volume must be 0-1, got ${JSON.stringify(vol)}`);\n }\n }\n\n function checkTimingWithin(startSec: unknown, durationSec: unknown, context: string): void {\n if (typeof startSec !== 'number' || startSec < 0) {\n errors.push(\n `${context}: startSec must be a non-negative number, got ${JSON.stringify(startSec)}`,\n );\n return;\n }\n if (typeof durationSec === 'number') {\n if (durationSec < 0) {\n errors.push(`${context}: durationSec must be non-negative, got ${durationSec}`);\n }\n // Only check bounds when totalDurationSec is known (v1 manifests)\n if (totalDur > 0 && startSec + durationSec > totalDur) {\n errors.push(\n `${context}: startSec (${startSec}) + durationSec (${durationSec}) = ${startSec + durationSec} exceeds totalDurationSec (${totalDur})`,\n );\n }\n }\n }\n\n // --- Dialog beats ---\n const ids = new Set<string>();\n for (let i = 0; i < dialog.length; i++) {\n const b = dialog[i];\n const ctx = `dialog[${i}] (${b.id ?? 'no id'})`;\n\n if (typeof b.id !== 'string' || b.id.length === 0) {\n errors.push(`${ctx}: id must be a non-empty string`);\n } else if (ids.has(b.id)) {\n errors.push(`${ctx}: duplicate id \"${b.id}\"`);\n } else {\n ids.add(b.id);\n }\n\n checkFilePath(b.file, ctx);\n\n if (typeof b.speaker !== 'string' || b.speaker.length === 0) {\n errors.push(`${ctx}: speaker must be a non-empty string`);\n }\n if (typeof b.text !== 'string') {\n errors.push(`${ctx}: text must be a string`);\n }\n if (typeof b.durationSec !== 'number' || b.durationSec <= 0) {\n errors.push(\n `${ctx}: durationSec must be a positive number, got ${JSON.stringify(b.durationSec)}`,\n );\n }\n\n checkTimingWithin(b.startSec, b.durationSec, ctx);\n checkVolume(b.volume, ctx, false);\n\n if (\n b.style !== undefined &&\n b.style !== 'quote' &&\n b.style !== 'narrator' &&\n b.style !== 'text-card'\n ) {\n errors.push(`${ctx}: style must be 'quote', 'narrator', or 'text-card', got \"${b.style}\"`);\n }\n }\n\n // --- Same-speaker overlap check ---\n const bySpeaker = new Map<string, DialogBeat[]>();\n for (const b of dialog) {\n if (typeof b.speaker !== 'string') continue;\n const list = bySpeaker.get(b.speaker) ?? [];\n list.push(b);\n bySpeaker.set(b.speaker, list);\n }\n for (const [speaker, beats] of bySpeaker) {\n const sorted = [...beats].sort((a, b) => a.startSec - b.startSec);\n for (let i = 1; i < sorted.length; i++) {\n const prev = sorted[i - 1];\n const curr = sorted[i];\n const prevEnd = prev.startSec + prev.durationSec;\n if (prevEnd > curr.startSec) {\n errors.push(\n `dialog overlap for speaker \"${speaker}\": \"${prev.id}\" ends at ${prevEnd}s but \"${curr.id}\" starts at ${curr.startSec}s`,\n );\n }\n }\n }\n\n // --- Music tracks ---\n for (let i = 0; i < music.length; i++) {\n const t = music[i];\n const ctx = `music[${i}] (${t.id ?? 'no id'})`;\n\n if (typeof t.id !== 'string' || t.id.length === 0) {\n errors.push(`${ctx}: id must be a non-empty string`);\n }\n checkFilePath(t.file, ctx);\n checkTimingWithin(t.startSec, t.durationSec, ctx);\n checkVolume(t.volume, ctx, true);\n\n if (t.fadeInSec != null && (typeof t.fadeInSec !== 'number' || t.fadeInSec < 0)) {\n errors.push(`${ctx}: fadeInSec must be a non-negative number`);\n }\n if (t.fadeOutSec != null && (typeof t.fadeOutSec !== 'number' || t.fadeOutSec < 0)) {\n errors.push(`${ctx}: fadeOutSec must be a non-negative number`);\n }\n if (t.duckTo != null) {\n if (typeof t.duckTo !== 'number' || t.duckTo < 0 || t.duckTo > 1) {\n errors.push(`${ctx}: duckTo must be 0-1, got ${JSON.stringify(t.duckTo)}`);\n }\n }\n }\n\n // --- SFX placements ---\n for (let i = 0; i < sfx.length; i++) {\n const s = sfx[i];\n const ctx = `sfx[${i}] (${s.id ?? 'no id'})`;\n\n if (typeof s.id !== 'string' || s.id.length === 0) {\n errors.push(`${ctx}: id must be a non-empty string`);\n }\n checkFilePath(s.file, ctx);\n if (typeof s.startSec !== 'number' || s.startSec < 0) {\n errors.push(\n `${ctx}: startSec must be a non-negative number, got ${JSON.stringify(s.startSec)}`,\n );\n }\n if (totalDur > 0 && s.startSec > totalDur) {\n errors.push(`${ctx}: startSec (${s.startSec}) exceeds totalDurationSec (${totalDur})`);\n }\n checkVolume(s.volume, ctx, false);\n }\n\n // --- Text overlays ---\n const validOverlayTypes = new Set(['title-card', 'speaker-label', 'data-accent', 'chapter']);\n const validPositions = new Set(['center', 'bottom-left', 'bottom-right', 'top']);\n for (let i = 0; i < overlays.length; i++) {\n const o = overlays[i];\n const ctx = `overlays[${i}] (${o.id ?? 'no id'})`;\n\n if (typeof o.id !== 'string' || o.id.length === 0) {\n errors.push(`${ctx}: id must be a non-empty string`);\n }\n if (!validOverlayTypes.has(o.type)) {\n errors.push(\n `${ctx}: type must be one of ${[...validOverlayTypes].join(', ')}, got \"${o.type}\"`,\n );\n }\n if (typeof o.text !== 'string' || o.text.length === 0) {\n errors.push(`${ctx}: text must be a non-empty string`);\n }\n if (typeof o.durationSec !== 'number' || o.durationSec <= 0) {\n errors.push(\n `${ctx}: durationSec must be a positive number, got ${JSON.stringify(o.durationSec)}`,\n );\n }\n checkTimingWithin(o.startSec, o.durationSec, ctx);\n\n if (o.style != null) {\n if (typeof o.style !== 'object') {\n errors.push(`${ctx}: style must be an object`);\n } else {\n if (\n o.style.fontSize != null &&\n (typeof o.style.fontSize !== 'number' || o.style.fontSize <= 0)\n ) {\n errors.push(`${ctx}: style.fontSize must be a positive number`);\n }\n if (o.style.color != null && typeof o.style.color !== 'string') {\n errors.push(`${ctx}: style.color must be a string`);\n }\n if (o.style.position != null && !validPositions.has(o.style.position)) {\n errors.push(\n `${ctx}: style.position must be one of ${[...validPositions].join(', ')}, got \"${o.style.position}\"`,\n );\n }\n if (\n o.style.typingSpeed !== undefined &&\n o.style.typingSpeed !== null &&\n (typeof o.style.typingSpeed !== 'number' || o.style.typingSpeed <= 0)\n ) {\n errors.push(`${ctx}: style.typingSpeed must be a positive number or null`);\n }\n }\n }\n }\n\n return { valid: errors.length === 0, errors };\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Compute total duration from manifest content.\n * Returns max(endTime) across all tracks + 2s padding.\n * Useful for agents building the manifest before totalDurationSec is known.\n */\nexport function computeTotalDuration(\n manifest: Pick<AudioManifest, 'dialog' | 'music' | 'sfx' | 'overlays'>,\n): number {\n let maxEnd = 0;\n\n for (const b of manifest.dialog) {\n maxEnd = Math.max(maxEnd, b.startSec + b.durationSec);\n }\n for (const t of manifest.music) {\n maxEnd = Math.max(maxEnd, t.startSec + t.durationSec);\n }\n for (const s of manifest.sfx) {\n // SFX don't have durationSec — use startSec only\n maxEnd = Math.max(maxEnd, s.startSec);\n }\n for (const o of manifest.overlays) {\n maxEnd = Math.max(maxEnd, o.startSec + o.durationSec);\n }\n\n return maxEnd + 2;\n}\n"]}
1
+ {"version":3,"sources":["../src/transform/transform-raw.ts","../src/transform/transform-curation.ts","../src/types/script.ts","../src/types/pacing.ts","../src/types/timing.ts","../src/audio/manifest.ts"],"names":["z"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Transform source data → RawData (Contract A).\n *\n * Pure function. Deterministic. No side effects.\n * Maps existing JSON files to the generic RawData contract.\n */\n\nimport type {\n RawAgent,\n RawArtifact,\n RawCommit,\n RawData,\n RawMessage,\n RawPR,\n} from '../types/raw-data.js';\nimport type {\n SourceArtifactData,\n SourceBeamEvent,\n SourceCommit,\n SourceMessage,\n SourceMessageEvent,\n SourcePR,\n SourcePRAgentMap,\n SourceRetroPageData,\n SourceTimelineEvents,\n TransformSources,\n} from './source-types.js';\n\n/**\n * Infer a RawAgent role from a freeform role string (e.g. from teamAssembly).\n *\n * Checks for known keywords in the string (case-insensitive).\n * Order matters — more specific matches first (e.g. \"eng-lead\" matches \"lead\").\n * Falls back to 'builder' as the safest default (most common role).\n */\nexport function inferRole(roleString: string): RawAgent['role'] {\n const s = roleString.toLowerCase();\n if (s.includes('human') || s === 'user') return 'human';\n if (s.includes('lead')) return 'lead';\n if (s.includes('pm')) return 'pm';\n if (s.includes('tester') || s.includes('qa')) return 'tester';\n if (s.includes('reviewer') || s.includes('review')) return 'reviewer';\n if (s.includes('auditor') || s.includes('audit')) return 'auditor';\n if (s.includes('challenger') || s.includes('challenge')) return 'challenger';\n if (s.includes('scout')) return 'scout';\n if (s.includes('ideation')) return 'ideation';\n if (s.includes('research')) return 'researcher';\n if (s.includes('builder') || s.includes('build')) return 'builder';\n return 'builder'; // safe default — most common role\n}\n\n/**\n * Transform all source data into RawData.\n * This is the main entry point for the extraction layer.\n */\nexport function transformToRawData(sources: TransformSources): RawData {\n // First agent from teamAssembly is the default for unattributed items\n const defaultAgent = sources.retroPageData.teamAssembly[0]?.agent.replace('@', '') ?? 'unknown';\n\n return {\n project: {\n name: sources.retroPageData.meta.title,\n description: sources.retroPageData.meta.subtitle,\n },\n agents: transformAgents(\n sources.retroPageData,\n sources.chatActivity.agentTotals,\n sources.timelineEvents,\n undefined,\n sources.messages,\n ),\n commits: transformCommits(sources.commits, sources.prAgentMap, defaultAgent),\n prs: transformPRs(sources.prs, sources.prAgentMap),\n messages: transformMessages(sources.timelineEvents, sources.messages),\n artifacts: sources.artifactData\n ? transformArtifacts(\n sources.artifactData,\n sources.retroPageData,\n sources.prs,\n sources.prAgentMap,\n )\n : [],\n };\n}\n\n/**\n * Build a map of agent → earliest message timestamp from timeline events.\n * Only counts messages where the agent is the sender (not just mentioned).\n */\nfunction buildFirstMessageTimeMap(timelineEvents?: SourceTimelineEvents): Map<string, number> {\n const map = new Map<string, number>();\n if (!timelineEvents) return map;\n\n for (const evt of timelineEvents.events) {\n if (evt.type !== 'message' && evt.type !== 'beam') continue;\n const sender = (evt as SourceMessageEvent | SourceBeamEvent).from;\n const ts = new Date(evt.t).getTime();\n const existing = map.get(sender);\n if (existing === undefined || ts < existing) {\n map.set(sender, ts);\n }\n }\n\n return map;\n}\n\n/**\n * Build RawAgent[] from team assembly data + chat activity.\n *\n * joinedAt resolution priority:\n * 1. First message timestamp from timeline events (most accurate)\n * 2. teamAssembly join time (curated/scaffold fallback)\n * 3. Project start date (last resort)\n *\n * Role resolution priority:\n * 1. Explicit `agentRoles` override (if provided)\n * 2. Inferred from teamAssembly `role` field (e.g. \"eng-lead\" → \"lead\")\n * 3. Default: 'builder' (most common role, safe fallback)\n *\n * Never throws on unknown agents — always infers or defaults.\n */\nexport function transformAgents(\n retroData: SourceRetroPageData,\n agentTotals: Record<string, number>,\n timelineEvents?: SourceTimelineEvents,\n agentRoles?: Record<string, string>,\n messages?: SourceMessage[],\n): RawAgent[] {\n const agents: RawAgent[] = [];\n const seen = new Set<string>();\n\n // Build first-message-time lookup from timeline events\n const firstMessageTime = buildFirstMessageTimeMap(timelineEvents);\n\n // Build a lookup from teamAssembly role fields for agents not in override\n const assemblyRoles = new Map<string, string>();\n for (const entry of retroData.teamAssembly) {\n const id = entry.agent.replace('@', '');\n assemblyRoles.set(id, entry.role);\n }\n\n /** Resolve role for an agent: override → teamAssembly inference → default */\n function resolveRole(id: string): RawAgent['role'] {\n // 1. Explicit override\n if (agentRoles?.[id]) {\n return inferRole(agentRoles[id]);\n }\n // 2. Infer from teamAssembly role field\n const assemblyRole = assemblyRoles.get(id);\n if (assemblyRole) {\n return inferRole(assemblyRole);\n }\n // 3. Default\n return 'builder';\n }\n\n /** Resolve joinedAt: earliest of (first message, teamAssembly time), or startDate */\n function resolveJoinedAt(id: string, assemblyTime?: number): number {\n const msgTime = firstMessageTime.get(id);\n // Use earliest available timestamp — agent was present from whichever came first\n if (msgTime !== undefined && assemblyTime !== undefined) {\n return Math.min(msgTime, assemblyTime);\n }\n if (msgTime !== undefined) return msgTime;\n if (assemblyTime !== undefined) return assemblyTime;\n // Last resort: project start date\n return new Date(retroData.meta.startDate).getTime();\n }\n\n // Primary source: team assembly (has join times)\n for (const entry of retroData.teamAssembly) {\n const id = entry.agent.replace('@', '');\n if (seen.has(id)) continue;\n seen.add(id);\n\n agents.push({\n id,\n role: resolveRole(id),\n joinedAt: resolveJoinedAt(id, new Date(entry.time).getTime()),\n });\n }\n\n // Catch any agents in chat activity not in team assembly\n for (const id of Object.keys(agentTotals)) {\n if (seen.has(id)) continue;\n agents.push({\n id,\n role: resolveRole(id),\n joinedAt: resolveJoinedAt(id),\n });\n seen.add(id);\n }\n\n // Detect human users from message senderType.\n // Two phases: (1) add unseen human senders, (2) upgrade already-seen\n // agents to role: 'human'. Phase 2 is needed because users like @snorre\n // appear in agentTotals (they send messages) and get role: 'builder'\n // before the senderType check — see PR #640 review by @check.\n if (messages) {\n const humanSenders = new Set<string>();\n for (const msg of messages) {\n if (msg.senderType === 'user') humanSenders.add(msg.sender);\n }\n\n // Phase 1: add unseen human senders\n for (const id of humanSenders) {\n if (!seen.has(id)) {\n seen.add(id);\n agents.push({\n id,\n role: 'human',\n joinedAt: resolveJoinedAt(id),\n });\n }\n }\n\n // Phase 2: upgrade already-seen agents to human\n for (const agent of agents) {\n if (humanSenders.has(agent.id)) {\n agent.role = 'human';\n }\n }\n }\n\n return agents;\n}\n\n/**\n * Transform git commits → RawCommit[].\n * Cross-references pr-agent-map for attribution.\n *\n * @param defaultAgent - Fallback agent for commits with no PR reference\n * (typically the first agent from teamAssembly/roster)\n */\nexport function transformCommits(\n commits: SourceCommit[],\n prAgentMap: SourcePRAgentMap,\n defaultAgent = 'unknown',\n): RawCommit[] {\n return commits.map((c) => {\n const agent = resolveCommitAgent(c, prAgentMap, defaultAgent);\n\n return {\n sha: c.hash,\n timestamp: new Date(c.date).getTime(),\n agent,\n message: c.subject,\n filesChanged: c.files.length,\n insertions: c.totalInsertions,\n deletions: c.totalDeletions,\n prNumber: c.prNumber ?? undefined,\n };\n });\n}\n\n/**\n * Resolve which agent authored a commit.\n * Strategy chain:\n * 1. prNumber field → pr-agent-map lookup\n * 2. \"Merge pull request #N\" in subject → pr-agent-map lookup\n * 3. \"(#N)\" suffix in subject → pr-agent-map lookup\n * 4. Fallback to defaultAgent (first agent from roster/teamAssembly)\n */\nexport function resolveCommitAgent(\n commit: SourceCommit,\n prAgentMap: SourcePRAgentMap,\n defaultAgent = 'unknown',\n): string {\n // Strategy 1: direct prNumber field\n if (commit.prNumber != null) {\n const agent = prAgentMap[String(commit.prNumber)];\n if (agent) return agent;\n }\n\n // Strategy 2: \"Merge pull request #N\" pattern\n const mergeMatch = commit.subject.match(/^Merge pull request #(\\d+)/);\n if (mergeMatch) {\n const agent = prAgentMap[mergeMatch[1]];\n if (agent) return agent;\n }\n\n // Strategy 3: \"(#N)\" suffix pattern\n const suffixMatch = commit.subject.match(/\\(#(\\d+)\\)\\s*$/);\n if (suffixMatch) {\n const agent = prAgentMap[suffixMatch[1]];\n if (agent) return agent;\n }\n\n // Fallback: first agent from roster (caller provides)\n return defaultAgent;\n}\n\n/**\n * Transform PR details → RawPR[].\n * Cross-references pr-agent-map for attribution.\n */\nexport function transformPRs(prs: SourcePR[], prAgentMap: SourcePRAgentMap): RawPR[] {\n return prs.map((pr) => {\n const agent = prAgentMap[String(pr.number)] ?? 'unknown';\n\n return {\n number: pr.number,\n title: pr.title,\n agent,\n createdAt: new Date(pr.createdAt).getTime(),\n mergedAt: pr.mergedAt ? new Date(pr.mergedAt).getTime() : null,\n additions: pr.additions,\n deletions: pr.deletions,\n branch: pr.headRefName,\n };\n });\n}\n\n/**\n * Infer artifact type from slug or file path.\n *\n * Handles both platforms:\n * - Redux: file paths with extensions (\"/specs/auth.md\", \"plan/task-X1Y2\")\n * - Cast: artifact slugs (\"spec-auth\", \"screenshot-login\", \"qa-review\")\n *\n * Redux patterns are checked first (more specific), cast patterns as fallback.\n */\nexport function inferArtifactType(slug: string): RawArtifact['type'] {\n // --- Redux: plan item prefixes ---\n if (slug.startsWith('plan/task-')) return 'task';\n if (slug.startsWith('plan/spec-')) return 'doc';\n\n // --- Extension-based (works for both platforms, but primarily redux file paths) ---\n const ext = slug.split('.').pop()?.toLowerCase();\n if (ext && ['ts', 'tsx', 'js', 'jsx', 'py', 'rs', 'go', 'sh'].includes(ext)) return 'code';\n if (ext && ['png', 'jpg', 'jpeg', 'svg', 'gif', 'webp', 'ico'].includes(ext)) return 'asset';\n if (ext && ['md', 'txt', 'json', 'yaml', 'yml', 'toml'].includes(ext)) return 'doc';\n\n // --- Redux: path-based patterns ---\n if (slug.includes('/specs/') || slug.includes('/spec/')) return 'doc';\n if (slug.includes('/assets/') || slug.includes('/images/')) return 'asset';\n\n // --- Cast: existing slug patterns (backward compat) ---\n if (slug.includes('.app.')) return 'code';\n if (slug.includes('screenshot') || slug.includes('qa-')) return 'asset';\n if (slug.includes('decision')) return 'decision';\n if (slug.includes('task') || slug.includes('phase-')) return 'task';\n if (slug.startsWith('spec-') || slug.startsWith('spec')) return 'doc';\n if (slug.includes('concept')) return 'doc';\n\n return 'doc';\n}\n\n/**\n * Resolve artifact agent from source data.\n *\n * Priority:\n * 1. Explicit `createdBy` from the artifact record (Miriad API provides this)\n * 2. PR number in slug → pr-agent-map lookup\n * 3. Configurable default (first agent from roster, typically the lead)\n */\nexport function resolveArtifactAgent(\n slug: string,\n prAgentMap: SourcePRAgentMap,\n createdBy: string | undefined,\n defaultAgent: string,\n): string {\n // 1. Explicit creator from source data\n if (createdBy) return createdBy;\n\n // 2. PR reference in slug → agent map\n const prMatch = slug.match(/#?(\\d+)/);\n if (prMatch) {\n const agent = prAgentMap[prMatch[1]];\n if (agent) return agent;\n }\n\n // 3. Default (first agent from roster)\n return defaultAgent;\n}\n\n/** Category name → artifact type */\nconst CATEGORY_TYPE_MAP: Record<string, RawArtifact['type']> = {\n qaScreenshots: 'asset',\n transitionSpecs: 'doc',\n transitionConcepts: 'doc',\n scenes: 'doc',\n vizConcepts: 'code',\n teamPrinciples: 'doc',\n retroData: 'doc',\n decisions: 'decision',\n};\n\n/**\n * Distribute N artifacts within time boundaries, clustered around\n * PR timestamps when available for realistic density.\n */\nexport function distributeTimestamps(\n count: number,\n bounds: { start: number; end: number },\n prTimestamps: number[],\n): number[] {\n const phasePRTimes = prTimestamps.filter((t) => t >= bounds.start && t <= bounds.end);\n const timestamps: number[] = [];\n\n for (let i = 0; i < count; i++) {\n let timestamp: number;\n if (phasePRTimes.length > 0) {\n const prIdx = i % phasePRTimes.length;\n timestamp = phasePRTimes[prIdx] + i * 60000;\n } else {\n const fraction = count > 1 ? i / (count - 1) : 0.5;\n timestamp = bounds.start + fraction * (bounds.end - bounds.start);\n }\n timestamps.push(Math.round(Math.max(bounds.start, Math.min(bounds.end, timestamp))));\n }\n\n return timestamps;\n}\n\n/**\n * Build a type distribution from category data.\n *\n * Each category maps to a type. We build a weighted list so bulk\n * artifacts can be assigned types proportional to category counts.\n * Returns entries sorted by count descending for deterministic assignment.\n *\n * Agent assignment is NOT done here — it's handled by the caller using\n * round-robin over the known agent list (from teamAssembly).\n */\nexport function buildCategoryDistribution(\n categories: SourceArtifactData['categories'],\n): Array<{ type: RawArtifact['type']; weight: number }> {\n const entries: Array<{ type: RawArtifact['type']; count: number }> = [];\n let total = 0;\n\n for (const [categoryName, categoryData] of Object.entries(categories)) {\n if (categoryData.count === 0) continue;\n entries.push({\n type: CATEGORY_TYPE_MAP[categoryName] ?? 'doc',\n count: categoryData.count,\n });\n total += categoryData.count;\n }\n\n if (total === 0) return [{ type: 'doc', weight: 1 }];\n\n return entries\n .sort((a, b) => b.count - a.count)\n .map((e) => ({ type: e.type, weight: e.count / total }));\n}\n\n/**\n * Build a slug → createdBy lookup from SourceArtifactData category items.\n * Items can be plain strings (no creator info) or objects with optional createdBy.\n */\nfunction buildCreatedByLookup(categories: SourceArtifactData['categories']): Map<string, string> {\n const lookup = new Map<string, string>();\n for (const categoryData of Object.values(categories)) {\n for (const item of categoryData.items ?? []) {\n if (typeof item === 'object' && item.createdBy) {\n lookup.set(item.slug, item.createdBy);\n }\n }\n }\n return lookup;\n}\n\n/**\n * Transform artifact-data.json → RawArtifact[].\n *\n * Uses phase `count` fields for correct per-phase density. Each phase\n * specifies how many artifacts were created during that time window:\n * Phase 1: 5, Phase 2: 45, Phase 3: 80, Phase 4: 120, Phase 5: 60 = 310\n *\n * Within each phase:\n * 1. Curated slugs get their own entries with createdBy from source data\n * 2. Remaining count filled with generated artifacts using category\n * type proportions and round-robin agent assignment\n * 3. All timestamps distributed within phase boundaries, clustered\n * around PR activity\n */\nexport function transformArtifacts(\n artifactData: SourceArtifactData,\n retroData: SourceRetroPageData,\n prs: SourcePR[],\n prAgentMap: SourcePRAgentMap,\n): RawArtifact[] {\n const artifacts: RawArtifact[] = [];\n\n // Build agent list from teamAssembly for round-robin and default\n const agentIds = retroData.teamAssembly.map((e) => e.agent.replace('@', ''));\n const defaultAgent = agentIds[0] ?? 'unknown';\n\n const phaseBoundaries = retroData.phases.map((p) => ({\n start: new Date(p.start).getTime(),\n end: new Date(p.end).getTime(),\n }));\n\n const prTimestamps = prs.map((pr) => new Date(pr.createdAt).getTime()).sort((a, b) => a - b);\n const distribution = buildCategoryDistribution(artifactData.categories);\n const createdByLookup = buildCreatedByLookup(artifactData.categories);\n\n let phaseIndex = 0;\n let globalBulkIndex = 0;\n\n for (const [_phaseName, phaseData] of Object.entries(artifactData.phases)) {\n if (phaseIndex >= phaseBoundaries.length) break;\n const bounds = phaseBoundaries[phaseIndex];\n phaseIndex++;\n\n const totalCount = phaseData.count;\n const slugs = phaseData.artifacts;\n const bulkCount = Math.max(0, totalCount - slugs.length);\n\n // All artifacts in this phase share one timestamp distribution\n const timestamps = distributeTimestamps(totalCount, bounds, prTimestamps);\n\n // ── Curated slugs first ──────────────────────────────────────────────\n let tsIdx = 0;\n for (const slug of slugs) {\n artifacts.push({\n slug,\n type: inferArtifactType(slug),\n createdAt: timestamps[tsIdx],\n updatedAt: timestamps[tsIdx],\n agent: resolveArtifactAgent(slug, prAgentMap, createdByLookup.get(slug), defaultAgent),\n });\n tsIdx++;\n }\n\n // ── Bulk artifacts fill remaining count ───────────────────────────────\n // Assign type by walking through the weighted distribution.\n // Assign agent by round-robin over the known agent list.\n let distIdx = 0;\n let distBudget = Math.round(distribution[0].weight * bulkCount);\n\n for (let i = 0; i < bulkCount; i++) {\n // Advance to next distribution bucket when current is exhausted\n while (distBudget <= 0 && distIdx < distribution.length - 1) {\n distIdx++;\n distBudget = Math.round(distribution[distIdx].weight * bulkCount);\n }\n distBudget--;\n\n const entry = distribution[distIdx];\n // Round-robin agent assignment across the roster\n const agent =\n agentIds.length > 0 ? agentIds[globalBulkIndex % agentIds.length] : defaultAgent;\n artifacts.push({\n slug: `phase${phaseIndex}-${entry.type}-${String(globalBulkIndex + 1).padStart(3, '0')}`,\n type: entry.type,\n createdAt: timestamps[tsIdx],\n updatedAt: timestamps[tsIdx],\n agent,\n });\n tsIdx++;\n globalBulkIndex++;\n }\n }\n\n artifacts.sort((a, b) => a.createdAt - b.createdAt);\n\n return artifacts;\n}\n\n/**\n * Transform curated timeline events into chat pills for the viewer.\n *\n * Chat pills come ONLY from timeline-events.json (curated).\n * Raw messages (messages-viz.json) are NEVER a source for chat pills —\n * they exist only for the agent to read during curation and for the\n * density table's \"Msgs\" column.\n *\n * Single source of truth: the curated file.\n */\nexport function transformMessages(\n timelineEvents: SourceTimelineEvents,\n rawMessages?: SourceMessage[],\n): RawMessage[] {\n // Curated events (timeline-events.json) → chat pills (labeled bubbles)\n const curatedMessages = timelineEvents.events\n .filter(\n (e): e is SourceMessageEvent | SourceBeamEvent => e.type === 'message' || e.type === 'beam',\n )\n .map((evt, i) => ({\n id: `curated-${String(i).padStart(4, '0')}`,\n timestamp: new Date(evt.t).getTime(),\n sender: evt.from,\n mentions: [evt.to],\n }));\n\n // Raw messages (messages-viz.json / messages-full.json) → beam channels + particles\n const rawMsgs: RawMessage[] = (rawMessages ?? []).map((msg, i) => ({\n id: msg.id || `raw-${String(i).padStart(4, '0')}`,\n timestamp: new Date(msg.timestamp).getTime(),\n sender: msg.sender,\n mentions: msg.mentions,\n }));\n\n // Merge: raw messages provide beam/particle density, curated provide labeled pills.\n // Deduplicate by timestamp+sender to avoid double-counting when a raw message\n // was also curated as a chat pill.\n const seen = new Set(rawMsgs.map((m) => `${m.timestamp}:${m.sender}`));\n const uniqueCurated = curatedMessages.filter((m) => !seen.has(`${m.timestamp}:${m.sender}`));\n\n return [...rawMsgs, ...uniqueCurated];\n}\n","/**\n * Transform source data → CurationData (editorial content).\n *\n * Pure function. Deterministic. No side effects.\n * Maps curated board artifacts to the CurationData contract.\n */\n\nimport type {\n CurationData,\n CurationMilestone,\n CurationNarrationEntry,\n CurationPhase,\n CurationQuote,\n CurationTrustKeyframe,\n} from '../types/raw-data.js';\nimport type {\n SourceRetroPageData,\n SourceRetroPageQuotes,\n TransformSources,\n} from './source-types.js';\n\n/**\n * Transform curated source data into CurationData.\n * This is the main entry point for the curation layer.\n */\nexport function transformToCurationData(sources: TransformSources): CurationData {\n const narration = transformNarration(sources.retroPageData);\n const meta = sources.retroPageData.meta;\n\n // Thread curated timeline bounds from meta.startDate/endDate\n const curatedStartMs = meta?.startDate ? new Date(meta.startDate).getTime() : undefined;\n const curatedEndMs = meta?.endDate ? new Date(meta.endDate).getTime() : undefined;\n\n return {\n phases: transformPhases(sources.retroPageData),\n quotes: transformQuotes(sources.retroPageData, sources.retroPageQuotes),\n milestones: transformMilestones(sources.retroPageData),\n trustKeyframes: transformTrustKeyframes(sources.retroPageData),\n ...(narration.length > 0 ? { editorialNarration: narration } : {}),\n ...(curatedStartMs && !Number.isNaN(curatedStartMs) ? { curatedStartMs } : {}),\n ...(curatedEndMs && !Number.isNaN(curatedEndMs) ? { curatedEndMs } : {}),\n };\n}\n\n/**\n * Transform phase definitions from retro-page-data.\n * Phases have hand-curated boundaries, names, and descriptions.\n */\nexport function transformPhases(retroData: SourceRetroPageData): CurationPhase[] {\n return retroData.phases.map((p) => ({\n id: p.id,\n name: p.name || p.label || '',\n startTime: new Date(p.start || p.startTime || '').getTime(),\n endTime: new Date(p.end || p.endTime || '').getTime(),\n }));\n}\n\n/**\n * Transform milestones from retro-page-data.\n * Each milestone is cross-referenced to its containing phase.\n */\nexport function transformMilestones(retroData: SourceRetroPageData): CurationMilestone[] {\n const phases = retroData.phases;\n\n return retroData.milestones.map((m) => {\n const milestoneTime = new Date(m.time).getTime();\n const phase = findPhaseForTimestamp(milestoneTime, phases);\n\n return {\n label: m.label,\n timestamp: milestoneTime,\n phase: phase?.id ?? 'unknown',\n };\n });\n}\n\n/**\n * Map mood category to mood string for quotes from retroPageData.\n */\nconst CATEGORY_MOOD: Record<string, string> = {\n theGood: 'good',\n theBad: 'bad',\n theUgly: 'angry',\n theFunny: 'good',\n};\n\n/**\n * Map mood category to mood string for quotes from retroPageQuotes.\n */\nconst ADDITION_MOOD: Record<string, string> = {\n good: 'good',\n bad: 'bad',\n ugly: 'angry',\n};\n\n/**\n * Transform quotes from both curated sources.\n * Merges retro-page-data quotes (theGood/theBad/theUgly/theFunny) with\n * retro-page-quotes additions (good/bad/ugly). Parses informal timestamps,\n * strips @ prefix from speakers, and cross-references to phases.\n * Sorted by timestamp.\n */\nexport function transformQuotes(\n retroData: SourceRetroPageData,\n retroQuotes: SourceRetroPageQuotes,\n): CurationQuote[] {\n const phases = retroData.phases;\n const quotes: CurationQuote[] = [];\n\n // Derive reference year from first phase start date (for informal timestamp parsing)\n const firstPhaseStart = phases[0]?.start;\n const referenceYear = firstPhaseStart\n ? new Date(firstPhaseStart).getUTCFullYear()\n : new Date().getUTCFullYear();\n\n // Source 1: retroPageData.quotes (theGood, theBad, theUgly, theFunny)\n for (const [category, entries] of Object.entries(retroData.quotes)) {\n if (!Array.isArray(entries)) continue; // skip _comment and other non-quote fields\n const mood = CATEGORY_MOOD[category] ?? 'good';\n for (const entry of entries) {\n const timestamp = parseInformalTimestamp(entry.time, referenceYear);\n if (timestamp == null) continue;\n const phase = findPhaseForTimestamp(timestamp, phases);\n quotes.push({\n text: entry.text,\n speaker: entry.author.replace(/^@/, ''),\n timestamp,\n phase: phase?.id ?? 'unknown',\n mood,\n });\n }\n }\n\n // Source 2: retroPageQuotes (good, bad, ugly)\n for (const [category, entries] of Object.entries(retroQuotes)) {\n if (!Array.isArray(entries)) continue; // skip _comment and other non-quote fields\n const mood = ADDITION_MOOD[category] ?? 'good';\n for (const entry of entries) {\n const timestamp = parseInformalTimestamp(entry.timestamp, referenceYear);\n if (timestamp == null) continue;\n const phase = findPhaseForTimestamp(timestamp, phases);\n quotes.push({\n text: entry.text,\n speaker: entry.author.replace(/^@/, ''),\n timestamp,\n phase: phase?.id ?? 'unknown',\n mood,\n });\n }\n }\n\n // Sort chronologically\n quotes.sort((a, b) => a.timestamp - b.timestamp);\n return quotes;\n}\n\n/**\n * Transform trust arc keyframes from retro-page-data.\n * Source levels are 0-100 integers; we normalize to 0-1.\n * Sorted by timestamp for interpolation.\n */\nexport function transformTrustKeyframes(retroData: SourceRetroPageData): CurationTrustKeyframe[] {\n if (!retroData.trustArc || retroData.trustArc.length === 0) return [];\n\n return retroData.trustArc\n .map((entry) => ({\n timestamp: new Date(entry.time).getTime(),\n level: entry.level / 100, // normalize 0-100 → 0-1\n label: entry.label,\n }))\n .sort((a, b) => a.timestamp - b.timestamp);\n}\n\n/** Month abbreviation → 0-based index */\nconst MONTH_ABBREVS: Record<string, number> = {\n jan: 0,\n feb: 1,\n mar: 2,\n apr: 3,\n may: 4,\n jun: 5,\n jul: 6,\n aug: 7,\n sep: 8,\n oct: 9,\n nov: 10,\n dec: 11,\n};\n\n/**\n * Transform editorial narration entries from retro-page-data.\n * Each entry has an ISO timestamp, phase title, color, text, and type.\n * Returns empty array if no narration is present in the source data.\n */\nexport function transformNarration(retroData: SourceRetroPageData): CurationNarrationEntry[] {\n if (!retroData.editorialNarration || retroData.editorialNarration.length === 0) return [];\n\n return retroData.editorialNarration\n .map((entry) => ({\n timestamp: new Date(entry.time).getTime(),\n phaseTitle: entry.phaseTitle,\n phaseColor: entry.phaseColor,\n text: entry.text,\n type: entry.type,\n }))\n .sort((a, b) => a.timestamp - b.timestamp);\n}\n\n/**\n * Parse informal timestamp strings like \"Feb 10 21:18\", \"Dec 31 (early)\", \"Jan 2 ~23:00\".\n * Accepts any 3-letter month abbreviation.\n *\n * @param timeStr - Informal timestamp (e.g., \"Feb 10 21:18\", \"Dec 31\")\n * @param referenceYear - Year to use (e.g., 2025). Required — no hardcoded default.\n * For projects spanning Dec→Jan, callers should handle year rollover.\n * @returns Unix ms or null if unparseable.\n */\nexport function parseInformalTimestamp(\n timeStr: string | undefined | null,\n referenceYear: number,\n): number | null {\n if (!timeStr) return null;\n\n // Try ISO 8601 first (scaffold generates ISO timestamps)\n const isoDate = new Date(timeStr);\n if (!Number.isNaN(isoDate.getTime()) && timeStr.includes('-')) {\n return isoDate.getTime();\n }\n\n // Strip tildes and parenthetical notes\n const cleaned = timeStr\n .replace(/~/g, '')\n .replace(/\\(.*?\\)/g, '')\n .trim();\n\n // Match \"Mon DD HH:MM\" or \"Mon DD\" (3-letter month abbreviation)\n const match = cleaned.match(/([A-Za-z]{3})\\s+(\\d{1,2})(?:\\s+(\\d{1,2}):(\\d{2}))?/);\n if (!match) return null;\n\n const monthIdx = MONTH_ABBREVS[match[1].toLowerCase()];\n if (monthIdx === undefined) return null;\n\n const day = Number.parseInt(match[2], 10);\n const hour = match[3] ? Number.parseInt(match[3], 10) : 12; // default to noon if no time\n const minute = match[4] ? Number.parseInt(match[4], 10) : 0;\n\n const date = new Date(Date.UTC(referenceYear, monthIdx, day, hour, minute, 0));\n return date.getTime();\n}\n\n/**\n * Find which phase a timestamp falls within.\n * First tries exact range match. If no phase contains the timestamp\n * (e.g., it falls in a gap between phases), falls back to the nearest\n * phase by distance to its start/end boundaries.\n *\n * Returns undefined only when phases array is empty.\n */\nexport function findPhaseForTimestamp(\n timestamp: number,\n phases: SourceRetroPageData['phases'],\n): SourceRetroPageData['phases'][number] | undefined {\n if (phases.length === 0) return undefined;\n\n // Try exact range match first\n const exact = phases.find((p) => {\n const start = new Date(p.start || p.startTime || '').getTime();\n const end = new Date(p.end || p.endTime || '').getTime();\n return timestamp >= start && timestamp <= end;\n });\n if (exact) return exact;\n\n // Fallback: find nearest phase by distance to boundaries\n let nearest: SourceRetroPageData['phases'][number] | undefined;\n let minDistance = Number.POSITIVE_INFINITY;\n\n for (const p of phases) {\n const start = new Date(p.start || p.startTime || '').getTime();\n const end = new Date(p.end || p.endTime || '').getTime();\n const distance = Math.min(Math.abs(timestamp - start), Math.abs(timestamp - end));\n if (distance < minDistance) {\n minDistance = distance;\n nearest = p;\n }\n }\n\n return nearest;\n}\n","/**\n * ScriptFile — the authoring contract for Step 2 (Script Writing).\n *\n * WHY: The script is the creative foundation. An agent writes this file\n * to define the narrative structure: who speaks, what they say, and in\n * what style. Every downstream file (pacing, timing) derives from this.\n *\n * The agent creates this from scratch in Step 2, guided by extracted data\n * (event density, agent activity, phases). The human reviews and approves.\n */\n\nimport { z } from 'zod';\n\n// --- Zod schemas (source of truth) ---\n\nexport const ScriptLineSchema = z.object({\n /** Unique identifier for this line (e.g., 'narrator-01', 'lead-03') */\n id: z.string().min(1),\n /** Who speaks this line (e.g., 'narrator', 'lead', 'snorre') */\n speaker: z.string().min(1),\n /** The spoken text */\n text: z.string().min(1),\n /** Rendering style: narrator voice (cursive) or agent quote (normal) */\n style: z.enum(['narrator', 'quote']),\n /** Optional phase this line belongs to (for grouping in the viz) */\n phaseId: z.string().optional(),\n});\n\nexport const ScriptFileSchema = z\n .object({\n /** Schema version — always 1 for now */\n version: z.literal(1),\n /** Ordered list of script lines */\n lines: z.array(ScriptLineSchema).min(1),\n })\n .superRefine((data, ctx) => {\n // Enforce unique line IDs\n const ids = new Set<string>();\n for (let i = 0; i < data.lines.length; i++) {\n const id = data.lines[i].id;\n if (ids.has(id)) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: `Duplicate line ID: \"${id}\" (line index ${i})`,\n path: ['lines', i, 'id'],\n });\n }\n ids.add(id);\n }\n });\n\n// --- TypeScript types (inferred from schemas) ---\n\nexport type ScriptLine = z.infer<typeof ScriptLineSchema>;\nexport type ScriptFile = z.infer<typeof ScriptFileSchema>;\n\n// --- Normalization ---\n\n/**\n * Auto-populate missing fields so a minimal script.json passes ScriptFileSchema.\n *\n * - If `version` is missing, defaults to `1`.\n * - If `style` is missing on a line, infers from speaker:\n * `speaker === 'narrator'` → `'narrator'`, otherwise → `'quote'`.\n *\n * Returns a new object (does not mutate the input).\n */\nexport function normalizeScript(raw: Record<string, unknown>): Record<string, unknown> {\n const out: Record<string, unknown> = { ...raw };\n\n if (out.version === undefined) {\n out.version = 1;\n }\n\n if (Array.isArray(out.lines)) {\n out.lines = (out.lines as Record<string, unknown>[]).map((line) => {\n if (line === null || typeof line !== 'object') return line;\n const l = { ...line };\n if (!l.style && typeof l.speaker === 'string') {\n l.style = l.speaker === 'narrator' ? 'narrator' : 'quote';\n }\n return l;\n });\n }\n\n return out;\n}\n","/**\n * PacingFile — the agent-facing timing contract for Step 4 (Viz Timing).\n *\n * WHY: The pacing file is what the agent edits to control how fast the viz\n * moves during each narration line. scaffold-pacing generates it from\n * script.json + audio clip durations. The agent then annotates 4 optional\n * fields per line: pauseAfter, vizSpeed, gapVizSpeed, note.\n *\n * Design: Approach A (Annotated Script) — mirrors the script with timing\n * annotations. Text + clip durations inline. Defaults handle 80% of lines.\n * No cascading edits (unlike start-time approaches).\n *\n * vizSpeed definition: multiplier on project-time-per-second.\n * 2.0 = viz moves 2x faster = LESS screen time for that period.\n * 0.5 = viz moves 2x slower = MORE screen time for that period.\n */\n\nimport { z } from 'zod';\n\n// --- Zod schemas (source of truth) ---\n\nexport const PacingLineSchema = z.object({\n /** Line ID — must match script.json line ID */\n id: z.string().min(1),\n /** Text from script (read-only, for context while editing pacing) */\n text: z.string().min(1),\n /** Audio clip duration in seconds (measured from file, read-only) */\n clipDuration: z.number().positive(),\n /** Silence after this line in seconds (overrides defaultPauseSec) */\n pauseAfter: z.number().nonnegative().optional(),\n /** Viz speed multiplier DURING this clip's audio. >1 = faster, <1 = slower */\n vizSpeed: z.number().positive().optional(),\n /** Viz speed multiplier DURING the pause after this clip (defaults to defaultVizSpeed) */\n gapVizSpeed: z.number().positive().optional(),\n /** Agent's reasoning for pacing choices (human reads during review) */\n note: z.string().optional(),\n});\n\nexport const PacingFileSchema = z\n .object({\n /** Schema version — always 1 for now */\n version: z.literal(1),\n /** Seconds of viz playback before first narration line */\n leadInSec: z.number().nonnegative().optional(),\n /** Seconds of viz playback after last narration line */\n tailOutSec: z.number().nonnegative().optional(),\n /** Default pause between lines in seconds (used when pauseAfter not set) */\n defaultPauseSec: z.number().nonnegative(),\n /** Default viz speed multiplier (used when vizSpeed/gapVizSpeed not set) */\n defaultVizSpeed: z.number().positive(),\n /** Ordered list of pacing lines — must match script.json order */\n lines: z.array(PacingLineSchema).min(1),\n })\n .superRefine((data, ctx) => {\n // Enforce unique line IDs\n const ids = new Set<string>();\n for (let i = 0; i < data.lines.length; i++) {\n const id = data.lines[i].id;\n if (ids.has(id)) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: `Duplicate line ID: \"${id}\" (line index ${i})`,\n path: ['lines', i, 'id'],\n });\n }\n ids.add(id);\n }\n });\n\n// --- TypeScript types (inferred from schemas) ---\n\nexport type PacingLine = z.infer<typeof PacingLineSchema>;\nexport type PacingFile = z.infer<typeof PacingFileSchema>;\n","/**\n * TimingFile — the engine-facing contract produced by generateTiming().\n *\n * WHY: This is the fully-resolved timing data that the transform layer reads\n * to produce narration entries with precise progress mapping. All fields are\n * required — no defaults, no optionals (except phase). generateTiming()\n * resolves all defaults from PacingFile and computes progress values.\n *\n * The transform layer validates this on read (belt-and-suspenders with\n * generateTiming's validation on write). If this file is corrupt, the\n * pipeline fails fast with a clear error.\n */\n\nimport { z } from 'zod';\n\n// --- Zod schemas (source of truth) ---\n\nexport const TimedLineSchema = z\n .object({\n /** Line ID — matches script.json and pacing.json */\n id: z.string().min(1),\n /** Speaker identifier (e.g., 'narrator', 'lead', 'snorre') */\n speaker: z.string().min(1),\n /** The spoken text */\n text: z.string().min(1),\n /** Rendering style: narrator voice (cursive) or agent quote (normal) */\n style: z.enum(['narrator', 'quote']),\n /** Wall-clock start time in seconds from video start */\n startSec: z.number().nonnegative(),\n /** Audio clip duration in seconds */\n durationSec: z.number().positive(),\n /** Pause after this line in seconds (resolved from defaults) */\n pauseAfterSec: z.number().nonnegative(),\n /** Audio file path relative to audio directory (e.g., 'narrator-01.mp3') */\n audioFile: z.string().min(1),\n /** Viz progress at clip start [0, 1] */\n progressStart: z.number().min(0).max(1),\n /** Viz progress at clip end [0, 1] */\n progressEnd: z.number().min(0).max(1),\n /** Viz speed multiplier during this clip */\n vizSpeed: z.number().positive(),\n /** Viz speed multiplier during the pause after this clip */\n gapVizSpeed: z.number().positive(),\n /** Phase this line belongs to (optional) */\n phase: z.string().optional(),\n })\n .refine((line) => line.progressStart <= line.progressEnd, {\n message: 'progressStart must be <= progressEnd',\n path: ['progressStart'],\n });\n\nexport const TimingFileSchema = z\n .object({\n /** Schema version — always 1 for now */\n version: z.literal(1),\n /** Total video duration in seconds */\n totalDurationSec: z.number().positive(),\n /** Ordered list of timed lines — fully resolved, all fields required */\n lines: z.array(TimedLineSchema).min(1),\n })\n .superRefine((data, ctx) => {\n // Enforce unique line IDs\n const ids = new Set<string>();\n for (let i = 0; i < data.lines.length; i++) {\n const id = data.lines[i].id;\n if (ids.has(id)) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: `Duplicate line ID: \"${id}\" (line index ${i})`,\n path: ['lines', i, 'id'],\n });\n }\n ids.add(id);\n }\n });\n\n// --- TypeScript types (inferred from schemas) ---\n\nexport type TimedLine = z.infer<typeof TimedLineSchema>;\nexport type TimingFile = z.infer<typeof TimingFileSchema>;\n","/**\n * Audio manifest schema — the contract between audio generation and Remotion consumption.\n * Lives at: remotion/public/audio/audio-manifest.json\n *\n * @module audio/manifest\n */\n\nimport type { TimedLine, TimingFile } from '../types/timing.js';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface AudioManifest {\n version: 1;\n fps: number;\n totalDurationSec: number;\n\n /** Per-beat voice clips */\n dialog: DialogBeat[];\n /** Background music tracks */\n music: MusicTrack[];\n /** One-shot sound effects */\n sfx: SfxPlacement[];\n /** Text overlays (title cards, labels, data accents) */\n overlays: TextOverlay[];\n}\n\n/**\n * v2 audio manifest — SFX + music only.\n * Dialog comes from timing.json (generated in Step 4).\n * No overlays section.\n */\nexport interface AudioManifestV2 {\n version: 2;\n /** Background music tracks */\n music: MusicTrack[];\n /** One-shot sound effects */\n sfx: SfxPlacement[];\n}\n\n/** Union of all manifest versions */\nexport type AudioManifestAny = AudioManifest | AudioManifestV2;\n\nexport interface DialogBeat {\n id: string;\n file: string;\n speaker: string;\n text: string;\n startSec: number;\n durationSec: number;\n volume?: number;\n style?: 'quote' | 'narrator' | 'text-card';\n}\n\nexport interface MusicTrack {\n id: string;\n file: string;\n startSec: number;\n durationSec: number;\n volume: number;\n fadeInSec?: number;\n fadeOutSec?: number;\n duckTo?: number;\n}\n\nexport interface SfxPlacement {\n id: string;\n file: string;\n startSec: number;\n volume?: number;\n note?: string;\n}\n\nexport interface TextOverlay {\n id: string;\n type: 'title-card' | 'speaker-label' | 'data-accent' | 'chapter';\n text: string;\n startSec: number;\n durationSec: number;\n style?: {\n fontSize?: number;\n color?: string;\n position?: 'center' | 'bottom-left' | 'bottom-right' | 'top';\n typingSpeed?: number | null;\n };\n}\n\n// ---------------------------------------------------------------------------\n// Validation\n// ---------------------------------------------------------------------------\n\nexport interface ValidationResult {\n valid: boolean;\n errors: string[];\n}\n\n/**\n * Validate an AudioManifest for structural correctness.\n *\n * Checks:\n * - Required top-level fields (version, fps, totalDurationSec)\n * - Dialog beats within totalDurationSec, no same-speaker overlap\n * - Music tracks within totalDurationSec, volume 0-1\n * - SFX placements within totalDurationSec\n * - Overlay timing within totalDurationSec\n * - File paths are relative strings (no absolute paths)\n * - Volume values in 0-1 range\n */\nexport function validateAudioManifest(manifest: unknown): ValidationResult {\n const errors: string[] = [];\n\n if (manifest == null || typeof manifest !== 'object') {\n return { valid: false, errors: ['Manifest must be a non-null object'] };\n }\n\n const m = manifest as Record<string, unknown>;\n\n // --- Required top-level fields ---\n const version = m.version;\n if (version !== 1 && version !== 2) {\n errors.push(`version must be 1 or 2, got ${JSON.stringify(version)}`);\n }\n\n // v1 requires fps and totalDurationSec; v2 does not\n if (version === 1) {\n if (typeof m.fps !== 'number' || m.fps <= 0) {\n errors.push(`fps must be a positive number, got ${JSON.stringify(m.fps)}`);\n }\n if (typeof m.totalDurationSec !== 'number' || m.totalDurationSec <= 0) {\n errors.push(\n `totalDurationSec must be a positive number, got ${JSON.stringify(m.totalDurationSec)}`,\n );\n }\n }\n\n const totalDur = typeof m.totalDurationSec === 'number' ? m.totalDurationSec : 0;\n\n // --- Arrays: v1 requires all four, v2 requires sfx + music only ---\n if (version === 1) {\n if (!Array.isArray(m.dialog)) {\n errors.push('dialog must be an array');\n }\n if (!Array.isArray(m.overlays)) {\n errors.push('overlays must be an array');\n }\n }\n if (!Array.isArray(m.music)) {\n errors.push('music must be an array');\n }\n if (!Array.isArray(m.sfx)) {\n errors.push('sfx must be an array');\n }\n\n // Bail early if arrays are missing — can't validate contents\n if (errors.length > 0) {\n return { valid: false, errors };\n }\n\n const dialog = (Array.isArray(m.dialog) ? m.dialog : []) as DialogBeat[];\n const music = m.music as MusicTrack[];\n const sfx = m.sfx as SfxPlacement[];\n const overlays = (Array.isArray(m.overlays) ? m.overlays : []) as TextOverlay[];\n\n // --- Shared helpers ---\n function checkFilePath(file: unknown, context: string): void {\n if (typeof file !== 'string' || file.length === 0) {\n errors.push(`${context}: file must be a non-empty string`);\n } else if (file.startsWith('/') || file.startsWith('\\\\')) {\n errors.push(`${context}: file must be a relative path, got \"${file}\"`);\n }\n }\n\n function checkVolume(vol: unknown, context: string, required: boolean): void {\n if (vol == null) {\n if (required) errors.push(`${context}: volume is required`);\n return;\n }\n if (typeof vol !== 'number' || vol < 0 || vol > 1) {\n errors.push(`${context}: volume must be 0-1, got ${JSON.stringify(vol)}`);\n }\n }\n\n function checkTimingWithin(startSec: unknown, durationSec: unknown, context: string): void {\n if (typeof startSec !== 'number' || startSec < 0) {\n errors.push(\n `${context}: startSec must be a non-negative number, got ${JSON.stringify(startSec)}`,\n );\n return;\n }\n if (typeof durationSec === 'number') {\n if (durationSec < 0) {\n errors.push(`${context}: durationSec must be non-negative, got ${durationSec}`);\n }\n // Only check bounds when totalDurationSec is known (v1 manifests)\n if (totalDur > 0 && startSec + durationSec > totalDur) {\n errors.push(\n `${context}: startSec (${startSec}) + durationSec (${durationSec}) = ${startSec + durationSec} exceeds totalDurationSec (${totalDur})`,\n );\n }\n }\n }\n\n // --- Dialog beats ---\n const ids = new Set<string>();\n for (let i = 0; i < dialog.length; i++) {\n const b = dialog[i];\n const ctx = `dialog[${i}] (${b.id ?? 'no id'})`;\n\n if (typeof b.id !== 'string' || b.id.length === 0) {\n errors.push(`${ctx}: id must be a non-empty string`);\n } else if (ids.has(b.id)) {\n errors.push(`${ctx}: duplicate id \"${b.id}\"`);\n } else {\n ids.add(b.id);\n }\n\n checkFilePath(b.file, ctx);\n\n if (typeof b.speaker !== 'string' || b.speaker.length === 0) {\n errors.push(`${ctx}: speaker must be a non-empty string`);\n }\n if (typeof b.text !== 'string') {\n errors.push(`${ctx}: text must be a string`);\n }\n if (typeof b.durationSec !== 'number' || b.durationSec <= 0) {\n errors.push(\n `${ctx}: durationSec must be a positive number, got ${JSON.stringify(b.durationSec)}`,\n );\n }\n\n checkTimingWithin(b.startSec, b.durationSec, ctx);\n checkVolume(b.volume, ctx, false);\n\n if (\n b.style !== undefined &&\n b.style !== 'quote' &&\n b.style !== 'narrator' &&\n b.style !== 'text-card'\n ) {\n errors.push(`${ctx}: style must be 'quote', 'narrator', or 'text-card', got \"${b.style}\"`);\n }\n }\n\n // --- Same-speaker overlap check ---\n const bySpeaker = new Map<string, DialogBeat[]>();\n for (const b of dialog) {\n if (typeof b.speaker !== 'string') continue;\n const list = bySpeaker.get(b.speaker) ?? [];\n list.push(b);\n bySpeaker.set(b.speaker, list);\n }\n for (const [speaker, beats] of bySpeaker) {\n const sorted = [...beats].sort((a, b) => a.startSec - b.startSec);\n for (let i = 1; i < sorted.length; i++) {\n const prev = sorted[i - 1];\n const curr = sorted[i];\n const prevEnd = prev.startSec + prev.durationSec;\n if (prevEnd > curr.startSec) {\n errors.push(\n `dialog overlap for speaker \"${speaker}\": \"${prev.id}\" ends at ${prevEnd}s but \"${curr.id}\" starts at ${curr.startSec}s`,\n );\n }\n }\n }\n\n // --- Music tracks ---\n for (let i = 0; i < music.length; i++) {\n const t = music[i];\n const ctx = `music[${i}] (${t.id ?? 'no id'})`;\n\n if (typeof t.id !== 'string' || t.id.length === 0) {\n errors.push(`${ctx}: id must be a non-empty string`);\n }\n checkFilePath(t.file, ctx);\n checkTimingWithin(t.startSec, t.durationSec, ctx);\n checkVolume(t.volume, ctx, true);\n\n if (t.fadeInSec != null && (typeof t.fadeInSec !== 'number' || t.fadeInSec < 0)) {\n errors.push(`${ctx}: fadeInSec must be a non-negative number`);\n }\n if (t.fadeOutSec != null && (typeof t.fadeOutSec !== 'number' || t.fadeOutSec < 0)) {\n errors.push(`${ctx}: fadeOutSec must be a non-negative number`);\n }\n if (t.duckTo != null) {\n if (typeof t.duckTo !== 'number' || t.duckTo < 0 || t.duckTo > 1) {\n errors.push(`${ctx}: duckTo must be 0-1, got ${JSON.stringify(t.duckTo)}`);\n }\n }\n }\n\n // --- SFX placements ---\n for (let i = 0; i < sfx.length; i++) {\n const s = sfx[i];\n const ctx = `sfx[${i}] (${s.id ?? 'no id'})`;\n\n if (typeof s.id !== 'string' || s.id.length === 0) {\n errors.push(`${ctx}: id must be a non-empty string`);\n }\n checkFilePath(s.file, ctx);\n if (typeof s.startSec !== 'number' || s.startSec < 0) {\n errors.push(\n `${ctx}: startSec must be a non-negative number, got ${JSON.stringify(s.startSec)}`,\n );\n }\n if (totalDur > 0 && s.startSec > totalDur) {\n errors.push(`${ctx}: startSec (${s.startSec}) exceeds totalDurationSec (${totalDur})`);\n }\n checkVolume(s.volume, ctx, false);\n }\n\n // --- Text overlays ---\n const validOverlayTypes = new Set(['title-card', 'speaker-label', 'data-accent', 'chapter']);\n const validPositions = new Set(['center', 'bottom-left', 'bottom-right', 'top']);\n for (let i = 0; i < overlays.length; i++) {\n const o = overlays[i];\n const ctx = `overlays[${i}] (${o.id ?? 'no id'})`;\n\n if (typeof o.id !== 'string' || o.id.length === 0) {\n errors.push(`${ctx}: id must be a non-empty string`);\n }\n if (!validOverlayTypes.has(o.type)) {\n errors.push(\n `${ctx}: type must be one of ${[...validOverlayTypes].join(', ')}, got \"${o.type}\"`,\n );\n }\n if (typeof o.text !== 'string' || o.text.length === 0) {\n errors.push(`${ctx}: text must be a non-empty string`);\n }\n if (typeof o.durationSec !== 'number' || o.durationSec <= 0) {\n errors.push(\n `${ctx}: durationSec must be a positive number, got ${JSON.stringify(o.durationSec)}`,\n );\n }\n checkTimingWithin(o.startSec, o.durationSec, ctx);\n\n if (o.style != null) {\n if (typeof o.style !== 'object') {\n errors.push(`${ctx}: style must be an object`);\n } else {\n if (\n o.style.fontSize != null &&\n (typeof o.style.fontSize !== 'number' || o.style.fontSize <= 0)\n ) {\n errors.push(`${ctx}: style.fontSize must be a positive number`);\n }\n if (o.style.color != null && typeof o.style.color !== 'string') {\n errors.push(`${ctx}: style.color must be a string`);\n }\n if (o.style.position != null && !validPositions.has(o.style.position)) {\n errors.push(\n `${ctx}: style.position must be one of ${[...validPositions].join(', ')}, got \"${o.style.position}\"`,\n );\n }\n if (\n o.style.typingSpeed !== undefined &&\n o.style.typingSpeed !== null &&\n (typeof o.style.typingSpeed !== 'number' || o.style.typingSpeed <= 0)\n ) {\n errors.push(`${ctx}: style.typingSpeed must be a positive number or null`);\n }\n }\n }\n }\n\n return { valid: errors.length === 0, errors };\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Compute total duration from manifest content.\n * Returns max(endTime) across all tracks + 2s padding.\n * Useful for agents building the manifest before totalDurationSec is known.\n */\nexport function computeTotalDuration(\n manifest: Pick<AudioManifest, 'dialog' | 'music' | 'sfx' | 'overlays'>,\n): number {\n let maxEnd = 0;\n\n for (const b of manifest.dialog) {\n maxEnd = Math.max(maxEnd, b.startSec + b.durationSec);\n }\n for (const t of manifest.music) {\n maxEnd = Math.max(maxEnd, t.startSec + t.durationSec);\n }\n for (const s of manifest.sfx) {\n // SFX don't have durationSec — use startSec only\n maxEnd = Math.max(maxEnd, s.startSec);\n }\n for (const o of manifest.overlays) {\n maxEnd = Math.max(maxEnd, o.startSec + o.durationSec);\n }\n\n return maxEnd + 2;\n}\n\n// ---------------------------------------------------------------------------\n// v2 → v1 manifest resolver (Bug #13: audio-narration sync)\n// ---------------------------------------------------------------------------\n\n/**\n * Raw SFX entry from the v2 sound design manifest.\n * May use `atLine` + `offsetSec` instead of absolute `startSec`.\n */\ninterface RawV2Sfx {\n id: string;\n file: string;\n startSec?: number;\n volume?: number;\n note?: string;\n /** Line ID reference — resolved to absolute startSec via timing.json */\n atLine?: string;\n /** Offset from the referenced line's startSec (default: 0) */\n offsetSec?: number;\n}\n\n/**\n * Raw music entry from the v2 sound design manifest.\n * May use `fromLine`/`toLine` instead of absolute `startSec`.\n */\ninterface RawV2Music {\n id: string;\n file: string;\n startSec: number;\n durationSec: number;\n volume: number;\n fadeInSec?: number;\n fadeOutSec?: number;\n duckTo?: number;\n /** Line ID reference — resolved to absolute startSec via timing.json */\n fromLine?: string;\n /** Line ID reference (informational — not used for timing resolution) */\n toLine?: string;\n}\n\n/** Raw v2 manifest input (may contain atLine/fromLine references) */\ninterface RawV2Manifest {\n version: 2;\n sfx: RawV2Sfx[];\n music: RawV2Music[];\n}\n\n/** Options for resolveAudioManifestForRemotion */\ninterface ResolveOptions {\n /** Frames per second (default: 30) */\n fps?: number;\n}\n\n/**\n * Resolve a v2 audio manifest + timing.json into a v1 AudioManifest for Remotion.\n *\n * 1. Builds dialog beats from timing.json lines (each line → DialogBeat)\n * 2. Resolves SFX `atLine` references to absolute `startSec` using timing.json\n * 3. Resolves music `fromLine` references to absolute `startSec` using timing.json\n * 4. Returns a complete v1 AudioManifest ready for Remotion consumption\n *\n * Pure function — no I/O.\n */\nexport function resolveAudioManifestForRemotion(\n v2: RawV2Manifest,\n timing: TimingFile,\n options?: ResolveOptions,\n): AudioManifest {\n const fps = options?.fps ?? 30;\n\n // Build a lookup map: line ID → TimedLine\n const lineById = new Map<string, TimedLine>();\n for (const line of timing.lines) {\n lineById.set(line.id, line);\n }\n\n // 1. Build dialog beats from timing.json lines\n const dialog: DialogBeat[] = timing.lines.map((line) => ({\n id: line.id,\n file: line.audioFile,\n speaker: line.speaker,\n text: line.text,\n startSec: line.startSec,\n durationSec: line.durationSec,\n style: line.style,\n }));\n\n // 2. Resolve SFX: atLine → absolute startSec\n const sfx: SfxPlacement[] = v2.sfx.map((raw) => {\n let startSec: number;\n\n if (raw.atLine != null) {\n const refLine = lineById.get(raw.atLine);\n if (refLine == null) {\n throw new Error(`SFX \"${raw.id}\": atLine \"${raw.atLine}\" not found in timing.json lines`);\n }\n startSec = refLine.startSec + (raw.offsetSec ?? 0);\n } else {\n startSec = raw.startSec ?? 0;\n }\n\n const resolved: SfxPlacement = {\n id: raw.id,\n file: raw.file,\n startSec,\n };\n if (raw.volume != null) resolved.volume = raw.volume;\n if (raw.note != null) resolved.note = raw.note;\n return resolved;\n });\n\n // 3. Resolve music: fromLine → absolute startSec\n const music: MusicTrack[] = v2.music.map((raw) => {\n let startSec: number;\n\n if (raw.fromLine != null) {\n const refLine = lineById.get(raw.fromLine);\n if (refLine == null) {\n throw new Error(\n `Music \"${raw.id}\": fromLine \"${raw.fromLine}\" not found in timing.json lines`,\n );\n }\n startSec = refLine.startSec;\n } else {\n startSec = raw.startSec;\n }\n\n const resolved: MusicTrack = {\n id: raw.id,\n file: raw.file,\n startSec,\n durationSec: raw.durationSec,\n volume: raw.volume,\n };\n if (raw.fadeInSec != null) resolved.fadeInSec = raw.fadeInSec;\n if (raw.fadeOutSec != null) resolved.fadeOutSec = raw.fadeOutSec;\n if (raw.duckTo != null) resolved.duckTo = raw.duckTo;\n return resolved;\n });\n\n // 4. Assemble v1 manifest\n return {\n version: 1,\n fps,\n totalDurationSec: timing.totalDurationSec,\n dialog,\n music,\n sfx,\n overlays: [],\n };\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "miriad-viz",
3
- "version": "0.13.13",
3
+ "version": "0.14.0",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/snorrees/miriad-viz.git"