miriad-viz 0.9.4 → 0.9.6

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.
@@ -28,7 +28,7 @@ function transformToRawData(sources) {
28
28
  ),
29
29
  commits: transformCommits(sources.commits, sources.prAgentMap, defaultAgent),
30
30
  prs: transformPRs(sources.prs, sources.prAgentMap),
31
- messages: transformMessages(sources.timelineEvents),
31
+ messages: transformMessages(sources.timelineEvents, sources.messages),
32
32
  artifacts: sources.artifactData ? transformArtifacts(
33
33
  sources.artifactData,
34
34
  sources.retroPageData,
@@ -280,16 +280,24 @@ function transformArtifacts(artifactData, retroData, prs, prAgentMap) {
280
280
  artifacts.sort((a, b) => a.createdAt - b.createdAt);
281
281
  return artifacts;
282
282
  }
283
- function transformMessages(timelineEvents) {
284
- const messageEvents = timelineEvents.events.filter(
283
+ function transformMessages(timelineEvents, rawMessages) {
284
+ const curatedMessages = timelineEvents.events.filter(
285
285
  (e) => e.type === "message" || e.type === "beam"
286
- );
287
- return messageEvents.map((evt, i) => ({
288
- id: `msg-${String(i).padStart(4, "0")}`,
286
+ ).map((evt, i) => ({
287
+ id: `curated-${String(i).padStart(4, "0")}`,
289
288
  timestamp: new Date(evt.t).getTime(),
290
289
  sender: evt.from,
291
290
  mentions: [evt.to]
292
291
  }));
292
+ const rawMsgs = (rawMessages ?? []).map((msg, i) => ({
293
+ id: msg.id || `raw-${String(i).padStart(4, "0")}`,
294
+ timestamp: new Date(msg.timestamp).getTime(),
295
+ sender: msg.sender,
296
+ mentions: msg.mentions
297
+ }));
298
+ const seen = new Set(rawMsgs.map((m) => `${m.timestamp}:${m.sender}`));
299
+ const uniqueCurated = curatedMessages.filter((m) => !seen.has(`${m.timestamp}:${m.sender}`));
300
+ return [...rawMsgs, ...uniqueCurated];
293
301
  }
294
302
 
295
303
  export {
@@ -4,7 +4,7 @@ import {
4
4
  } from "./chunk-CUDVVNEZ.js";
5
5
  import {
6
6
  inferRole
7
- } from "./chunk-WP7ZSXBZ.js";
7
+ } from "./chunk-JU7XARHL.js";
8
8
  import {
9
9
  markComplete,
10
10
  markInProgress,
package/dist-cli/index.js CHANGED
@@ -1425,6 +1425,7 @@ Options:
1425
1425
  --platform Platform target: 'cast' (old, default) or 'redux' (new) (for init)
1426
1426
  --pad-start <dur> Pad timeline before first event (e.g., 5s, 30s, 2m)
1427
1427
  --pad-end <dur> Pad timeline after last event (e.g., 5s, 30s, 2m)
1428
+ --no-trim Disable auto-trimming git/PR data to message window
1428
1429
  --draft Render at half resolution (for render)
1429
1430
  --skip-audio Skip audio step (render silent video)
1430
1431
  --audio-approved Mark audio as reviewed and approved
@@ -1769,24 +1770,25 @@ async function main() {
1769
1770
  await runExtract({
1770
1771
  projectDir,
1771
1772
  progress,
1772
- repoPath: typeof flags["repo-path"] === "string" ? flags["repo-path"] : void 0,
1773
+ repoPath: typeof flags["repo-path"] === "string" ? flags["repo-path"] : progress.extractConfig?.repoPath,
1773
1774
  chatInput: typeof flags["chat-input"] === "string" ? flags["chat-input"] : void 0,
1774
1775
  artifactInput: typeof flags["artifact-input"] === "string" ? flags["artifact-input"] : void 0,
1775
1776
  from: typeof flags.from === "string" ? flags.from : void 0,
1776
- to: typeof flags.to === "string" ? flags.to : void 0
1777
+ to: typeof flags.to === "string" ? flags.to : void 0,
1778
+ noTrim: flags["no-trim"] === true
1777
1779
  });
1778
1780
  break;
1779
1781
  }
1780
1782
  case "curate": {
1781
1783
  const { projectDir, progress } = requireProject();
1782
- const { runCurate } = await import("./curate-OPFP3APX.js");
1784
+ const { runCurate } = await import("./curate-5CHB2ERJ.js");
1783
1785
  await runCurate({ projectDir, progress });
1784
1786
  break;
1785
1787
  }
1786
1788
  case "transform": {
1787
1789
  const { projectDir, progress } = requireProject();
1788
1790
  const { parseDuration } = await import("./parse-duration-NVLCEFAF.js");
1789
- const { runTransform } = await import("./transform-3YUJZORK.js");
1791
+ const { runTransform } = await import("./transform-7KY5KAHZ.js");
1790
1792
  const padding = {};
1791
1793
  if (typeof flags["pad-start"] === "string") {
1792
1794
  padding.padStartMs = parseDuration(flags["pad-start"]);
@@ -1814,7 +1816,7 @@ async function main() {
1814
1816
  console.log("");
1815
1817
  console.log(chainResult.previewTable);
1816
1818
  }
1817
- const { runTransform } = await import("./transform-3YUJZORK.js");
1819
+ const { runTransform } = await import("./transform-7KY5KAHZ.js");
1818
1820
  await runTransform({ projectDir, progress });
1819
1821
  const { runPreview: runPreview2 } = await import("./preview-7AGBBMPI.js");
1820
1822
  await runPreview2({ projectDir, progress, port, noOpen: flags["no-open"] === true });
@@ -14,7 +14,7 @@ import {
14
14
  } from "./chunk-7BH6QQNB.js";
15
15
  import {
16
16
  transformToRawData
17
- } from "./chunk-WP7ZSXBZ.js";
17
+ } from "./chunk-JU7XARHL.js";
18
18
  import {
19
19
  markComplete,
20
20
  markError,
@@ -35,7 +35,7 @@ function transformToRawData(sources) {
35
35
  ),
36
36
  commits: transformCommits(sources.commits, sources.prAgentMap, defaultAgent),
37
37
  prs: transformPRs(sources.prs, sources.prAgentMap),
38
- messages: transformMessages(sources.timelineEvents),
38
+ messages: transformMessages(sources.timelineEvents, sources.messages),
39
39
  artifacts: sources.artifactData ? transformArtifacts(
40
40
  sources.artifactData,
41
41
  sources.retroPageData,
@@ -284,16 +284,24 @@ function transformArtifacts(artifactData, retroData, prs, prAgentMap) {
284
284
  artifacts.sort((a, b) => a.createdAt - b.createdAt);
285
285
  return artifacts;
286
286
  }
287
- function transformMessages(timelineEvents) {
288
- const messageEvents = timelineEvents.events.filter(
287
+ function transformMessages(timelineEvents, rawMessages) {
288
+ const curatedMessages = timelineEvents.events.filter(
289
289
  (e) => e.type === "message" || e.type === "beam"
290
- );
291
- return messageEvents.map((evt, i) => ({
292
- id: `msg-${String(i).padStart(4, "0")}`,
290
+ ).map((evt, i) => ({
291
+ id: `curated-${String(i).padStart(4, "0")}`,
293
292
  timestamp: new Date(evt.t).getTime(),
294
293
  sender: evt.from,
295
294
  mentions: [evt.to]
296
295
  }));
296
+ const rawMsgs = (rawMessages ?? []).map((msg, i) => ({
297
+ id: msg.id || `raw-${String(i).padStart(4, "0")}`,
298
+ timestamp: new Date(msg.timestamp).getTime(),
299
+ sender: msg.sender,
300
+ mentions: msg.mentions
301
+ }));
302
+ const seen = new Set(rawMsgs.map((m) => `${m.timestamp}:${m.sender}`));
303
+ const uniqueCurated = curatedMessages.filter((m) => !seen.has(`${m.timestamp}:${m.sender}`));
304
+ return [...rawMsgs, ...uniqueCurated];
297
305
  }
298
306
 
299
307
  // src/transform/transform-curation.ts
@@ -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 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 ),\n commits: transformCommits(sources.commits, sources.prAgentMap, defaultAgent),\n prs: transformPRs(sources.prs, sources.prAgentMap),\n messages: transformMessages(sources.timelineEvents),\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): 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 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(timelineEvents: SourceTimelineEvents): RawMessage[] {\n const messageEvents = timelineEvents.events.filter(\n (e): e is SourceMessageEvent | SourceBeamEvent => e.type === 'message' || e.type === 'beam',\n );\n\n return messageEvents.map((evt, i) => ({\n id: `msg-${String(i).padStart(4, '0')}`,\n timestamp: new Date(evt.t).getTime(),\n sender: evt.from,\n mentions: [evt.to],\n }));\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,\n startTime: new Date(p.start).getTime(),\n endTime: new Date(p.end).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).getTime();\n const end = new Date(p.end).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).getTime();\n const end = new Date(p.end).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 * 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\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 if (m.version !== 1) {\n errors.push(`version must be 1, got ${JSON.stringify(m.version)}`);\n }\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 const totalDur = typeof m.totalDurationSec === 'number' ? m.totalDurationSec : 0;\n\n // --- Arrays must exist ---\n if (!Array.isArray(m.dialog)) {\n errors.push('dialog must be an array');\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 if (!Array.isArray(m.overlays)) {\n errors.push('overlays 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 = m.dialog as DialogBeat[];\n const music = m.music as MusicTrack[];\n const sfx = m.sfx as SfxPlacement[];\n const 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 if (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 (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 ),\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): 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 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,\n startTime: new Date(p.start).getTime(),\n endTime: new Date(p.end).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).getTime();\n const end = new Date(p.end).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).getTime();\n const end = new Date(p.end).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 * 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\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 if (m.version !== 1) {\n errors.push(`version must be 1, got ${JSON.stringify(m.version)}`);\n }\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 const totalDur = typeof m.totalDurationSec === 'number' ? m.totalDurationSec : 0;\n\n // --- Arrays must exist ---\n if (!Array.isArray(m.dialog)) {\n errors.push('dialog must be an array');\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 if (!Array.isArray(m.overlays)) {\n errors.push('overlays 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 = m.dialog as DialogBeat[];\n const music = m.music as MusicTrack[];\n const sfx = m.sfx as SfxPlacement[];\n const 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 if (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 (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"]}
package/dist-lib/index.js CHANGED
@@ -33,7 +33,7 @@ function transformToRawData(sources) {
33
33
  ),
34
34
  commits: transformCommits(sources.commits, sources.prAgentMap, defaultAgent),
35
35
  prs: transformPRs(sources.prs, sources.prAgentMap),
36
- messages: transformMessages(sources.timelineEvents),
36
+ messages: transformMessages(sources.timelineEvents, sources.messages),
37
37
  artifacts: sources.artifactData ? transformArtifacts(
38
38
  sources.artifactData,
39
39
  sources.retroPageData,
@@ -282,16 +282,24 @@ function transformArtifacts(artifactData, retroData, prs, prAgentMap) {
282
282
  artifacts.sort((a, b) => a.createdAt - b.createdAt);
283
283
  return artifacts;
284
284
  }
285
- function transformMessages(timelineEvents) {
286
- const messageEvents = timelineEvents.events.filter(
285
+ function transformMessages(timelineEvents, rawMessages) {
286
+ const curatedMessages = timelineEvents.events.filter(
287
287
  (e) => e.type === "message" || e.type === "beam"
288
- );
289
- return messageEvents.map((evt, i) => ({
290
- id: `msg-${String(i).padStart(4, "0")}`,
288
+ ).map((evt, i) => ({
289
+ id: `curated-${String(i).padStart(4, "0")}`,
291
290
  timestamp: new Date(evt.t).getTime(),
292
291
  sender: evt.from,
293
292
  mentions: [evt.to]
294
293
  }));
294
+ const rawMsgs = (rawMessages ?? []).map((msg, i) => ({
295
+ id: msg.id || `raw-${String(i).padStart(4, "0")}`,
296
+ timestamp: new Date(msg.timestamp).getTime(),
297
+ sender: msg.sender,
298
+ mentions: msg.mentions
299
+ }));
300
+ const seen = new Set(rawMsgs.map((m) => `${m.timestamp}:${m.sender}`));
301
+ const uniqueCurated = curatedMessages.filter((m) => !seen.has(`${m.timestamp}:${m.sender}`));
302
+ return [...rawMsgs, ...uniqueCurated];
295
303
  }
296
304
 
297
305
  // src/transform/transform-curation.ts
@@ -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 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 ),\n commits: transformCommits(sources.commits, sources.prAgentMap, defaultAgent),\n prs: transformPRs(sources.prs, sources.prAgentMap),\n messages: transformMessages(sources.timelineEvents),\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): 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 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(timelineEvents: SourceTimelineEvents): RawMessage[] {\n const messageEvents = timelineEvents.events.filter(\n (e): e is SourceMessageEvent | SourceBeamEvent => e.type === 'message' || e.type === 'beam',\n );\n\n return messageEvents.map((evt, i) => ({\n id: `msg-${String(i).padStart(4, '0')}`,\n timestamp: new Date(evt.t).getTime(),\n sender: evt.from,\n mentions: [evt.to],\n }));\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,\n startTime: new Date(p.start).getTime(),\n endTime: new Date(p.end).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).getTime();\n const end = new Date(p.end).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).getTime();\n const end = new Date(p.end).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 * 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\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 if (m.version !== 1) {\n errors.push(`version must be 1, got ${JSON.stringify(m.version)}`);\n }\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 const totalDur = typeof m.totalDurationSec === 'number' ? m.totalDurationSec : 0;\n\n // --- Arrays must exist ---\n if (!Array.isArray(m.dialog)) {\n errors.push('dialog must be an array');\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 if (!Array.isArray(m.overlays)) {\n errors.push('overlays 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 = m.dialog as DialogBeat[];\n const music = m.music as MusicTrack[];\n const sfx = m.sfx as SfxPlacement[];\n const 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 if (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 (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":";;;;;;AAmCO,SAAS,UAAU,UAAA,EAAsC;AAC9D,EAAA,MAAM,CAAA,GAAI,WAAW,WAAA,EAAY;AACjC,EAAA,IAAI,EAAE,QAAA,CAAS,OAAO,CAAA,IAAK,CAAA,KAAM,QAAQ,OAAO,OAAA;AAChD,EAAA,IAAI,CAAA,CAAE,QAAA,CAAS,MAAM,CAAA,EAAG,OAAO,MAAA;AAC/B,EAAA,IAAI,CAAA,CAAE,QAAA,CAAS,IAAI,CAAA,EAAG,OAAO,IAAA;AAC7B,EAAA,IAAI,CAAA,CAAE,SAAS,QAAQ,CAAA,IAAK,EAAE,QAAA,CAAS,IAAI,GAAG,OAAO,QAAA;AACrD,EAAA,IAAI,CAAA,CAAE,SAAS,UAAU,CAAA,IAAK,EAAE,QAAA,CAAS,QAAQ,GAAG,OAAO,UAAA;AAC3D,EAAA,IAAI,CAAA,CAAE,SAAS,SAAS,CAAA,IAAK,EAAE,QAAA,CAAS,OAAO,GAAG,OAAO,SAAA;AACzD,EAAA,IAAI,CAAA,CAAE,SAAS,YAAY,CAAA,IAAK,EAAE,QAAA,CAAS,WAAW,GAAG,OAAO,YAAA;AAChE,EAAA,IAAI,CAAA,CAAE,QAAA,CAAS,OAAO,CAAA,EAAG,OAAO,OAAA;AAChC,EAAA,IAAI,CAAA,CAAE,QAAA,CAAS,UAAU,CAAA,EAAG,OAAO,UAAA;AACnC,EAAA,IAAI,CAAA,CAAE,QAAA,CAAS,UAAU,CAAA,EAAG,OAAO,YAAA;AACnC,EAAA,IAAI,CAAA,CAAE,SAAS,SAAS,CAAA,IAAK,EAAE,QAAA,CAAS,OAAO,GAAG,OAAO,SAAA;AACzD,EAAA,OAAO,SAAA;AACT;AAMO,SAAS,mBAAmB,OAAA,EAAoC;AAErE,EAAA,MAAM,YAAA,GAAe,OAAA,CAAQ,aAAA,CAAc,YAAA,CAAa,CAAC,GAAG,KAAA,CAAM,OAAA,CAAQ,GAAA,EAAK,EAAE,CAAA,IAAK,SAAA;AAEtF,EAAA,OAAO;AAAA,IACL,OAAA,EAAS;AAAA,MACP,IAAA,EAAM,OAAA,CAAQ,aAAA,CAAc,IAAA,CAAK,KAAA;AAAA,MACjC,WAAA,EAAa,OAAA,CAAQ,aAAA,CAAc,IAAA,CAAK;AAAA,KAC1C;AAAA,IACA,MAAA,EAAQ,eAAA;AAAA,MACN,OAAA,CAAQ,aAAA;AAAA,MACR,QAAQ,YAAA,CAAa,WAAA;AAAA,MACrB,OAAA,CAAQ;AAAA,KACV;AAAA,IACA,SAAS,gBAAA,CAAiB,OAAA,CAAQ,OAAA,EAAS,OAAA,CAAQ,YAAY,YAAY,CAAA;AAAA,IAC3E,GAAA,EAAK,YAAA,CAAa,OAAA,CAAQ,GAAA,EAAK,QAAQ,UAAU,CAAA;AAAA,IACjD,QAAA,EAAU,iBAAA,CAAkB,OAAA,CAAQ,cAAA,EAAgB,QAAQ,QAAQ,CAAA;AAAA,IACpE,SAAA,EAAW,QAAQ,YAAA,GACf,kBAAA;AAAA,MACE,OAAA,CAAQ,YAAA;AAAA,MACR,OAAA,CAAQ,aAAA;AAAA,MACR,OAAA,CAAQ,GAAA;AAAA,MACR,OAAA,CAAQ;AAAA,QAEV;AAAC,GACP;AACF;AAMA,SAAS,yBAAyB,cAAA,EAA4D;AAC5F,EAAA,MAAM,GAAA,uBAAU,GAAA,EAAoB;AACpC,EAAA,IAAI,CAAC,gBAAgB,OAAO,GAAA;AAE5B,EAAA,KAAA,MAAW,GAAA,IAAO,eAAe,MAAA,EAAQ;AACvC,IAAA,IAAI,GAAA,CAAI,IAAA,KAAS,SAAA,IAAa,GAAA,CAAI,SAAS,MAAA,EAAQ;AACnD,IAAA,MAAM,SAAU,GAAA,CAA6C,IAAA;AAC7D,IAAA,MAAM,KAAK,IAAI,IAAA,CAAK,GAAA,CAAI,CAAC,EAAE,OAAA,EAAQ;AACnC,IAAA,MAAM,QAAA,GAAW,GAAA,CAAI,GAAA,CAAI,MAAM,CAAA;AAC/B,IAAA,IAAI,QAAA,KAAa,MAAA,IAAa,EAAA,GAAK,QAAA,EAAU;AAC3C,MAAA,GAAA,CAAI,GAAA,CAAI,QAAQ,EAAE,CAAA;AAAA,IACpB;AAAA,EACF;AAEA,EAAA,OAAO,GAAA;AACT;AAiBO,SAAS,eAAA,CACd,SAAA,EACA,WAAA,EACA,cAAA,EACA,UAAA,EACY;AACZ,EAAA,MAAM,SAAqB,EAAC;AAC5B,EAAA,MAAM,IAAA,uBAAW,GAAA,EAAY;AAG7B,EAAA,MAAM,gBAAA,GAAmB,yBAAyB,cAAc,CAAA;AAGhE,EAAA,MAAM,aAAA,uBAAoB,GAAA,EAAoB;AAC9C,EAAA,KAAA,MAAW,KAAA,IAAS,UAAU,YAAA,EAAc;AAC1C,IAAA,MAAM,EAAA,GAAK,KAAA,CAAM,KAAA,CAAM,OAAA,CAAQ,KAAK,EAAE,CAAA;AACtC,IAAA,aAAA,CAAc,GAAA,CAAI,EAAA,EAAI,KAAA,CAAM,IAAI,CAAA;AAAA,EAClC;AAGA,EAAA,SAAS,YAAY,EAAA,EAA8B;AAMjD,IAAA,MAAM,YAAA,GAAe,aAAA,CAAc,GAAA,CAAI,EAAE,CAAA;AACzC,IAAA,IAAI,YAAA,EAAc;AAChB,MAAA,OAAO,UAAU,YAAY,CAAA;AAAA,IAC/B;AAEA,IAAA,OAAO,SAAA;AAAA,EACT;AAGA,EAAA,SAAS,eAAA,CAAgB,IAAY,YAAA,EAA+B;AAClE,IAAA,MAAM,OAAA,GAAU,gBAAA,CAAiB,GAAA,CAAI,EAAE,CAAA;AAEvC,IAAA,IAAI,OAAA,KAAY,MAAA,IAAa,YAAA,KAAiB,MAAA,EAAW;AACvD,MAAA,OAAO,IAAA,CAAK,GAAA,CAAI,OAAA,EAAS,YAAY,CAAA;AAAA,IACvC;AACA,IAAA,IAAI,OAAA,KAAY,QAAW,OAAO,OAAA;AAClC,IAAA,IAAI,YAAA,KAAiB,QAAW,OAAO,YAAA;AAEvC,IAAA,OAAO,IAAI,IAAA,CAAK,SAAA,CAAU,IAAA,CAAK,SAAS,EAAE,OAAA,EAAQ;AAAA,EACpD;AAGA,EAAA,KAAA,MAAW,KAAA,IAAS,UAAU,YAAA,EAAc;AAC1C,IAAA,MAAM,EAAA,GAAK,KAAA,CAAM,KAAA,CAAM,OAAA,CAAQ,KAAK,EAAE,CAAA;AACtC,IAAA,IAAI,IAAA,CAAK,GAAA,CAAI,EAAE,CAAA,EAAG;AAClB,IAAA,IAAA,CAAK,IAAI,EAAE,CAAA;AAEX,IAAA,MAAA,CAAO,IAAA,CAAK;AAAA,MACV,EAAA;AAAA,MACA,IAAA,EAAM,YAAY,EAAE,CAAA;AAAA,MACpB,QAAA,EAAU,gBAAgB,EAAA,EAAI,IAAI,KAAK,KAAA,CAAM,IAAI,CAAA,CAAE,OAAA,EAAS;AAAA,KAC7D,CAAA;AAAA,EACH;AAGA,EAAA,KAAA,MAAW,EAAA,IAAM,MAAA,CAAO,IAAA,CAAK,WAAW,CAAA,EAAG;AACzC,IAAA,IAAI,IAAA,CAAK,GAAA,CAAI,EAAE,CAAA,EAAG;AAClB,IAAA,MAAA,CAAO,IAAA,CAAK;AAAA,MACV,EAAA;AAAA,MACA,IAAA,EAAM,YAAY,EAAE,CAAA;AAAA,MACpB,QAAA,EAAU,gBAAgB,EAAE;AAAA,KAC7B,CAAA;AACD,IAAA,IAAA,CAAK,IAAI,EAAE,CAAA;AAAA,EACb;AAEA,EAAA,OAAO,MAAA;AACT;AASO,SAAS,gBAAA,CACd,OAAA,EACA,UAAA,EACA,YAAA,GAAe,SAAA,EACF;AACb,EAAA,OAAO,OAAA,CAAQ,GAAA,CAAI,CAAC,CAAA,KAAM;AACxB,IAAA,MAAM,KAAA,GAAQ,kBAAA,CAAmB,CAAA,EAAG,UAAA,EAAY,YAAY,CAAA;AAE5D,IAAA,OAAO;AAAA,MACL,KAAK,CAAA,CAAE,IAAA;AAAA,MACP,WAAW,IAAI,IAAA,CAAK,CAAA,CAAE,IAAI,EAAE,OAAA,EAAQ;AAAA,MACpC,KAAA;AAAA,MACA,SAAS,CAAA,CAAE,OAAA;AAAA,MACX,YAAA,EAAc,EAAE,KAAA,CAAM,MAAA;AAAA,MACtB,YAAY,CAAA,CAAE,eAAA;AAAA,MACd,WAAW,CAAA,CAAE,cAAA;AAAA,MACb,QAAA,EAAU,EAAE,QAAA,IAAY;AAAA,KAC1B;AAAA,EACF,CAAC,CAAA;AACH;AAUO,SAAS,kBAAA,CACd,MAAA,EACA,UAAA,EACA,YAAA,GAAe,SAAA,EACP;AAER,EAAA,IAAI,MAAA,CAAO,YAAY,IAAA,EAAM;AAC3B,IAAA,MAAM,KAAA,GAAQ,UAAA,CAAW,MAAA,CAAO,MAAA,CAAO,QAAQ,CAAC,CAAA;AAChD,IAAA,IAAI,OAAO,OAAO,KAAA;AAAA,EACpB;AAGA,EAAA,MAAM,UAAA,GAAa,MAAA,CAAO,OAAA,CAAQ,KAAA,CAAM,4BAA4B,CAAA;AACpE,EAAA,IAAI,UAAA,EAAY;AACd,IAAA,MAAM,KAAA,GAAQ,UAAA,CAAW,UAAA,CAAW,CAAC,CAAC,CAAA;AACtC,IAAA,IAAI,OAAO,OAAO,KAAA;AAAA,EACpB;AAGA,EAAA,MAAM,WAAA,GAAc,MAAA,CAAO,OAAA,CAAQ,KAAA,CAAM,gBAAgB,CAAA;AACzD,EAAA,IAAI,WAAA,EAAa;AACf,IAAA,MAAM,KAAA,GAAQ,UAAA,CAAW,WAAA,CAAY,CAAC,CAAC,CAAA;AACvC,IAAA,IAAI,OAAO,OAAO,KAAA;AAAA,EACpB;AAGA,EAAA,OAAO,YAAA;AACT;AAMO,SAAS,YAAA,CAAa,KAAiB,UAAA,EAAuC;AACnF,EAAA,OAAO,GAAA,CAAI,GAAA,CAAI,CAAC,EAAA,KAAO;AACrB,IAAA,MAAM,QAAQ,UAAA,CAAW,MAAA,CAAO,EAAA,CAAG,MAAM,CAAC,CAAA,IAAK,SAAA;AAE/C,IAAA,OAAO;AAAA,MACL,QAAQ,EAAA,CAAG,MAAA;AAAA,MACX,OAAO,EAAA,CAAG,KAAA;AAAA,MACV,KAAA;AAAA,MACA,WAAW,IAAI,IAAA,CAAK,EAAA,CAAG,SAAS,EAAE,OAAA,EAAQ;AAAA,MAC1C,QAAA,EAAU,GAAG,QAAA,GAAW,IAAI,KAAK,EAAA,CAAG,QAAQ,CAAA,CAAE,OAAA,EAAQ,GAAI,IAAA;AAAA,MAC1D,WAAW,EAAA,CAAG,SAAA;AAAA,MACd,WAAW,EAAA,CAAG,SAAA;AAAA,MACd,QAAQ,EAAA,CAAG;AAAA,KACb;AAAA,EACF,CAAC,CAAA;AACH;AAWO,SAAS,kBAAkB,IAAA,EAAmC;AAEnE,EAAA,IAAI,IAAA,CAAK,UAAA,CAAW,YAAY,CAAA,EAAG,OAAO,MAAA;AAC1C,EAAA,IAAI,IAAA,CAAK,UAAA,CAAW,YAAY,CAAA,EAAG,OAAO,KAAA;AAG1C,EAAA,MAAM,MAAM,IAAA,CAAK,KAAA,CAAM,GAAG,CAAA,CAAE,GAAA,IAAO,WAAA,EAAY;AAC/C,EAAA,IAAI,GAAA,IAAO,CAAC,IAAA,EAAM,KAAA,EAAO,MAAM,KAAA,EAAO,IAAA,EAAM,IAAA,EAAM,IAAA,EAAM,IAAI,CAAA,CAAE,QAAA,CAAS,GAAG,GAAG,OAAO,MAAA;AACpF,EAAA,IAAI,GAAA,IAAO,CAAC,KAAA,EAAO,KAAA,EAAO,MAAA,EAAQ,KAAA,EAAO,KAAA,EAAO,MAAA,EAAQ,KAAK,CAAA,CAAE,QAAA,CAAS,GAAG,GAAG,OAAO,OAAA;AACrF,EAAA,IAAI,GAAA,IAAO,CAAC,IAAA,EAAM,KAAA,EAAO,MAAA,EAAQ,MAAA,EAAQ,KAAA,EAAO,MAAM,CAAA,CAAE,QAAA,CAAS,GAAG,CAAA,EAAG,OAAO,KAAA;AAG9E,EAAA,IAAI,IAAA,CAAK,SAAS,SAAS,CAAA,IAAK,KAAK,QAAA,CAAS,QAAQ,GAAG,OAAO,KAAA;AAChE,EAAA,IAAI,IAAA,CAAK,SAAS,UAAU,CAAA,IAAK,KAAK,QAAA,CAAS,UAAU,GAAG,OAAO,OAAA;AAGnE,EAAA,IAAI,IAAA,CAAK,QAAA,CAAS,OAAO,CAAA,EAAG,OAAO,MAAA;AACnC,EAAA,IAAI,IAAA,CAAK,SAAS,YAAY,CAAA,IAAK,KAAK,QAAA,CAAS,KAAK,GAAG,OAAO,OAAA;AAChE,EAAA,IAAI,IAAA,CAAK,QAAA,CAAS,UAAU,CAAA,EAAG,OAAO,UAAA;AACtC,EAAA,IAAI,IAAA,CAAK,SAAS,MAAM,CAAA,IAAK,KAAK,QAAA,CAAS,QAAQ,GAAG,OAAO,MAAA;AAC7D,EAAA,IAAI,IAAA,CAAK,WAAW,OAAO,CAAA,IAAK,KAAK,UAAA,CAAW,MAAM,GAAG,OAAO,KAAA;AAChE,EAAA,IAAI,IAAA,CAAK,QAAA,CAAS,SAAS,CAAA,EAAG,OAAO,KAAA;AAErC,EAAA,OAAO,KAAA;AACT;AAUO,SAAS,oBAAA,CACd,IAAA,EACA,UAAA,EACA,SAAA,EACA,YAAA,EACQ;AAER,EAAA,IAAI,WAAW,OAAO,SAAA;AAGtB,EAAA,MAAM,OAAA,GAAU,IAAA,CAAK,KAAA,CAAM,SAAS,CAAA;AACpC,EAAA,IAAI,OAAA,EAAS;AACX,IAAA,MAAM,KAAA,GAAQ,UAAA,CAAW,OAAA,CAAQ,CAAC,CAAC,CAAA;AACnC,IAAA,IAAI,OAAO,OAAO,KAAA;AAAA,EACpB;AAGA,EAAA,OAAO,YAAA;AACT;AAGA,IAAM,iBAAA,GAAyD;AAAA,EAC7D,aAAA,EAAe,OAAA;AAAA,EACf,eAAA,EAAiB,KAAA;AAAA,EACjB,kBAAA,EAAoB,KAAA;AAAA,EACpB,MAAA,EAAQ,KAAA;AAAA,EACR,WAAA,EAAa,MAAA;AAAA,EACb,cAAA,EAAgB,KAAA;AAAA,EAChB,SAAA,EAAW,KAAA;AAAA,EACX,SAAA,EAAW;AACb,CAAA;AAMO,SAAS,oBAAA,CACd,KAAA,EACA,MAAA,EACA,YAAA,EACU;AACV,EAAA,MAAM,YAAA,GAAe,YAAA,CAAa,MAAA,CAAO,CAAC,CAAA,KAAM,KAAK,MAAA,CAAO,KAAA,IAAS,CAAA,IAAK,MAAA,CAAO,GAAG,CAAA;AACpF,EAAA,MAAM,aAAuB,EAAC;AAE9B,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,KAAA,EAAO,CAAA,EAAA,EAAK;AAC9B,IAAA,IAAI,SAAA;AACJ,IAAA,IAAI,YAAA,CAAa,SAAS,CAAA,EAAG;AAC3B,MAAA,MAAM,KAAA,GAAQ,IAAI,YAAA,CAAa,MAAA;AAC/B,MAAA,SAAA,GAAY,YAAA,CAAa,KAAK,CAAA,GAAI,CAAA,GAAI,GAAA;AAAA,IACxC,CAAA,MAAO;AACL,MAAA,MAAM,QAAA,GAAW,KAAA,GAAQ,CAAA,GAAI,CAAA,IAAK,QAAQ,CAAA,CAAA,GAAK,GAAA;AAC/C,MAAA,SAAA,GAAY,MAAA,CAAO,KAAA,GAAQ,QAAA,IAAY,MAAA,CAAO,MAAM,MAAA,CAAO,KAAA,CAAA;AAAA,IAC7D;AACA,IAAA,UAAA,CAAW,IAAA,CAAK,IAAA,CAAK,KAAA,CAAM,IAAA,CAAK,IAAI,MAAA,CAAO,KAAA,EAAO,IAAA,CAAK,GAAA,CAAI,MAAA,CAAO,GAAA,EAAK,SAAS,CAAC,CAAC,CAAC,CAAA;AAAA,EACrF;AAEA,EAAA,OAAO,UAAA;AACT;AAYO,SAAS,0BACd,UAAA,EACsD;AACtD,EAAA,MAAM,UAA+D,EAAC;AACtE,EAAA,IAAI,KAAA,GAAQ,CAAA;AAEZ,EAAA,KAAA,MAAW,CAAC,YAAA,EAAc,YAAY,KAAK,MAAA,CAAO,OAAA,CAAQ,UAAU,CAAA,EAAG;AACrE,IAAA,IAAI,YAAA,CAAa,UAAU,CAAA,EAAG;AAC9B,IAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,MACX,IAAA,EAAM,iBAAA,CAAkB,YAAY,CAAA,IAAK,KAAA;AAAA,MACzC,OAAO,YAAA,CAAa;AAAA,KACrB,CAAA;AACD,IAAA,KAAA,IAAS,YAAA,CAAa,KAAA;AAAA,EACxB;AAEA,EAAA,IAAI,KAAA,KAAU,GAAG,OAAO,CAAC,EAAE,IAAA,EAAM,KAAA,EAAO,MAAA,EAAQ,CAAA,EAAG,CAAA;AAEnD,EAAA,OAAO,OAAA,CACJ,KAAK,CAAC,CAAA,EAAG,MAAM,CAAA,CAAE,KAAA,GAAQ,EAAE,KAAK,CAAA,CAChC,IAAI,CAAC,CAAA,MAAO,EAAE,IAAA,EAAM,CAAA,CAAE,MAAM,MAAA,EAAQ,CAAA,CAAE,KAAA,GAAQ,KAAA,EAAM,CAAE,CAAA;AAC3D;AAMA,SAAS,qBAAqB,UAAA,EAAmE;AAC/F,EAAA,MAAM,MAAA,uBAAa,GAAA,EAAoB;AACvC,EAAA,KAAA,MAAW,YAAA,IAAgB,MAAA,CAAO,MAAA,CAAO,UAAU,CAAA,EAAG;AACpD,IAAA,KAAA,MAAW,IAAA,IAAQ,YAAA,CAAa,KAAA,IAAS,EAAC,EAAG;AAC3C,MAAA,IAAI,OAAO,IAAA,KAAS,QAAA,IAAY,IAAA,CAAK,SAAA,EAAW;AAC9C,QAAA,MAAA,CAAO,GAAA,CAAI,IAAA,CAAK,IAAA,EAAM,IAAA,CAAK,SAAS,CAAA;AAAA,MACtC;AAAA,IACF;AAAA,EACF;AACA,EAAA,OAAO,MAAA;AACT;AAgBO,SAAS,kBAAA,CACd,YAAA,EACA,SAAA,EACA,GAAA,EACA,UAAA,EACe;AACf,EAAA,MAAM,YAA2B,EAAC;AAGlC,EAAA,MAAM,QAAA,GAAW,SAAA,CAAU,YAAA,CAAa,GAAA,CAAI,CAAC,CAAA,KAAM,CAAA,CAAE,KAAA,CAAM,OAAA,CAAQ,GAAA,EAAK,EAAE,CAAC,CAAA;AAC3E,EAAA,MAAM,YAAA,GAAe,QAAA,CAAS,CAAC,CAAA,IAAK,SAAA;AAEpC,EAAA,MAAM,eAAA,GAAkB,SAAA,CAAU,MAAA,CAAO,GAAA,CAAI,CAAC,CAAA,MAAO;AAAA,IACnD,OAAO,IAAI,IAAA,CAAK,CAAA,CAAE,KAAK,EAAE,OAAA,EAAQ;AAAA,IACjC,KAAK,IAAI,IAAA,CAAK,CAAA,CAAE,GAAG,EAAE,OAAA;AAAQ,GAC/B,CAAE,CAAA;AAEF,EAAA,MAAM,eAAe,GAAA,CAAI,GAAA,CAAI,CAAC,EAAA,KAAO,IAAI,KAAK,EAAA,CAAG,SAAS,CAAA,CAAE,OAAA,EAAS,CAAA,CAAE,IAAA,CAAK,CAAC,CAAA,EAAG,CAAA,KAAM,IAAI,CAAC,CAAA;AAC3F,EAAA,MAAM,YAAA,GAAe,yBAAA,CAA0B,YAAA,CAAa,UAAU,CAAA;AACtE,EAAA,MAAM,eAAA,GAAkB,oBAAA,CAAqB,YAAA,CAAa,UAAU,CAAA;AAEpE,EAAA,IAAI,UAAA,GAAa,CAAA;AACjB,EAAA,IAAI,eAAA,GAAkB,CAAA;AAEtB,EAAA,KAAA,MAAW,CAAC,YAAY,SAAS,CAAA,IAAK,OAAO,OAAA,CAAQ,YAAA,CAAa,MAAM,CAAA,EAAG;AACzE,IAAA,IAAI,UAAA,IAAc,gBAAgB,MAAA,EAAQ;AAC1C,IAAA,MAAM,MAAA,GAAS,gBAAgB,UAAU,CAAA;AACzC,IAAA,UAAA,EAAA;AAEA,IAAA,MAAM,aAAa,SAAA,CAAU,KAAA;AAC7B,IAAA,MAAM,QAAQ,SAAA,CAAU,SAAA;AACxB,IAAA,MAAM,YAAY,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,UAAA,GAAa,MAAM,MAAM,CAAA;AAGvD,IAAA,MAAM,UAAA,GAAa,oBAAA,CAAqB,UAAA,EAAY,MAAA,EAAQ,YAAY,CAAA;AAGxE,IAAA,IAAI,KAAA,GAAQ,CAAA;AACZ,IAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AACxB,MAAA,SAAA,CAAU,IAAA,CAAK;AAAA,QACb,IAAA;AAAA,QACA,IAAA,EAAM,kBAAkB,IAAI,CAAA;AAAA,QAC5B,SAAA,EAAW,WAAW,KAAK,CAAA;AAAA,QAC3B,SAAA,EAAW,WAAW,KAAK,CAAA;AAAA,QAC3B,KAAA,EAAO,qBAAqB,IAAA,EAAM,UAAA,EAAY,gBAAgB,GAAA,CAAI,IAAI,GAAG,YAAY;AAAA,OACtF,CAAA;AACD,MAAA,KAAA,EAAA;AAAA,IACF;AAKA,IAAA,IAAI,OAAA,GAAU,CAAA;AACd,IAAA,IAAI,aAAa,IAAA,CAAK,KAAA,CAAM,aAAa,CAAC,CAAA,CAAE,SAAS,SAAS,CAAA;AAE9D,IAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,SAAA,EAAW,CAAA,EAAA,EAAK;AAElC,MAAA,OAAO,UAAA,IAAc,CAAA,IAAK,OAAA,GAAU,YAAA,CAAa,SAAS,CAAA,EAAG;AAC3D,QAAA,OAAA,EAAA;AACA,QAAA,UAAA,GAAa,KAAK,KAAA,CAAM,YAAA,CAAa,OAAO,CAAA,CAAE,SAAS,SAAS,CAAA;AAAA,MAClE;AACA,MAAA,UAAA,EAAA;AAEA,MAAA,MAAM,KAAA,GAAQ,aAAa,OAAO,CAAA;AAElC,MAAA,MAAM,KAAA,GACJ,SAAS,MAAA,GAAS,CAAA,GAAI,SAAS,eAAA,GAAkB,QAAA,CAAS,MAAM,CAAA,GAAI,YAAA;AACtE,MAAA,SAAA,CAAU,IAAA,CAAK;AAAA,QACb,IAAA,EAAM,CAAA,KAAA,EAAQ,UAAU,CAAA,CAAA,EAAI,MAAM,IAAI,CAAA,CAAA,EAAI,MAAA,CAAO,eAAA,GAAkB,CAAC,CAAA,CAAE,QAAA,CAAS,CAAA,EAAG,GAAG,CAAC,CAAA,CAAA;AAAA,QACtF,MAAM,KAAA,CAAM,IAAA;AAAA,QACZ,SAAA,EAAW,WAAW,KAAK,CAAA;AAAA,QAC3B,SAAA,EAAW,WAAW,KAAK,CAAA;AAAA,QAC3B;AAAA,OACD,CAAA;AACD,MAAA,KAAA,EAAA;AACA,MAAA,eAAA,EAAA;AAAA,IACF;AAAA,EACF;AAEA,EAAA,SAAA,CAAU,KAAK,CAAC,CAAA,EAAG,MAAM,CAAA,CAAE,SAAA,GAAY,EAAE,SAAS,CAAA;AAElD,EAAA,OAAO,SAAA;AACT;AAYO,SAAS,iBAAA,CACd,gBACA,WAAA,EACc;AAEd,EAAA,MAAM,eAAA,GAAkB,eAAe,MAAA,CACpC,MAAA;AAAA,IACC,CAAC,CAAA,KAAiD,CAAA,CAAE,IAAA,KAAS,SAAA,IAAa,EAAE,IAAA,KAAS;AAAA,GACvF,CACC,GAAA,CAAI,CAAC,GAAA,EAAK,CAAA,MAAO;AAAA,IAChB,EAAA,EAAI,WAAW,MAAA,CAAO,CAAC,EAAE,QAAA,CAAS,CAAA,EAAG,GAAG,CAAC,CAAA,CAAA;AAAA,IACzC,WAAW,IAAI,IAAA,CAAK,GAAA,CAAI,CAAC,EAAE,OAAA,EAAQ;AAAA,IACnC,QAAQ,GAAA,CAAI,IAAA;AAAA,IACZ,QAAA,EAAU,CAAC,GAAA,CAAI,EAAE;AAAA,GACnB,CAAE,CAAA;AAGJ,EAAA,MAAM,WAAyB,WAAA,IAAe,IAAI,GAAA,CAAI,CAAC,KAAK,CAAA,MAAO;AAAA,IACjE,EAAA,EAAI,GAAA,CAAI,EAAA,IAAM,CAAA,IAAA,EAAO,MAAA,CAAO,CAAC,CAAA,CAAE,QAAA,CAAS,CAAA,EAAG,GAAG,CAAC,CAAA,CAAA;AAAA,IAC/C,WAAW,IAAI,IAAA,CAAK,GAAA,CAAI,SAAS,EAAE,OAAA,EAAQ;AAAA,IAC3C,QAAQ,GAAA,CAAI,MAAA;AAAA,IACZ,UAAU,GAAA,CAAI;AAAA,GAChB,CAAE,CAAA;AAKF,EAAA,MAAM,IAAA,GAAO,IAAI,GAAA,CAAI,OAAA,CAAQ,IAAI,CAAC,CAAA,KAAM,CAAA,EAAG,CAAA,CAAE,SAAS,CAAA,CAAA,EAAI,CAAA,CAAE,MAAM,EAAE,CAAC,CAAA;AACrE,EAAA,MAAM,aAAA,GAAgB,eAAA,CAAgB,MAAA,CAAO,CAAC,MAAM,CAAC,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,EAAE,SAAS,CAAA,CAAA,EAAI,CAAA,CAAE,MAAM,EAAE,CAAC,CAAA;AAE3F,EAAA,OAAO,CAAC,GAAG,OAAA,EAAS,GAAG,aAAa,CAAA;AACtC;;;AC/hBO,SAAS,wBAAwB,OAAA,EAAyC;AAC/E,EAAA,MAAM,SAAA,GAAY,kBAAA,CAAmB,OAAA,CAAQ,aAAa,CAAA;AAC1D,EAAA,MAAM,IAAA,GAAO,QAAQ,aAAA,CAAc,IAAA;AAGnC,EAAA,MAAM,cAAA,GAAiB,MAAM,SAAA,GAAY,IAAI,KAAK,IAAA,CAAK,SAAS,CAAA,CAAE,OAAA,EAAQ,GAAI,MAAA;AAC9E,EAAA,MAAM,YAAA,GAAe,MAAM,OAAA,GAAU,IAAI,KAAK,IAAA,CAAK,OAAO,CAAA,CAAE,OAAA,EAAQ,GAAI,MAAA;AAExE,EAAA,OAAO;AAAA,IACL,MAAA,EAAQ,eAAA,CAAgB,OAAA,CAAQ,aAAa,CAAA;AAAA,IAC7C,MAAA,EAAQ,eAAA,CAAgB,OAAA,CAAQ,aAAA,EAAe,QAAQ,eAAe,CAAA;AAAA,IACtE,UAAA,EAAY,mBAAA,CAAoB,OAAA,CAAQ,aAAa,CAAA;AAAA,IACrD,cAAA,EAAgB,uBAAA,CAAwB,OAAA,CAAQ,aAAa,CAAA;AAAA,IAC7D,GAAI,UAAU,MAAA,GAAS,CAAA,GAAI,EAAE,kBAAA,EAAoB,SAAA,KAAc,EAAC;AAAA,IAChE,GAAI,cAAA,IAAkB,CAAC,MAAA,CAAO,KAAA,CAAM,cAAc,CAAA,GAAI,EAAE,cAAA,EAAe,GAAI,EAAC;AAAA,IAC5E,GAAI,YAAA,IAAgB,CAAC,MAAA,CAAO,KAAA,CAAM,YAAY,CAAA,GAAI,EAAE,YAAA,EAAa,GAAI;AAAC,GACxE;AACF;AAMO,SAAS,gBAAgB,SAAA,EAAiD;AAC/E,EAAA,OAAO,SAAA,CAAU,MAAA,CAAO,GAAA,CAAI,CAAC,CAAA,MAAO;AAAA,IAClC,IAAI,CAAA,CAAE,EAAA;AAAA,IACN,MAAM,CAAA,CAAE,IAAA;AAAA,IACR,WAAW,IAAI,IAAA,CAAK,CAAA,CAAE,KAAK,EAAE,OAAA,EAAQ;AAAA,IACrC,SAAS,IAAI,IAAA,CAAK,CAAA,CAAE,GAAG,EAAE,OAAA;AAAQ,GACnC,CAAE,CAAA;AACJ;AAMO,SAAS,oBAAoB,SAAA,EAAqD;AACvF,EAAA,MAAM,SAAS,SAAA,CAAU,MAAA;AAEzB,EAAA,OAAO,SAAA,CAAU,UAAA,CAAW,GAAA,CAAI,CAAC,CAAA,KAAM;AACrC,IAAA,MAAM,gBAAgB,IAAI,IAAA,CAAK,CAAA,CAAE,IAAI,EAAE,OAAA,EAAQ;AAC/C,IAAA,MAAM,KAAA,GAAQ,qBAAA,CAAsB,aAAA,EAAe,MAAM,CAAA;AAEzD,IAAA,OAAO;AAAA,MACL,OAAO,CAAA,CAAE,KAAA;AAAA,MACT,SAAA,EAAW,aAAA;AAAA,MACX,KAAA,EAAO,OAAO,EAAA,IAAM;AAAA,KACtB;AAAA,EACF,CAAC,CAAA;AACH;AAKA,IAAM,aAAA,GAAwC;AAAA,EAC5C,OAAA,EAAS,MAAA;AAAA,EACT,MAAA,EAAQ,KAAA;AAAA,EACR,OAAA,EAAS,OAAA;AAAA,EACT,QAAA,EAAU;AACZ,CAAA;AAKA,IAAM,aAAA,GAAwC;AAAA,EAC5C,IAAA,EAAM,MAAA;AAAA,EACN,GAAA,EAAK,KAAA;AAAA,EACL,IAAA,EAAM;AACR,CAAA;AASO,SAAS,eAAA,CACd,WACA,WAAA,EACiB;AACjB,EAAA,MAAM,SAAS,SAAA,CAAU,MAAA;AACzB,EAAA,MAAM,SAA0B,EAAC;AAGjC,EAAA,MAAM,eAAA,GAAkB,MAAA,CAAO,CAAC,CAAA,EAAG,KAAA;AACnC,EAAA,MAAM,aAAA,GAAgB,eAAA,GAClB,IAAI,IAAA,CAAK,eAAe,CAAA,CAAE,cAAA,EAAe,GAAA,iBACzC,IAAI,IAAA,EAAK,EAAE,cAAA,EAAe;AAG9B,EAAA,KAAA,MAAW,CAAC,UAAU,OAAO,CAAA,IAAK,OAAO,OAAA,CAAQ,SAAA,CAAU,MAAM,CAAA,EAAG;AAClE,IAAA,IAAI,CAAC,KAAA,CAAM,OAAA,CAAQ,OAAO,CAAA,EAAG;AAC7B,IAAA,MAAM,IAAA,GAAO,aAAA,CAAc,QAAQ,CAAA,IAAK,MAAA;AACxC,IAAA,KAAA,MAAW,SAAS,OAAA,EAAS;AAC3B,MAAA,MAAM,SAAA,GAAY,sBAAA,CAAuB,KAAA,CAAM,IAAA,EAAM,aAAa,CAAA;AAClE,MAAA,IAAI,aAAa,IAAA,EAAM;AACvB,MAAA,MAAM,KAAA,GAAQ,qBAAA,CAAsB,SAAA,EAAW,MAAM,CAAA;AACrD,MAAA,MAAA,CAAO,IAAA,CAAK;AAAA,QACV,MAAM,KAAA,CAAM,IAAA;AAAA,QACZ,OAAA,EAAS,KAAA,CAAM,MAAA,CAAO,OAAA,CAAQ,MAAM,EAAE,CAAA;AAAA,QACtC,SAAA;AAAA,QACA,KAAA,EAAO,OAAO,EAAA,IAAM,SAAA;AAAA,QACpB;AAAA,OACD,CAAA;AAAA,IACH;AAAA,EACF;AAGA,EAAA,KAAA,MAAW,CAAC,QAAA,EAAU,OAAO,KAAK,MAAA,CAAO,OAAA,CAAQ,WAAW,CAAA,EAAG;AAC7D,IAAA,IAAI,CAAC,KAAA,CAAM,OAAA,CAAQ,OAAO,CAAA,EAAG;AAC7B,IAAA,MAAM,IAAA,GAAO,aAAA,CAAc,QAAQ,CAAA,IAAK,MAAA;AACxC,IAAA,KAAA,MAAW,SAAS,OAAA,EAAS;AAC3B,MAAA,MAAM,SAAA,GAAY,sBAAA,CAAuB,KAAA,CAAM,SAAA,EAAW,aAAa,CAAA;AACvE,MAAA,IAAI,aAAa,IAAA,EAAM;AACvB,MAAA,MAAM,KAAA,GAAQ,qBAAA,CAAsB,SAAA,EAAW,MAAM,CAAA;AACrD,MAAA,MAAA,CAAO,IAAA,CAAK;AAAA,QACV,MAAM,KAAA,CAAM,IAAA;AAAA,QACZ,OAAA,EAAS,KAAA,CAAM,MAAA,CAAO,OAAA,CAAQ,MAAM,EAAE,CAAA;AAAA,QACtC,SAAA;AAAA,QACA,KAAA,EAAO,OAAO,EAAA,IAAM,SAAA;AAAA,QACpB;AAAA,OACD,CAAA;AAAA,IACH;AAAA,EACF;AAGA,EAAA,MAAA,CAAO,KAAK,CAAC,CAAA,EAAG,MAAM,CAAA,CAAE,SAAA,GAAY,EAAE,SAAS,CAAA;AAC/C,EAAA,OAAO,MAAA;AACT;AAOO,SAAS,wBAAwB,SAAA,EAAyD;AAC/F,EAAA,IAAI,CAAC,UAAU,QAAA,IAAY,SAAA,CAAU,SAAS,MAAA,KAAW,CAAA,SAAU,EAAC;AAEpE,EAAA,OAAO,SAAA,CAAU,QAAA,CACd,GAAA,CAAI,CAAC,KAAA,MAAW;AAAA,IACf,WAAW,IAAI,IAAA,CAAK,KAAA,CAAM,IAAI,EAAE,OAAA,EAAQ;AAAA,IACxC,KAAA,EAAO,MAAM,KAAA,GAAQ,GAAA;AAAA;AAAA,IACrB,OAAO,KAAA,CAAM;AAAA,GACf,CAAE,EACD,IAAA,CAAK,CAAC,GAAG,CAAA,KAAM,CAAA,CAAE,SAAA,GAAY,CAAA,CAAE,SAAS,CAAA;AAC7C;AAGA,IAAM,aAAA,GAAwC;AAAA,EAC5C,GAAA,EAAK,CAAA;AAAA,EACL,GAAA,EAAK,CAAA;AAAA,EACL,GAAA,EAAK,CAAA;AAAA,EACL,GAAA,EAAK,CAAA;AAAA,EACL,GAAA,EAAK,CAAA;AAAA,EACL,GAAA,EAAK,CAAA;AAAA,EACL,GAAA,EAAK,CAAA;AAAA,EACL,GAAA,EAAK,CAAA;AAAA,EACL,GAAA,EAAK,CAAA;AAAA,EACL,GAAA,EAAK,CAAA;AAAA,EACL,GAAA,EAAK,EAAA;AAAA,EACL,GAAA,EAAK;AACP,CAAA;AAOO,SAAS,mBAAmB,SAAA,EAA0D;AAC3F,EAAA,IAAI,CAAC,UAAU,kBAAA,IAAsB,SAAA,CAAU,mBAAmB,MAAA,KAAW,CAAA,SAAU,EAAC;AAExF,EAAA,OAAO,SAAA,CAAU,kBAAA,CACd,GAAA,CAAI,CAAC,KAAA,MAAW;AAAA,IACf,WAAW,IAAI,IAAA,CAAK,KAAA,CAAM,IAAI,EAAE,OAAA,EAAQ;AAAA,IACxC,YAAY,KAAA,CAAM,UAAA;AAAA,IAClB,YAAY,KAAA,CAAM,UAAA;AAAA,IAClB,MAAM,KAAA,CAAM,IAAA;AAAA,IACZ,MAAM,KAAA,CAAM;AAAA,GACd,CAAE,EACD,IAAA,CAAK,CAAC,GAAG,CAAA,KAAM,CAAA,CAAE,SAAA,GAAY,CAAA,CAAE,SAAS,CAAA;AAC7C;AAWO,SAAS,sBAAA,CACd,SACA,aAAA,EACe;AACf,EAAA,IAAI,CAAC,SAAS,OAAO,IAAA;AAGrB,EAAA,MAAM,OAAA,GAAU,IAAI,IAAA,CAAK,OAAO,CAAA;AAChC,EAAA,IAAI,CAAC,MAAA,CAAO,KAAA,CAAM,OAAA,CAAQ,OAAA,EAAS,CAAA,IAAK,OAAA,CAAQ,QAAA,CAAS,GAAG,CAAA,EAAG;AAC7D,IAAA,OAAO,QAAQ,OAAA,EAAQ;AAAA,EACzB;AAGA,EAAA,MAAM,OAAA,GAAU,OAAA,CACb,OAAA,CAAQ,IAAA,EAAM,EAAE,EAChB,OAAA,CAAQ,UAAA,EAAY,EAAE,CAAA,CACtB,IAAA,EAAK;AAGR,EAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,KAAA,CAAM,oDAAoD,CAAA;AAChF,EAAA,IAAI,CAAC,OAAO,OAAO,IAAA;AAEnB,EAAA,MAAM,WAAW,aAAA,CAAc,KAAA,CAAM,CAAC,CAAA,CAAE,aAAa,CAAA;AACrD,EAAA,IAAI,QAAA,KAAa,QAAW,OAAO,IAAA;AAEnC,EAAA,MAAM,MAAM,MAAA,CAAO,QAAA,CAAS,KAAA,CAAM,CAAC,GAAG,EAAE,CAAA;AACxC,EAAA,MAAM,IAAA,GAAO,KAAA,CAAM,CAAC,CAAA,GAAI,MAAA,CAAO,SAAS,KAAA,CAAM,CAAC,CAAA,EAAG,EAAE,CAAA,GAAI,EAAA;AACxD,EAAA,MAAM,MAAA,GAAS,KAAA,CAAM,CAAC,CAAA,GAAI,MAAA,CAAO,SAAS,KAAA,CAAM,CAAC,CAAA,EAAG,EAAE,CAAA,GAAI,CAAA;AAE1D,EAAA,MAAM,IAAA,GAAO,IAAI,IAAA,CAAK,IAAA,CAAK,GAAA,CAAI,aAAA,EAAe,QAAA,EAAU,GAAA,EAAK,IAAA,EAAM,MAAA,EAAQ,CAAC,CAAC,CAAA;AAC7E,EAAA,OAAO,KAAK,OAAA,EAAQ;AACtB;AAUO,SAAS,qBAAA,CACd,WACA,MAAA,EACmD;AACnD,EAAA,IAAI,MAAA,CAAO,MAAA,KAAW,CAAA,EAAG,OAAO,MAAA;AAGhC,EAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,IAAA,CAAK,CAAC,CAAA,KAAM;AAC/B,IAAA,MAAM,QAAQ,IAAI,IAAA,CAAK,CAAA,CAAE,KAAK,EAAE,OAAA,EAAQ;AACxC,IAAA,MAAM,MAAM,IAAI,IAAA,CAAK,CAAA,CAAE,GAAG,EAAE,OAAA,EAAQ;AACpC,IAAA,OAAO,SAAA,IAAa,SAAS,SAAA,IAAa,GAAA;AAAA,EAC5C,CAAC,CAAA;AACD,EAAA,IAAI,OAAO,OAAO,KAAA;AAGlB,EAAA,IAAI,OAAA;AACJ,EAAA,IAAI,cAAc,MAAA,CAAO,iBAAA;AAEzB,EAAA,KAAA,MAAW,KAAK,MAAA,EAAQ;AACtB,IAAA,MAAM,QAAQ,IAAI,IAAA,CAAK,CAAA,CAAE,KAAK,EAAE,OAAA,EAAQ;AACxC,IAAA,MAAM,MAAM,IAAI,IAAA,CAAK,CAAA,CAAE,GAAG,EAAE,OAAA,EAAQ;AACpC,IAAA,MAAM,QAAA,GAAW,IAAA,CAAK,GAAA,CAAI,IAAA,CAAK,GAAA,CAAI,SAAA,GAAY,KAAK,CAAA,EAAG,IAAA,CAAK,GAAA,CAAI,SAAA,GAAY,GAAG,CAAC,CAAA;AAChF,IAAA,IAAI,WAAW,WAAA,EAAa;AAC1B,MAAA,WAAA,GAAc,QAAA;AACd,MAAA,OAAA,GAAU,CAAA;AAAA,IACZ;AAAA,EACF;AAEA,EAAA,OAAO,OAAA;AACT;AChRO,IAAM,gBAAA,GAAmB,EAAE,MAAA,CAAO;AAAA;AAAA,EAEvC,EAAA,EAAI,CAAA,CAAE,MAAA,EAAO,CAAE,IAAI,CAAC,CAAA;AAAA;AAAA,EAEpB,OAAA,EAAS,CAAA,CAAE,MAAA,EAAO,CAAE,IAAI,CAAC,CAAA;AAAA;AAAA,EAEzB,IAAA,EAAM,CAAA,CAAE,MAAA,EAAO,CAAE,IAAI,CAAC,CAAA;AAAA;AAAA,EAEtB,OAAO,CAAA,CAAE,IAAA,CAAK,CAAC,UAAA,EAAY,OAAO,CAAC,CAAA;AAAA;AAAA,EAEnC,OAAA,EAAS,CAAA,CAAE,MAAA,EAAO,CAAE,QAAA;AACtB,CAAC;AAEM,IAAM,gBAAA,GAAmB,EAC7B,MAAA,CAAO;AAAA;AAAA,EAEN,OAAA,EAAS,CAAA,CAAE,OAAA,CAAQ,CAAC,CAAA;AAAA;AAAA,EAEpB,OAAO,CAAA,CAAE,KAAA,CAAM,gBAAgB,CAAA,CAAE,IAAI,CAAC;AACxC,CAAC,CAAA,CACA,WAAA,CAAY,CAAC,IAAA,EAAM,GAAA,KAAQ;AAE1B,EAAA,MAAM,GAAA,uBAAU,GAAA,EAAY;AAC5B,EAAA,KAAA,IAAS,IAAI,CAAA,EAAG,CAAA,GAAI,IAAA,CAAK,KAAA,CAAM,QAAQ,CAAA,EAAA,EAAK;AAC1C,IAAA,MAAM,EAAA,GAAK,IAAA,CAAK,KAAA,CAAM,CAAC,CAAA,CAAE,EAAA;AACzB,IAAA,IAAI,GAAA,CAAI,GAAA,CAAI,EAAE,CAAA,EAAG;AACf,MAAA,GAAA,CAAI,QAAA,CAAS;AAAA,QACX,IAAA,EAAM,EAAE,YAAA,CAAa,MAAA;AAAA,QACrB,OAAA,EAAS,CAAA,oBAAA,EAAuB,EAAE,CAAA,cAAA,EAAiB,CAAC,CAAA,CAAA,CAAA;AAAA,QACpD,IAAA,EAAM,CAAC,OAAA,EAAS,CAAA,EAAG,IAAI;AAAA,OACxB,CAAA;AAAA,IACH;AACA,IAAA,GAAA,CAAI,IAAI,EAAE,CAAA;AAAA,EACZ;AACF,CAAC;AC5BI,IAAM,gBAAA,GAAmBA,EAAE,MAAA,CAAO;AAAA;AAAA,EAEvC,EAAA,EAAIA,CAAAA,CAAE,MAAA,EAAO,CAAE,IAAI,CAAC,CAAA;AAAA;AAAA,EAEpB,IAAA,EAAMA,CAAAA,CAAE,MAAA,EAAO,CAAE,IAAI,CAAC,CAAA;AAAA;AAAA,EAEtB,YAAA,EAAcA,CAAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS;AAAA;AAAA,EAElC,YAAYA,CAAAA,CAAE,MAAA,EAAO,CAAE,WAAA,GAAc,QAAA,EAAS;AAAA;AAAA,EAE9C,UAAUA,CAAAA,CAAE,MAAA,EAAO,CAAE,QAAA,GAAW,QAAA,EAAS;AAAA;AAAA,EAEzC,aAAaA,CAAAA,CAAE,MAAA,EAAO,CAAE,QAAA,GAAW,QAAA,EAAS;AAAA;AAAA,EAE5C,IAAA,EAAMA,CAAAA,CAAE,MAAA,EAAO,CAAE,QAAA;AACnB,CAAC;AAEM,IAAM,gBAAA,GAAmBA,EAC7B,MAAA,CAAO;AAAA;AAAA,EAEN,OAAA,EAASA,CAAAA,CAAE,OAAA,CAAQ,CAAC,CAAA;AAAA;AAAA,EAEpB,WAAWA,CAAAA,CAAE,MAAA,EAAO,CAAE,WAAA,GAAc,QAAA,EAAS;AAAA;AAAA,EAE7C,YAAYA,CAAAA,CAAE,MAAA,EAAO,CAAE,WAAA,GAAc,QAAA,EAAS;AAAA;AAAA,EAE9C,eAAA,EAAiBA,CAAAA,CAAE,MAAA,EAAO,CAAE,WAAA,EAAY;AAAA;AAAA,EAExC,eAAA,EAAiBA,CAAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS;AAAA;AAAA,EAErC,OAAOA,CAAAA,CAAE,KAAA,CAAM,gBAAgB,CAAA,CAAE,IAAI,CAAC;AACxC,CAAC,CAAA,CACA,WAAA,CAAY,CAAC,IAAA,EAAM,GAAA,KAAQ;AAE1B,EAAA,MAAM,GAAA,uBAAU,GAAA,EAAY;AAC5B,EAAA,KAAA,IAAS,IAAI,CAAA,EAAG,CAAA,GAAI,IAAA,CAAK,KAAA,CAAM,QAAQ,CAAA,EAAA,EAAK;AAC1C,IAAA,MAAM,EAAA,GAAK,IAAA,CAAK,KAAA,CAAM,CAAC,CAAA,CAAE,EAAA;AACzB,IAAA,IAAI,GAAA,CAAI,GAAA,CAAI,EAAE,CAAA,EAAG;AACf,MAAA,GAAA,CAAI,QAAA,CAAS;AAAA,QACX,IAAA,EAAMA,EAAE,YAAA,CAAa,MAAA;AAAA,QACrB,OAAA,EAAS,CAAA,oBAAA,EAAuB,EAAE,CAAA,cAAA,EAAiB,CAAC,CAAA,CAAA,CAAA;AAAA,QACpD,IAAA,EAAM,CAAC,OAAA,EAAS,CAAA,EAAG,IAAI;AAAA,OACxB,CAAA;AAAA,IACH;AACA,IAAA,GAAA,CAAI,IAAI,EAAE,CAAA;AAAA,EACZ;AACF,CAAC;AClDI,IAAM,eAAA,GAAkBA,EAC5B,MAAA,CAAO;AAAA;AAAA,EAEN,EAAA,EAAIA,CAAAA,CAAE,MAAA,EAAO,CAAE,IAAI,CAAC,CAAA;AAAA;AAAA,EAEpB,OAAA,EAASA,CAAAA,CAAE,MAAA,EAAO,CAAE,IAAI,CAAC,CAAA;AAAA;AAAA,EAEzB,IAAA,EAAMA,CAAAA,CAAE,MAAA,EAAO,CAAE,IAAI,CAAC,CAAA;AAAA;AAAA,EAEtB,OAAOA,CAAAA,CAAE,IAAA,CAAK,CAAC,UAAA,EAAY,OAAO,CAAC,CAAA;AAAA;AAAA,EAEnC,QAAA,EAAUA,CAAAA,CAAE,MAAA,EAAO,CAAE,WAAA,EAAY;AAAA;AAAA,EAEjC,WAAA,EAAaA,CAAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS;AAAA;AAAA,EAEjC,aAAA,EAAeA,CAAAA,CAAE,MAAA,EAAO,CAAE,WAAA,EAAY;AAAA;AAAA,EAEtC,SAAA,EAAWA,CAAAA,CAAE,MAAA,EAAO,CAAE,IAAI,CAAC,CAAA;AAAA;AAAA,EAE3B,aAAA,EAAeA,EAAE,MAAA,EAAO,CAAE,IAAI,CAAC,CAAA,CAAE,IAAI,CAAC,CAAA;AAAA;AAAA,EAEtC,WAAA,EAAaA,EAAE,MAAA,EAAO,CAAE,IAAI,CAAC,CAAA,CAAE,IAAI,CAAC,CAAA;AAAA;AAAA,EAEpC,QAAA,EAAUA,CAAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS;AAAA;AAAA,EAE9B,WAAA,EAAaA,CAAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS;AAAA;AAAA,EAEjC,KAAA,EAAOA,CAAAA,CAAE,MAAA,EAAO,CAAE,QAAA;AACpB,CAAC,EACA,MAAA,CAAO,CAAC,SAAS,IAAA,CAAK,aAAA,IAAiB,KAAK,WAAA,EAAa;AAAA,EACxD,OAAA,EAAS,sCAAA;AAAA,EACT,IAAA,EAAM,CAAC,eAAe;AACxB,CAAC;AAEI,IAAM,gBAAA,GAAmBA,EAC7B,MAAA,CAAO;AAAA;AAAA,EAEN,OAAA,EAASA,CAAAA,CAAE,OAAA,CAAQ,CAAC,CAAA;AAAA;AAAA,EAEpB,gBAAA,EAAkBA,CAAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS;AAAA;AAAA,EAEtC,OAAOA,CAAAA,CAAE,KAAA,CAAM,eAAe,CAAA,CAAE,IAAI,CAAC;AACvC,CAAC,CAAA,CACA,WAAA,CAAY,CAAC,IAAA,EAAM,GAAA,KAAQ;AAE1B,EAAA,MAAM,GAAA,uBAAU,GAAA,EAAY;AAC5B,EAAA,KAAA,IAAS,IAAI,CAAA,EAAG,CAAA,GAAI,IAAA,CAAK,KAAA,CAAM,QAAQ,CAAA,EAAA,EAAK;AAC1C,IAAA,MAAM,EAAA,GAAK,IAAA,CAAK,KAAA,CAAM,CAAC,CAAA,CAAE,EAAA;AACzB,IAAA,IAAI,GAAA,CAAI,GAAA,CAAI,EAAE,CAAA,EAAG;AACf,MAAA,GAAA,CAAI,QAAA,CAAS;AAAA,QACX,IAAA,EAAMA,EAAE,YAAA,CAAa,MAAA;AAAA,QACrB,OAAA,EAAS,CAAA,oBAAA,EAAuB,EAAE,CAAA,cAAA,EAAiB,CAAC,CAAA,CAAA,CAAA;AAAA,QACpD,IAAA,EAAM,CAAC,OAAA,EAAS,CAAA,EAAG,IAAI;AAAA,OACxB,CAAA;AAAA,IACH;AACA,IAAA,GAAA,CAAI,IAAI,EAAE,CAAA;AAAA,EACZ;AACF,CAAC;;;ACiBI,SAAS,sBAAsB,QAAA,EAAqC;AACzE,EAAA,MAAM,SAAmB,EAAC;AAE1B,EAAA,IAAI,QAAA,IAAY,IAAA,IAAQ,OAAO,QAAA,KAAa,QAAA,EAAU;AACpD,IAAA,OAAO,EAAE,KAAA,EAAO,KAAA,EAAO,MAAA,EAAQ,CAAC,oCAAoC,CAAA,EAAE;AAAA,EACxE;AAEA,EAAA,MAAM,CAAA,GAAI,QAAA;AAGV,EAAA,IAAI,CAAA,CAAE,YAAY,CAAA,EAAG;AACnB,IAAA,MAAA,CAAO,KAAK,CAAA,uBAAA,EAA0B,IAAA,CAAK,UAAU,CAAA,CAAE,OAAO,CAAC,CAAA,CAAE,CAAA;AAAA,EACnE;AACA,EAAA,IAAI,OAAO,CAAA,CAAE,GAAA,KAAQ,QAAA,IAAY,CAAA,CAAE,OAAO,CAAA,EAAG;AAC3C,IAAA,MAAA,CAAO,KAAK,CAAA,mCAAA,EAAsC,IAAA,CAAK,UAAU,CAAA,CAAE,GAAG,CAAC,CAAA,CAAE,CAAA;AAAA,EAC3E;AACA,EAAA,IAAI,OAAO,CAAA,CAAE,gBAAA,KAAqB,QAAA,IAAY,CAAA,CAAE,oBAAoB,CAAA,EAAG;AACrE,IAAA,MAAA,CAAO,IAAA;AAAA,MACL,CAAA,gDAAA,EAAmD,IAAA,CAAK,SAAA,CAAU,CAAA,CAAE,gBAAgB,CAAC,CAAA;AAAA,KACvF;AAAA,EACF;AAEA,EAAA,MAAM,WAAW,OAAO,CAAA,CAAE,gBAAA,KAAqB,QAAA,GAAW,EAAE,gBAAA,GAAmB,CAAA;AAG/E,EAAA,IAAI,CAAC,KAAA,CAAM,OAAA,CAAQ,CAAA,CAAE,MAAM,CAAA,EAAG;AAC5B,IAAA,MAAA,CAAO,KAAK,yBAAyB,CAAA;AAAA,EACvC;AACA,EAAA,IAAI,CAAC,KAAA,CAAM,OAAA,CAAQ,CAAA,CAAE,KAAK,CAAA,EAAG;AAC3B,IAAA,MAAA,CAAO,KAAK,wBAAwB,CAAA;AAAA,EACtC;AACA,EAAA,IAAI,CAAC,KAAA,CAAM,OAAA,CAAQ,CAAA,CAAE,GAAG,CAAA,EAAG;AACzB,IAAA,MAAA,CAAO,KAAK,sBAAsB,CAAA;AAAA,EACpC;AACA,EAAA,IAAI,CAAC,KAAA,CAAM,OAAA,CAAQ,CAAA,CAAE,QAAQ,CAAA,EAAG;AAC9B,IAAA,MAAA,CAAO,KAAK,2BAA2B,CAAA;AAAA,EACzC;AAGA,EAAA,IAAI,MAAA,CAAO,SAAS,CAAA,EAAG;AACrB,IAAA,OAAO,EAAE,KAAA,EAAO,KAAA,EAAO,MAAA,EAAO;AAAA,EAChC;AAEA,EAAA,MAAM,SAAS,CAAA,CAAE,MAAA;AACjB,EAAA,MAAM,QAAQ,CAAA,CAAE,KAAA;AAChB,EAAA,MAAM,MAAM,CAAA,CAAE,GAAA;AACd,EAAA,MAAM,WAAW,CAAA,CAAE,QAAA;AAGnB,EAAA,SAAS,aAAA,CAAc,MAAe,OAAA,EAAuB;AAC3D,IAAA,IAAI,OAAO,IAAA,KAAS,QAAA,IAAY,IAAA,CAAK,WAAW,CAAA,EAAG;AACjD,MAAA,MAAA,CAAO,IAAA,CAAK,CAAA,EAAG,OAAO,CAAA,iCAAA,CAAmC,CAAA;AAAA,IAC3D,CAAA,MAAA,IAAW,KAAK,UAAA,CAAW,GAAG,KAAK,IAAA,CAAK,UAAA,CAAW,IAAI,CAAA,EAAG;AACxD,MAAA,MAAA,CAAO,IAAA,CAAK,CAAA,EAAG,OAAO,CAAA,qCAAA,EAAwC,IAAI,CAAA,CAAA,CAAG,CAAA;AAAA,IACvE;AAAA,EACF;AAEA,EAAA,SAAS,WAAA,CAAY,GAAA,EAAc,OAAA,EAAiB,QAAA,EAAyB;AAC3E,IAAA,IAAI,OAAO,IAAA,EAAM;AACf,MAAA,IAAI,QAAA,EAAU,MAAA,CAAO,IAAA,CAAK,CAAA,EAAG,OAAO,CAAA,oBAAA,CAAsB,CAAA;AAC1D,MAAA;AAAA,IACF;AACA,IAAA,IAAI,OAAO,GAAA,KAAQ,QAAA,IAAY,GAAA,GAAM,CAAA,IAAK,MAAM,CAAA,EAAG;AACjD,MAAA,MAAA,CAAO,IAAA,CAAK,GAAG,OAAO,CAAA,0BAAA,EAA6B,KAAK,SAAA,CAAU,GAAG,CAAC,CAAA,CAAE,CAAA;AAAA,IAC1E;AAAA,EACF;AAEA,EAAA,SAAS,iBAAA,CAAkB,QAAA,EAAmB,WAAA,EAAsB,OAAA,EAAuB;AACzF,IAAA,IAAI,OAAO,QAAA,KAAa,QAAA,IAAY,QAAA,GAAW,CAAA,EAAG;AAChD,MAAA,MAAA,CAAO,IAAA;AAAA,QACL,GAAG,OAAO,CAAA,8CAAA,EAAiD,IAAA,CAAK,SAAA,CAAU,QAAQ,CAAC,CAAA;AAAA,OACrF;AACA,MAAA;AAAA,IACF;AACA,IAAA,IAAI,OAAO,gBAAgB,QAAA,EAAU;AACnC,MAAA,IAAI,cAAc,CAAA,EAAG;AACnB,QAAA,MAAA,CAAO,IAAA,CAAK,CAAA,EAAG,OAAO,CAAA,wCAAA,EAA2C,WAAW,CAAA,CAAE,CAAA;AAAA,MAChF;AACA,MAAA,IAAI,QAAA,GAAW,cAAc,QAAA,EAAU;AACrC,QAAA,MAAA,CAAO,IAAA;AAAA,UACL,CAAA,EAAG,OAAO,CAAA,YAAA,EAAe,QAAQ,CAAA,iBAAA,EAAoB,WAAW,CAAA,IAAA,EAAO,QAAA,GAAW,WAAW,CAAA,2BAAA,EAA8B,QAAQ,CAAA,CAAA;AAAA,SACrI;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAGA,EAAA,MAAM,GAAA,uBAAU,GAAA,EAAY;AAC5B,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,MAAA,CAAO,QAAQ,CAAA,EAAA,EAAK;AACtC,IAAA,MAAM,CAAA,GAAI,OAAO,CAAC,CAAA;AAClB,IAAA,MAAM,MAAM,CAAA,OAAA,EAAU,CAAC,CAAA,GAAA,EAAM,CAAA,CAAE,MAAM,OAAO,CAAA,CAAA,CAAA;AAE5C,IAAA,IAAI,OAAO,CAAA,CAAE,EAAA,KAAO,YAAY,CAAA,CAAE,EAAA,CAAG,WAAW,CAAA,EAAG;AACjD,MAAA,MAAA,CAAO,IAAA,CAAK,CAAA,EAAG,GAAG,CAAA,+BAAA,CAAiC,CAAA;AAAA,IACrD,CAAA,MAAA,IAAW,GAAA,CAAI,GAAA,CAAI,CAAA,CAAE,EAAE,CAAA,EAAG;AACxB,MAAA,MAAA,CAAO,KAAK,CAAA,EAAG,GAAG,CAAA,gBAAA,EAAmB,CAAA,CAAE,EAAE,CAAA,CAAA,CAAG,CAAA;AAAA,IAC9C,CAAA,MAAO;AACL,MAAA,GAAA,CAAI,GAAA,CAAI,EAAE,EAAE,CAAA;AAAA,IACd;AAEA,IAAA,aAAA,CAAc,CAAA,CAAE,MAAM,GAAG,CAAA;AAEzB,IAAA,IAAI,OAAO,CAAA,CAAE,OAAA,KAAY,YAAY,CAAA,CAAE,OAAA,CAAQ,WAAW,CAAA,EAAG;AAC3D,MAAA,MAAA,CAAO,IAAA,CAAK,CAAA,EAAG,GAAG,CAAA,oCAAA,CAAsC,CAAA;AAAA,IAC1D;AACA,IAAA,IAAI,OAAO,CAAA,CAAE,IAAA,KAAS,QAAA,EAAU;AAC9B,MAAA,MAAA,CAAO,IAAA,CAAK,CAAA,EAAG,GAAG,CAAA,uBAAA,CAAyB,CAAA;AAAA,IAC7C;AACA,IAAA,IAAI,OAAO,CAAA,CAAE,WAAA,KAAgB,QAAA,IAAY,CAAA,CAAE,eAAe,CAAA,EAAG;AAC3D,MAAA,MAAA,CAAO,IAAA;AAAA,QACL,GAAG,GAAG,CAAA,6CAAA,EAAgD,KAAK,SAAA,CAAU,CAAA,CAAE,WAAW,CAAC,CAAA;AAAA,OACrF;AAAA,IACF;AAEA,IAAA,iBAAA,CAAkB,CAAA,CAAE,QAAA,EAAU,CAAA,CAAE,WAAA,EAAa,GAAG,CAAA;AAChD,IAAA,WAAA,CAAY,CAAA,CAAE,MAAA,EAAQ,GAAA,EAAK,KAAK,CAAA;AAEhC,IAAA,IACE,CAAA,CAAE,KAAA,KAAU,MAAA,IACZ,CAAA,CAAE,KAAA,KAAU,OAAA,IACZ,CAAA,CAAE,KAAA,KAAU,UAAA,IACZ,CAAA,CAAE,KAAA,KAAU,WAAA,EACZ;AACA,MAAA,MAAA,CAAO,KAAK,CAAA,EAAG,GAAG,CAAA,0DAAA,EAA6D,CAAA,CAAE,KAAK,CAAA,CAAA,CAAG,CAAA;AAAA,IAC3F;AAAA,EACF;AAGA,EAAA,MAAM,SAAA,uBAAgB,GAAA,EAA0B;AAChD,EAAA,KAAA,MAAW,KAAK,MAAA,EAAQ;AACtB,IAAA,IAAI,OAAO,CAAA,CAAE,OAAA,KAAY,QAAA,EAAU;AACnC,IAAA,MAAM,OAAO,SAAA,CAAU,GAAA,CAAI,CAAA,CAAE,OAAO,KAAK,EAAC;AAC1C,IAAA,IAAA,CAAK,KAAK,CAAC,CAAA;AACX,IAAA,SAAA,CAAU,GAAA,CAAI,CAAA,CAAE,OAAA,EAAS,IAAI,CAAA;AAAA,EAC/B;AACA,EAAA,KAAA,MAAW,CAAC,OAAA,EAAS,KAAK,CAAA,IAAK,SAAA,EAAW;AACxC,IAAA,MAAM,MAAA,GAAS,CAAC,GAAG,KAAK,CAAA,CAAE,IAAA,CAAK,CAAC,CAAA,EAAG,CAAA,KAAM,CAAA,CAAE,QAAA,GAAW,CAAA,CAAE,QAAQ,CAAA;AAChE,IAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,MAAA,CAAO,QAAQ,CAAA,EAAA,EAAK;AACtC,MAAA,MAAM,IAAA,GAAO,MAAA,CAAO,CAAA,GAAI,CAAC,CAAA;AACzB,MAAA,MAAM,IAAA,GAAO,OAAO,CAAC,CAAA;AACrB,MAAA,MAAM,OAAA,GAAU,IAAA,CAAK,QAAA,GAAW,IAAA,CAAK,WAAA;AACrC,MAAA,IAAI,OAAA,GAAU,KAAK,QAAA,EAAU;AAC3B,QAAA,MAAA,CAAO,IAAA;AAAA,UACL,CAAA,4BAAA,EAA+B,OAAO,CAAA,IAAA,EAAO,IAAA,CAAK,EAAE,CAAA,UAAA,EAAa,OAAO,CAAA,OAAA,EAAU,IAAA,CAAK,EAAE,CAAA,YAAA,EAAe,IAAA,CAAK,QAAQ,CAAA,CAAA;AAAA,SACvH;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAGA,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,KAAA,CAAM,QAAQ,CAAA,EAAA,EAAK;AACrC,IAAA,MAAM,CAAA,GAAI,MAAM,CAAC,CAAA;AACjB,IAAA,MAAM,MAAM,CAAA,MAAA,EAAS,CAAC,CAAA,GAAA,EAAM,CAAA,CAAE,MAAM,OAAO,CAAA,CAAA,CAAA;AAE3C,IAAA,IAAI,OAAO,CAAA,CAAE,EAAA,KAAO,YAAY,CAAA,CAAE,EAAA,CAAG,WAAW,CAAA,EAAG;AACjD,MAAA,MAAA,CAAO,IAAA,CAAK,CAAA,EAAG,GAAG,CAAA,+BAAA,CAAiC,CAAA;AAAA,IACrD;AACA,IAAA,aAAA,CAAc,CAAA,CAAE,MAAM,GAAG,CAAA;AACzB,IAAA,iBAAA,CAAkB,CAAA,CAAE,QAAA,EAAU,CAAA,CAAE,WAAA,EAAa,GAAG,CAAA;AAChD,IAAA,WAAA,CAAY,CAAA,CAAE,MAAA,EAAQ,GAAA,EAAK,IAAI,CAAA;AAE/B,IAAA,IAAI,CAAA,CAAE,aAAa,IAAA,KAAS,OAAO,EAAE,SAAA,KAAc,QAAA,IAAY,CAAA,CAAE,SAAA,GAAY,CAAA,CAAA,EAAI;AAC/E,MAAA,MAAA,CAAO,IAAA,CAAK,CAAA,EAAG,GAAG,CAAA,yCAAA,CAA2C,CAAA;AAAA,IAC/D;AACA,IAAA,IAAI,CAAA,CAAE,cAAc,IAAA,KAAS,OAAO,EAAE,UAAA,KAAe,QAAA,IAAY,CAAA,CAAE,UAAA,GAAa,CAAA,CAAA,EAAI;AAClF,MAAA,MAAA,CAAO,IAAA,CAAK,CAAA,EAAG,GAAG,CAAA,0CAAA,CAA4C,CAAA;AAAA,IAChE;AACA,IAAA,IAAI,CAAA,CAAE,UAAU,IAAA,EAAM;AACpB,MAAA,IAAI,OAAO,EAAE,MAAA,KAAW,QAAA,IAAY,EAAE,MAAA,GAAS,CAAA,IAAK,CAAA,CAAE,MAAA,GAAS,CAAA,EAAG;AAChE,QAAA,MAAA,CAAO,IAAA,CAAK,GAAG,GAAG,CAAA,0BAAA,EAA6B,KAAK,SAAA,CAAU,CAAA,CAAE,MAAM,CAAC,CAAA,CAAE,CAAA;AAAA,MAC3E;AAAA,IACF;AAAA,EACF;AAGA,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,GAAA,CAAI,QAAQ,CAAA,EAAA,EAAK;AACnC,IAAA,MAAM,CAAA,GAAI,IAAI,CAAC,CAAA;AACf,IAAA,MAAM,MAAM,CAAA,IAAA,EAAO,CAAC,CAAA,GAAA,EAAM,CAAA,CAAE,MAAM,OAAO,CAAA,CAAA,CAAA;AAEzC,IAAA,IAAI,OAAO,CAAA,CAAE,EAAA,KAAO,YAAY,CAAA,CAAE,EAAA,CAAG,WAAW,CAAA,EAAG;AACjD,MAAA,MAAA,CAAO,IAAA,CAAK,CAAA,EAAG,GAAG,CAAA,+BAAA,CAAiC,CAAA;AAAA,IACrD;AACA,IAAA,aAAA,CAAc,CAAA,CAAE,MAAM,GAAG,CAAA;AACzB,IAAA,IAAI,OAAO,CAAA,CAAE,QAAA,KAAa,QAAA,IAAY,CAAA,CAAE,WAAW,CAAA,EAAG;AACpD,MAAA,MAAA,CAAO,IAAA;AAAA,QACL,GAAG,GAAG,CAAA,8CAAA,EAAiD,KAAK,SAAA,CAAU,CAAA,CAAE,QAAQ,CAAC,CAAA;AAAA,OACnF;AAAA,IACF;AACA,IAAA,IAAI,CAAA,CAAE,WAAW,QAAA,EAAU;AACzB,MAAA,MAAA,CAAO,IAAA,CAAK,GAAG,GAAG,CAAA,YAAA,EAAe,EAAE,QAAQ,CAAA,4BAAA,EAA+B,QAAQ,CAAA,CAAA,CAAG,CAAA;AAAA,IACvF;AACA,IAAA,WAAA,CAAY,CAAA,CAAE,MAAA,EAAQ,GAAA,EAAK,KAAK,CAAA;AAAA,EAClC;AAGA,EAAA,MAAM,iBAAA,uBAAwB,GAAA,CAAI,CAAC,cAAc,eAAA,EAAiB,aAAA,EAAe,SAAS,CAAC,CAAA;AAC3F,EAAA,MAAM,cAAA,uBAAqB,GAAA,CAAI,CAAC,UAAU,aAAA,EAAe,cAAA,EAAgB,KAAK,CAAC,CAAA;AAC/E,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,QAAA,CAAS,QAAQ,CAAA,EAAA,EAAK;AACxC,IAAA,MAAM,CAAA,GAAI,SAAS,CAAC,CAAA;AACpB,IAAA,MAAM,MAAM,CAAA,SAAA,EAAY,CAAC,CAAA,GAAA,EAAM,CAAA,CAAE,MAAM,OAAO,CAAA,CAAA,CAAA;AAE9C,IAAA,IAAI,OAAO,CAAA,CAAE,EAAA,KAAO,YAAY,CAAA,CAAE,EAAA,CAAG,WAAW,CAAA,EAAG;AACjD,MAAA,MAAA,CAAO,IAAA,CAAK,CAAA,EAAG,GAAG,CAAA,+BAAA,CAAiC,CAAA;AAAA,IACrD;AACA,IAAA,IAAI,CAAC,iBAAA,CAAkB,GAAA,CAAI,CAAA,CAAE,IAAI,CAAA,EAAG;AAClC,MAAA,MAAA,CAAO,IAAA;AAAA,QACL,CAAA,EAAG,GAAG,CAAA,sBAAA,EAAyB,CAAC,GAAG,iBAAiB,CAAA,CAAE,IAAA,CAAK,IAAI,CAAC,CAAA,OAAA,EAAU,CAAA,CAAE,IAAI,CAAA,CAAA;AAAA,OAClF;AAAA,IACF;AACA,IAAA,IAAI,OAAO,CAAA,CAAE,IAAA,KAAS,YAAY,CAAA,CAAE,IAAA,CAAK,WAAW,CAAA,EAAG;AACrD,MAAA,MAAA,CAAO,IAAA,CAAK,CAAA,EAAG,GAAG,CAAA,iCAAA,CAAmC,CAAA;AAAA,IACvD;AACA,IAAA,IAAI,OAAO,CAAA,CAAE,WAAA,KAAgB,QAAA,IAAY,CAAA,CAAE,eAAe,CAAA,EAAG;AAC3D,MAAA,MAAA,CAAO,IAAA;AAAA,QACL,GAAG,GAAG,CAAA,6CAAA,EAAgD,KAAK,SAAA,CAAU,CAAA,CAAE,WAAW,CAAC,CAAA;AAAA,OACrF;AAAA,IACF;AACA,IAAA,iBAAA,CAAkB,CAAA,CAAE,QAAA,EAAU,CAAA,CAAE,WAAA,EAAa,GAAG,CAAA;AAEhD,IAAA,IAAI,CAAA,CAAE,SAAS,IAAA,EAAM;AACnB,MAAA,IAAI,OAAO,CAAA,CAAE,KAAA,KAAU,QAAA,EAAU;AAC/B,QAAA,MAAA,CAAO,IAAA,CAAK,CAAA,EAAG,GAAG,CAAA,yBAAA,CAA2B,CAAA;AAAA,MAC/C,CAAA,MAAO;AACL,QAAA,IACE,CAAA,CAAE,KAAA,CAAM,QAAA,IAAY,IAAA,KACnB,OAAO,CAAA,CAAE,KAAA,CAAM,QAAA,KAAa,QAAA,IAAY,CAAA,CAAE,KAAA,CAAM,QAAA,IAAY,CAAA,CAAA,EAC7D;AACA,UAAA,MAAA,CAAO,IAAA,CAAK,CAAA,EAAG,GAAG,CAAA,0CAAA,CAA4C,CAAA;AAAA,QAChE;AACA,QAAA,IAAI,CAAA,CAAE,MAAM,KAAA,IAAS,IAAA,IAAQ,OAAO,CAAA,CAAE,KAAA,CAAM,UAAU,QAAA,EAAU;AAC9D,UAAA,MAAA,CAAO,IAAA,CAAK,CAAA,EAAG,GAAG,CAAA,8BAAA,CAAgC,CAAA;AAAA,QACpD;AACA,QAAA,IAAI,CAAA,CAAE,KAAA,CAAM,QAAA,IAAY,IAAA,IAAQ,CAAC,eAAe,GAAA,CAAI,CAAA,CAAE,KAAA,CAAM,QAAQ,CAAA,EAAG;AACrE,UAAA,MAAA,CAAO,IAAA;AAAA,YACL,CAAA,EAAG,GAAG,CAAA,gCAAA,EAAmC,CAAC,GAAG,cAAc,CAAA,CAAE,IAAA,CAAK,IAAI,CAAC,CAAA,OAAA,EAAU,CAAA,CAAE,MAAM,QAAQ,CAAA,CAAA;AAAA,WACnG;AAAA,QACF;AACA,QAAA,IACE,EAAE,KAAA,CAAM,WAAA,KAAgB,MAAA,IACxB,CAAA,CAAE,MAAM,WAAA,KAAgB,IAAA,KACvB,OAAO,CAAA,CAAE,MAAM,WAAA,KAAgB,QAAA,IAAY,CAAA,CAAE,KAAA,CAAM,eAAe,CAAA,CAAA,EACnE;AACA,UAAA,MAAA,CAAO,IAAA,CAAK,CAAA,EAAG,GAAG,CAAA,qDAAA,CAAuD,CAAA;AAAA,QAC3E;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,EAAA,OAAO,EAAE,KAAA,EAAO,MAAA,CAAO,MAAA,KAAW,GAAG,MAAA,EAAO;AAC9C;AAWO,SAAS,qBACd,QAAA,EACQ;AACR,EAAA,IAAI,MAAA,GAAS,CAAA;AAEb,EAAA,KAAA,MAAW,CAAA,IAAK,SAAS,MAAA,EAAQ;AAC/B,IAAA,MAAA,GAAS,KAAK,GAAA,CAAI,MAAA,EAAQ,CAAA,CAAE,QAAA,GAAW,EAAE,WAAW,CAAA;AAAA,EACtD;AACA,EAAA,KAAA,MAAW,CAAA,IAAK,SAAS,KAAA,EAAO;AAC9B,IAAA,MAAA,GAAS,KAAK,GAAA,CAAI,MAAA,EAAQ,CAAA,CAAE,QAAA,GAAW,EAAE,WAAW,CAAA;AAAA,EACtD;AACA,EAAA,KAAA,MAAW,CAAA,IAAK,SAAS,GAAA,EAAK;AAE5B,IAAA,MAAA,GAAS,IAAA,CAAK,GAAA,CAAI,MAAA,EAAQ,CAAA,CAAE,QAAQ,CAAA;AAAA,EACtC;AACA,EAAA,KAAA,MAAW,CAAA,IAAK,SAAS,QAAA,EAAU;AACjC,IAAA,MAAA,GAAS,KAAK,GAAA,CAAI,MAAA,EAAQ,CAAA,CAAE,QAAA,GAAW,EAAE,WAAW,CAAA;AAAA,EACtD;AAEA,EAAA,OAAO,MAAA,GAAS,CAAA;AAClB","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 ),\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): 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 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,\n startTime: new Date(p.start).getTime(),\n endTime: new Date(p.end).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).getTime();\n const end = new Date(p.end).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).getTime();\n const end = new Date(p.end).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 * 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\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 if (m.version !== 1) {\n errors.push(`version must be 1, got ${JSON.stringify(m.version)}`);\n }\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 const totalDur = typeof m.totalDurationSec === 'number' ? m.totalDurationSec : 0;\n\n // --- Arrays must exist ---\n if (!Array.isArray(m.dialog)) {\n errors.push('dialog must be an array');\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 if (!Array.isArray(m.overlays)) {\n errors.push('overlays 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 = m.dialog as DialogBeat[];\n const music = m.music as MusicTrack[];\n const sfx = m.sfx as SfxPlacement[];\n const 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 if (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 (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"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "miriad-viz",
3
- "version": "0.9.4",
3
+ "version": "0.9.6",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/snorrees/miriad-viz.git"