Ionosphere.tv
3
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'ionosphere-format-trans'

+8255 -850
+7 -1
.gitignore
··· 19 19 .claude/worktrees 20 20 .superpowers/ 21 21 docs/superpowers/ 22 - __pycache__/ 23 22 Trace-*.json.gz 23 + 24 + # Python NLP pipeline 25 + pipeline/.venv/ 26 + pipeline/data/ 27 + pipeline/*.egg-info/ 28 + __pycache__/ 29 + *.pyc
+1
.panproto/HEAD
··· 1 + {"Branch":"main"}
+5
.panproto/index.json
··· 1 + { 2 + "staged": null, 3 + "staged_data": [], 4 + "staged_protocol": null 5 + }
.panproto/objects/1b/b664060ba18e4a0b3b0bff1add938bd3d0127f3a7d3b3d03a22468e3d46276

This is a binary file and will not be displayed.

.panproto/objects/2c/6ca16b08d3b822ce25804cd147f8a8887d00d7b64a0a62d32f3d44b6f29807

This is a binary file and will not be displayed.

.panproto/objects/89/215c53859ff49be231d954234820efd393906a6a0499477369c709eba3d53c

This is a binary file and will not be displayed.

.panproto/objects/fb/de01706511f5588e0c43d349742ac27d048b903fed4355c45e1dd78980269e

This is a binary file and will not be displayed.

+1
.panproto/refs/heads/main
··· 1 + fbde01706511f5588e0c43d349742ac27d048b903fed4355c45e1dd78980269e
+1
.panproto/refs/tags/v0.5.0
··· 1 + fbde01706511f5588e0c43d349742ac27d048b903fed4355c45e1dd78980269e
+266
apps/ionosphere-appview/src/__tests__/layers-pub.test.ts
··· 1 + import { describe, it, expect } from 'vitest'; 2 + import { transcriptToLayersPub, nlpToAnnotationLayers, layersPubToDocument } from '../../../../formats/tv.ionosphere/ts/layers-pub.js'; 3 + 4 + describe('Lens 1: transcript → expression + segmentation', () => { 5 + const transcript = { 6 + $type: 'tv.ionosphere.transcript', 7 + talkUri: 'at://did:plc:test/tv.ionosphere.talk/test-talk', 8 + text: 'Hello world foo bar', 9 + startMs: 1000, 10 + // word durations: Hello=200ms, world=300ms, 100ms gap, foo=150ms, bar=250ms 11 + timings: [200, 300, -100, 150, 250], 12 + }; 13 + 14 + const did = 'did:plc:test'; 15 + const talkRkey = 'test-talk'; 16 + 17 + it('produces an expression record with correct fields', async () => { 18 + const { expression } = await transcriptToLayersPub(transcript, did, talkRkey); 19 + expect(expression.$type).toBe('pub.layers.expression.expression'); 20 + expect(expression.id).toBe('test-talk'); 21 + expect(expression.kind).toBe('transcript'); 22 + expect(expression.text).toBe('Hello world foo bar'); 23 + expect(expression.language).toBe('en'); 24 + expect(expression.sourceRef).toBe('at://did:plc:test/tv.ionosphere.transcript/test-talk-transcript'); 25 + expect(expression.metadata.tool).toBe('ionosphere-pipeline'); 26 + expect(expression.metadata.timestamp).toBeDefined(); 27 + expect(expression.createdAt).toBeDefined(); 28 + }); 29 + 30 + it('produces segmentation records with textSpan-only tokens', async () => { 31 + const { segmentations } = await transcriptToLayersPub(transcript, did, talkRkey); 32 + expect(segmentations).toHaveLength(1); // small transcript = 1 chunk 33 + 34 + const seg = segmentations[0]; 35 + expect(seg.$type).toBe('pub.layers.segmentation.segmentation'); 36 + expect(seg.expression).toBe( 37 + 'at://did:plc:test/pub.layers.expression.expression/test-talk-expression' 38 + ); 39 + 40 + const tok = seg.tokenizations[0]; 41 + expect(tok.kind).toBe('word'); 42 + expect(tok.tokens).toHaveLength(4); 43 + 44 + // Check first token — textSpan only (word text recoverable via expression.text + byte offsets) 45 + expect(tok.tokens[0].tokenIndex).toBe(0); 46 + expect(tok.tokens[0].textSpan.byteStart).toBe(0); 47 + expect(tok.tokens[0].textSpan.byteEnd).toBe(5); 48 + 49 + // Check third token (after gap) — byte offsets 50 + expect(tok.tokens[2].textSpan.byteStart).toBe(12); // "Hello world " = 12 bytes 51 + expect(tok.tokens[2].textSpan.byteEnd).toBe(15); 52 + }); 53 + 54 + it('produces separate temporal segmentation records', async () => { 55 + const { temporals } = await transcriptToLayersPub(transcript, did, talkRkey); 56 + expect(temporals).toHaveLength(1); // small transcript = 1 chunk 57 + 58 + const temp = temporals[0]; 59 + expect(temp.$type).toBe('pub.layers.segmentation.segmentation'); 60 + 61 + const tok = temp.tokenizations[0]; 62 + expect(tok.kind).toBe('word-temporal'); 63 + expect(tok.tokens).toHaveLength(4); 64 + 65 + // First token temporal span 66 + expect(tok.tokens[0].tokenIndex).toBe(0); 67 + expect(tok.tokens[0].temporalSpan.start).toBe(1000); 68 + expect(tok.tokens[0].temporalSpan.ending).toBe(1200); 69 + 70 + // Third token (after gap) 71 + expect(tok.tokens[2].temporalSpan.start).toBe(1600); // 1000+200+300+100gap 72 + expect(tok.tokens[2].temporalSpan.ending).toBe(1750); 73 + }); 74 + }); 75 + 76 + describe('Lens 2: NLP annotations → annotation layers', () => { 77 + const nlpAnnotations = { 78 + talkRkey: 'test-talk', 79 + sentences: [ 80 + { byteStart: 0, byteEnd: 11 }, 81 + { byteStart: 12, byteEnd: 19 }, 82 + ], 83 + paragraphs: [ 84 + { byteStart: 0, byteEnd: 19 }, 85 + ], 86 + entities: [ 87 + { byteStart: 0, byteEnd: 5, label: 'Hello', nerType: 'MISC' }, 88 + { byteStart: 12, byteEnd: 15, label: 'foo', nerType: 'ORG', conceptUri: 'at://did:plc:test/tv.ionosphere.concept/foo' }, 89 + ], 90 + topicBreaks: [ 91 + { byteStart: 12 }, 92 + ], 93 + metadata: { tool: 'spacy/en_core_web_sm' }, 94 + }; 95 + 96 + const did = 'did:plc:test'; 97 + const talkRkey = 'test-talk'; 98 + const expressionUri = 'at://did:plc:test/pub.layers.expression.expression/test-talk-expression'; 99 + 100 + it('produces 4 annotation layer records', async () => { 101 + const layers = await nlpToAnnotationLayers(nlpAnnotations, did, talkRkey, expressionUri); 102 + expect(Object.keys(layers)).toEqual(['sentences', 'paragraphs', 'entities', 'topics']); 103 + }); 104 + 105 + it('sentences layer has correct structure', async () => { 106 + const { sentences } = await nlpToAnnotationLayers(nlpAnnotations, did, talkRkey, expressionUri); 107 + expect(sentences.$type).toBe('pub.layers.annotation.annotationLayer'); 108 + expect(sentences.expression).toBe(expressionUri); 109 + expect(sentences.kind).toBe('span'); 110 + expect(sentences.subkind).toBe('sentence-boundary'); 111 + expect(sentences.sourceMethod).toBe('automatic'); 112 + expect(sentences.metadata.tool).toBe('ionosphere-nlp-pipeline'); 113 + expect(sentences.annotations).toHaveLength(2); 114 + expect(sentences.annotations[0].anchor.textSpan).toEqual({ byteStart: 0, byteEnd: 11 }); 115 + }); 116 + 117 + it('entities layer wraps features in featureMap', async () => { 118 + const { entities } = await nlpToAnnotationLayers(nlpAnnotations, did, talkRkey, expressionUri); 119 + expect(entities.annotations).toHaveLength(2); 120 + 121 + // Plain entity — nerType is always present 122 + const plain = entities.annotations[0]; 123 + expect(plain.label).toBe('Hello'); 124 + expect(plain.features.entries).toContainEqual({ key: 'nerType', value: 'MISC' }); 125 + 126 + // Entity with conceptUri — all known keys forwarded to features 127 + const withConcept = entities.annotations[1]; 128 + expect(withConcept.features.entries).toContainEqual({ 129 + key: 'conceptUri', 130 + value: 'at://did:plc:test/tv.ionosphere.concept/foo', 131 + }); 132 + expect(withConcept.features.entries).toContainEqual({ key: 'nerType', value: 'ORG' }); 133 + }); 134 + 135 + it('topics layer has correct subkind and uses zero-width spans', async () => { 136 + const { topics } = await nlpToAnnotationLayers(nlpAnnotations, did, talkRkey, expressionUri); 137 + expect(topics.subkind).toBe('topic-segment'); 138 + expect(topics.annotations).toHaveLength(1); 139 + expect(topics.annotations[0].anchor.textSpan).toEqual({ byteStart: 12, byteEnd: 12 }); 140 + }); 141 + }); 142 + 143 + describe('Stage 6 integration: full record production', () => { 144 + it('produces 6 records for a talk with transcript + NLP data', async () => { 145 + const fs = await import('node:fs'); 146 + const path = await import('node:path'); 147 + 148 + const transcriptsDir = path.resolve(import.meta.dirname, '../../../data/transcripts'); 149 + const nlpDir = path.resolve(import.meta.dirname, '../../../../pipeline/data/nlp'); 150 + 151 + const rkey = 'ats26-keynote'; 152 + const transcriptPath = path.join(transcriptsDir, `${rkey}.json`); 153 + const nlpPath = path.join(nlpDir, `${rkey}.json`); 154 + 155 + // Skip if fixtures not available 156 + if (!fs.existsSync(transcriptPath) || !fs.existsSync(nlpPath)) { 157 + console.log('Skipping: fixture data not available'); 158 + return; 159 + } 160 + 161 + const { encode } = await import('../../../../formats/tv.ionosphere/ts/transcript-encoding.js'); 162 + 163 + const transcriptData = JSON.parse(fs.readFileSync(transcriptPath, 'utf-8')); 164 + const nlpData = JSON.parse(fs.readFileSync(nlpPath, 'utf-8')); 165 + const compact = encode(transcriptData); 166 + 167 + const did = 'did:plc:test'; 168 + const transcriptRecord = { 169 + $type: 'tv.ionosphere.transcript' as const, 170 + text: compact.text, 171 + startMs: compact.startMs, 172 + timings: compact.timings, 173 + talkUri: `at://${did}/tv.ionosphere.talk/${rkey}`, 174 + }; 175 + 176 + const { expression, segmentations, temporals } = await transcriptToLayersPub(transcriptRecord, did, rkey); 177 + const expressionUri = `at://${did}/pub.layers.expression.expression/${rkey}-expression`; 178 + const layers = await nlpToAnnotationLayers(nlpData, did, rkey, expressionUri); 179 + 180 + // Verify records have correct $type 181 + expect(expression.$type).toBe('pub.layers.expression.expression'); 182 + for (const seg of segmentations) expect(seg.$type).toBe('pub.layers.segmentation.segmentation'); 183 + for (const temp of temporals) expect(temp.$type).toBe('pub.layers.segmentation.segmentation'); 184 + expect(layers.sentences.$type).toBe('pub.layers.annotation.annotationLayer'); 185 + expect(layers.paragraphs.$type).toBe('pub.layers.annotation.annotationLayer'); 186 + expect(layers.entities.$type).toBe('pub.layers.annotation.annotationLayer'); 187 + expect(layers.topics.$type).toBe('pub.layers.annotation.annotationLayer'); 188 + 189 + // Verify real data produces non-trivial results (keynote has 8040 tokens = 2 chunks) 190 + const totalTokens = segmentations.reduce((n, s) => n + s.tokenizations[0].tokens.length, 0); 191 + expect(totalTokens).toBeGreaterThan(100); 192 + expect(segmentations.length).toBe(temporals.length); 193 + expect(layers.sentences.annotations.length).toBeGreaterThan(10); 194 + expect(layers.entities.annotations.length).toBeGreaterThan(10); 195 + }); 196 + }); 197 + 198 + describe('Lens 3: round-trip correctness', () => { 199 + it('layers.pub → document matches decodeToDocumentWithStructure output', async () => { 200 + const fs = await import('node:fs'); 201 + const path = await import('node:path'); 202 + 203 + const transcriptsDir = path.resolve(import.meta.dirname, '../../../data/transcripts'); 204 + const nlpDir = path.resolve(import.meta.dirname, '../../../../pipeline/data/nlp'); 205 + 206 + const rkey = 'ats26-keynote'; 207 + const transcriptPath = path.join(transcriptsDir, `${rkey}.json`); 208 + const nlpPath = path.join(nlpDir, `${rkey}.json`); 209 + 210 + if (!fs.existsSync(transcriptPath) || !fs.existsSync(nlpPath)) { 211 + console.log('Skipping: fixture data not available'); 212 + return; 213 + } 214 + 215 + const { encode, decodeToDocumentWithStructure } = await import( 216 + '../../../../formats/tv.ionosphere/ts/transcript-encoding.js' 217 + ); 218 + 219 + const transcriptData = JSON.parse(fs.readFileSync(transcriptPath, 'utf-8')); 220 + const nlpData = JSON.parse(fs.readFileSync(nlpPath, 'utf-8')); 221 + const compact = encode(transcriptData); 222 + 223 + // Path A: existing direct path 224 + const directDoc = decodeToDocumentWithStructure(compact, nlpData); 225 + 226 + // Path B: through lenses 227 + const did = 'did:plc:test'; 228 + const transcriptRecord = { 229 + $type: 'tv.ionosphere.transcript' as const, 230 + text: compact.text, 231 + startMs: compact.startMs, 232 + timings: compact.timings, 233 + talkUri: `at://${did}/tv.ionosphere.talk/${rkey}`, 234 + }; 235 + const { expression, segmentations } = await transcriptToLayersPub(transcriptRecord, did, rkey); 236 + const expressionUri = `at://${did}/pub.layers.expression.expression/${rkey}-expression`; 237 + const layers = await nlpToAnnotationLayers(nlpData, did, rkey, expressionUri); 238 + const lensDoc = await layersPubToDocument(expression, segmentations, layers, compact); 239 + 240 + // Compare text 241 + expect(lensDoc.text).toBe(directDoc.text); 242 + 243 + // Compare facet counts 244 + expect(lensDoc.facets.length).toBe(directDoc.facets.length); 245 + 246 + // Sort both facet arrays by byteStart then by $type for deterministic comparison 247 + const sortFacets = (facets: typeof directDoc.facets) => 248 + [...facets].sort((a, b) => { 249 + const posA = a.index.byteStart; 250 + const posB = b.index.byteStart; 251 + if (posA !== posB) return posA - posB; 252 + const typeA = a.features[0]?.$type ?? ''; 253 + const typeB = b.features[0]?.$type ?? ''; 254 + return typeA.localeCompare(typeB); 255 + }); 256 + 257 + const sortedDirect = sortFacets(directDoc.facets); 258 + const sortedLens = sortFacets(lensDoc.facets); 259 + 260 + // Check each facet matches 261 + for (let i = 0; i < sortedDirect.length; i++) { 262 + expect(sortedLens[i].index).toEqual(sortedDirect[i].index); 263 + expect(sortedLens[i].features[0].$type).toBe(sortedDirect[i].features[0].$type); 264 + } 265 + }); 266 + });
+2 -1
apps/ionosphere-appview/src/appview.ts
··· 1 1 import { serve } from "@hono/node-server"; 2 2 import { openDb, migrate, getCursor, setCursor } from "./db.js"; 3 3 import { createRoutes } from "./routes.js"; 4 - import { processEvent } from "./indexer.js"; 4 + import { processEvent, setBotDid } from "./indexer.js"; 5 5 import { JetstreamClient } from "./jetstream.js"; 6 6 import { backfill } from "./backfill.js"; 7 7 import { startPublicJetstream } from "./public-jetstream.js"; ··· 39 39 } 40 40 41 41 if (did) { 42 + setBotDid(did); 42 43 console.log(`Backfilling from ${did}`); 43 44 try { 44 45 await backfill(db, PDS_URL, did);
+34
apps/ionosphere-appview/src/db.ts
··· 252 252 cursor_us INTEGER 253 253 ); 254 254 INSERT OR IGNORE INTO _cursor (id, cursor_us) VALUES (1, NULL); 255 + 256 + -- layers.pub records 257 + CREATE TABLE IF NOT EXISTS layers_expressions ( 258 + uri TEXT PRIMARY KEY, 259 + rkey TEXT NOT NULL, 260 + did TEXT NOT NULL, 261 + transcript_uri TEXT NOT NULL, 262 + text TEXT NOT NULL, 263 + language TEXT NOT NULL DEFAULT 'en', 264 + created_at TEXT DEFAULT CURRENT_TIMESTAMP 265 + ); 266 + CREATE INDEX IF NOT EXISTS idx_layers_expr_transcript ON layers_expressions(transcript_uri); 267 + 268 + CREATE TABLE IF NOT EXISTS layers_segmentations ( 269 + uri TEXT PRIMARY KEY, 270 + rkey TEXT NOT NULL, 271 + did TEXT NOT NULL, 272 + expression_uri TEXT NOT NULL, 273 + tokens_json TEXT NOT NULL, 274 + created_at TEXT DEFAULT CURRENT_TIMESTAMP 275 + ); 276 + CREATE INDEX IF NOT EXISTS idx_layers_seg_expression ON layers_segmentations(expression_uri); 277 + 278 + CREATE TABLE IF NOT EXISTS layers_annotations ( 279 + uri TEXT PRIMARY KEY, 280 + rkey TEXT NOT NULL, 281 + did TEXT NOT NULL, 282 + expression_uri TEXT NOT NULL, 283 + kind TEXT NOT NULL, 284 + subkind TEXT NOT NULL, 285 + annotations_json TEXT NOT NULL, 286 + created_at TEXT DEFAULT CURRENT_TIMESTAMP 287 + ); 288 + CREATE INDEX IF NOT EXISTS idx_layers_ann_expression ON layers_annotations(expression_uri); 255 289 `); 256 290 } 257 291
-107
apps/ionosphere-appview/src/enrich-all.ts
··· 1 - /** 2 - * Batch enrichment of all transcribed talks. 3 - * 4 - * Finds all talks with transcripts but no annotations, then runs 5 - * enrichment for each one sequentially. 6 - * 7 - * Usage: npx tsx src/enrich-all.ts [--limit N] [--dry-run] 8 - */ 9 - import "./env.js"; 10 - import { execFileSync } from "node:child_process"; 11 - import path from "node:path"; 12 - 13 - const PDS_URL = process.env.PDS_URL ?? "http://localhost:2690"; 14 - const BOT_HANDLE = process.env.BOT_HANDLE ?? "ionosphere.test"; 15 - 16 - const limitArg = process.argv.indexOf("--limit"); 17 - const limit = 18 - limitArg !== -1 ? parseInt(process.argv[limitArg + 1], 10) : Infinity; 19 - const dryRun = process.argv.includes("--dry-run"); 20 - 21 - async function listAll(collection: string, repo: string): Promise<any[]> { 22 - const records: any[] = []; 23 - let cursor: string | undefined; 24 - do { 25 - const params = new URLSearchParams({ 26 - repo, 27 - collection, 28 - limit: "100", 29 - }); 30 - if (cursor) params.set("cursor", cursor); 31 - const res = await fetch( 32 - `${PDS_URL}/xrpc/com.atproto.repo.listRecords?${params}` 33 - ); 34 - if (!res.ok) throw new Error(`listRecords failed: ${res.status}`); 35 - const data = await res.json(); 36 - records.push(...data.records); 37 - cursor = data.cursor; 38 - } while (cursor); 39 - return records; 40 - } 41 - 42 - async function main() { 43 - // Resolve DID 44 - const handleRes = await fetch( 45 - `${PDS_URL}/xrpc/com.atproto.identity.resolveHandle?handle=${BOT_HANDLE}` 46 - ); 47 - if (!handleRes.ok) throw new Error("Failed to resolve handle"); 48 - const { did } = (await handleRes.json()) as { did: string }; 49 - console.log(`Resolved ${BOT_HANDLE} → ${did}`); 50 - 51 - // Get transcript rkeys 52 - const transcripts = await listAll("tv.ionosphere.transcript", did); 53 - const transcriptTalkRkeys = new Set( 54 - transcripts.map((r) => r.uri.split("/").pop()!.replace("-transcript", "")) 55 - ); 56 - 57 - // Get already-enriched talk rkeys from annotations 58 - const annotations = await listAll("tv.ionosphere.annotation", did); 59 - const enrichedRkeys = new Set<string>(); 60 - for (const a of annotations) { 61 - const talkUri = a.value?.talkUri; 62 - if (talkUri) enrichedRkeys.add(talkUri.split("/").pop()!); 63 - } 64 - 65 - const unenriched = [...transcriptTalkRkeys] 66 - .filter((rkey) => !enrichedRkeys.has(rkey)) 67 - .sort(); 68 - const batch = unenriched.slice(0, limit); 69 - 70 - console.log(`\nBatch enrichment:`); 71 - console.log(` ${transcriptTalkRkeys.size} talks with transcripts`); 72 - console.log(` ${enrichedRkeys.size} already enriched`); 73 - console.log(` ${unenriched.length} need enrichment`); 74 - console.log(` ${batch.length} in this batch`); 75 - 76 - if (dryRun) { 77 - console.log(`\nDry run — would enrich:`); 78 - for (const rkey of batch) console.log(` ${rkey}`); 79 - return; 80 - } 81 - 82 - const enrichScript = path.resolve(import.meta.dirname, "enrich.ts"); 83 - let completed = 0; 84 - let failed = 0; 85 - 86 - for (const rkey of batch) { 87 - const idx = completed + failed + 1; 88 - console.log(`\n[${idx}/${batch.length}] Enriching ${rkey}...`); 89 - try { 90 - execFileSync("npx", ["tsx", enrichScript, rkey], { 91 - cwd: path.resolve(import.meta.dirname, ".."), 92 - stdio: "inherit", 93 - timeout: 120_000, // 2 min per talk 94 - }); 95 - completed++; 96 - console.log(` ✓ ${rkey} (${completed} done, ${failed} failed)`); 97 - } catch (err: any) { 98 - failed++; 99 - console.error(` ✗ ${rkey} failed: ${err.message}`); 100 - } 101 - } 102 - 103 - console.log(`\n--- Batch complete ---`); 104 - console.log(` ${completed} enriched, ${failed} failed`); 105 - } 106 - 107 - main().catch(console.error);
-377
apps/ionosphere-appview/src/enrich.ts
··· 1 - /** 2 - * LLM-assisted semantic enrichment of talk transcripts. 3 - * 4 - * Reads talk and transcript records from the PDS, extracts concepts 5 - * and cross-references via LLM, and writes concept records back to the PDS. 6 - * 7 - * Usage: npx tsx src/enrich.ts <rkey> 8 - */ 9 - import "./env.js"; 10 - import OpenAI from "openai"; 11 - import { readFileSync } from "node:fs"; 12 - import path from "node:path"; 13 - import { PdsClient, slugToRkey } from "./pds-client.js"; 14 - 15 - const PDS_URL = process.env.PDS_URL ?? "http://localhost:2690"; 16 - const BOT_HANDLE = process.env.BOT_HANDLE ?? "ionosphere.test"; 17 - const BOT_PASSWORD = process.env.BOT_PASSWORD ?? "ionosphere-dev-password"; 18 - 19 - function loadApiKey(): string { 20 - if (process.env.OPENAI_API_KEY) return process.env.OPENAI_API_KEY; 21 - try { 22 - const envContent = readFileSync( 23 - path.resolve(import.meta.dirname, "../.env"), 24 - "utf-8" 25 - ); 26 - for (const line of envContent.split("\n")) { 27 - const match = line.match(/^OPENAI_API_KEY=(.+)$/); 28 - if (match) return match[1].trim(); 29 - } 30 - } catch {} 31 - throw new Error("OPENAI_API_KEY not found in environment or .env file"); 32 - } 33 - 34 - const llm = new OpenAI({ apiKey: loadApiKey() }); 35 - 36 - // --- XRPC helpers --- 37 - 38 - async function listRecords( 39 - collection: string, 40 - repo: string 41 - ): Promise<any[]> { 42 - const records: any[] = []; 43 - let cursor: string | undefined; 44 - 45 - do { 46 - const params = new URLSearchParams({ 47 - repo, 48 - collection, 49 - limit: "100", 50 - }); 51 - if (cursor) params.set("cursor", cursor); 52 - 53 - const res = await fetch( 54 - `${PDS_URL}/xrpc/com.atproto.repo.listRecords?${params}` 55 - ); 56 - if (!res.ok) throw new Error(`listRecords failed: ${res.status}`); 57 - const data = await res.json(); 58 - records.push(...data.records); 59 - cursor = data.cursor; 60 - } while (cursor); 61 - 62 - return records; 63 - } 64 - 65 - async function getRecord( 66 - collection: string, 67 - repo: string, 68 - rkey: string 69 - ): Promise<any> { 70 - const params = new URLSearchParams({ repo, collection, rkey }); 71 - const res = await fetch( 72 - `${PDS_URL}/xrpc/com.atproto.repo.getRecord?${params}` 73 - ); 74 - if (!res.ok) { 75 - if (res.status === 404) return null; 76 - throw new Error(`getRecord failed: ${res.status}`); 77 - } 78 - return res.json(); 79 - } 80 - 81 - // --- Types --- 82 - 83 - interface EnrichmentResult { 84 - concepts: Array<{ 85 - name: string; 86 - aliases?: string[]; 87 - description?: string; 88 - wikidataId?: string; 89 - url?: string; 90 - mentions: Array<{ text: string; context: string }>; 91 - }>; 92 - speakerMentions: Array<{ 93 - name: string; 94 - handle?: string; 95 - mentions: Array<{ text: string; context: string }>; 96 - }>; 97 - crossRefs: Array<{ 98 - targetRkey: string; 99 - targetTitle: string; 100 - context: string; 101 - }>; 102 - links: Array<{ 103 - url: string; 104 - title?: string; 105 - context: string; 106 - }>; 107 - } 108 - 109 - // --- LLM --- 110 - 111 - async function enrichTranscript( 112 - title: string, 113 - speaker: string, 114 - transcript: string, 115 - talkIndex: string, 116 - speakerIndex: string 117 - ): Promise<EnrichmentResult> { 118 - const response = await llm.chat.completions.create({ 119 - model: "gpt-5.4-mini", 120 - response_format: { type: "json_object" }, 121 - messages: [ 122 - { 123 - role: "system", 124 - content: `You are a research librarian and knowledge graph curator. You analyze conference talk transcripts and extract structured semantic annotations. 125 - 126 - You will be given: 127 - 1. A talk title and speaker 128 - 2. The transcript text 129 - 3. An index of all talks at the conference 130 - 4. An index of all speakers at the conference 131 - 132 - Extract the following, returning JSON: 133 - 134 - { 135 - "concepts": [ 136 - { 137 - "name": "canonical name for this concept", 138 - "aliases": ["alternative names used in the transcript"], 139 - "description": "one-sentence description", 140 - "wikidataId": "Q-identifier if you're confident (e.g. Q80071 for AT Protocol)", 141 - "url": "canonical URL if applicable (project homepage, spec URL, etc)", 142 - "mentions": [{"text": "exact quote from transcript", "context": "surrounding sentence for context"}] 143 - } 144 - ], 145 - "speakerMentions": [ 146 - { 147 - "name": "person's name as mentioned", 148 - "handle": "AT Protocol handle if known from the speaker index", 149 - "mentions": [{"text": "exact quote", "context": "surrounding sentence"}] 150 - } 151 - ], 152 - "crossRefs": [ 153 - { 154 - "targetRkey": "rkey from the talk index", 155 - "targetTitle": "title of the referenced talk", 156 - "context": "sentence where the cross-reference occurs" 157 - } 158 - ], 159 - "links": [ 160 - { 161 - "url": "URL mentioned verbally", 162 - "title": "description of what it links to", 163 - "context": "sentence where mentioned" 164 - } 165 - ] 166 - } 167 - 168 - Guidelines: 169 - - For concepts: cast a wide net. Include: 170 - - Technical concepts, protocols, projects, organizations, standards, tools 171 - - AT Protocol ecosystem concepts (PDS, DID, Jetstream, lexicons, etc.) 172 - - Key metaphors, analogies, and thematic imagery the speaker uses (e.g., "kelp forest", "landslide", "garden") 173 - - Books, papers, academic works, and theoretical frameworks referenced 174 - - Historical events, places, and phenomena discussed (even as metaphor) 175 - - Named entities: companies, communities, movements, legislation 176 - - Aim for 20-40 concepts per talk. If a speaker discusses it substantively, it's a concept. 177 - - For speaker mentions: people actually named in the transcript, matched to the speaker index when possible. 178 - - For cross-refs: when the speaker explicitly references another talk or topic that matches a talk in the index. 179 - - For links: URLs spoken aloud or clearly referenced. 180 - - Be precise with quotes — use the exact text from the transcript. 181 - - Be thorough — if in doubt, include it. A rich knowledge graph is more valuable than a sparse one.`, 182 - }, 183 - { 184 - role: "user", 185 - content: `# Talk: ${title} 186 - # Speaker: ${speaker} 187 - 188 - ## Transcript 189 - ${transcript} 190 - 191 - ## All Conference Talks 192 - ${talkIndex} 193 - 194 - ## All Conference Speakers 195 - ${speakerIndex}`, 196 - }, 197 - ], 198 - }); 199 - 200 - const content = response.choices[0]?.message?.content; 201 - if (!content) throw new Error("No response from LLM"); 202 - 203 - return JSON.parse(content); 204 - } 205 - 206 - // --- Main --- 207 - 208 - async function main() { 209 - const rkey = process.argv[2]; 210 - if (!rkey) { 211 - console.error("Usage: npx tsx src/enrich.ts <rkey>"); 212 - process.exit(1); 213 - } 214 - 215 - // Connect to PDS 216 - const pds = new PdsClient(PDS_URL); 217 - await pds.login(BOT_HANDLE, BOT_PASSWORD); 218 - const did = pds.getDid(); 219 - console.log(`Connected to PDS as ${did}`); 220 - 221 - // 1. Read talk record from PDS 222 - const talkRecord = await getRecord("tv.ionosphere.talk", did, rkey); 223 - if (!talkRecord) { 224 - console.error(`Talk not found on PDS: ${rkey}`); 225 - process.exit(1); 226 - } 227 - const talk = talkRecord.value; 228 - 229 - // 2. Read transcript record from PDS 230 - const transcriptRkey = `${rkey}-transcript`; 231 - const transcriptRecord = await getRecord( 232 - "tv.ionosphere.transcript", 233 - did, 234 - transcriptRkey 235 - ); 236 - if (!transcriptRecord) { 237 - console.error(`Transcript not found on PDS: ${transcriptRkey}`); 238 - process.exit(1); 239 - } 240 - const transcript = transcriptRecord.value.text; 241 - 242 - // 3. Build context indexes from PDS records 243 - console.log("Building talk and speaker indexes from PDS..."); 244 - const allTalks = await listRecords("tv.ionosphere.talk", did); 245 - const talkIndex = allTalks 246 - .map((r: any) => { 247 - const tRkey = r.uri.split("/").pop(); 248 - return `${tRkey}: ${r.value.title}`; 249 - }) 250 - .join("\n"); 251 - 252 - const allSpeakers = await listRecords("tv.ionosphere.speaker", did); 253 - const speakerIndex = allSpeakers 254 - .map((r: any) => { 255 - const s = r.value; 256 - return `${s.name}${s.handle ? ` (@${s.handle})` : ""}`; 257 - }) 258 - .join("\n"); 259 - 260 - // Get speaker names for this talk 261 - const speakerNames = (talk.speakerUris || []) 262 - .map((uri: string) => { 263 - const sRkey = uri.split("/").pop(); 264 - const speaker = allSpeakers.find( 265 - (r: any) => r.uri.split("/").pop() === sRkey 266 - ); 267 - return speaker?.value.name || sRkey; 268 - }) 269 - .join(", "); 270 - 271 - console.log(`Enriching: ${talk.title} (${speakerNames})`); 272 - console.log(` Transcript: ${transcript.length} chars`); 273 - console.log(` Context: ${allTalks.length} talks, ${allSpeakers.length} speakers`); 274 - 275 - // 4. Call LLM 276 - console.log(" Calling LLM..."); 277 - const result = await enrichTranscript( 278 - talk.title, 279 - speakerNames, 280 - transcript, 281 - talkIndex, 282 - speakerIndex 283 - ); 284 - 285 - console.log(`\nResults:`); 286 - console.log(` Concepts: ${result.concepts.length}`); 287 - console.log(` Speaker mentions: ${result.speakerMentions.length}`); 288 - console.log(` Cross-refs: ${result.crossRefs.length}`); 289 - console.log(` Links: ${result.links.length}`); 290 - 291 - // 5. Delete old annotations for this talk before writing new ones 292 - const allAnnotations = await listRecords("tv.ionosphere.annotation", did); 293 - const talkUri = `at://${did}/tv.ionosphere.talk/${rkey}`; 294 - const transcriptUri = `at://${did}/tv.ionosphere.transcript/${transcriptRkey}`; 295 - const oldAnnotations = allAnnotations.filter( 296 - (a: any) => a.value.talkUri === talkUri 297 - ); 298 - if (oldAnnotations.length > 0) { 299 - console.log(` Deleting ${oldAnnotations.length} old annotations...`); 300 - for (const a of oldAnnotations) { 301 - const aRkey = a.uri.split("/").pop(); 302 - await pds.deleteRecord("tv.ionosphere.annotation", aRkey); 303 - } 304 - } 305 - 306 - // 6. Write concept records and annotation records to PDS 307 - const encoder = new TextEncoder(); 308 - const transcriptLower = transcript.toLowerCase(); 309 - let annotationCount = 0; 310 - 311 - for (const concept of result.concepts) { 312 - const conceptRkey = slugToRkey(concept.name); 313 - const conceptUri = `at://${did}/tv.ionosphere.concept/${conceptRkey}`; 314 - 315 - // Write concept record 316 - await pds.putRecord("tv.ionosphere.concept", conceptRkey, { 317 - $type: "tv.ionosphere.concept", 318 - name: concept.name, 319 - ...(concept.aliases?.length && { aliases: concept.aliases }), 320 - ...(concept.description && { description: concept.description }), 321 - ...(concept.wikidataId && { wikidataId: concept.wikidataId }), 322 - ...(concept.url && { url: concept.url }), 323 - }); 324 - 325 - // Find all mentions in the transcript and write annotation records 326 - const terms = [concept.name, ...(concept.aliases || [])]; 327 - for (const term of terms) { 328 - const termLower = term.toLowerCase(); 329 - let searchFrom = 0; 330 - 331 - while (true) { 332 - const idx = transcriptLower.indexOf(termLower, searchFrom); 333 - if (idx === -1) break; 334 - 335 - // Word boundary check 336 - const before = idx > 0 ? transcript[idx - 1] : " "; 337 - const after = 338 - idx + term.length < transcript.length 339 - ? transcript[idx + term.length] 340 - : " "; 341 - if (/\w/.test(before) || /\w/.test(after)) { 342 - searchFrom = idx + 1; 343 - continue; 344 - } 345 - 346 - const byteStart = encoder.encode(transcript.slice(0, idx)).length; 347 - const byteEnd = encoder.encode( 348 - transcript.slice(0, idx + term.length) 349 - ).length; 350 - 351 - const annotRkey = `${rkey}-${conceptRkey}-${byteStart}`; 352 - await pds.putRecord("tv.ionosphere.annotation", annotRkey, { 353 - $type: "tv.ionosphere.annotation", 354 - transcriptUri, 355 - talkUri, 356 - conceptUri, 357 - byteStart, 358 - byteEnd, 359 - text: transcript.slice(idx, idx + term.length), 360 - }); 361 - annotationCount++; 362 - 363 - searchFrom = idx + term.length; 364 - } 365 - } 366 - 367 - console.log(` + concept: ${concept.name}`); 368 - } 369 - 370 - console.log(` ${annotationCount} annotations written`); 371 - 372 - // Print summary 373 - console.log("\n--- Full enrichment output ---"); 374 - console.log(JSON.stringify(result, null, 2)); 375 - } 376 - 377 - main().catch(console.error);
+63 -67
apps/ionosphere-appview/src/indexer.ts
··· 1 1 import type Database from "better-sqlite3"; 2 2 import { ensureProfile } from "./profiles.js"; 3 + import { 4 + indexExpression, 5 + indexSegmentation, 6 + indexAnnotationLayer, 7 + deleteExpression, 8 + deleteSegmentation, 9 + deleteAnnotationLayer, 10 + rebuildDocument, 11 + } from "./layers-indexer.js"; 3 12 4 13 // ─── Types ──────────────────────────────────────────────────────────────────── 5 14 ··· 17 26 time_us: number; 18 27 } 19 28 29 + // ─── Bot DID filter ────────────────────────────────────────────────────────── 30 + 31 + let _botDid = ""; 32 + 33 + /** Set the bot DID for filtering layers.pub records. Called from appview.ts. */ 34 + export function setBotDid(did: string): void { 35 + _botDid = did; 36 + } 37 + 20 38 // ─── Constants ──────────────────────────────────────────────────────────────── 21 39 22 40 export const IONOSPHERE_COLLECTIONS = [ ··· 25 43 "tv.ionosphere.speaker", 26 44 "tv.ionosphere.concept", 27 45 "tv.ionosphere.transcript", 28 - "tv.ionosphere.annotation", 29 46 "tv.ionosphere.comment", 30 47 "tv.ionosphere.stream", 31 48 "tv.ionosphere.streamTranscript", 32 49 "tv.ionosphere.diarization", 33 50 "org.relationaltext.lens", 51 + "pub.layers.expression.expression", 52 + "pub.layers.segmentation.segmentation", 53 + "pub.layers.annotation.annotationLayer", 34 54 ]; 35 55 36 56 const COLLECTIONS_SET = new Set(IONOSPHERE_COLLECTIONS); 37 57 58 + const LAYERS_PUB_COLLECTIONS = new Set([ 59 + "pub.layers.expression.expression", 60 + "pub.layers.segmentation.segmentation", 61 + "pub.layers.annotation.annotationLayer", 62 + ]); 63 + 38 64 // ─── Event processor ────────────────────────────────────────────────────────── 39 65 40 66 export function processEvent(db: Database.Database, event: JetstreamEvent): void { ··· 44 70 if (!COLLECTIONS_SET.has(collection)) return; 45 71 46 72 const uri = `at://${event.did}/${collection}/${rkey}`; 73 + 74 + // Only process layers.pub records from the bot DID 75 + if (LAYERS_PUB_COLLECTIONS.has(collection) && _botDid && event.did !== _botDid) { 76 + return; 77 + } 47 78 48 79 // ── Deletes ─────────────────────────────────────────────────────────────── 49 80 ··· 69 100 case "tv.ionosphere.transcript": 70 101 db.prepare("DELETE FROM transcripts WHERE uri = ?").run(uri); 71 102 break; 72 - case "tv.ionosphere.annotation": 73 - db.prepare("DELETE FROM annotations WHERE uri = ?").run(uri); 74 - // Recompute talk_concepts for affected talk 75 - rebuildTalkConcepts(db, uri); 76 - break; 77 103 case "tv.ionosphere.comment": 78 104 db.prepare("DELETE FROM comments WHERE uri = ?").run(uri); 79 105 break; ··· 88 114 break; 89 115 case "org.relationaltext.lens": 90 116 db.prepare("DELETE FROM lenses WHERE uri = ?").run(uri); 117 + break; 118 + case "pub.layers.expression.expression": 119 + deleteExpression(db, uri); 120 + break; 121 + case "pub.layers.segmentation.segmentation": 122 + deleteSegmentation(db, uri); 123 + break; 124 + case "pub.layers.annotation.annotationLayer": 125 + deleteAnnotationLayer(db, uri); 91 126 break; 92 127 } 93 128 return; ··· 113 148 case "tv.ionosphere.transcript": 114 149 indexTranscript(db, event.did, rkey, uri, record); 115 150 break; 116 - case "tv.ionosphere.annotation": 117 - indexAnnotation(db, event.did, rkey, uri, record); 118 - break; 119 151 case "tv.ionosphere.comment": 120 152 indexUserComment(db, event.did, rkey, uri, record); 121 153 break; ··· 131 163 case "org.relationaltext.lens": 132 164 indexLens(db, event.did, rkey, uri, record); 133 165 break; 166 + case "pub.layers.expression.expression": 167 + indexExpression(db, event.did, rkey, uri, record); 168 + rebuildDocument(db, uri).catch((err) => 169 + console.error("rebuildDocument error:", err), 170 + ); 171 + break; 172 + case "pub.layers.segmentation.segmentation": 173 + indexSegmentation(db, event.did, rkey, uri, record); 174 + rebuildDocument(db, (record.expression as string) || "").catch((err) => 175 + console.error("rebuildDocument error:", err), 176 + ); 177 + break; 178 + case "pub.layers.annotation.annotationLayer": 179 + indexAnnotationLayer(db, event.did, rkey, uri, record); 180 + rebuildDocument(db, (record.expression as string) || "").catch((err) => 181 + console.error("rebuildDocument error:", err), 182 + ); 183 + break; 134 184 } 135 185 } 136 186 ··· 175 225 176 226 db.prepare( 177 227 `INSERT OR REPLACE INTO talks 178 - (uri, did, rkey, title, description, video_uri, video_offset_ns, video_segments, schedule_uri, event_uri, room, category, talk_type, starts_at, ends_at, duration) 179 - VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)` 228 + (uri, did, rkey, title, description, video_uri, video_offset_ns, video_segments, schedule_uri, event_uri, room, category, talk_type, starts_at, ends_at, duration, document) 229 + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)` 180 230 ).run( 181 231 uri, 182 232 did, ··· 193 243 (record.talkType as string) || null, 194 244 (record.startsAt as string) || null, 195 245 (record.endsAt as string) || null, 196 - (record.duration as number) || 0 246 + (record.duration as number) || 0, 247 + (record.document as string) ? JSON.stringify(record.document) : null 197 248 ); 198 249 199 250 // Update speaker join table ··· 277 328 ); 278 329 } 279 330 280 - function indexAnnotation( 281 - db: Database.Database, 282 - did: string, 283 - rkey: string, 284 - uri: string, 285 - record: Record<string, unknown> 286 - ): void { 287 - const talkUri = (record.talkUri as string) || null; 288 - const transcriptUri = record.transcriptUri as string; 289 - const conceptUri = record.conceptUri as string; 290 - 291 - db.prepare( 292 - `INSERT OR REPLACE INTO annotations 293 - (uri, did, rkey, transcript_uri, talk_uri, concept_uri, byte_start, byte_end, text) 294 - VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)` 295 - ).run( 296 - uri, 297 - did, 298 - rkey, 299 - transcriptUri, 300 - talkUri, 301 - conceptUri, 302 - record.byteStart as number, 303 - record.byteEnd as number, 304 - (record.text as string) || null 305 - ); 306 - 307 - // Maintain talk_concepts join: if this annotation links a concept to a talk, 308 - // ensure there's a row in talk_concepts 309 - if (talkUri && conceptUri) { 310 - db.prepare( 311 - `INSERT OR IGNORE INTO talk_concepts (talk_uri, concept_uri, mention_count) 312 - VALUES (?, ?, 1)` 313 - ).run(talkUri, conceptUri); 314 - 315 - // Update mention count 316 - db.prepare( 317 - `UPDATE talk_concepts SET mention_count = ( 318 - SELECT COUNT(*) FROM annotations 319 - WHERE talk_uri = ? AND concept_uri = ? 320 - ) WHERE talk_uri = ? AND concept_uri = ?` 321 - ).run(talkUri, conceptUri, talkUri, conceptUri); 322 - } 323 - } 324 - 325 331 function indexLens( 326 332 db: Database.Database, 327 333 did: string, ··· 434 440 ); 435 441 } 436 442 437 - function rebuildTalkConcepts(db: Database.Database, _deletedUri: string): void { 438 - // Full rebuild — simple and correct for now 439 - db.prepare("DELETE FROM talk_concepts").run(); 440 - db.prepare( 441 - `INSERT INTO talk_concepts (talk_uri, concept_uri, mention_count) 442 - SELECT talk_uri, concept_uri, COUNT(*) FROM annotations 443 - WHERE talk_uri IS NOT NULL 444 - GROUP BY talk_uri, concept_uri` 445 - ).run(); 446 - }
+219
apps/ionosphere-appview/src/layers-indexer.ts
··· 1 + import type Database from "better-sqlite3"; 2 + import { 3 + layersPubToDocument, 4 + type ExpressionRecord, 5 + type SegmentationRecord, 6 + type AnnotationLayersResult, 7 + type AnnotationLayerRecord, 8 + } from "@ionosphere/format/layers-pub"; 9 + 10 + // ─── Index functions (create/update) ───────────────────────────────────────── 11 + 12 + export function indexExpression( 13 + db: Database.Database, 14 + did: string, 15 + rkey: string, 16 + uri: string, 17 + record: Record<string, unknown>, 18 + ): void { 19 + db.prepare( 20 + `INSERT OR REPLACE INTO layers_expressions 21 + (uri, rkey, did, transcript_uri, text, language, created_at) 22 + VALUES (?, ?, ?, ?, ?, ?, ?)`, 23 + ).run( 24 + uri, 25 + rkey, 26 + did, 27 + (record.sourceRef as string) || "", 28 + (record.text as string) || "", 29 + (record.language as string) || "en", 30 + (record.createdAt as string) || new Date().toISOString(), 31 + ); 32 + } 33 + 34 + export function indexSegmentation( 35 + db: Database.Database, 36 + did: string, 37 + rkey: string, 38 + uri: string, 39 + record: Record<string, unknown>, 40 + ): void { 41 + db.prepare( 42 + `INSERT OR REPLACE INTO layers_segmentations 43 + (uri, rkey, did, expression_uri, tokens_json, created_at) 44 + VALUES (?, ?, ?, ?, ?, ?)`, 45 + ).run( 46 + uri, 47 + rkey, 48 + did, 49 + (record.expression as string) || "", 50 + JSON.stringify(record.tokenizations), 51 + (record.createdAt as string) || new Date().toISOString(), 52 + ); 53 + } 54 + 55 + export function indexAnnotationLayer( 56 + db: Database.Database, 57 + did: string, 58 + rkey: string, 59 + uri: string, 60 + record: Record<string, unknown>, 61 + ): void { 62 + db.prepare( 63 + `INSERT OR REPLACE INTO layers_annotations 64 + (uri, rkey, did, expression_uri, kind, subkind, annotations_json, created_at) 65 + VALUES (?, ?, ?, ?, ?, ?, ?, ?)`, 66 + ).run( 67 + uri, 68 + rkey, 69 + did, 70 + (record.expression as string) || "", 71 + (record.kind as string) || "", 72 + (record.subkind as string) || "", 73 + JSON.stringify(record.annotations), 74 + (record.createdAt as string) || new Date().toISOString(), 75 + ); 76 + } 77 + 78 + // ─── Delete functions ──────────────────────────────────────────────────────── 79 + 80 + export function deleteExpression(db: Database.Database, uri: string): void { 81 + // CASCADE: delete segmentations and annotations that reference this expression 82 + db.prepare("DELETE FROM layers_segmentations WHERE expression_uri = ?").run(uri); 83 + db.prepare("DELETE FROM layers_annotations WHERE expression_uri = ?").run(uri); 84 + db.prepare("DELETE FROM layers_expressions WHERE uri = ?").run(uri); 85 + } 86 + 87 + export function deleteSegmentation(db: Database.Database, uri: string): void { 88 + db.prepare("DELETE FROM layers_segmentations WHERE uri = ?").run(uri); 89 + } 90 + 91 + export function deleteAnnotationLayer(db: Database.Database, uri: string): void { 92 + db.prepare("DELETE FROM layers_annotations WHERE uri = ?").run(uri); 93 + } 94 + 95 + // ─── Document rebuild ──────────────────────────────────────────────────────── 96 + 97 + /** 98 + * Rebuild the materialized document for a talk by re-running Lens 3 99 + * (layersPubToDocument) from the stored layers.pub records. 100 + * 101 + * Called after any layers.pub record is created/updated. If the full set 102 + * of records (expression + segmentation + at least one annotation layer) 103 + * isn't available yet, this is a no-op — the document will be rebuilt 104 + * when the final piece arrives. 105 + */ 106 + export async function rebuildDocument( 107 + db: Database.Database, 108 + expressionUri: string, 109 + ): Promise<void> { 110 + // 1. Look up expression 111 + const expr = db 112 + .prepare("SELECT * FROM layers_expressions WHERE uri = ?") 113 + .get(expressionUri) as any; 114 + if (!expr) return; 115 + 116 + // 2. Look up segmentation chunks (may be multiple for large transcripts) 117 + const segRows = db 118 + .prepare("SELECT * FROM layers_segmentations WHERE expression_uri = ? AND rkey NOT LIKE '%-temporal%' ORDER BY rkey") 119 + .all(expressionUri) as any[]; 120 + if (segRows.length === 0) return; 121 + 122 + // 3. Look up all annotation layers 123 + const annRows = db 124 + .prepare("SELECT * FROM layers_annotations WHERE expression_uri = ?") 125 + .all(expressionUri) as any[]; 126 + 127 + // Map subkind → layer key 128 + const subkindToKey: Record<string, keyof AnnotationLayersResult> = { 129 + "sentence-boundary": "sentences", 130 + "paragraph-boundary": "paragraphs", 131 + ner: "entities", 132 + "topic-segment": "topics", 133 + }; 134 + 135 + const annotationLayers: Partial<AnnotationLayersResult> = {}; 136 + for (const row of annRows) { 137 + const key = subkindToKey[row.subkind]; 138 + if (key) { 139 + annotationLayers[key] = { 140 + $type: "pub.layers.annotation.annotationLayer", 141 + expression: expressionUri, 142 + kind: row.kind, 143 + subkind: row.subkind, 144 + sourceMethod: "automatic", 145 + metadata: { tool: "ionosphere-pipeline", timestamp: row.created_at }, 146 + annotations: JSON.parse(row.annotations_json), 147 + createdAt: row.created_at, 148 + } as AnnotationLayerRecord; 149 + } 150 + } 151 + 152 + // Need at least one annotation layer to produce a useful document 153 + if (Object.keys(annotationLayers).length === 0) return; 154 + 155 + // 4. Build typed records for layersPubToDocument 156 + const expressionRecord: ExpressionRecord = { 157 + $type: "pub.layers.expression.expression", 158 + id: expr.rkey, 159 + kind: "transcript", 160 + text: expr.text, 161 + language: expr.language, 162 + sourceRef: expr.transcript_uri, 163 + metadata: { tool: "ionosphere-pipeline", timestamp: expr.created_at }, 164 + createdAt: expr.created_at, 165 + }; 166 + 167 + const segmentationRecords: SegmentationRecord[] = segRows.map((seg: any) => ({ 168 + $type: "pub.layers.segmentation.segmentation" as const, 169 + expression: expressionUri, 170 + tokenizations: JSON.parse(seg.tokens_json), 171 + createdAt: seg.created_at, 172 + })); 173 + 174 + // Fill missing layers with empty annotations so layersPubToDocument gets 175 + // the full AnnotationLayersResult shape it expects 176 + const emptyLayer = (kind: string, subkind: string): AnnotationLayerRecord => ({ 177 + $type: "pub.layers.annotation.annotationLayer", 178 + expression: expressionUri, 179 + kind, 180 + subkind, 181 + sourceMethod: "automatic", 182 + metadata: { tool: "ionosphere-pipeline", timestamp: "" }, 183 + annotations: [], 184 + createdAt: "", 185 + }); 186 + 187 + const fullLayers: AnnotationLayersResult = { 188 + sentences: annotationLayers.sentences ?? emptyLayer("span", "sentence-boundary"), 189 + paragraphs: annotationLayers.paragraphs ?? emptyLayer("span", "paragraph-boundary"), 190 + entities: annotationLayers.entities ?? emptyLayer("span", "ner"), 191 + topics: annotationLayers.topics ?? emptyLayer("span", "topic-segment"), 192 + }; 193 + 194 + // 5. Look up the transcript for timing data + talk_uri 195 + const transcript = db 196 + .prepare("SELECT * FROM transcripts WHERE uri = ?") 197 + .get(expr.transcript_uri) as any; 198 + if (!transcript) return; 199 + 200 + // 6. Run Lens 3 with compact transcript for timestamp facets 201 + const compact = { 202 + text: transcript.text, 203 + startMs: transcript.start_ms, 204 + timings: JSON.parse(transcript.timings), 205 + }; 206 + 207 + const document = await layersPubToDocument( 208 + expressionRecord, 209 + segmentationRecords, 210 + fullLayers, 211 + compact, 212 + ); 213 + 214 + // 7. Update the talk's document field 215 + db.prepare("UPDATE talks SET document = ? WHERE uri = ?").run( 216 + JSON.stringify(document), 217 + transcript.talk_uri, 218 + ); 219 + }
-43
apps/ionosphere-appview/src/publish-annotations.ts
··· 1 - /** 2 - * Publish only annotations to the PDS. Use when other records are 3 - * already published but annotations hit a rate limit. 4 - */ 5 - import { PdsClient } from "./pds-client.js"; 6 - import { openDb } from "./db.js"; 7 - 8 - const PDS_URL = process.env.PDS_URL ?? "http://localhost:2690"; 9 - const BOT_HANDLE = process.env.BOT_HANDLE ?? "ionosphere.test"; 10 - const BOT_PASSWORD = process.env.BOT_PASSWORD ?? "ionosphere-dev-password"; 11 - 12 - async function main() { 13 - const pds = new PdsClient(PDS_URL); 14 - await pds.login(BOT_HANDLE, BOT_PASSWORD); 15 - const did = pds.getDid(); 16 - const db = openDb(); 17 - 18 - const annotations = db.prepare("SELECT * FROM annotations").all() as any[]; 19 - console.log(`Publishing ${annotations.length} annotations...`); 20 - let count = 0; 21 - for (const ann of annotations) { 22 - const talkUri = ann.talk_uri 23 - ? ann.talk_uri.replace(/^at:\/\/[^/]+/, `at://${did}`) 24 - : null; 25 - const transcriptUri = ann.transcript_uri.replace(/^at:\/\/[^/]+/, `at://${did}`); 26 - const conceptUri = ann.concept_uri.replace(/^at:\/\/[^/]+/, `at://${did}`); 27 - await pds.putRecord("tv.ionosphere.annotation", ann.rkey, { 28 - $type: "tv.ionosphere.annotation", 29 - transcriptUri, 30 - ...(talkUri && { talkUri }), 31 - conceptUri, 32 - byteStart: ann.byte_start, 33 - byteEnd: ann.byte_end, 34 - ...(ann.text && { text: ann.text }), 35 - }); 36 - count++; 37 - if (count % 100 === 0) console.log(` ${count}/${annotations.length}`); 38 - } 39 - console.log(`Done: ${count} annotations published`); 40 - db.close(); 41 - } 42 - 43 - main().catch(console.error);
+121 -52
apps/ionosphere-appview/src/publish.ts
··· 11 11 import { openDb } from "./db.js"; 12 12 import { readFileSync, existsSync } from "node:fs"; 13 13 import path from "node:path"; 14 - import { encode } from "@ionosphere/format/transcript-encoding"; 14 + import { encode, decodeToDocumentWithStructure, type NlpAnnotations } from "@ionosphere/format/transcript-encoding"; 15 + import { transcriptToLayersPub, nlpToAnnotationLayers } from "@ionosphere/format/layers-pub"; 15 16 16 17 const PDS_URL = process.env.PDS_URL ?? "http://localhost:2690"; 17 18 const BOT_HANDLE = process.env.BOT_HANDLE ?? "ionosphere.test"; ··· 26 27 // 0. Publish lens records 27 28 console.log("Publishing lens records..."); 28 29 const lensDir = path.resolve(import.meta.dirname, "../../../formats/tv.ionosphere/lenses"); 29 - for (const file of ["schedule-to-talk.lens.json", "vod-to-talk.lens.json", "openai-whisper-to-transcript.lens.json", "transcript-to-document.lens.json"]) { 30 + for (const file of ["schedule-to-talk.lens.json", "vod-to-talk.lens.json", "openai-whisper-to-transcript.lens.json", "transcript-to-document.lens.json", "transcript-to-expression.lens.json", "nlp-to-annotation-layers.lens.json", "layers-to-document.lens.json"]) { 30 31 const lensPath = path.join(lensDir, file); 31 32 if (!existsSync(lensPath)) continue; 32 33 const spec = JSON.parse(readFileSync(lensPath, "utf-8")); ··· 86 87 ? `at://${did}/tv.ionosphere.event/${event.rkey}` 87 88 : undefined; 88 89 90 + const transcriptsDir = path.resolve(import.meta.dirname, "../../data/transcripts"); 91 + const nlpDir = path.resolve(import.meta.dirname, "../../../pipeline/data/nlp"); 92 + let docCount = 0; 93 + 89 94 for (const talk of talks) { 90 95 const speakerRkeys = db 91 96 .prepare( ··· 98 103 (s: any) => `at://${did}/tv.ionosphere.speaker/${s.rkey}` 99 104 ); 100 105 101 - await pds.putRecord("tv.ionosphere.talk", talk.rkey, { 102 - $type: "tv.ionosphere.talk", 103 - title: talk.title, 104 - ...(eventUri && { eventUri }), 105 - ...(speakerUris.length > 0 && { speakerUris }), 106 - ...(talk.video_uri && { videoUri: talk.video_uri }), 107 - ...(talk.video_offset_ns && { videoOffsetNs: talk.video_offset_ns }), 108 - ...(talk.schedule_uri && { scheduleUri: talk.schedule_uri }), 109 - ...(talk.room && { room: talk.room }), 110 - ...(talk.category && { category: talk.category }), 111 - ...(talk.talk_type && { talkType: talk.talk_type }), 112 - ...(talk.starts_at && { startsAt: talk.starts_at }), 113 - ...(talk.ends_at && { endsAt: talk.ends_at }), 114 - ...(talk.duration && { duration: talk.duration }), 115 - ...(talk.description && { description: talk.description }), 116 - }); 106 + // Try to assemble a document with NLP structural annotations 107 + let document = undefined; 108 + const nlpPath = path.join(nlpDir, `${talk.rkey}.json`); 109 + const transcriptPath = path.join(transcriptsDir, `${talk.rkey}.json`); 110 + 111 + if (existsSync(nlpPath) && existsSync(transcriptPath)) { 112 + const nlpData = JSON.parse(readFileSync(nlpPath, "utf-8")) as { 113 + sentences: NlpAnnotations["sentences"]; 114 + paragraphs: NlpAnnotations["paragraphs"]; 115 + entities: NlpAnnotations["entities"]; 116 + topicBreaks: NlpAnnotations["topicBreaks"]; 117 + }; 118 + const transcriptData = JSON.parse(readFileSync(transcriptPath, "utf-8")); 119 + const compact = encode(transcriptData); 120 + document = decodeToDocumentWithStructure(compact, { 121 + sentences: nlpData.sentences, 122 + paragraphs: nlpData.paragraphs, 123 + entities: nlpData.entities, 124 + topicBreaks: nlpData.topicBreaks, 125 + }); 126 + docCount++; 127 + } 128 + 129 + try { 130 + await pds.putRecord("tv.ionosphere.talk", talk.rkey, { 131 + $type: "tv.ionosphere.talk", 132 + title: talk.title, 133 + ...(document && { document }), 134 + ...(eventUri && { eventUri }), 135 + ...(speakerUris.length > 0 && { speakerUris }), 136 + ...(talk.video_uri && { videoUri: talk.video_uri }), 137 + ...(talk.video_offset_ns && { videoOffsetNs: talk.video_offset_ns }), 138 + ...(talk.schedule_uri && { scheduleUri: talk.schedule_uri }), 139 + ...(talk.room && { room: talk.room }), 140 + ...(talk.category && { category: talk.category }), 141 + ...(talk.talk_type && { talkType: talk.talk_type }), 142 + ...(talk.starts_at && { startsAt: talk.starts_at }), 143 + ...(talk.ends_at && { endsAt: talk.ends_at }), 144 + ...(talk.duration && { duration: talk.duration }), 145 + ...(talk.description && { description: talk.description }), 146 + }); 147 + } catch (err: any) { 148 + if (err?.status === 413) { 149 + console.warn(` ⚠ Talk ${talk.rkey}: payload too large, publishing without document`); 150 + await pds.putRecord("tv.ionosphere.talk", talk.rkey, { 151 + $type: "tv.ionosphere.talk", 152 + title: talk.title, 153 + ...(eventUri && { eventUri }), 154 + ...(speakerUris.length > 0 && { speakerUris }), 155 + ...(talk.video_uri && { videoUri: talk.video_uri }), 156 + ...(talk.video_offset_ns && { videoOffsetNs: talk.video_offset_ns }), 157 + ...(talk.schedule_uri && { scheduleUri: talk.schedule_uri }), 158 + ...(talk.room && { room: talk.room }), 159 + ...(talk.category && { category: talk.category }), 160 + ...(talk.talk_type && { talkType: talk.talk_type }), 161 + ...(talk.starts_at && { startsAt: talk.starts_at }), 162 + ...(talk.ends_at && { endsAt: talk.ends_at }), 163 + ...(talk.duration && { duration: talk.duration }), 164 + ...(talk.description && { description: talk.description }), 165 + }); 166 + } else { 167 + throw err; 168 + } 169 + } 117 170 } 171 + console.log(` ${docCount} talks with assembled documents.`); 118 172 console.log(` Done.`); 119 173 120 174 // 4. Publish transcripts from cached files 121 - const transcriptsDir = path.resolve(import.meta.dirname, "../../data/transcripts"); 122 175 let transcriptCount = 0; 123 176 124 177 for (const talk of talks) { ··· 140 193 } 141 194 console.log(`\nPublished ${transcriptCount} transcripts.`); 142 195 143 - // 5. Publish concepts 144 - const concepts = db.prepare("SELECT * FROM concepts").all() as any[]; 145 - console.log(`\nPublishing ${concepts.length} concepts...`); 146 - for (const concept of concepts) { 147 - await pds.putRecord("tv.ionosphere.concept", concept.rkey, { 148 - $type: "tv.ionosphere.concept", 149 - name: concept.name, 150 - ...(concept.aliases && { aliases: JSON.parse(concept.aliases) }), 151 - ...(concept.description && { description: concept.description }), 152 - ...(concept.wikidata_id && { wikidataId: concept.wikidata_id }), 153 - ...(concept.url && { url: concept.url }), 154 - }); 155 - } 156 - console.log(` Done.`); 196 + // 5. Publish layers.pub records 197 + console.log("\n=== Stage 6: layers.pub records ==="); 198 + let layersCount = 0; 157 199 158 - // 6. Publish annotations 159 - const annotations = db.prepare("SELECT * FROM annotations").all() as any[]; 160 - console.log(`\nPublishing ${annotations.length} annotations...`); 161 - for (const ann of annotations) { 162 - const talkUri = ann.talk_uri 163 - ? ann.talk_uri.replace(/^at:\/\/[^/]+/, `at://${did}`) 164 - : null; 165 - const transcriptUri = ann.transcript_uri.replace(/^at:\/\/[^/]+/, `at://${did}`); 166 - const conceptUri = ann.concept_uri.replace(/^at:\/\/[^/]+/, `at://${did}`); 167 - await pds.putRecord("tv.ionosphere.annotation", ann.rkey, { 168 - $type: "tv.ionosphere.annotation", 169 - transcriptUri, 170 - ...(talkUri && { talkUri }), 171 - conceptUri, 172 - byteStart: ann.byte_start, 173 - byteEnd: ann.byte_end, 174 - ...(ann.text && { text: ann.text }), 175 - }); 200 + for (const talk of talks) { 201 + const transcriptPath = path.join(transcriptsDir, `${talk.rkey}.json`); 202 + const nlpPath = path.join(nlpDir, `${talk.rkey}.json`); 203 + if (!existsSync(transcriptPath) || !existsSync(nlpPath)) continue; 204 + 205 + const transcriptData = JSON.parse(readFileSync(transcriptPath, "utf-8")); 206 + const nlpData = JSON.parse(readFileSync(nlpPath, "utf-8")); 207 + const compact = encode(transcriptData); 208 + 209 + const transcriptRecord = { 210 + $type: "tv.ionosphere.transcript" as const, 211 + text: compact.text, 212 + startMs: compact.startMs, 213 + timings: compact.timings, 214 + talkUri: `at://${did}/tv.ionosphere.talk/${talk.rkey}`, 215 + }; 216 + 217 + const { expression, segmentations, temporals } = await transcriptToLayersPub(transcriptRecord, did, talk.rkey); 218 + const expressionUri = `at://${did}/pub.layers.expression.expression/${talk.rkey}-expression`; 219 + const layers = await nlpToAnnotationLayers(nlpData, did, talk.rkey, expressionUri); 220 + 221 + const segPuts = segmentations.map((seg, i) => 222 + pds.putRecord("pub.layers.segmentation.segmentation", 223 + segmentations.length === 1 ? `${talk.rkey}-segmentation` : `${talk.rkey}-segmentation-${i}`, 224 + seg) 225 + ); 226 + const temporalPuts = temporals.map((temp, i) => 227 + pds.putRecord("pub.layers.segmentation.segmentation", 228 + temporals.length === 1 ? `${talk.rkey}-temporal` : `${talk.rkey}-temporal-${i}`, 229 + temp) 230 + ); 231 + 232 + await Promise.all([ 233 + pds.putRecord("pub.layers.expression.expression", `${talk.rkey}-expression`, expression), 234 + ...segPuts, 235 + ...temporalPuts, 236 + pds.putRecord("pub.layers.annotation.annotationLayer", `${talk.rkey}-sentences`, layers.sentences), 237 + pds.putRecord("pub.layers.annotation.annotationLayer", `${talk.rkey}-paragraphs`, layers.paragraphs), 238 + pds.putRecord("pub.layers.annotation.annotationLayer", `${talk.rkey}-entities`, layers.entities), 239 + pds.putRecord("pub.layers.annotation.annotationLayer", `${talk.rkey}-topics`, layers.topics), 240 + ]); 241 + 242 + const totalRecords = 1 + segmentations.length + temporals.length + 4; 243 + console.log(` layers.pub: ${talk.rkey} (${totalRecords} records${segmentations.length > 1 ? `, ${segmentations.length} seg chunks` : ''})`); 244 + layersCount++; 176 245 } 177 - console.log(` Done.`); 246 + console.log(`Published layers.pub records for ${layersCount} talks.`); 178 247 179 248 console.log(`\nAll records published to ${PDS_URL}`); 180 249 console.log(`DID: ${did}`);
+16 -77
apps/ionosphere-appview/src/routes.ts
··· 6 6 import path from "node:path"; 7 7 import { 8 8 decodeToDocument, 9 - type Document, 10 - type DocumentFacet, 11 9 } from "@ionosphere/format/transcript-encoding"; 12 - 13 - /** 14 - * Overlay concept-ref facets onto a document from annotation records. 15 - * Reads pre-computed annotations from the DB — no text matching at serve time. 16 - */ 17 - function overlayAnnotations( 18 - doc: Document, 19 - annotations: Array<{ 20 - concept_uri: string; 21 - byte_start: number; 22 - byte_end: number; 23 - text: string | null; 24 - concept_name: string; 25 - concept_rkey: string; 26 - }> 27 - ): Document { 28 - const facets: DocumentFacet[] = annotations.map((a) => { 29 - // Find nearest timestamp facet for temporal position 30 - let nearestTime = 0; 31 - for (const f of doc.facets) { 32 - const ts = f.features.find( 33 - (feat) => feat.$type === "tv.ionosphere.facet#timestamp" 34 - ); 35 - if (ts && Math.abs(f.index.byteStart - a.byte_start) < 50) { 36 - nearestTime = ts.startTime; 37 - break; 38 - } 39 - } 40 - 41 - return { 42 - index: { byteStart: a.byte_start, byteEnd: a.byte_end }, 43 - features: [ 44 - { 45 - $type: "tv.ionosphere.facet#concept-ref", 46 - conceptUri: a.concept_uri, 47 - conceptRkey: a.concept_rkey, 48 - conceptName: a.concept_name, 49 - startTime: nearestTime, 50 - }, 51 - ], 52 - }; 53 - }); 54 - 55 - return { 56 - text: doc.text, 57 - facets: [...doc.facets, ...facets], 58 - }; 59 - } 60 10 61 11 export function createRoutes(db: Database.Database): Hono { 62 12 const app = new Hono(); ··· 156 106 ) 157 107 .all((talk as any).uri); 158 108 159 - // Decode compact transcript into full document 160 - const transcript = db 161 - .prepare("SELECT * FROM transcripts WHERE talk_uri = ?") 162 - .get((talk as any).uri) as any; 163 - 164 109 let document = null; 165 - if (transcript) { 166 - const compact = { 167 - text: transcript.text, 168 - startMs: transcript.start_ms, 169 - timings: JSON.parse(transcript.timings), 170 - }; 171 - let doc = decodeToDocument(compact); 110 + // Prefer pre-assembled document from talk record 111 + if ((talk as any).document) { 112 + document = JSON.parse((talk as any).document); 113 + } else { 114 + // Fallback: decode from compact transcript (no structural facets) 115 + const transcript = db 116 + .prepare("SELECT * FROM transcripts WHERE talk_uri = ?") 117 + .get((talk as any).uri) as any; 172 118 173 - // Overlay concept annotations from the DB 174 - const annotations = db 175 - .prepare( 176 - `SELECT a.*, c.name as concept_name, c.rkey as concept_rkey 177 - FROM annotations a 178 - JOIN concepts c ON c.uri = a.concept_uri 179 - WHERE a.transcript_uri = ?` 180 - ) 181 - .all(transcript.uri) as any[]; 182 - 183 - if (annotations.length > 0) { 184 - doc = overlayAnnotations(doc, annotations); 119 + if (transcript) { 120 + const compact = { 121 + text: transcript.text, 122 + startMs: transcript.start_ms, 123 + timings: JSON.parse(transcript.timings), 124 + }; 125 + document = decodeToDocument(compact); 185 126 } 186 - 187 - document = doc; 188 127 } 189 128 190 129 return c.json({ 191 130 talk: { 192 131 ...(talk as any), 193 - document: document ? JSON.stringify(document) : null, 132 + document: document ?? null, 194 133 }, 195 134 speakers, 196 135 concepts,
+17 -1
apps/ionosphere-appview/src/tracks.ts
··· 325 325 || (hardcoded ? loadDiarizationFromFile(hardcoded.dirName) : []); 326 326 327 327 const streamRecordUri = dbStream ? `at://${dbStream.did}/tv.ionosphere.stream/${slug}` : ""; 328 - const transcript = getStreamTranscriptFromDb(db, streamRecordUri) 328 + let transcript = getStreamTranscriptFromDb(db, streamRecordUri) 329 329 ?? (hardcoded ? loadTranscriptFromFile(hardcoded.dirName) : null); 330 + 331 + // Overlay NLP paragraph facets for structural gaps (no entities/concepts — no sidebar to contextualize them) 332 + if (transcript) { 333 + const nlpPath = path.join(path.resolve(import.meta.dirname, "../../../pipeline/data/stream-nlp"), `stream-${slug}.json`); 334 + if (existsSync(nlpPath)) { 335 + try { 336 + const nlp = JSON.parse(readFileSync(nlpPath, "utf-8")); 337 + for (const p of nlp.paragraphs || []) { 338 + transcript.facets.push({ index: { byteStart: p.byteStart, byteEnd: p.byteEnd }, features: [{ $type: "tv.ionosphere.facet#paragraph" }] }); 339 + } 340 + for (const tb of nlp.topicBreaks || []) { 341 + transcript.facets.push({ index: { byteStart: tb.byteStart, byteEnd: tb.byteStart }, features: [{ $type: "tv.ionosphere.facet#topic-break" }] }); 342 + } 343 + } catch {} 344 + } 345 + } 330 346 const words = getStreamWordsFromDb(db, streamRecordUri).length > 0 331 347 ? getStreamWordsFromDb(db, streamRecordUri) 332 348 : (hardcoded ? loadWordsFromFile(hardcoded.dirName) : []);
+80 -15
apps/ionosphere/src/app/components/TranscriptView.tsx
··· 1 1 "use client"; 2 2 3 3 import { useTimestamp } from "./TimestampProvider"; 4 - import { useRef, useEffect, useMemo, useCallback, forwardRef, useState } from "react"; 4 + import React, { useRef, useEffect, useMemo, useCallback, forwardRef, useState } from "react"; 5 5 import { 6 6 extractData, 7 7 brightnessAtTime, ··· 9 9 type TranscriptDocument, 10 10 type WordSpan, 11 11 type ConceptSpan, 12 + type ParagraphSpan, 13 + type EntitySpan, 12 14 } from "@/lib/transcript"; 13 15 import { useAuth } from "@/lib/auth"; 14 16 import { publishComment, type CommentData, isEmojiReaction } from "@/lib/comments"; ··· 80 82 const scrollScrubbing = useRef(false); 81 83 const wordRefsMap = useRef<Map<number, HTMLSpanElement>>(new Map()); 82 84 83 - const { words, wordConcepts } = useMemo( 85 + const { words, wordConcepts, paragraphs, entities, topicBreaks } = useMemo( 84 86 () => extractData(document), 85 87 [document] 86 88 ); 87 89 90 + // Map each word object in the paragraph hierarchy to its flat index, 91 + // so the nested render can look up wordConcepts, wordRefs, comments, etc. 92 + const wordToGlobalIndex = useMemo(() => { 93 + const map = new Map<WordSpan, number>(); 94 + let idx = 0; 95 + for (const para of paragraphs) { 96 + for (const sent of para.sentences) { 97 + for (const word of sent.words) { 98 + map.set(word, idx++); 99 + } 100 + } 101 + } 102 + return map; 103 + }, [paragraphs]); 104 + 105 + // Map each word index to its overlapping entity (if any) 106 + const wordEntities = useMemo(() => { 107 + const map = new Map<number, EntitySpan>(); 108 + for (const entity of entities) { 109 + for (let i = 0; i < words.length; i++) { 110 + const w = words[i]; 111 + if (w.byteStart >= entity.byteStart && w.byteEnd <= entity.byteEnd) { 112 + if (!map.has(i)) map.set(i, entity); 113 + } 114 + } 115 + } 116 + return map; 117 + }, [words, entities]); 118 + 88 119 // Find the active word index 89 120 const activeIndex = useMemo(() => { 90 121 for (let i = 0; i < words.length; i++) { ··· 197 228 const container = containerRef.current; 198 229 if (!container) return; 199 230 200 - const LERP = 0.15; // easing factor — higher = snappier 231 + const LERP = 0.25; // easing factor — higher = snappier 232 + const SNAP_THRESHOLD = 2; // px — snap to target below this to avoid float 201 233 202 234 const animate = () => { 203 235 // Check selection state directly every frame — more reliable than selectionchange event ··· 206 238 207 239 if (!userScrolling.current && !hasSelection && scrollTarget.current !== null) { 208 240 const diff = scrollTarget.current - container.scrollTop; 209 - if (Math.abs(diff) > 0.5) { 241 + if (Math.abs(diff) > SNAP_THRESHOLD) { 210 242 container.scrollTop += diff * LERP; 243 + } else if (Math.abs(diff) > 0.5) { 244 + // Snap to exact target — no more visible floating 245 + container.scrollTop = scrollTarget.current; 211 246 } 212 247 } 213 248 animFrameId.current = requestAnimationFrame(animate); ··· 315 350 // Reset the "hand back to auto-scroll" timer 316 351 clearTimeout(userScrollTimer.current); 317 352 userScrollTimer.current = setTimeout(() => { 353 + // Anchor auto-scroll to current position so it resumes 354 + // smoothly from where the user left off — no jump 355 + scrollTarget.current = container.scrollTop; 318 356 userScrolling.current = false; 319 - }, paused ? 999999 : 2000); 357 + }, paused ? 999999 : 800); 320 358 321 359 cancelAnimationFrame(rafId); 322 360 rafId = requestAnimationFrame(() => { ··· 507 545 </div> 508 546 {/* Top spacer: pushes first word down to the playhead (33% mark) */} 509 547 <div style={{ height: "calc(33% + 1rem)" }} /> 510 - {words.map((word, i) => ( 511 - <WordSpanComponent 512 - key={i} 513 - ref={(el) => setWordRef(i, el)} 514 - word={word} 515 - concept={wordConcepts[i]?.[0] || null} 516 - currentTimeNs={currentTimeNs} 517 - onSeek={handleSeek} 518 - hasComment={wordHasComment.has(i)} 519 - /> 548 + {paragraphs.map((para, pi) => ( 549 + <React.Fragment key={pi}> 550 + {topicBreaks.has(pi) && ( 551 + <hr className="border-neutral-800 my-6" /> 552 + )} 553 + <div className="mb-4"> 554 + {para.sentences.map((sent, si) => ( 555 + <span key={si} className="sentence" style={{ display: "block", marginBottom: "0.25em" }}> 556 + {sent.words.map((word) => { 557 + const idx = wordToGlobalIndex.get(word) ?? 0; 558 + const entityForWord = wordEntities.get(idx); 559 + const entityClass = entityForWord 560 + ? entityForWord.speakerDid 561 + ? "underline decoration-blue-400/40 underline-offset-2" 562 + : entityForWord.conceptUri 563 + ? "" // Already handled by concept prop 564 + : "underline decoration-dotted decoration-neutral-500/40 underline-offset-2" 565 + : ""; 566 + const wordEl = ( 567 + <WordSpanComponent 568 + key={idx} 569 + ref={(el) => setWordRef(idx, el)} 570 + word={word} 571 + concept={wordConcepts[idx]?.[0] || null} 572 + currentTimeNs={currentTimeNs} 573 + onSeek={handleSeek} 574 + hasComment={wordHasComment.has(idx)} 575 + /> 576 + ); 577 + return entityClass ? ( 578 + <span key={idx} className={entityClass}>{wordEl}</span> 579 + ) : wordEl; 580 + })} 581 + </span> 582 + ))} 583 + </div> 584 + </React.Fragment> 520 585 ))} 521 586 {/* Reaction margin indicators */} 522 587 {[...reactionGroups.entries()].map(([key, group]) => {
+82 -52
apps/ionosphere/src/app/components/VideoPlayer.tsx
··· 32 32 // Select AAC audio track before playback starts to avoid mid-play rebuffer. 33 33 // Streamplace serves both original + AAC renditions — switching after 34 34 // playback begins causes a visible stall. 35 + // 36 + // Strategy: wait for MANIFEST_PARSED, then select the audio track 37 + // before any playback begins. Only auto-play after the track is set 38 + // and the first fragment is buffered — this avoids the reload cycle 39 + // caused by switching tracks mid-stream. 35 40 let audioSettled = false; 41 + let seekSettled = offsetS <= 0; // no seek needed if no offset 42 + let hasAutoPlayed = false; 43 + 44 + const tryAutoPlay = () => { 45 + if (!hasAutoPlayed && video!.paused && audioSettled && seekSettled) { 46 + hasAutoPlayed = true; 47 + video!.play().catch(() => {}); 48 + } 49 + }; 50 + 36 51 hls.on(Hls.Events.AUDIO_TRACKS_UPDATED, () => { 52 + if (audioSettled) return; // only run once 37 53 const tracks = hls!.audioTracks; 38 54 if (tracks.length > 1) { 39 55 const aacTrack = tracks.findIndex((t: any) => ··· 44 60 } 45 61 } 46 62 audioSettled = true; 63 + tryAutoPlay(); 47 64 }); 48 65 49 - // Auto-play once audio track is settled and first fragment is buffered 50 - let hasAutoPlayed = false; 51 - hls.on(Hls.Events.FRAG_BUFFERED, () => { 52 - if (!hasAutoPlayed && video!.paused && audioSettled) { 53 - hasAutoPlayed = true; 54 - video!.play().catch(() => {}); 66 + hls.on(Hls.Events.MANIFEST_PARSED, () => { 67 + // If no audio tracks event fires within 200ms, consider audio settled 68 + setTimeout(() => { 69 + if (!audioSettled) { 70 + audioSettled = true; 71 + tryAutoPlay(); 72 + } 73 + }, 200); 74 + 75 + // Seek to offset before playback starts 76 + if (offsetS > 0) { 77 + video!.currentTime = offsetS; 78 + // Wait for seek to complete before allowing auto-play 79 + video!.addEventListener("seeked", () => { 80 + seekSettled = true; 81 + tryAutoPlay(); 82 + }, { once: true }); 55 83 } 56 84 }); 57 85 58 - // Fallback: if audio tracks never fire (single track), play after manifest 59 - hls.on(Hls.Events.MANIFEST_PARSED, () => { 60 - // Give AUDIO_TRACKS_UPDATED a chance to fire first 61 - setTimeout(() => { audioSettled = true; }, 100); 86 + // Auto-play once audio is settled, seek is done, and we have buffered data 87 + hls.on(Hls.Events.FRAG_BUFFERED, () => { 88 + tryAutoPlay(); 62 89 }); 63 90 64 - // Error recovery with logging 65 - let mediaErrorRecoveries = 0; 91 + // Error recovery — conservative approach to avoid reload cycles. 92 + // Only recover from fatal errors; non-fatal errors are handled by HLS.js internally. 66 93 hls.on(Hls.Events.ERROR, (_: any, data: any) => { 67 - console.warn("[HLS]", data.type, data.details, data.fatal ? "FATAL" : ""); 68 - if (data.type === Hls.ErrorTypes.MEDIA_ERROR) { 69 - if (mediaErrorRecoveries < 5) { 70 - mediaErrorRecoveries++; 94 + if (!data.fatal) return; 95 + 96 + console.warn("[HLS] Fatal error:", data.type, data.details); 97 + switch (data.type) { 98 + case Hls.ErrorTypes.NETWORK_ERROR: 99 + // Network errors: retry loading 100 + hls!.startLoad(); 101 + break; 102 + case Hls.ErrorTypes.MEDIA_ERROR: 103 + // Media errors: single recovery attempt 71 104 hls!.recoverMediaError(); 72 - return; 73 - } 74 - const tracks = hls!.audioTracks; 75 - if (tracks.length > 1) { 76 - const next = (hls!.audioTrack + 1) % tracks.length; 77 - console.warn("[HLS] Swapping to audio track", next); 78 - hls!.audioTrack = next; 79 - mediaErrorRecoveries = 0; 80 - return; 81 - } 82 - } 83 - if (data.fatal) { 84 - switch (data.type) { 85 - case Hls.ErrorTypes.NETWORK_ERROR: 86 - hls!.startLoad(); 87 - break; 88 - case Hls.ErrorTypes.MEDIA_ERROR: 89 - hls!.recoverMediaError(); 90 - break; 91 - default: 92 - hls!.destroy(); 93 - break; 94 - } 105 + break; 106 + default: 107 + // Unrecoverable: destroy and give up 108 + hls!.destroy(); 109 + break; 95 110 } 96 111 }); 97 - 98 - // Seek to offset once media is loaded 99 - if (offsetS > 0) { 100 - hls.on(Hls.Events.MANIFEST_PARSED, () => { 101 - video!.currentTime = offsetS; 102 - }); 103 - } 104 112 } else if (video!.canPlayType("application/vnd.apple.mpegurl")) { 105 113 video!.src = playlistUrl; 106 114 if (offsetS > 0) { ··· 115 123 return () => { if (hls) hls.destroy(); }; 116 124 }, [playlistUrl, offsetS]); 117 125 118 - // Broadcast current time and play/pause state 126 + // Broadcast current time at 60fps via RAF (instead of ~4Hz timeupdate). 127 + // This eliminates up to 250ms of stale time data and makes the 128 + // transcript highlight track the audio much more tightly. 119 129 useEffect(() => { 120 130 const video = videoRef.current; 121 131 if (!video) return; 122 132 123 - const onTime = () => { 133 + let rafId = 0; 134 + let isPlaying = false; 135 + 136 + const pollTime = () => { 137 + setCurrentTimeNs((video.currentTime - offsetS) * 1e9); 138 + if (isPlaying) rafId = requestAnimationFrame(pollTime); 139 + }; 140 + 141 + const onPlay = () => { 142 + isPlaying = true; 143 + setPaused(false); 144 + rafId = requestAnimationFrame(pollTime); 145 + }; 146 + const onPause = () => { 147 + isPlaying = false; 148 + setPaused(true); 149 + cancelAnimationFrame(rafId); 150 + // One final update to capture exact pause position 124 151 setCurrentTimeNs((video.currentTime - offsetS) * 1e9); 125 152 }; 126 - const onPlay = () => setPaused(false); 127 - const onPause = () => setPaused(true); 153 + // Also update on seek (click-to-seek while paused) 154 + const onSeeked = () => { 155 + setCurrentTimeNs((video.currentTime - offsetS) * 1e9); 156 + }; 128 157 129 - video.addEventListener("timeupdate", onTime); 130 158 video.addEventListener("play", onPlay); 131 159 video.addEventListener("pause", onPause); 160 + video.addEventListener("seeked", onSeeked); 132 161 return () => { 133 - video.removeEventListener("timeupdate", onTime); 162 + cancelAnimationFrame(rafId); 134 163 video.removeEventListener("play", onPlay); 135 164 video.removeEventListener("pause", onPause); 165 + video.removeEventListener("seeked", onSeeked); 136 166 }; 137 167 }, [setCurrentTimeNs, setPaused, offsetS]); 138 168
+41 -10
apps/ionosphere/src/app/components/WindowedTranscriptView.tsx
··· 68 68 timeEnd: number; // ns 69 69 wordStartIdx: number; 70 70 wordEndIdx: number; // exclusive 71 + isParagraphStart: boolean; 71 72 } 72 73 73 74 /** ··· 80 81 containerWidthPx: number, 81 82 charWidthPx: number, 82 83 lineHeightPx: number, 84 + paragraphStarts: Set<number> = new Set(), 83 85 ): LineEntry[] { 84 86 if (words.length === 0 || containerWidthPx < charWidthPx) return []; 85 87 86 88 const maxCharsPerLine = Math.floor(containerWidthPx / charWidthPx); 87 89 const lines: LineEntry[] = []; 88 90 89 - let lineIdx = 0; 91 + let currentY = 0; 90 92 let col = 0; // current column position in characters 91 93 let lineWordStart = 0; 92 94 ··· 96 98 97 99 if (col > 0 && col + wordLen > maxCharsPerLine) { 98 100 // This word doesn't fit — flush current line 101 + const isParaStart = paragraphStarts.has(lineWordStart); 102 + if (isParaStart) { 103 + currentY += lineHeightPx; // add paragraph gap 104 + } 99 105 lines.push({ 100 - yTop: lineIdx * lineHeightPx, 101 - yBottom: (lineIdx + 1) * lineHeightPx, 106 + yTop: currentY, 107 + yBottom: currentY + lineHeightPx, 102 108 timeStart: words[lineWordStart].startTime, 103 109 timeEnd: words[i - 1].endTime, 104 110 wordStartIdx: lineWordStart, 105 111 wordEndIdx: i, 112 + isParagraphStart: isParaStart, 106 113 }); 107 - lineIdx++; 114 + currentY += lineHeightPx; 108 115 col = 0; 109 116 lineWordStart = i; 110 117 } ··· 114 121 115 122 // Flush last line 116 123 if (lineWordStart < words.length) { 124 + const isParaStart = paragraphStarts.has(lineWordStart); 125 + if (isParaStart) { 126 + currentY += lineHeightPx; // add paragraph gap 127 + } 117 128 lines.push({ 118 - yTop: lineIdx * lineHeightPx, 119 - yBottom: (lineIdx + 1) * lineHeightPx, 129 + yTop: currentY, 130 + yBottom: currentY + lineHeightPx, 120 131 timeStart: words[lineWordStart].startTime, 121 132 timeEnd: words[words.length - 1].endTime, 122 133 wordStartIdx: lineWordStart, 123 134 wordEndIdx: words.length, 135 + isParagraphStart: isParaStart, 124 136 }); 125 137 } 126 138 ··· 135 147 136 148 export default function WindowedTranscriptView({ document }: WindowedTranscriptViewProps) { 137 149 const { currentTimeNs, seekTo, paused } = useTimestamp(); 150 + const pausedRef = useRef(paused); 151 + pausedRef.current = paused; 138 152 const containerRef = useRef<HTMLDivElement>(null); 139 153 const [containerWidth, setContainerWidth] = useState(0); 140 154 141 - const { words, wordConcepts } = useMemo(() => extractData(document), [document]); 155 + const { words, wordConcepts, paragraphs } = useMemo(() => extractData(document), [document]); 156 + 157 + // Compute paragraph start word indices for gap insertion 158 + const paragraphStartIndices = useMemo(() => { 159 + const set = new Set<number>(); 160 + let globalIdx = 0; 161 + for (const para of paragraphs) { 162 + const firstWordIdx = globalIdx; 163 + for (const sent of para.sentences) { 164 + globalIdx += sent.words.length; 165 + } 166 + if (firstWordIdx > 0) { 167 + set.add(firstWordIdx); 168 + } 169 + } 170 + return set; 171 + }, [paragraphs]); 142 172 143 173 // Measure container width 144 174 useEffect(() => { ··· 171 201 // Compute layout — pure computation, no DOM/canvas needed 172 202 const lines = useMemo(() => { 173 203 if (containerWidth < 50) return []; 174 - return computeMonospaceLayout(words, containerWidth, charWidth, LINE_HEIGHT); 175 - }, [words, containerWidth, charWidth]); 204 + return computeMonospaceLayout(words, containerWidth, charWidth, LINE_HEIGHT, paragraphStartIndices); 205 + }, [words, containerWidth, charWidth, paragraphStartIndices]); 176 206 177 207 const totalHeight = lines.length > 0 ? lines[lines.length - 1].yBottom : 0; 178 208 ··· 290 320 291 321 if (!userScrolling.current && scrollTargetRef.current !== null) { 292 322 // Extrapolate target forward using velocity since last timeupdate 293 - const msSinceUpdate = now - lastTickMs.current; 323 + // When paused, don't extrapolate — velocity is stale 324 + const msSinceUpdate = pausedRef.current ? 0 : now - lastTickMs.current; 294 325 const extrapolated = scrollTargetRef.current + scrollVelocity.current * msSinceUpdate; 295 326 296 327 const diff = extrapolated - container.scrollTop;
+1 -1
apps/ionosphere/src/app/concepts/ConceptsListContent.tsx
··· 99 99 const res = await fetch(`${API_BASE}/xrpc/tv.ionosphere.getTalk?rkey=${encodeURIComponent(rkey)}`); 100 100 if (!res.ok) return; 101 101 const { talk } = await res.json(); 102 - const doc = talk.document ? JSON.parse(talk.document) : null; 102 + const doc = talk.document ? (typeof talk.document === "string" ? JSON.parse(talk.document) : talk.document) : null; 103 103 setSelectedTalk({ 104 104 rkey, title: talk.title, videoUri: talk.video_uri, 105 105 offsetNs: talk.video_offset_ns || 0,
+1 -1
apps/ionosphere/src/app/concordance/IndexContent.tsx
··· 422 422 const res = await fetch(`${API_BASE}/xrpc/tv.ionosphere.getTalk?rkey=${encodeURIComponent(rkey)}`); 423 423 if (!res.ok) return; 424 424 const { talk } = await res.json(); 425 - const doc = talk.document ? JSON.parse(talk.document) : null; 425 + const doc = talk.document ? (typeof talk.document === "string" ? JSON.parse(talk.document) : talk.document) : null; 426 426 setSelectedTalk({ 427 427 rkey, title: talk.title, videoUri: talk.video_uri, 428 428 offsetNs: talk.video_offset_ns || 0,
+1 -1
apps/ionosphere/src/app/speakers/SpeakersListContent.tsx
··· 152 152 const talkRes = await fetch(`${API_BASE}/xrpc/tv.ionosphere.getTalk?rkey=${encodeURIComponent(rkey)}`); 153 153 if (!talkRes.ok) return; 154 154 const { talk } = await talkRes.json(); 155 - const doc = talk.document ? JSON.parse(talk.document) : null; 155 + const doc = talk.document ? (typeof talk.document === "string" ? JSON.parse(talk.document) : talk.document) : null; 156 156 157 157 setSelectedTalk({ 158 158 rkey: talk.rkey,
+1 -1
apps/ionosphere/src/app/talks/TalksListContent.tsx
··· 168 168 const res = await fetch(`${API_BASE}/xrpc/tv.ionosphere.getTalk?rkey=${encodeURIComponent(rkey)}`); 169 169 if (!res.ok) return; 170 170 const { talk } = await res.json(); 171 - const doc = talk.document ? JSON.parse(talk.document) : null; 171 + const doc = talk.document ? (typeof talk.document === "string" ? JSON.parse(talk.document) : talk.document) : null; 172 172 setSelectedTalk({ 173 173 rkey, 174 174 title: talk.title,
+67 -20
apps/ionosphere/src/app/talks/[rkey]/TalkContent.tsx
··· 1 1 "use client"; 2 2 3 3 import { useMemo, useRef, useState, useEffect, useCallback } from "react"; 4 - import { TimestampProvider } from "@/app/components/TimestampProvider"; 4 + import { TimestampProvider, useTimestamp } from "@/app/components/TimestampProvider"; 5 5 import VideoPlayer from "@/app/components/VideoPlayer"; 6 6 import TranscriptView from "@/app/components/TranscriptView"; 7 7 import { fetchComments, type CommentData } from "@/lib/comments"; 8 8 import ReactionBar from "@/app/components/ReactionBar"; 9 9 import MentionsSidebar from "@/app/components/MentionsSidebar"; 10 + 11 + function ConceptSidebar({ concepts }: { concepts: Array<{ rkey: string; name: string; timeNs?: number }> }) { 12 + const { seekTo } = useTimestamp(); 13 + return ( 14 + <section> 15 + <h2 className="text-xs font-semibold text-neutral-500 uppercase tracking-wide mb-2">Concepts</h2> 16 + <div className="flex flex-wrap gap-1.5"> 17 + {concepts.map((c) => ( 18 + <button 19 + key={c.rkey} 20 + onClick={() => c.timeNs ? seekTo(c.timeNs) : undefined} 21 + className="text-xs px-2 py-0.5 rounded-full bg-amber-500/10 text-amber-300/80 hover:bg-amber-500/20 hover:text-amber-200 transition-colors cursor-pointer" 22 + title={c.timeNs ? `Jump to ${Math.floor(c.timeNs / 1e9 / 60)}:${String(Math.floor((c.timeNs / 1e9) % 60)).padStart(2, "0")}` : c.name} 23 + > 24 + {c.name} 25 + </button> 26 + ))} 27 + </div> 28 + </section> 29 + ); 30 + } 10 31 11 32 interface TalkContentProps { 12 33 talk: any; ··· 57 78 const durationMin = talk.duration ? (talk.duration / 1e9 / 60).toFixed(0) : null; 58 79 const document = useMemo(() => { 59 80 if (!talk.document) return null; 60 - const doc = JSON.parse(talk.document); 81 + const doc = typeof talk.document === "string" ? JSON.parse(talk.document) : talk.document; 61 82 return doc?.facets?.length > 0 ? doc : null; 62 83 }, [talk.document]); 84 + 85 + // Derive concepts from document facets (concept-ref entities) 86 + // For each concept, find the timestamp of its first mention 87 + const docConcepts = useMemo(() => { 88 + if (!document) return []; 89 + 90 + // Build a byte→time lookup from timestamp facets 91 + const byteToTime: Array<{ byteStart: number; byteEnd: number; startTime: number }> = []; 92 + for (const f of document.facets) { 93 + for (const feat of f.features) { 94 + if (feat.$type === "tv.ionosphere.facet#timestamp" && feat.startTime != null) { 95 + byteToTime.push({ byteStart: f.index.byteStart, byteEnd: f.index.byteEnd, startTime: feat.startTime }); 96 + } 97 + } 98 + } 99 + 100 + const seen = new Map<string, { name: string; uri: string; rkey: string; timeNs: number }>(); 101 + for (const f of document.facets) { 102 + for (const feat of f.features) { 103 + if (feat.$type === "tv.ionosphere.facet#concept-ref" && feat.conceptUri) { 104 + if (!seen.has(feat.conceptUri)) { 105 + const rkey = feat.conceptUri.split("/").pop() || ""; 106 + // Find the nearest timestamp facet overlapping this byte range 107 + let timeNs = 0; 108 + for (const ts of byteToTime) { 109 + if (ts.byteStart < f.index.byteEnd && ts.byteEnd > f.index.byteStart) { 110 + timeNs = ts.startTime; 111 + break; 112 + } 113 + } 114 + seen.set(feat.conceptUri, { 115 + name: feat.conceptName || feat.label || rkey, 116 + uri: feat.conceptUri, 117 + rkey, 118 + timeNs, 119 + }); 120 + } 121 + } 122 + } 123 + } 124 + return [...seen.values()].sort((a, b) => a.name.localeCompare(b.name)); 125 + }, [document]); 63 126 64 127 const videoContainerRef = useRef<HTMLDivElement>(null); 65 128 const [videoWidth, setVideoWidth] = useState<number | null>(null); ··· 207 270 : "text-neutral-500 hover:text-neutral-300" 208 271 }`} 209 272 > 210 - Concepts ({concepts.length}) 273 + Concepts ({(concepts.length > 0 ? concepts : docConcepts).length}) 211 274 </button> 212 275 <button 213 276 onClick={() => setSidebarTab("mentions")} ··· 224 287 {/* Tab content */} 225 288 <div className="flex-1 overflow-y-auto p-4"> 226 289 {sidebarTab === "concepts" && ( 227 - <> 228 - {concepts.length > 0 ? ( 229 - <div className="flex flex-wrap gap-1.5"> 230 - {concepts.map((c: any) => ( 231 - <a 232 - key={c.rkey} 233 - href={`/concepts/${c.rkey}`} 234 - className="text-xs px-2 py-0.5 rounded-full bg-amber-500/10 text-amber-300/80 hover:bg-amber-500/20 hover:text-amber-200 transition-colors" 235 - > 236 - {c.name} 237 - </a> 238 - ))} 239 - </div> 240 - ) : ( 241 - <div className="text-xs text-neutral-500">No concepts extracted yet.</div> 242 - )} 243 - </> 290 + <ConceptSidebar concepts={concepts.length > 0 ? concepts : docConcepts} /> 244 291 )} 245 292 {sidebarTab === "mentions" && ( 246 293 <MentionsSidebar mentions={mentions} words={[]} />
+8 -19
apps/ionosphere/src/app/tracks/page.tsx
··· 28 28 } 29 29 30 30 return ( 31 - <div className="max-w-3xl mx-auto px-4 py-8"> 32 - <h1 className="text-2xl font-bold mb-6">Full-Day Streams</h1> 33 - <p className="text-neutral-400 text-sm mb-8"> 34 - Browse complete conference recordings by room and day. Each track shows 35 - the full stream with talk segments, speaker diarization, and transcript. 36 - </p> 37 - 31 + <div className="max-w-5xl mx-auto px-4 py-6"> 38 32 {DAY_ORDER.filter((d) => byDay.has(d)).map((day) => ( 39 - <div key={day} className="mb-8"> 40 - <h2 className="text-lg font-semibold text-neutral-300 mb-3 border-b border-neutral-800 pb-1"> 33 + <div key={day} className="mb-6"> 34 + <h2 className="text-xs font-semibold text-neutral-500 uppercase tracking-wide mb-3"> 41 35 {day} 42 36 </h2> 43 - <div className="space-y-2"> 37 + <div className="grid gap-2 sm:grid-cols-2 lg:grid-cols-3"> 44 38 {byDay.get(day)!.map((track) => ( 45 39 <Link 46 40 key={track.slug} 47 41 href={`/tracks/${track.slug}`} 48 - className="block p-4 rounded-lg border border-neutral-800 hover:border-neutral-600 transition-colors" 42 + className="block p-3 rounded-lg bg-neutral-900/50 hover:bg-neutral-800/70 transition-colors" 49 43 > 50 - <div className="flex items-baseline justify-between"> 51 - <span className="font-medium">{track.room}</span> 52 - <span className="text-sm text-neutral-500"> 53 - {formatDuration(track.durationSeconds)} 54 - </span> 55 - </div> 56 - <div className="text-sm text-neutral-400 mt-1"> 57 - {track.talkCount} talks 44 + <div className="font-medium text-sm">{track.room}</div> 45 + <div className="text-xs text-neutral-500 mt-1"> 46 + {track.talkCount} talks · {formatDuration(track.durationSeconds)} 58 47 </div> 59 48 </Link> 60 49 ))}
+197
apps/ionosphere/src/lib/transcript.test.ts
··· 8 8 WINDOW_NS, 9 9 type TranscriptDocument, 10 10 type ConceptSpan, 11 + type EntitySpan, 12 + type ParagraphSpan, 13 + type SentenceSpan, 11 14 } from "./transcript"; 12 15 13 16 // --------------------------------------------------------------------------- ··· 246 249 expect(Math.abs(g - b)).toBeLessThan(15); 247 250 }); 248 251 }); 252 + 253 + // --------------------------------------------------------------------------- 254 + // extractData — hierarchical structure 255 + // --------------------------------------------------------------------------- 256 + 257 + describe("extractData — hierarchical structure", () => { 258 + it("groups words into sentences and paragraphs when facets present", () => { 259 + const doc = makeDoc([ 260 + { text: "Hello", startNs: 1000, endNs: 2000 }, 261 + { text: "world.", startNs: 2000, endNs: 3000 }, 262 + { text: "New", startNs: 4000, endNs: 5000 }, 263 + { text: "sentence.", startNs: 5000, endNs: 6000 }, 264 + ]); 265 + const encoder = new TextEncoder(); 266 + const text = "Hello world. New sentence."; 267 + // Add sentence facets 268 + doc.facets.push({ 269 + index: { 270 + byteStart: 0, 271 + byteEnd: encoder.encode("Hello world.").length, 272 + }, 273 + features: [{ $type: "tv.ionosphere.facet#sentence" }], 274 + }); 275 + doc.facets.push({ 276 + index: { 277 + byteStart: encoder.encode("Hello world. ").length, 278 + byteEnd: encoder.encode(text).length, 279 + }, 280 + features: [{ $type: "tv.ionosphere.facet#sentence" }], 281 + }); 282 + // Add paragraph facet covering everything 283 + doc.facets.push({ 284 + index: { byteStart: 0, byteEnd: encoder.encode(text).length }, 285 + features: [{ $type: "tv.ionosphere.facet#paragraph" }], 286 + }); 287 + 288 + const result = extractData(doc); 289 + expect(result.paragraphs).toHaveLength(1); 290 + expect(result.paragraphs[0].sentences).toHaveLength(2); 291 + expect(result.paragraphs[0].sentences[0].words).toHaveLength(2); 292 + expect(result.paragraphs[0].sentences[1].words).toHaveLength(2); 293 + }); 294 + 295 + it("gracefully degrades to singleton paragraph/sentence when no structural facets", () => { 296 + const doc = makeDoc([ 297 + { text: "Hello", startNs: 1000, endNs: 2000 }, 298 + { text: "world", startNs: 2000, endNs: 3000 }, 299 + ]); 300 + 301 + const result = extractData(doc); 302 + expect(result.paragraphs).toHaveLength(1); 303 + expect(result.paragraphs[0].sentences).toHaveLength(1); 304 + expect(result.paragraphs[0].sentences[0].words).toHaveLength(2); 305 + // Legacy flat access still works 306 + expect(result.words).toHaveLength(2); 307 + }); 308 + 309 + it("handles multiple paragraphs with multiple sentences each", () => { 310 + const doc = makeDoc([ 311 + { text: "A", startNs: 1000, endNs: 2000 }, 312 + { text: "B.", startNs: 2000, endNs: 3000 }, 313 + { text: "C", startNs: 4000, endNs: 5000 }, 314 + { text: "D.", startNs: 5000, endNs: 6000 }, 315 + { text: "E", startNs: 7000, endNs: 8000 }, 316 + { text: "F.", startNs: 8000, endNs: 9000 }, 317 + ]); 318 + const encoder = new TextEncoder(); 319 + const text = "A B. C D. E F."; 320 + 321 + // 3 sentences 322 + const s1End = encoder.encode("A B.").length; 323 + const s2Start = encoder.encode("A B. ").length; 324 + const s2End = encoder.encode("A B. C D.").length; 325 + const s3Start = encoder.encode("A B. C D. ").length; 326 + const s3End = encoder.encode(text).length; 327 + 328 + doc.facets.push({ index: { byteStart: 0, byteEnd: s1End }, features: [{ $type: "tv.ionosphere.facet#sentence" }] }); 329 + doc.facets.push({ index: { byteStart: s2Start, byteEnd: s2End }, features: [{ $type: "tv.ionosphere.facet#sentence" }] }); 330 + doc.facets.push({ index: { byteStart: s3Start, byteEnd: s3End }, features: [{ $type: "tv.ionosphere.facet#sentence" }] }); 331 + 332 + // 2 paragraphs: first has sentences 1-2, second has sentence 3 333 + doc.facets.push({ index: { byteStart: 0, byteEnd: s2End }, features: [{ $type: "tv.ionosphere.facet#paragraph" }] }); 334 + doc.facets.push({ index: { byteStart: s3Start, byteEnd: s3End }, features: [{ $type: "tv.ionosphere.facet#paragraph" }] }); 335 + 336 + const result = extractData(doc); 337 + expect(result.paragraphs).toHaveLength(2); 338 + expect(result.paragraphs[0].sentences).toHaveLength(2); 339 + expect(result.paragraphs[1].sentences).toHaveLength(1); 340 + expect(result.words).toHaveLength(6); // flat access still works 341 + }); 342 + }); 343 + 344 + // --------------------------------------------------------------------------- 345 + // extractData — entities and topic breaks 346 + // --------------------------------------------------------------------------- 347 + 348 + describe("extractData — entities and topic breaks", () => { 349 + it("extracts entity spans from facets", () => { 350 + const doc = makeDoc([ 351 + { text: "Matt", startNs: 1000, endNs: 2000 }, 352 + { text: "presented.", startNs: 2000, endNs: 3000 }, 353 + ]); 354 + const encoder = new TextEncoder(); 355 + doc.facets.push({ 356 + index: { byteStart: 0, byteEnd: encoder.encode("Matt").length }, 357 + features: [{ 358 + $type: "tv.ionosphere.facet#speaker-ref", 359 + speakerDid: "did:plc:matt123", 360 + label: "Matt", 361 + }], 362 + }); 363 + 364 + const result = extractData(doc); 365 + expect(result.entities).toHaveLength(1); 366 + expect(result.entities[0].speakerDid).toBe("did:plc:matt123"); 367 + expect(result.entities[0].byteStart).toBe(0); 368 + }); 369 + 370 + it("extracts concept-ref entities", () => { 371 + const doc = makeDoc([ 372 + { text: "AT", startNs: 1000, endNs: 2000 }, 373 + { text: "Protocol", startNs: 2000, endNs: 3000 }, 374 + ]); 375 + const encoder = new TextEncoder(); 376 + doc.facets.push({ 377 + index: { byteStart: 0, byteEnd: encoder.encode("AT Protocol").length }, 378 + features: [{ 379 + $type: "tv.ionosphere.facet#concept-ref", 380 + conceptUri: "at://did:example/concept/atp", 381 + conceptRkey: "atp", 382 + conceptName: "AT Protocol", 383 + }], 384 + }); 385 + 386 + const result = extractData(doc); 387 + expect(result.entities).toHaveLength(1); 388 + expect(result.entities[0].conceptUri).toBe("at://did:example/concept/atp"); 389 + expect(result.entities[0].conceptName).toBe("AT Protocol"); 390 + expect(result.entities[0].label).toBe("AT Protocol"); 391 + }); 392 + 393 + it("extracts #entity facets with nerType", () => { 394 + const doc = makeDoc([ 395 + { text: "London", startNs: 1000, endNs: 2000 }, 396 + { text: "is", startNs: 2000, endNs: 3000 }, 397 + { text: "great.", startNs: 3000, endNs: 4000 }, 398 + ]); 399 + const encoder = new TextEncoder(); 400 + doc.facets.push({ 401 + index: { byteStart: 0, byteEnd: encoder.encode("London").length }, 402 + features: [{ 403 + $type: "tv.ionosphere.facet#entity", 404 + label: "London", 405 + nerType: "GPE", 406 + }], 407 + }); 408 + 409 + const result = extractData(doc); 410 + expect(result.entities).toHaveLength(1); 411 + expect(result.entities[0].label).toBe("London"); 412 + expect(result.entities[0].nerType).toBe("GPE"); 413 + }); 414 + 415 + it("extracts topic breaks as paragraph indices", () => { 416 + const doc = makeDoc([ 417 + { text: "A.", startNs: 1000, endNs: 2000 }, 418 + { text: "B.", startNs: 3000, endNs: 4000 }, 419 + ]); 420 + const encoder = new TextEncoder(); 421 + const text = "A. B."; 422 + const s1End = encoder.encode("A.").length; 423 + const s2Start = encoder.encode("A. ").length; 424 + const s2End = encoder.encode(text).length; 425 + 426 + doc.facets.push({ index: { byteStart: 0, byteEnd: s1End }, features: [{ $type: "tv.ionosphere.facet#paragraph" }] }); 427 + doc.facets.push({ index: { byteStart: s2Start, byteEnd: s2End }, features: [{ $type: "tv.ionosphere.facet#paragraph" }] }); 428 + doc.facets.push({ index: { byteStart: s2Start, byteEnd: s2Start }, features: [{ $type: "tv.ionosphere.facet#topic-break" }] }); 429 + doc.facets.push({ index: { byteStart: 0, byteEnd: s1End }, features: [{ $type: "tv.ionosphere.facet#sentence" }] }); 430 + doc.facets.push({ index: { byteStart: s2Start, byteEnd: s2End }, features: [{ $type: "tv.ionosphere.facet#sentence" }] }); 431 + 432 + const result = extractData(doc); 433 + expect(result.topicBreaks.has(1)).toBe(true); 434 + expect(result.topicBreaks.has(0)).toBe(false); 435 + }); 436 + 437 + it("returns empty entities and topicBreaks when no such facets exist", () => { 438 + const doc = makeDoc([ 439 + { text: "Hello", startNs: 1000, endNs: 2000 }, 440 + ]); 441 + const result = extractData(doc); 442 + expect(result.entities).toHaveLength(0); 443 + expect(result.topicBreaks.size).toBe(0); 444 + }); 445 + });
+165 -1
apps/ionosphere/src/lib/transcript.ts
··· 36 36 conceptName: string; 37 37 } 38 38 39 + export interface EntitySpan { 40 + byteStart: number; 41 + byteEnd: number; 42 + label: string; 43 + nerType?: string; 44 + speakerDid?: string; 45 + conceptUri?: string; 46 + conceptName?: string; 47 + } 48 + 49 + export interface SentenceSpan { 50 + byteStart: number; 51 + byteEnd: number; 52 + words: WordSpan[]; 53 + } 54 + 55 + export interface ParagraphSpan { 56 + byteStart: number; 57 + byteEnd: number; 58 + sentences: SentenceSpan[]; 59 + } 60 + 39 61 export function extractData(doc: TranscriptDocument) { 40 62 const encoder = new TextEncoder(); 41 63 const textBytes = encoder.encode(doc.text); ··· 43 65 44 66 const words: WordSpan[] = []; 45 67 const concepts: ConceptSpan[] = []; 68 + const entities: EntitySpan[] = []; 69 + const topicBreakPositions: number[] = []; 46 70 47 71 for (const f of doc.facets) { 48 72 for (const feat of f.features) { ··· 66 90 conceptRkey: feat.conceptRkey!, 67 91 conceptName: feat.conceptName!, 68 92 }); 93 + entities.push({ 94 + byteStart: f.index.byteStart, 95 + byteEnd: f.index.byteEnd, 96 + label: feat.conceptName!, 97 + conceptUri: feat.conceptUri, 98 + conceptName: feat.conceptName, 99 + }); 100 + } else if (feat.$type === "tv.ionosphere.facet#speaker-ref") { 101 + entities.push({ 102 + byteStart: f.index.byteStart, 103 + byteEnd: f.index.byteEnd, 104 + label: feat.label!, 105 + speakerDid: feat.speakerDid, 106 + }); 107 + } else if (feat.$type === "tv.ionosphere.facet#entity") { 108 + entities.push({ 109 + byteStart: f.index.byteStart, 110 + byteEnd: f.index.byteEnd, 111 + label: feat.label!, 112 + nerType: feat.nerType, 113 + }); 114 + } else if (feat.$type === "tv.ionosphere.facet#topic-break") { 115 + topicBreakPositions.push(f.index.byteStart); 69 116 } 70 117 } 71 118 } ··· 91 138 ) 92 139 ); 93 140 94 - return { words, concepts, wordConcepts }; 141 + // --- Build hierarchical structure: paragraphs > sentences > words --- 142 + 143 + // Extract sentence facets 144 + const sentenceRanges: Array<{ byteStart: number; byteEnd: number }> = []; 145 + const paragraphRanges: Array<{ byteStart: number; byteEnd: number }> = []; 146 + 147 + for (const f of doc.facets) { 148 + for (const feat of f.features) { 149 + if (feat.$type === "tv.ionosphere.facet#sentence") { 150 + sentenceRanges.push({ byteStart: f.index.byteStart, byteEnd: f.index.byteEnd }); 151 + } else if (feat.$type === "tv.ionosphere.facet#paragraph") { 152 + paragraphRanges.push({ byteStart: f.index.byteStart, byteEnd: f.index.byteEnd }); 153 + } 154 + } 155 + } 156 + 157 + sentenceRanges.sort((a, b) => a.byteStart - b.byteStart); 158 + paragraphRanges.sort((a, b) => a.byteStart - b.byteStart); 159 + 160 + // If no sentence facets, wrap all words in one singleton sentence 161 + if (sentenceRanges.length === 0 && words.length > 0) { 162 + sentenceRanges.push({ 163 + byteStart: 0, 164 + byteEnd: textBytes.length, 165 + }); 166 + } 167 + 168 + // If no paragraph facets, wrap all sentences in one singleton paragraph 169 + if (paragraphRanges.length === 0 && sentenceRanges.length > 0) { 170 + paragraphRanges.push({ 171 + byteStart: 0, 172 + byteEnd: textBytes.length, 173 + }); 174 + } 175 + 176 + // Assign words to sentences 177 + const sentences: SentenceSpan[] = sentenceRanges.map((s) => ({ 178 + byteStart: s.byteStart, 179 + byteEnd: s.byteEnd, 180 + words: [], 181 + })); 182 + 183 + // Track unassigned words for catch-all sentence 184 + const assignedWords = new Set<number>(); 185 + 186 + for (let wi = 0; wi < words.length; wi++) { 187 + const w = words[wi]; 188 + for (const s of sentences) { 189 + if (w.byteStart >= s.byteStart && w.byteEnd <= s.byteEnd) { 190 + s.words.push(w); 191 + assignedWords.add(wi); 192 + break; 193 + } 194 + } 195 + } 196 + 197 + // Words not covered by any sentence go into a catch-all sentence 198 + if (assignedWords.size < words.length) { 199 + const catchAll: SentenceSpan = { 200 + byteStart: 0, 201 + byteEnd: textBytes.length, 202 + words: [], 203 + }; 204 + for (let wi = 0; wi < words.length; wi++) { 205 + if (!assignedWords.has(wi)) { 206 + catchAll.words.push(words[wi]); 207 + } 208 + } 209 + sentences.push(catchAll); 210 + } 211 + 212 + // Assign sentences to paragraphs 213 + const paragraphs: ParagraphSpan[] = paragraphRanges.map((p) => ({ 214 + byteStart: p.byteStart, 215 + byteEnd: p.byteEnd, 216 + sentences: [], 217 + })); 218 + 219 + const assignedSentences = new Set<number>(); 220 + 221 + for (let si = 0; si < sentences.length; si++) { 222 + const s = sentences[si]; 223 + for (const p of paragraphs) { 224 + if (s.byteStart >= p.byteStart && s.byteEnd <= p.byteEnd) { 225 + p.sentences.push(s); 226 + assignedSentences.add(si); 227 + break; 228 + } 229 + } 230 + } 231 + 232 + // Sentences not covered by any paragraph go into a catch-all paragraph 233 + if (assignedSentences.size < sentences.length) { 234 + const catchAll: ParagraphSpan = { 235 + byteStart: 0, 236 + byteEnd: textBytes.length, 237 + sentences: [], 238 + }; 239 + for (let si = 0; si < sentences.length; si++) { 240 + if (!assignedSentences.has(si)) { 241 + catchAll.sentences.push(sentences[si]); 242 + } 243 + } 244 + paragraphs.push(catchAll); 245 + } 246 + 247 + // Map topic break byte positions to paragraph indices 248 + const topicBreaks = new Set<number>(); 249 + for (const pos of topicBreakPositions) { 250 + for (let pi = 0; pi < paragraphs.length; pi++) { 251 + if (pos >= paragraphs[pi].byteStart && pos <= paragraphs[pi].byteEnd) { 252 + topicBreaks.add(pi); 253 + break; 254 + } 255 + } 256 + } 257 + 258 + return { words, concepts, wordConcepts, paragraphs, entities, topicBreaks }; 95 259 } 96 260 97 261 // --- Brightness ---
+1 -1
apps/ionosphere/tsconfig.tsbuildinfo
··· 1 - {"fileNames":["../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es5.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2015.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2016.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2017.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2018.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2019.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2020.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2021.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2022.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2023.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2024.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.esnext.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.dom.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.dom.iterable.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2015.core.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2015.collection.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2015.generator.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2015.iterable.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2015.promise.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2015.proxy.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2015.reflect.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2015.symbol.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2015.symbol.wellknown.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2016.array.include.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2016.intl.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2017.arraybuffer.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2017.date.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2017.object.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2017.sharedmemory.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2017.string.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2017.intl.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2017.typedarrays.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2018.asyncgenerator.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2018.asynciterable.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2018.intl.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2018.promise.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2018.regexp.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2019.array.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2019.object.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2019.string.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2019.symbol.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2019.intl.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2020.bigint.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2020.date.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2020.promise.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2020.sharedmemory.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2020.string.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2020.symbol.wellknown.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2020.intl.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2020.number.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2021.promise.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2021.string.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2021.weakref.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2021.intl.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2022.array.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2022.error.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2022.intl.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2022.object.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2022.string.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2022.regexp.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2023.array.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2023.collection.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2023.intl.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2024.arraybuffer.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2024.collection.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2024.object.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2024.promise.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2024.regexp.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2024.sharedmemory.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2024.string.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.esnext.array.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.esnext.collection.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.esnext.intl.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.esnext.disposable.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.esnext.promise.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.esnext.decorators.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.esnext.iterator.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.esnext.float16.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.esnext.error.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.esnext.sharedmemory.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.decorators.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.decorators.legacy.d.ts","./.next/types/routes.d.ts","../../node_modules/.pnpm/@types+react@18.3.28/node_modules/@types/react/global.d.ts","../../node_modules/.pnpm/csstype@3.2.3/node_modules/csstype/index.d.ts","../../node_modules/.pnpm/@types+prop-types@15.7.15/node_modules/@types/prop-types/index.d.ts","../../node_modules/.pnpm/@types+react@18.3.28/node_modules/@types/react/index.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/styled-jsx/types/css.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/styled-jsx/types/macro.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/styled-jsx/types/style.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/styled-jsx/types/global.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/styled-jsx/types/index.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/shared/lib/amp.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/amp.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/get-page-files.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/compatibility/disposable.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/compatibility/indexable.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/compatibility/iterators.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/compatibility/index.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/globals.typedarray.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/buffer.buffer.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/globals.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/web-globals/abortcontroller.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/web-globals/domexception.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/web-globals/events.d.ts","../../node_modules/.pnpm/buffer@5.7.1/node_modules/buffer/index.d.ts","../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/header.d.ts","../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/readable.d.ts","../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/file.d.ts","../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/fetch.d.ts","../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/formdata.d.ts","../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/connector.d.ts","../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/client.d.ts","../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/errors.d.ts","../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/dispatcher.d.ts","../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/global-dispatcher.d.ts","../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/global-origin.d.ts","../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/pool-stats.d.ts","../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/pool.d.ts","../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/handlers.d.ts","../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/balanced-pool.d.ts","../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/agent.d.ts","../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/mock-interceptor.d.ts","../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/mock-agent.d.ts","../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/mock-client.d.ts","../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/mock-pool.d.ts","../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/mock-errors.d.ts","../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/proxy-agent.d.ts","../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/env-http-proxy-agent.d.ts","../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/retry-handler.d.ts","../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/retry-agent.d.ts","../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/api.d.ts","../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/interceptors.d.ts","../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/util.d.ts","../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/cookies.d.ts","../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/patch.d.ts","../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/websocket.d.ts","../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/eventsource.d.ts","../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/filereader.d.ts","../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/diagnostics-channel.d.ts","../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/content-type.d.ts","../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/cache.d.ts","../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/index.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/web-globals/fetch.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/web-globals/navigator.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/web-globals/storage.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/assert.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/assert/strict.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/async_hooks.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/buffer.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/child_process.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/cluster.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/console.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/constants.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/crypto.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/dgram.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/diagnostics_channel.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/dns.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/dns/promises.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/domain.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/events.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/fs.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/fs/promises.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/http.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/http2.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/https.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/inspector.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/inspector.generated.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/module.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/net.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/os.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/path.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/perf_hooks.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/process.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/punycode.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/querystring.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/readline.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/readline/promises.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/repl.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/sea.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/sqlite.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/stream.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/stream/promises.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/stream/consumers.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/stream/web.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/string_decoder.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/test.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/timers.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/timers/promises.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/tls.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/trace_events.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/tty.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/url.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/util.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/v8.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/vm.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/wasi.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/worker_threads.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/zlib.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/index.d.ts","../../node_modules/.pnpm/@types+react@18.3.28/node_modules/@types/react/canary.d.ts","../../node_modules/.pnpm/@types+react@18.3.28/node_modules/@types/react/experimental.d.ts","../../node_modules/.pnpm/@types+react-dom@18.3.7_@types+react@18.3.28/node_modules/@types/react-dom/index.d.ts","../../node_modules/.pnpm/@types+react-dom@18.3.7_@types+react@18.3.28/node_modules/@types/react-dom/canary.d.ts","../../node_modules/.pnpm/@types+react-dom@18.3.7_@types+react@18.3.28/node_modules/@types/react-dom/experimental.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/lib/fallback.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/compiled/webpack/webpack.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/config.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/lib/load-custom-routes.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/shared/lib/image-config.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/build/webpack/plugins/subresource-integrity-plugin.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/body-streams.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/lib/cache-control.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/lib/setup-exception-listeners.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/lib/worker.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/lib/constants.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/client/components/app-router-headers.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/build/rendering-mode.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/lib/router-utils/build-prefetch-segment-data-route.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/require-hook.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/lib/experimental/ppr.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/build/webpack/plugins/app-build-manifest-plugin.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/lib/page-types.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/build/segment-config/app/app-segment-config.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/build/segment-config/pages/pages-segment-config.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/build/analysis/get-page-static-info.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/build/webpack/loaders/get-module-build-info.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/build/webpack/plugins/middleware-plugin.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/node-polyfill-crypto.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/node-environment-baseline.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/node-environment-extensions/error-inspect.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/node-environment-extensions/random.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/node-environment-extensions/date.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/node-environment-extensions/web-crypto.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/node-environment-extensions/node-crypto.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/node-environment.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/build/page-extensions-type.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/build/webpack/plugins/flight-manifest-plugin.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/instrumentation/types.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/lib/coalesced-function.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/shared/lib/router/utils/middleware-route-matcher.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/lib/router-utils/types.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/shared/lib/modern-browserslist-target.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/shared/lib/constants.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/trace/types.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/trace/trace.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/trace/shared.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/trace/index.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/build/load-jsconfig.d.ts","../../node_modules/.pnpm/@next+env@15.5.14/node_modules/@next/env/dist/index.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/build/webpack/plugins/telemetry-plugin/use-cache-tracker-utils.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/build/webpack/plugins/telemetry-plugin/telemetry-plugin.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/telemetry/storage.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/build/build-context.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/shared/lib/bloom-filter.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/build/webpack-config.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/route-kind.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/route-definitions/route-definition.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/build/swc/generated-native.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/build/swc/types.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/dev/parse-version-info.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/next-devtools/shared/types.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/dev/dev-indicator-server-state.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/lib/parse-stack.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/next-devtools/server/shared.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/next-devtools/shared/stack-frame.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/next-devtools/dev-overlay/utils/get-error-by-type.d.ts","../../node_modules/.pnpm/@types+react@18.3.28/node_modules/@types/react/jsx-runtime.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/next-devtools/dev-overlay/container/runtime-error/render-error.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/next-devtools/dev-overlay/shared.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/dev/hot-reloader-types.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/lib/cache-handlers/types.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/response-cache/types.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/resume-data-cache/cache-store.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/resume-data-cache/resume-data-cache.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/render-result.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/lib/i18n-provider.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/web/next-url.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/compiled/@edge-runtime/cookies/index.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/web/spec-extension/cookies.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/web/spec-extension/request.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/after/builtin-request-context.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/web/spec-extension/fetch-event.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/web/spec-extension/response.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/build/segment-config/middleware/middleware-config.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/web/types.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/build/webpack/plugins/pages-manifest-plugin.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/shared/lib/router/utils/parse-url.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/base-http/node.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/build/webpack/plugins/next-font-manifest-plugin.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/route-definitions/locale-route-definition.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/route-definitions/pages-route-definition.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/shared/lib/mitt.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/client/with-router.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/client/router.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/client/route-loader.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/client/page-loader.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/shared/lib/router/router.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/shared/lib/router-context.shared-runtime.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/shared/lib/loadable-context.shared-runtime.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/shared/lib/loadable.shared-runtime.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/shared/lib/image-config-context.shared-runtime.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/shared/lib/hooks-client-context.shared-runtime.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/shared/lib/head-manager-context.shared-runtime.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/route-definitions/app-page-route-definition.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/build/webpack/loaders/metadata/types.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/build/webpack/loaders/next-app-loader/index.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/lib/app-dir-module.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/web/spec-extension/adapters/request-cookies.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/async-storage/draft-mode-provider.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/web/spec-extension/adapters/headers.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/app-render/cache-signal.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/app-render/dynamic-rendering.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/request/fallback-params.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/app-render/work-unit-async-storage-instance.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/response-cache/index.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/lib/lazy-result.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/lib/implicit-tags.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/app-render/work-unit-async-storage.external.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/shared/lib/deep-readonly.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/shared/lib/router/utils/parse-relative-url.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/app-render/app-render.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/shared/lib/server-inserted-html.shared-runtime.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/shared/lib/amp-context.shared-runtime.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/route-modules/app-page/vendored/contexts/entrypoints.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/route-modules/app-page/module.compiled.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/client/components/error-boundary.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/client/components/layout-router.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/client/components/render-from-template-context.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/app-render/action-async-storage-instance.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/app-render/action-async-storage.external.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/client/components/client-page.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/client/components/client-segment.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/request/search-params.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/client/components/hooks-server-context.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/client/components/http-access-fallback/error-boundary.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/lib/metadata/types/alternative-urls-types.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/lib/metadata/types/extra-types.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/lib/metadata/types/metadata-types.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/lib/metadata/types/manifest-types.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/lib/metadata/types/opengraph-types.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/lib/metadata/types/twitter-types.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/lib/metadata/types/metadata-interface.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/lib/metadata/types/resolvers.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/lib/metadata/types/icons.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/lib/metadata/resolve-metadata.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/lib/metadata/metadata.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/lib/framework/boundary-components.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/app-render/rsc/preloads.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/app-render/rsc/postpone.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/app-render/rsc/taint.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/shared/lib/segment-cache/segment-value-encoding.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/app-render/collect-segment-data.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/next-devtools/userspace/app/segment-explorer-node.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/app-render/entry-base.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/build/templates/app-page.d.ts","../../node_modules/.pnpm/@types+react@18.3.28/node_modules/@types/react/jsx-dev-runtime.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/route-modules/app-page/vendored/rsc/entrypoints.d.ts","../../node_modules/.pnpm/@types+react-dom@18.3.7_@types+react@18.3.28/node_modules/@types/react-dom/client.d.ts","../../node_modules/.pnpm/@types+react-dom@18.3.7_@types+react@18.3.28/node_modules/@types/react-dom/server.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/route-modules/app-page/vendored/ssr/entrypoints.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/route-modules/app-page/module.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/web/adapter.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/use-cache/cache-life.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/app-render/types.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/client/components/router-reducer/router-reducer-types.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/client/flight-data-helpers.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/client/components/router-reducer/fetch-server-response.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/shared/lib/app-router-context.shared-runtime.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/route-modules/pages/vendored/contexts/entrypoints.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/route-modules/pages/module.compiled.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/build/templates/pages.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/route-modules/pages/module.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/next-devtools/userspace/pages/pages-dev-overlay-setup.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/render.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/route-definitions/pages-api-route-definition.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/route-matches/pages-api-route-match.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/route-matchers/route-matcher.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/route-matcher-providers/route-matcher-provider.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/route-matcher-managers/route-matcher-manager.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/normalizers/normalizer.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/normalizers/locale-route-normalizer.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/normalizers/request/pathname-normalizer.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/normalizers/request/suffix.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/normalizers/request/rsc.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/normalizers/request/prefetch-rsc.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/normalizers/request/next-data.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/normalizers/request/segment-prefix-rsc.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/build/static-paths/types.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/base-server.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/lib/async-callback-set.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/shared/lib/router/utils/route-regex.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/shared/lib/router/utils/route-matcher.d.ts","../../node_modules/.pnpm/sharp@0.34.5/node_modules/sharp/lib/index.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/image-optimizer.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/next-server.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/lib/types.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/lib/lru-cache.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/lib/dev-bundler-service.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/dev/static-paths-worker.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/dev/next-dev-server.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/next.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/lib/render-server.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/lib/router-server.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/shared/lib/router/utils/path-match.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/lib/router-utils/filesystem.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/lib/router-utils/setup-dev-bundler.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/lib/router-utils/router-server-context.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/route-modules/route-module.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/load-components.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/route-definitions/app-route-route-definition.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/async-storage/work-store.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/web/http.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/route-modules/app-route/shared-modules.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/client/components/redirect-status-code.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/client/components/redirect-error.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/build/templates/app-route.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/route-modules/app-route/module.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/route-modules/app-route/module.compiled.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/build/segment-config/app/app-segments.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/build/utils.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/build/turborepo-access-trace/types.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/build/turborepo-access-trace/result.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/build/turborepo-access-trace/helpers.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/build/turborepo-access-trace/index.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/export/routes/types.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/export/types.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/export/worker.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/build/worker.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/build/index.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/lib/incremental-cache/index.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/after/after.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/after/after-context.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/app-render/work-async-storage-instance.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/app-render/work-async-storage.external.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/request/params.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/route-matches/route-match.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/request-meta.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/cli/next-test.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/config-shared.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/base-http/index.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/api-utils/index.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/types.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/shared/lib/html-context.shared-runtime.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/shared/lib/utils.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/pages/_app.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/app.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/web/spec-extension/unstable-cache.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/web/spec-extension/revalidate.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/web/spec-extension/unstable-no-store.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/use-cache/cache-tag.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/cache.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/shared/lib/runtime-config.external.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/config.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/pages/_document.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/document.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/shared/lib/dynamic.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dynamic.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/pages/_error.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/error.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/shared/lib/head.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/head.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/request/cookies.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/request/headers.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/request/draft-mode.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/headers.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/shared/lib/get-img-props.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/client/image-component.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/shared/lib/image-external.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/image.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/client/link.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/link.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/client/components/redirect.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/client/components/not-found.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/client/components/forbidden.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/client/components/unauthorized.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/client/components/unstable-rethrow.server.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/client/components/unstable-rethrow.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/client/components/navigation.react-server.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/client/components/unrecognized-action-error.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/client/components/navigation.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/navigation.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/router.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/client/script.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/script.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/web/spec-extension/user-agent.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/compiled/@edge-runtime/primitives/url.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/web/spec-extension/image-response.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/compiled/@vercel/og/satori/index.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/compiled/@vercel/og/emoji/index.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/compiled/@vercel/og/types.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/after/index.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/request/root-params.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/request/connection.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/server.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/types/global.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/types/compiled.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/types.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/index.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/image-types/global.d.ts","./next-env.d.ts","./next.config.ts","../../node_modules/.pnpm/source-map-js@1.2.1/node_modules/source-map-js/source-map.d.ts","../../node_modules/.pnpm/postcss@8.5.8/node_modules/postcss/lib/previous-map.d.ts","../../node_modules/.pnpm/postcss@8.5.8/node_modules/postcss/lib/input.d.ts","../../node_modules/.pnpm/postcss@8.5.8/node_modules/postcss/lib/css-syntax-error.d.ts","../../node_modules/.pnpm/postcss@8.5.8/node_modules/postcss/lib/declaration.d.ts","../../node_modules/.pnpm/postcss@8.5.8/node_modules/postcss/lib/root.d.ts","../../node_modules/.pnpm/postcss@8.5.8/node_modules/postcss/lib/warning.d.ts","../../node_modules/.pnpm/postcss@8.5.8/node_modules/postcss/lib/lazy-result.d.ts","../../node_modules/.pnpm/postcss@8.5.8/node_modules/postcss/lib/no-work-result.d.ts","../../node_modules/.pnpm/postcss@8.5.8/node_modules/postcss/lib/processor.d.ts","../../node_modules/.pnpm/postcss@8.5.8/node_modules/postcss/lib/result.d.ts","../../node_modules/.pnpm/postcss@8.5.8/node_modules/postcss/lib/document.d.ts","../../node_modules/.pnpm/postcss@8.5.8/node_modules/postcss/lib/rule.d.ts","../../node_modules/.pnpm/postcss@8.5.8/node_modules/postcss/lib/node.d.ts","../../node_modules/.pnpm/postcss@8.5.8/node_modules/postcss/lib/comment.d.ts","../../node_modules/.pnpm/postcss@8.5.8/node_modules/postcss/lib/container.d.ts","../../node_modules/.pnpm/postcss@8.5.8/node_modules/postcss/lib/at-rule.d.ts","../../node_modules/.pnpm/postcss@8.5.8/node_modules/postcss/lib/list.d.ts","../../node_modules/.pnpm/postcss@8.5.8/node_modules/postcss/lib/postcss.d.ts","../../node_modules/.pnpm/postcss@8.5.8/node_modules/postcss/lib/postcss.d.mts","../../node_modules/.pnpm/tailwindcss@3.4.19_tsx@4.21.0/node_modules/tailwindcss/types/generated/corepluginlist.d.ts","../../node_modules/.pnpm/tailwindcss@3.4.19_tsx@4.21.0/node_modules/tailwindcss/types/generated/colors.d.ts","../../node_modules/.pnpm/tailwindcss@3.4.19_tsx@4.21.0/node_modules/tailwindcss/types/config.d.ts","../../node_modules/.pnpm/tailwindcss@3.4.19_tsx@4.21.0/node_modules/tailwindcss/types/index.d.ts","../../node_modules/.pnpm/@tailwindcss+typography@0.5.19_tailwindcss@3.4.19_tsx@4.21.0_/node_modules/@tailwindcss/typography/src/index.d.ts","./tailwind.config.ts","../../node_modules/.pnpm/@vitest+spy@3.2.4/node_modules/@vitest/spy/dist/index.d.ts","../../node_modules/.pnpm/@vitest+pretty-format@3.2.4/node_modules/@vitest/pretty-format/dist/index.d.ts","../../node_modules/.pnpm/@vitest+utils@3.2.4/node_modules/@vitest/utils/dist/types.d.ts","../../node_modules/.pnpm/@vitest+utils@3.2.4/node_modules/@vitest/utils/dist/helpers.d.ts","../../node_modules/.pnpm/tinyrainbow@2.0.0/node_modules/tinyrainbow/dist/index-8b61d5bc.d.ts","../../node_modules/.pnpm/tinyrainbow@2.0.0/node_modules/tinyrainbow/dist/node.d.ts","../../node_modules/.pnpm/@vitest+utils@3.2.4/node_modules/@vitest/utils/dist/index.d.ts","../../node_modules/.pnpm/@vitest+utils@3.2.4/node_modules/@vitest/utils/dist/types.d-bcelap-c.d.ts","../../node_modules/.pnpm/@vitest+utils@3.2.4/node_modules/@vitest/utils/dist/diff.d.ts","../../node_modules/.pnpm/@vitest+expect@3.2.4/node_modules/@vitest/expect/dist/index.d.ts","../../node_modules/.pnpm/vite@7.3.1_@types+node@22.19.15_jiti@1.21.7_tsx@4.21.0/node_modules/vite/types/hmrpayload.d.ts","../../node_modules/.pnpm/vite@7.3.1_@types+node@22.19.15_jiti@1.21.7_tsx@4.21.0/node_modules/vite/dist/node/chunks/modulerunnertransport.d.ts","../../node_modules/.pnpm/vite@7.3.1_@types+node@22.19.15_jiti@1.21.7_tsx@4.21.0/node_modules/vite/types/customevent.d.ts","../../node_modules/.pnpm/@types+estree@1.0.8/node_modules/@types/estree/index.d.ts","../../node_modules/.pnpm/rollup@4.60.1/node_modules/rollup/dist/rollup.d.ts","../../node_modules/.pnpm/rollup@4.60.1/node_modules/rollup/dist/parseast.d.ts","../../node_modules/.pnpm/vite@7.3.1_@types+node@22.19.15_jiti@1.21.7_tsx@4.21.0/node_modules/vite/types/hot.d.ts","../../node_modules/.pnpm/vite@7.3.1_@types+node@22.19.15_jiti@1.21.7_tsx@4.21.0/node_modules/vite/dist/node/module-runner.d.ts","../../node_modules/.pnpm/esbuild@0.27.4/node_modules/esbuild/lib/main.d.ts","../../node_modules/.pnpm/vite@7.3.1_@types+node@22.19.15_jiti@1.21.7_tsx@4.21.0/node_modules/vite/types/internal/terseroptions.d.ts","../../node_modules/.pnpm/vite@7.3.1_@types+node@22.19.15_jiti@1.21.7_tsx@4.21.0/node_modules/vite/types/internal/csspreprocessoroptions.d.ts","../../node_modules/.pnpm/vite@7.3.1_@types+node@22.19.15_jiti@1.21.7_tsx@4.21.0/node_modules/vite/types/internal/lightningcssoptions.d.ts","../../node_modules/.pnpm/vite@7.3.1_@types+node@22.19.15_jiti@1.21.7_tsx@4.21.0/node_modules/vite/types/importglob.d.ts","../../node_modules/.pnpm/vite@7.3.1_@types+node@22.19.15_jiti@1.21.7_tsx@4.21.0/node_modules/vite/types/metadata.d.ts","../../node_modules/.pnpm/vite@7.3.1_@types+node@22.19.15_jiti@1.21.7_tsx@4.21.0/node_modules/vite/dist/node/index.d.ts","../../node_modules/.pnpm/@vitest+runner@3.2.4/node_modules/@vitest/runner/dist/tasks.d-cksck4of.d.ts","../../node_modules/.pnpm/@vitest+runner@3.2.4/node_modules/@vitest/runner/dist/types.d.ts","../../node_modules/.pnpm/@vitest+utils@3.2.4/node_modules/@vitest/utils/dist/error.d.ts","../../node_modules/.pnpm/@vitest+runner@3.2.4/node_modules/@vitest/runner/dist/index.d.ts","../../node_modules/.pnpm/vitest@3.2.4_@types+node@22.19.15_jiti@1.21.7_tsx@4.21.0/node_modules/vitest/optional-types.d.ts","../../node_modules/.pnpm/vitest@3.2.4_@types+node@22.19.15_jiti@1.21.7_tsx@4.21.0/node_modules/vitest/dist/chunks/environment.d.cl3nlxbe.d.ts","../../node_modules/.pnpm/@vitest+mocker@3.2.4_vite@7.3.1_@types+node@22.19.15_jiti@1.21.7_tsx@4.21.0_/node_modules/@vitest/mocker/dist/registry.d-d765pazg.d.ts","../../node_modules/.pnpm/@vitest+mocker@3.2.4_vite@7.3.1_@types+node@22.19.15_jiti@1.21.7_tsx@4.21.0_/node_modules/@vitest/mocker/dist/types.d-d_arzrdy.d.ts","../../node_modules/.pnpm/@vitest+mocker@3.2.4_vite@7.3.1_@types+node@22.19.15_jiti@1.21.7_tsx@4.21.0_/node_modules/@vitest/mocker/dist/index.d.ts","../../node_modules/.pnpm/@vitest+utils@3.2.4/node_modules/@vitest/utils/dist/source-map.d.ts","../../node_modules/.pnpm/vite-node@3.2.4_@types+node@22.19.15_jiti@1.21.7_tsx@4.21.0/node_modules/vite-node/dist/trace-mapping.d-dlvdeqop.d.ts","../../node_modules/.pnpm/vite-node@3.2.4_@types+node@22.19.15_jiti@1.21.7_tsx@4.21.0/node_modules/vite-node/dist/index.d-dgmxd2u7.d.ts","../../node_modules/.pnpm/vite-node@3.2.4_@types+node@22.19.15_jiti@1.21.7_tsx@4.21.0/node_modules/vite-node/dist/index.d.ts","../../node_modules/.pnpm/@vitest+snapshot@3.2.4/node_modules/@vitest/snapshot/dist/environment.d-dhdq1csl.d.ts","../../node_modules/.pnpm/@vitest+snapshot@3.2.4/node_modules/@vitest/snapshot/dist/rawsnapshot.d-lfsmjfud.d.ts","../../node_modules/.pnpm/@vitest+snapshot@3.2.4/node_modules/@vitest/snapshot/dist/index.d.ts","../../node_modules/.pnpm/@vitest+snapshot@3.2.4/node_modules/@vitest/snapshot/dist/environment.d.ts","../../node_modules/.pnpm/vitest@3.2.4_@types+node@22.19.15_jiti@1.21.7_tsx@4.21.0/node_modules/vitest/dist/chunks/config.d.d2roskhv.d.ts","../../node_modules/.pnpm/vitest@3.2.4_@types+node@22.19.15_jiti@1.21.7_tsx@4.21.0/node_modules/vitest/dist/chunks/worker.d.1gmbbd7g.d.ts","../../node_modules/.pnpm/@types+deep-eql@4.0.2/node_modules/@types/deep-eql/index.d.ts","../../node_modules/.pnpm/assertion-error@2.0.1/node_modules/assertion-error/index.d.ts","../../node_modules/.pnpm/@types+chai@5.2.3/node_modules/@types/chai/index.d.ts","../../node_modules/.pnpm/@vitest+runner@3.2.4/node_modules/@vitest/runner/dist/utils.d.ts","../../node_modules/.pnpm/tinybench@2.9.0/node_modules/tinybench/dist/index.d.ts","../../node_modules/.pnpm/vitest@3.2.4_@types+node@22.19.15_jiti@1.21.7_tsx@4.21.0/node_modules/vitest/dist/chunks/benchmark.d.bwvbvtda.d.ts","../../node_modules/.pnpm/vite-node@3.2.4_@types+node@22.19.15_jiti@1.21.7_tsx@4.21.0/node_modules/vite-node/dist/client.d.ts","../../node_modules/.pnpm/vitest@3.2.4_@types+node@22.19.15_jiti@1.21.7_tsx@4.21.0/node_modules/vitest/dist/chunks/coverage.d.s9rmnxie.d.ts","../../node_modules/.pnpm/@vitest+snapshot@3.2.4/node_modules/@vitest/snapshot/dist/manager.d.ts","../../node_modules/.pnpm/vitest@3.2.4_@types+node@22.19.15_jiti@1.21.7_tsx@4.21.0/node_modules/vitest/dist/chunks/reporters.d.bflkqcl6.d.ts","../../node_modules/.pnpm/vitest@3.2.4_@types+node@22.19.15_jiti@1.21.7_tsx@4.21.0/node_modules/vitest/dist/chunks/vite.d.cmlllifp.d.ts","../../node_modules/.pnpm/vitest@3.2.4_@types+node@22.19.15_jiti@1.21.7_tsx@4.21.0/node_modules/vitest/dist/config.d.ts","../../node_modules/.pnpm/vitest@3.2.4_@types+node@22.19.15_jiti@1.21.7_tsx@4.21.0/node_modules/vitest/config.d.ts","./vitest.config.ts","./src/app/api/revalidate/route.ts","./src/lib/corrections.ts","./src/lib/snap-targets.ts","./src/lib/timeline-engine.tsx","./src/app/components/timestampprovider.tsx","./src/app/components/useeditorkeyboard.ts","./src/lib/api.ts","../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/helpers/typealiases.d.cts","../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/helpers/util.d.cts","../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/index.d.cts","../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/zoderror.d.cts","../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/locales/en.d.cts","../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/errors.d.cts","../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/helpers/parseutil.d.cts","../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/helpers/enumutil.d.cts","../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/helpers/errorutil.d.cts","../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/helpers/partialutil.d.cts","../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/standard-schema.d.cts","../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/types.d.cts","../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/external.d.cts","../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/index.d.cts","../../node_modules/.pnpm/@atproto+lexicon@0.4.14/node_modules/@atproto/lexicon/dist/types.d.ts","../../node_modules/.pnpm/@atproto+lexicon@0.4.14/node_modules/@atproto/lexicon/dist/lexicons.d.ts","../../node_modules/.pnpm/@atproto+lexicon@0.4.14/node_modules/@atproto/lexicon/dist/blob-refs.d.ts","../../node_modules/.pnpm/@atproto+common-web@0.4.19/node_modules/@atproto/common-web/dist/check.d.ts","../../node_modules/.pnpm/@atproto+common-web@0.4.19/node_modules/@atproto/common-web/dist/util.d.ts","../../node_modules/.pnpm/@atproto+common-web@0.4.19/node_modules/@atproto/common-web/dist/arrays.d.ts","../../node_modules/.pnpm/@atproto+common-web@0.4.19/node_modules/@atproto/common-web/dist/async.d.ts","../../node_modules/.pnpm/@atproto+common-web@0.4.19/node_modules/@atproto/common-web/dist/tid.d.ts","../../node_modules/.pnpm/@atproto+common-web@0.4.19/node_modules/@atproto/common-web/dist/ipld.d.ts","../../node_modules/.pnpm/@atproto+common-web@0.4.19/node_modules/@atproto/common-web/dist/retry.d.ts","../../node_modules/.pnpm/@atproto+lex-data@0.0.14/node_modules/@atproto/lex-data/dist/cid.d.ts","../../node_modules/.pnpm/@atproto+lex-data@0.0.14/node_modules/@atproto/lex-data/dist/lex.d.ts","../../node_modules/.pnpm/@atproto+lex-data@0.0.14/node_modules/@atproto/lex-data/dist/blob.d.ts","../../node_modules/.pnpm/@atproto+lex-data@0.0.14/node_modules/@atproto/lex-data/dist/lex-equals.d.ts","../../node_modules/.pnpm/@atproto+lex-data@0.0.14/node_modules/@atproto/lex-data/dist/lex-error.d.ts","../../node_modules/.pnpm/@atproto+lex-data@0.0.14/node_modules/@atproto/lex-data/dist/object.d.ts","../../node_modules/.pnpm/@atproto+lex-data@0.0.14/node_modules/@atproto/lex-data/dist/uint8array-base64.d.ts","../../node_modules/.pnpm/@atproto+lex-data@0.0.14/node_modules/@atproto/lex-data/dist/uint8array.d.ts","../../node_modules/.pnpm/@atproto+lex-data@0.0.14/node_modules/@atproto/lex-data/dist/utf8.d.ts","../../node_modules/.pnpm/@atproto+lex-data@0.0.14/node_modules/@atproto/lex-data/dist/index.d.ts","../../node_modules/.pnpm/@atproto+common-web@0.4.19/node_modules/@atproto/common-web/dist/types.d.ts","../../node_modules/.pnpm/@atproto+common-web@0.4.19/node_modules/@atproto/common-web/dist/times.d.ts","../../node_modules/.pnpm/@atproto+syntax@0.5.2/node_modules/@atproto/syntax/dist/did.d.ts","../../node_modules/.pnpm/@atproto+syntax@0.5.2/node_modules/@atproto/syntax/dist/handle.d.ts","../../node_modules/.pnpm/@atproto+syntax@0.5.2/node_modules/@atproto/syntax/dist/at-identifier.d.ts","../../node_modules/.pnpm/@atproto+syntax@0.5.2/node_modules/@atproto/syntax/dist/nsid.d.ts","../../node_modules/.pnpm/@atproto+syntax@0.5.2/node_modules/@atproto/syntax/dist/aturi_validation.d.ts","../../node_modules/.pnpm/@atproto+syntax@0.5.2/node_modules/@atproto/syntax/dist/recordkey.d.ts","../../node_modules/.pnpm/@atproto+syntax@0.5.2/node_modules/@atproto/syntax/dist/aturi.d.ts","../../node_modules/.pnpm/@atproto+syntax@0.5.2/node_modules/@atproto/syntax/dist/datetime.d.ts","../../node_modules/.pnpm/@atproto+syntax@0.5.2/node_modules/@atproto/syntax/dist/language.d.ts","../../node_modules/.pnpm/@atproto+syntax@0.5.2/node_modules/@atproto/syntax/dist/tid.d.ts","../../node_modules/.pnpm/@atproto+syntax@0.5.2/node_modules/@atproto/syntax/dist/uri.d.ts","../../node_modules/.pnpm/@atproto+syntax@0.5.2/node_modules/@atproto/syntax/dist/index.d.ts","../../node_modules/.pnpm/@atproto+common-web@0.4.19/node_modules/@atproto/common-web/dist/strings.d.ts","../../node_modules/.pnpm/@atproto+common-web@0.4.19/node_modules/@atproto/common-web/dist/did-doc.d.ts","../../node_modules/.pnpm/@atproto+common-web@0.4.19/node_modules/@atproto/common-web/dist/index.d.ts","../../node_modules/.pnpm/@atproto+lexicon@0.4.14/node_modules/@atproto/lexicon/dist/serialize.d.ts","../../node_modules/.pnpm/@atproto+lexicon@0.4.14/node_modules/@atproto/lexicon/dist/index.d.ts","../../node_modules/.pnpm/@atproto+syntax@0.4.3/node_modules/@atproto/syntax/dist/did.d.ts","../../node_modules/.pnpm/@atproto+syntax@0.4.3/node_modules/@atproto/syntax/dist/handle.d.ts","../../node_modules/.pnpm/@atproto+syntax@0.4.3/node_modules/@atproto/syntax/dist/at-identifier.d.ts","../../node_modules/.pnpm/@atproto+syntax@0.4.3/node_modules/@atproto/syntax/dist/nsid.d.ts","../../node_modules/.pnpm/@atproto+syntax@0.4.3/node_modules/@atproto/syntax/dist/aturi_validation.d.ts","../../node_modules/.pnpm/@atproto+syntax@0.4.3/node_modules/@atproto/syntax/dist/aturi.d.ts","../../node_modules/.pnpm/@atproto+syntax@0.4.3/node_modules/@atproto/syntax/dist/datetime.d.ts","../../node_modules/.pnpm/@atproto+syntax@0.4.3/node_modules/@atproto/syntax/dist/language.d.ts","../../node_modules/.pnpm/@atproto+syntax@0.4.3/node_modules/@atproto/syntax/dist/recordkey.d.ts","../../node_modules/.pnpm/@atproto+syntax@0.4.3/node_modules/@atproto/syntax/dist/tid.d.ts","../../node_modules/.pnpm/@atproto+syntax@0.4.3/node_modules/@atproto/syntax/dist/uri.d.ts","../../node_modules/.pnpm/@atproto+syntax@0.4.3/node_modules/@atproto/syntax/dist/index.d.ts","../../node_modules/.pnpm/@atproto+lexicon@0.6.2/node_modules/@atproto/lexicon/dist/types.d.ts","../../node_modules/.pnpm/@atproto+lexicon@0.6.2/node_modules/@atproto/lexicon/dist/lexicons.d.ts","../../node_modules/.pnpm/@atproto+lexicon@0.6.2/node_modules/@atproto/lexicon/dist/blob-refs.d.ts","../../node_modules/.pnpm/@atproto+lexicon@0.6.2/node_modules/@atproto/lexicon/dist/serialize.d.ts","../../node_modules/.pnpm/@atproto+lexicon@0.6.2/node_modules/@atproto/lexicon/dist/index.d.ts","../../node_modules/.pnpm/@atproto+xrpc@0.7.7/node_modules/@atproto/xrpc/dist/types.d.ts","../../node_modules/.pnpm/@atproto+xrpc@0.7.7/node_modules/@atproto/xrpc/dist/fetch-handler.d.ts","../../node_modules/.pnpm/@atproto+xrpc@0.7.7/node_modules/@atproto/xrpc/dist/xrpc-client.d.ts","../../node_modules/.pnpm/@atproto+xrpc@0.7.7/node_modules/@atproto/xrpc/dist/client.d.ts","../../node_modules/.pnpm/@atproto+xrpc@0.7.7/node_modules/@atproto/xrpc/dist/util.d.ts","../../node_modules/.pnpm/@atproto+xrpc@0.7.7/node_modules/@atproto/xrpc/dist/index.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/util.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/admin/deleteaccount.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/admin/disableaccountinvites.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/admin/disableinvitecodes.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/admin/enableaccountinvites.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/server/defs.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/admin/defs.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/admin/getaccountinfo.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/admin/getaccountinfos.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/admin/getinvitecodes.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/repo/strongref.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/admin/getsubjectstatus.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/admin/searchaccounts.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/admin/sendemail.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/admin/updateaccountemail.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/admin/updateaccounthandle.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/admin/updateaccountpassword.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/admin/updateaccountsigningkey.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/admin/updatesubjectstatus.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/identity/getrecommendeddidcredentials.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/identity/defs.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/identity/refreshidentity.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/identity/requestplcoperationsignature.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/identity/resolvedid.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/identity/resolvehandle.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/identity/resolveidentity.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/identity/signplcoperation.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/identity/submitplcoperation.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/identity/updatehandle.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/label/defs.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/label/querylabels.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/lexicon/schema.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/moderation/defs.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/moderation/createreport.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/repo/defs.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/repo/applywrites.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/repo/createrecord.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/repo/deleterecord.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/repo/describerepo.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/repo/getrecord.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/repo/importrepo.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/repo/listmissingblobs.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/repo/listrecords.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/repo/putrecord.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/repo/uploadblob.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/server/activateaccount.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/server/checkaccountstatus.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/server/confirmemail.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/server/createaccount.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/server/createapppassword.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/server/createinvitecode.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/server/createinvitecodes.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/server/createsession.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/server/deactivateaccount.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/server/deleteaccount.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/server/deletesession.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/server/describeserver.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/server/getaccountinvitecodes.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/server/getserviceauth.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/server/getsession.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/server/listapppasswords.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/server/refreshsession.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/server/requestaccountdelete.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/server/requestemailconfirmation.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/server/requestemailupdate.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/server/requestpasswordreset.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/server/reservesigningkey.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/server/resetpassword.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/server/revokeapppassword.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/server/updateemail.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/sync/getblob.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/sync/getblocks.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/sync/getcheckout.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/sync/gethead.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/sync/defs.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/sync/gethoststatus.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/sync/getlatestcommit.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/sync/getrecord.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/sync/getrepo.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/sync/getrepostatus.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/sync/listblobs.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/sync/listhosts.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/sync/listrepos.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/sync/listreposbycollection.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/sync/notifyofupdate.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/sync/requestcrawl.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/temp/addreservedhandle.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/temp/checksignupqueue.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/temp/fetchlabels.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/temp/requestphoneverification.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/richtext/facet.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/embed/defs.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/embed/images.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/embed/video.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/embed/external.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/labeler/defs.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/embed/recordwithmedia.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/embed/record.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/feed/defs.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/graph/defs.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/notification/defs.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/feed/threadgate.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/feed/postgate.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/actor/defs.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/actor/getpreferences.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/actor/getprofile.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/actor/getprofiles.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/actor/getsuggestions.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/actor/profile.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/actor/putpreferences.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/actor/searchactors.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/actor/searchactorstypeahead.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/actor/status.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/feed/describefeedgenerator.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/feed/generator.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/feed/getactorfeeds.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/feed/getactorlikes.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/feed/getauthorfeed.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/feed/getfeed.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/feed/getfeedgenerator.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/feed/getfeedgenerators.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/feed/getfeedskeleton.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/feed/getlikes.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/feed/getlistfeed.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/feed/getposts.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/feed/getpostthread.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/feed/getquotes.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/feed/getrepostedby.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/feed/getsuggestedfeeds.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/feed/gettimeline.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/feed/like.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/feed/post.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/feed/repost.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/feed/searchposts.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/feed/sendinteractions.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/graph/block.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/graph/follow.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/graph/getactorstarterpacks.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/graph/getblocks.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/graph/getfollowers.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/graph/getfollows.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/graph/getknownfollowers.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/graph/getlist.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/graph/getlistblocks.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/graph/getlistmutes.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/graph/getlists.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/graph/getmutes.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/graph/getrelationships.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/graph/getstarterpack.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/graph/getstarterpacks.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/graph/getsuggestedfollowsbyactor.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/graph/list.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/graph/listblock.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/graph/listitem.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/graph/muteactor.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/graph/muteactorlist.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/graph/mutethread.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/graph/searchstarterpacks.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/graph/starterpack.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/graph/unmuteactor.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/graph/unmuteactorlist.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/graph/unmutethread.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/graph/verification.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/labeler/getservices.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/labeler/service.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/notification/declaration.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/notification/getpreferences.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/notification/getunreadcount.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/notification/listactivitysubscriptions.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/notification/listnotifications.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/notification/putactivitysubscription.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/notification/putpreferences.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/notification/putpreferencesv2.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/notification/registerpush.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/notification/unregisterpush.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/notification/updateseen.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/unspecced/checkhandleavailability.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/unspecced/defs.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/unspecced/getageassurancestate.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/unspecced/getconfig.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/unspecced/getpopularfeedgenerators.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/unspecced/getpostthreadotherv2.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/unspecced/getpostthreadv2.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/unspecced/getsuggestedfeeds.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/unspecced/getsuggestedfeedsskeleton.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/unspecced/getsuggestedstarterpacks.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/unspecced/getsuggestedstarterpacksskeleton.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/unspecced/getsuggestedusers.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/unspecced/getsuggestedusersskeleton.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/unspecced/getsuggestionsskeleton.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/unspecced/gettaggedsuggestions.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/unspecced/gettrendingtopics.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/unspecced/gettrends.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/unspecced/gettrendsskeleton.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/unspecced/initageassurance.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/unspecced/searchactorsskeleton.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/unspecced/searchpostsskeleton.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/unspecced/searchstarterpacksskeleton.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/video/defs.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/video/getjobstatus.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/video/getuploadlimits.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/video/uploadvideo.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/chat/bsky/actor/declaration.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/chat/bsky/actor/deleteaccount.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/chat/bsky/actor/exportaccountdata.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/chat/bsky/convo/acceptconvo.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/chat/bsky/actor/defs.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/chat/bsky/convo/defs.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/chat/bsky/convo/addreaction.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/chat/bsky/convo/deletemessageforself.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/chat/bsky/convo/getconvo.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/chat/bsky/convo/getconvoavailability.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/chat/bsky/convo/getconvoformembers.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/chat/bsky/convo/getlog.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/chat/bsky/convo/getmessages.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/chat/bsky/convo/leaveconvo.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/chat/bsky/convo/listconvos.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/chat/bsky/convo/muteconvo.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/chat/bsky/convo/removereaction.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/chat/bsky/convo/sendmessage.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/chat/bsky/convo/sendmessagebatch.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/chat/bsky/convo/unmuteconvo.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/chat/bsky/convo/updateallread.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/chat/bsky/convo/updateread.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/chat/bsky/moderation/getactormetadata.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/chat/bsky/moderation/getmessagecontext.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/chat/bsky/moderation/updateactoraccess.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/tools/ozone/communication/defs.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/tools/ozone/communication/createtemplate.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/tools/ozone/communication/deletetemplate.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/tools/ozone/communication/listtemplates.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/tools/ozone/communication/updatetemplate.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/tools/ozone/hosting/getaccounthistory.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/tools/ozone/moderation/defs.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/tools/ozone/moderation/emitevent.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/tools/ozone/moderation/getevent.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/tools/ozone/moderation/getrecord.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/tools/ozone/moderation/getrecords.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/tools/ozone/moderation/getrepo.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/tools/ozone/moderation/getreporterstats.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/tools/ozone/moderation/getrepos.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/tools/ozone/moderation/getsubjects.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/tools/ozone/moderation/queryevents.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/tools/ozone/moderation/querystatuses.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/tools/ozone/moderation/searchrepos.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/tools/ozone/safelink/defs.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/tools/ozone/safelink/addrule.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/tools/ozone/safelink/queryevents.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/tools/ozone/safelink/queryrules.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/tools/ozone/safelink/removerule.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/tools/ozone/safelink/updaterule.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/tools/ozone/server/getconfig.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/tools/ozone/set/addvalues.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/tools/ozone/set/deleteset.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/tools/ozone/set/deletevalues.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/tools/ozone/set/defs.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/tools/ozone/set/getvalues.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/tools/ozone/set/querysets.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/tools/ozone/set/upsertset.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/tools/ozone/setting/defs.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/tools/ozone/setting/listoptions.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/tools/ozone/setting/removeoptions.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/tools/ozone/setting/upsertoption.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/tools/ozone/signature/defs.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/tools/ozone/signature/findcorrelation.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/tools/ozone/signature/findrelatedaccounts.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/tools/ozone/signature/searchaccounts.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/tools/ozone/team/defs.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/tools/ozone/team/addmember.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/tools/ozone/team/deletemember.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/tools/ozone/team/listmembers.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/tools/ozone/team/updatemember.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/tools/ozone/verification/defs.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/tools/ozone/verification/grantverifications.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/tools/ozone/verification/listverifications.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/tools/ozone/verification/revokeverifications.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/label/subscribelabels.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/sync/subscriberepos.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/index.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/moderation/const/labels.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/moderation/mutewords.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/moderation/types.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/types.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/const.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/util.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/lexicons.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/rich-text/unicode.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/rich-text/rich-text.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/rich-text/sanitization.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/rich-text/util.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/moderation/ui.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/moderation/decision.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/moderation/util.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/moderation/index.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/mocker.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/session-manager.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/agent.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/atp-agent.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/bsky-agent.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/index.d.ts","./src/lib/comments.ts","../../node_modules/.pnpm/vitest@3.2.4_@types+node@22.19.15_jiti@1.21.7_tsx@4.21.0/node_modules/vitest/dist/chunks/worker.d.ckwwzbsj.d.ts","../../node_modules/.pnpm/vitest@3.2.4_@types+node@22.19.15_jiti@1.21.7_tsx@4.21.0/node_modules/vitest/dist/chunks/global.d.mamajcmj.d.ts","../../node_modules/.pnpm/vitest@3.2.4_@types+node@22.19.15_jiti@1.21.7_tsx@4.21.0/node_modules/vitest/dist/chunks/mocker.d.be_2ls6u.d.ts","../../node_modules/.pnpm/vitest@3.2.4_@types+node@22.19.15_jiti@1.21.7_tsx@4.21.0/node_modules/vitest/dist/chunks/suite.d.fvehnv49.d.ts","../../node_modules/.pnpm/expect-type@1.3.0/node_modules/expect-type/dist/utils.d.ts","../../node_modules/.pnpm/expect-type@1.3.0/node_modules/expect-type/dist/overloads.d.ts","../../node_modules/.pnpm/expect-type@1.3.0/node_modules/expect-type/dist/branding.d.ts","../../node_modules/.pnpm/expect-type@1.3.0/node_modules/expect-type/dist/messages.d.ts","../../node_modules/.pnpm/expect-type@1.3.0/node_modules/expect-type/dist/index.d.ts","../../node_modules/.pnpm/vitest@3.2.4_@types+node@22.19.15_jiti@1.21.7_tsx@4.21.0/node_modules/vitest/dist/index.d.ts","./src/lib/corrections.test.ts","./src/lib/ground-truth-export.ts","./src/lib/ground-truth-export.test.ts","./src/lib/snap-targets.test.ts","./src/lib/track-colors.ts","./src/lib/transcript.ts","./src/lib/transcript.test.ts","../../node_modules/.pnpm/@atproto+jwk@0.6.0/node_modules/@atproto/jwk/dist/jwk.d.ts","../../node_modules/.pnpm/@atproto+jwk@0.6.0/node_modules/@atproto/jwk/dist/alg.d.ts","../../node_modules/.pnpm/@atproto+jwk@0.6.0/node_modules/@atproto/jwk/dist/errors.d.ts","../../node_modules/.pnpm/@atproto+jwk@0.6.0/node_modules/@atproto/jwk/dist/jwks.d.ts","../../node_modules/.pnpm/@atproto+jwk@0.6.0/node_modules/@atproto/jwk/dist/jwt.d.ts","../../node_modules/.pnpm/@atproto+jwk@0.6.0/node_modules/@atproto/jwk/dist/jwt-decode.d.ts","../../node_modules/.pnpm/@atproto+jwk@0.6.0/node_modules/@atproto/jwk/dist/util.d.ts","../../node_modules/.pnpm/@atproto+jwk@0.6.0/node_modules/@atproto/jwk/dist/jwt-verify.d.ts","../../node_modules/.pnpm/@atproto+jwk@0.6.0/node_modules/@atproto/jwk/dist/key.d.ts","../../node_modules/.pnpm/@atproto+jwk@0.6.0/node_modules/@atproto/jwk/dist/keyset.d.ts","../../node_modules/.pnpm/@atproto+jwk@0.6.0/node_modules/@atproto/jwk/dist/index.d.ts","../../node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/types/types.d.ts","../../node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/types/jwe/compact/decrypt.d.ts","../../node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/types/jwe/flattened/decrypt.d.ts","../../node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/types/jwe/general/decrypt.d.ts","../../node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/types/jwe/general/encrypt.d.ts","../../node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/types/jws/compact/verify.d.ts","../../node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/types/jws/flattened/verify.d.ts","../../node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/types/jws/general/verify.d.ts","../../node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/types/jwt/verify.d.ts","../../node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/types/jwt/decrypt.d.ts","../../node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/types/jwt/produce.d.ts","../../node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/types/jwe/compact/encrypt.d.ts","../../node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/types/jwe/flattened/encrypt.d.ts","../../node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/types/jws/compact/sign.d.ts","../../node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/types/jws/flattened/sign.d.ts","../../node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/types/jws/general/sign.d.ts","../../node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/types/jwt/sign.d.ts","../../node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/types/jwt/encrypt.d.ts","../../node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/types/jwk/thumbprint.d.ts","../../node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/types/jwk/embedded.d.ts","../../node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/types/jwks/local.d.ts","../../node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/types/jwks/remote.d.ts","../../node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/types/jwt/unsecured.d.ts","../../node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/types/key/export.d.ts","../../node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/types/key/import.d.ts","../../node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/types/util/decode_protected_header.d.ts","../../node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/types/util/decode_jwt.d.ts","../../node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/types/util/errors.d.ts","../../node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/types/key/generate_key_pair.d.ts","../../node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/types/key/generate_secret.d.ts","../../node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/types/util/base64url.d.ts","../../node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/types/util/runtime.d.ts","../../node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/types/index.d.ts","../../node_modules/.pnpm/@atproto+jwk-jose@0.1.11/node_modules/@atproto/jwk-jose/dist/jose-key.d.ts","../../node_modules/.pnpm/@atproto+jwk-jose@0.1.11/node_modules/@atproto/jwk-jose/dist/index.d.ts","../../node_modules/.pnpm/@atproto+jwk-webcrypto@0.2.0/node_modules/@atproto/jwk-webcrypto/dist/webcrypto-key.d.ts","../../node_modules/.pnpm/@atproto+jwk-webcrypto@0.2.0/node_modules/@atproto/jwk-webcrypto/dist/index.d.ts","../../node_modules/.pnpm/@atproto+did@0.3.0/node_modules/@atproto/did/dist/did.d.ts","../../node_modules/.pnpm/@atproto+did@0.3.0/node_modules/@atproto/did/dist/did-document.d.ts","../../node_modules/.pnpm/@atproto+did@0.3.0/node_modules/@atproto/did/dist/utils.d.ts","../../node_modules/.pnpm/@atproto+did@0.3.0/node_modules/@atproto/did/dist/atproto.d.ts","../../node_modules/.pnpm/@atproto+did@0.3.0/node_modules/@atproto/did/dist/did-error.d.ts","../../node_modules/.pnpm/@atproto+did@0.3.0/node_modules/@atproto/did/dist/methods/plc.d.ts","../../node_modules/.pnpm/@atproto+did@0.3.0/node_modules/@atproto/did/dist/methods/web.d.ts","../../node_modules/.pnpm/@atproto+did@0.3.0/node_modules/@atproto/did/dist/methods.d.ts","../../node_modules/.pnpm/@atproto+did@0.3.0/node_modules/@atproto/did/dist/index.d.ts","../../node_modules/.pnpm/@atproto-labs+simple-store@0.3.0/node_modules/@atproto-labs/simple-store/dist/util.d.ts","../../node_modules/.pnpm/@atproto-labs+simple-store@0.3.0/node_modules/@atproto-labs/simple-store/dist/simple-store.d.ts","../../node_modules/.pnpm/@atproto-labs+simple-store@0.3.0/node_modules/@atproto-labs/simple-store/dist/cached-getter.d.ts","../../node_modules/.pnpm/@atproto-labs+simple-store@0.3.0/node_modules/@atproto-labs/simple-store/dist/index.d.ts","../../node_modules/.pnpm/@atproto-labs+did-resolver@0.2.6/node_modules/@atproto-labs/did-resolver/dist/did-method.d.ts","../../node_modules/.pnpm/@atproto-labs+did-resolver@0.2.6/node_modules/@atproto-labs/did-resolver/dist/did-resolver.d.ts","../../node_modules/.pnpm/@atproto-labs+did-resolver@0.2.6/node_modules/@atproto-labs/did-resolver/dist/did-cache.d.ts","../../node_modules/.pnpm/@atproto-labs+did-resolver@0.2.6/node_modules/@atproto-labs/did-resolver/dist/did-resolver-base.d.ts","../../node_modules/.pnpm/@atproto-labs+fetch@0.2.3/node_modules/@atproto-labs/fetch/dist/fetch-error.d.ts","../../node_modules/.pnpm/@atproto-labs+fetch@0.2.3/node_modules/@atproto-labs/fetch/dist/util.d.ts","../../node_modules/.pnpm/@atproto-labs+fetch@0.2.3/node_modules/@atproto-labs/fetch/dist/fetch.d.ts","../../node_modules/.pnpm/@atproto-labs+fetch@0.2.3/node_modules/@atproto-labs/fetch/dist/fetch-request.d.ts","../../node_modules/.pnpm/@atproto-labs+pipe@0.1.1/node_modules/@atproto-labs/pipe/dist/type.d.ts","../../node_modules/.pnpm/@atproto-labs+pipe@0.1.1/node_modules/@atproto-labs/pipe/dist/pipe.d.ts","../../node_modules/.pnpm/@atproto-labs+pipe@0.1.1/node_modules/@atproto-labs/pipe/dist/index.d.ts","../../node_modules/.pnpm/@atproto-labs+fetch@0.2.3/node_modules/@atproto-labs/fetch/dist/fetch-response.d.ts","../../node_modules/.pnpm/@atproto-labs+fetch@0.2.3/node_modules/@atproto-labs/fetch/dist/fetch-wrap.d.ts","../../node_modules/.pnpm/@atproto-labs+fetch@0.2.3/node_modules/@atproto-labs/fetch/dist/index.d.ts","../../node_modules/.pnpm/@atproto-labs+did-resolver@0.2.6/node_modules/@atproto-labs/did-resolver/dist/methods/plc.d.ts","../../node_modules/.pnpm/@atproto-labs+did-resolver@0.2.6/node_modules/@atproto-labs/did-resolver/dist/methods/web.d.ts","../../node_modules/.pnpm/@atproto-labs+did-resolver@0.2.6/node_modules/@atproto-labs/did-resolver/dist/util.d.ts","../../node_modules/.pnpm/@atproto-labs+did-resolver@0.2.6/node_modules/@atproto-labs/did-resolver/dist/did-resolver-common.d.ts","../../node_modules/.pnpm/@atproto-labs+did-resolver@0.2.6/node_modules/@atproto-labs/did-resolver/dist/create-did-resolver.d.ts","../../node_modules/.pnpm/@atproto-labs+simple-store-memory@0.1.4/node_modules/@atproto-labs/simple-store-memory/dist/index.d.ts","../../node_modules/.pnpm/@atproto-labs+did-resolver@0.2.6/node_modules/@atproto-labs/did-resolver/dist/did-cache-memory.d.ts","../../node_modules/.pnpm/@atproto-labs+did-resolver@0.2.6/node_modules/@atproto-labs/did-resolver/dist/methods.d.ts","../../node_modules/.pnpm/@atproto-labs+did-resolver@0.2.6/node_modules/@atproto-labs/did-resolver/dist/index.d.ts","../../node_modules/.pnpm/@atproto-labs+handle-resolver@0.3.6/node_modules/@atproto-labs/handle-resolver/dist/handle-resolver-error.d.ts","../../node_modules/.pnpm/@atproto-labs+handle-resolver@0.3.6/node_modules/@atproto-labs/handle-resolver/dist/types.d.ts","../../node_modules/.pnpm/@atproto-labs+handle-resolver@0.3.6/node_modules/@atproto-labs/handle-resolver/dist/xrpc-handle-resolver.d.ts","../../node_modules/.pnpm/@atproto-labs+handle-resolver@0.3.6/node_modules/@atproto-labs/handle-resolver/dist/internal-resolvers/dns-handle-resolver.d.ts","../../node_modules/.pnpm/@atproto-labs+handle-resolver@0.3.6/node_modules/@atproto-labs/handle-resolver/dist/internal-resolvers/well-known-handler-resolver.d.ts","../../node_modules/.pnpm/@atproto-labs+handle-resolver@0.3.6/node_modules/@atproto-labs/handle-resolver/dist/atproto-handle-resolver.d.ts","../../node_modules/.pnpm/@atproto-labs+handle-resolver@0.3.6/node_modules/@atproto-labs/handle-resolver/dist/atproto-doh-handle-resolver.d.ts","../../node_modules/.pnpm/@atproto-labs+handle-resolver@0.3.6/node_modules/@atproto-labs/handle-resolver/dist/cached-handle-resolver.d.ts","../../node_modules/.pnpm/@atproto-labs+handle-resolver@0.3.6/node_modules/@atproto-labs/handle-resolver/dist/create-handle-resolver.d.ts","../../node_modules/.pnpm/@atproto-labs+handle-resolver@0.3.6/node_modules/@atproto-labs/handle-resolver/dist/index.d.ts","../../node_modules/.pnpm/@atproto+oauth-types@0.6.3/node_modules/@atproto/oauth-types/dist/constants.d.ts","../../node_modules/.pnpm/@atproto+oauth-types@0.6.3/node_modules/@atproto/oauth-types/dist/uri.d.ts","../../node_modules/.pnpm/@atproto+oauth-types@0.6.3/node_modules/@atproto/oauth-types/dist/util.d.ts","../../node_modules/.pnpm/@atproto+oauth-types@0.6.3/node_modules/@atproto/oauth-types/dist/oauth-scope.d.ts","../../node_modules/.pnpm/@atproto+oauth-types@0.6.3/node_modules/@atproto/oauth-types/dist/atproto-oauth-scope.d.ts","../../node_modules/.pnpm/@atproto+oauth-types@0.6.3/node_modules/@atproto/oauth-types/dist/oauth-redirect-uri.d.ts","../../node_modules/.pnpm/@atproto+oauth-types@0.6.3/node_modules/@atproto/oauth-types/dist/oauth-client-id-loopback.d.ts","../../node_modules/.pnpm/@atproto+oauth-types@0.6.3/node_modules/@atproto/oauth-types/dist/atproto-loopback-client-id.d.ts","../../node_modules/.pnpm/@atproto+oauth-types@0.6.3/node_modules/@atproto/oauth-types/dist/oauth-client-metadata.d.ts","../../node_modules/.pnpm/@atproto+oauth-types@0.6.3/node_modules/@atproto/oauth-types/dist/atproto-loopback-client-metadata.d.ts","../../node_modules/.pnpm/@atproto+oauth-types@0.6.3/node_modules/@atproto/oauth-types/dist/atproto-loopback-client-redirect-uris.d.ts","../../node_modules/.pnpm/@atproto+oauth-types@0.6.3/node_modules/@atproto/oauth-types/dist/atproto-oauth-token-response.d.ts","../../node_modules/.pnpm/@atproto+oauth-types@0.6.3/node_modules/@atproto/oauth-types/dist/oauth-access-token.d.ts","../../node_modules/.pnpm/@atproto+oauth-types@0.6.3/node_modules/@atproto/oauth-types/dist/oauth-authorization-code-grant-token-request.d.ts","../../node_modules/.pnpm/@atproto+oauth-types@0.6.3/node_modules/@atproto/oauth-types/dist/oauth-authorization-details.d.ts","../../node_modules/.pnpm/@atproto+oauth-types@0.6.3/node_modules/@atproto/oauth-types/dist/oauth-authorization-request-jar.d.ts","../../node_modules/.pnpm/@atproto+oauth-types@0.6.3/node_modules/@atproto/oauth-types/dist/oauth-authorization-request-par.d.ts","../../node_modules/.pnpm/@atproto+oauth-types@0.6.3/node_modules/@atproto/oauth-types/dist/oauth-authorization-request-parameters.d.ts","../../node_modules/.pnpm/@atproto+oauth-types@0.6.3/node_modules/@atproto/oauth-types/dist/oauth-authorization-request-query.d.ts","../../node_modules/.pnpm/@atproto+oauth-types@0.6.3/node_modules/@atproto/oauth-types/dist/oauth-authorization-request-uri.d.ts","../../node_modules/.pnpm/@atproto+oauth-types@0.6.3/node_modules/@atproto/oauth-types/dist/oauth-authorization-response-error.d.ts","../../node_modules/.pnpm/@atproto+oauth-types@0.6.3/node_modules/@atproto/oauth-types/dist/oauth-authorization-server-metadata.d.ts","../../node_modules/.pnpm/@atproto+oauth-types@0.6.3/node_modules/@atproto/oauth-types/dist/oauth-client-credentials-grant-token-request.d.ts","../../node_modules/.pnpm/@atproto+oauth-types@0.6.3/node_modules/@atproto/oauth-types/dist/oauth-client-credentials.d.ts","../../node_modules/.pnpm/@atproto+oauth-types@0.6.3/node_modules/@atproto/oauth-types/dist/oauth-client-id-discoverable.d.ts","../../node_modules/.pnpm/@atproto+oauth-types@0.6.3/node_modules/@atproto/oauth-types/dist/oauth-client-id.d.ts","../../node_modules/.pnpm/@atproto+oauth-types@0.6.3/node_modules/@atproto/oauth-types/dist/oauth-endpoint-auth-method.d.ts","../../node_modules/.pnpm/@atproto+oauth-types@0.6.3/node_modules/@atproto/oauth-types/dist/oauth-endpoint-name.d.ts","../../node_modules/.pnpm/@atproto+oauth-types@0.6.3/node_modules/@atproto/oauth-types/dist/oauth-grant-type.d.ts","../../node_modules/.pnpm/@atproto+oauth-types@0.6.3/node_modules/@atproto/oauth-types/dist/oauth-token-type.d.ts","../../node_modules/.pnpm/@atproto+oauth-types@0.6.3/node_modules/@atproto/oauth-types/dist/oauth-introspection-response.d.ts","../../node_modules/.pnpm/@atproto+oauth-types@0.6.3/node_modules/@atproto/oauth-types/dist/oauth-issuer-identifier.d.ts","../../node_modules/.pnpm/@atproto+oauth-types@0.6.3/node_modules/@atproto/oauth-types/dist/oauth-par-response.d.ts","../../node_modules/.pnpm/@atproto+oauth-types@0.6.3/node_modules/@atproto/oauth-types/dist/oauth-password-grant-token-request.d.ts","../../node_modules/.pnpm/@atproto+oauth-types@0.6.3/node_modules/@atproto/oauth-types/dist/oauth-prompt-mode.d.ts","../../node_modules/.pnpm/@atproto+oauth-types@0.6.3/node_modules/@atproto/oauth-types/dist/oauth-protected-resource-metadata.d.ts","../../node_modules/.pnpm/@atproto+oauth-types@0.6.3/node_modules/@atproto/oauth-types/dist/oauth-refresh-token-grant-token-request.d.ts","../../node_modules/.pnpm/@atproto+oauth-types@0.6.3/node_modules/@atproto/oauth-types/dist/oauth-refresh-token.d.ts","../../node_modules/.pnpm/@atproto+oauth-types@0.6.3/node_modules/@atproto/oauth-types/dist/oauth-request-uri.d.ts","../../node_modules/.pnpm/@atproto+oauth-types@0.6.3/node_modules/@atproto/oauth-types/dist/oauth-response-mode.d.ts","../../node_modules/.pnpm/@atproto+oauth-types@0.6.3/node_modules/@atproto/oauth-types/dist/oauth-response-type.d.ts","../../node_modules/.pnpm/@atproto+oauth-types@0.6.3/node_modules/@atproto/oauth-types/dist/oauth-token-identification.d.ts","../../node_modules/.pnpm/@atproto+oauth-types@0.6.3/node_modules/@atproto/oauth-types/dist/oauth-token-request.d.ts","../../node_modules/.pnpm/@atproto+oauth-types@0.6.3/node_modules/@atproto/oauth-types/dist/oauth-token-response.d.ts","../../node_modules/.pnpm/@atproto+oauth-types@0.6.3/node_modules/@atproto/oauth-types/dist/oidc-authorization-error-response.d.ts","../../node_modules/.pnpm/@atproto+oauth-types@0.6.3/node_modules/@atproto/oauth-types/dist/oidc-claims-parameter.d.ts","../../node_modules/.pnpm/@atproto+oauth-types@0.6.3/node_modules/@atproto/oauth-types/dist/oidc-claims-properties.d.ts","../../node_modules/.pnpm/@atproto+oauth-types@0.6.3/node_modules/@atproto/oauth-types/dist/oidc-entity-type.d.ts","../../node_modules/.pnpm/@atproto+oauth-types@0.6.3/node_modules/@atproto/oauth-types/dist/oidc-userinfo.d.ts","../../node_modules/.pnpm/@atproto+oauth-types@0.6.3/node_modules/@atproto/oauth-types/dist/index.d.ts","../../node_modules/.pnpm/@atproto+oauth-client@0.6.0/node_modules/@atproto/oauth-client/dist/util.d.ts","../../node_modules/.pnpm/@atproto+oauth-client@0.6.0/node_modules/@atproto/oauth-client/dist/runtime-implementation.d.ts","../../node_modules/.pnpm/@atproto+oauth-client@0.6.0/node_modules/@atproto/oauth-client/dist/lock.d.ts","../../node_modules/.pnpm/@atproto+oauth-client@0.6.0/node_modules/@atproto/oauth-client/dist/oauth-authorization-server-metadata-resolver.d.ts","../../node_modules/.pnpm/@atproto+oauth-client@0.6.0/node_modules/@atproto/oauth-client/dist/oauth-callback-error.d.ts","../../node_modules/.pnpm/@atproto-labs+identity-resolver@0.3.6/node_modules/@atproto-labs/identity-resolver/dist/constants.d.ts","../../node_modules/.pnpm/@atproto-labs+identity-resolver@0.3.6/node_modules/@atproto-labs/identity-resolver/dist/identity-resolver.d.ts","../../node_modules/.pnpm/@atproto-labs+identity-resolver@0.3.6/node_modules/@atproto-labs/identity-resolver/dist/atproto-identity-resolver.d.ts","../../node_modules/.pnpm/@atproto-labs+identity-resolver@0.3.6/node_modules/@atproto-labs/identity-resolver/dist/create-identity-resolver.d.ts","../../node_modules/.pnpm/@atproto-labs+identity-resolver@0.3.6/node_modules/@atproto-labs/identity-resolver/dist/identity-resolver-error.d.ts","../../node_modules/.pnpm/@atproto-labs+identity-resolver@0.3.6/node_modules/@atproto-labs/identity-resolver/dist/util.d.ts","../../node_modules/.pnpm/@atproto-labs+identity-resolver@0.3.6/node_modules/@atproto-labs/identity-resolver/dist/index.d.ts","../../node_modules/.pnpm/@atproto+oauth-client@0.6.0/node_modules/@atproto/oauth-client/dist/identity-resolver.d.ts","../../node_modules/.pnpm/@atproto+oauth-client@0.6.0/node_modules/@atproto/oauth-client/dist/oauth-protected-resource-metadata-resolver.d.ts","../../node_modules/.pnpm/@atproto+oauth-client@0.6.0/node_modules/@atproto/oauth-client/dist/oauth-resolver.d.ts","../../node_modules/.pnpm/@atproto+oauth-client@0.6.0/node_modules/@atproto/oauth-client/dist/runtime.d.ts","../../node_modules/.pnpm/@atproto+oauth-client@0.6.0/node_modules/@atproto/oauth-client/dist/types.d.ts","../../node_modules/.pnpm/@atproto+oauth-client@0.6.0/node_modules/@atproto/oauth-client/dist/oauth-client-auth.d.ts","../../node_modules/.pnpm/@atproto+oauth-client@0.6.0/node_modules/@atproto/oauth-client/dist/oauth-server-agent.d.ts","../../node_modules/.pnpm/@atproto+oauth-client@0.6.0/node_modules/@atproto/oauth-client/dist/oauth-server-factory.d.ts","../../node_modules/.pnpm/@atproto+oauth-client@0.6.0/node_modules/@atproto/oauth-client/dist/errors/auth-method-unsatisfiable-error.d.ts","../../node_modules/.pnpm/@atproto+oauth-client@0.6.0/node_modules/@atproto/oauth-client/dist/errors/token-invalid-error.d.ts","../../node_modules/.pnpm/@atproto+oauth-client@0.6.0/node_modules/@atproto/oauth-client/dist/errors/token-refresh-error.d.ts","../../node_modules/.pnpm/@atproto+oauth-client@0.6.0/node_modules/@atproto/oauth-client/dist/errors/token-revoked-error.d.ts","../../node_modules/.pnpm/@atproto+oauth-client@0.6.0/node_modules/@atproto/oauth-client/dist/session-getter.d.ts","../../node_modules/.pnpm/@atproto+oauth-client@0.6.0/node_modules/@atproto/oauth-client/dist/oauth-session.d.ts","../../node_modules/.pnpm/@atproto+oauth-client@0.6.0/node_modules/@atproto/oauth-client/dist/state-store.d.ts","../../node_modules/.pnpm/@atproto+oauth-client@0.6.0/node_modules/@atproto/oauth-client/dist/oauth-client.d.ts","../../node_modules/.pnpm/@atproto+oauth-client@0.6.0/node_modules/@atproto/oauth-client/dist/oauth-resolver-error.d.ts","../../node_modules/.pnpm/@atproto+oauth-client@0.6.0/node_modules/@atproto/oauth-client/dist/oauth-response-error.d.ts","../../node_modules/.pnpm/@atproto+oauth-client@0.6.0/node_modules/@atproto/oauth-client/dist/index.d.ts","../../node_modules/.pnpm/@atproto+oauth-client-browser@0.3.41/node_modules/@atproto/oauth-client-browser/dist/util.d.ts","../../node_modules/.pnpm/@atproto+oauth-client-browser@0.3.41/node_modules/@atproto/oauth-client-browser/dist/browser-oauth-client.d.ts","../../node_modules/.pnpm/@atproto+oauth-client-browser@0.3.41/node_modules/@atproto/oauth-client-browser/dist/errors.d.ts","../../node_modules/.pnpm/@atproto+oauth-client-browser@0.3.41/node_modules/@atproto/oauth-client-browser/dist/index.d.ts","./src/lib/auth.tsx","./src/app/components/authbutton.tsx","./src/app/components/navheader.tsx","./src/app/layout.tsx","./src/app/page.tsx","./src/app/auth/callback/page.tsx","./src/app/components/commentpanel.tsx","./src/app/components/diarizationband.tsx","./src/app/components/interactionoverlay.tsx","./src/app/components/reactionbar.tsx","./src/app/components/speakerpopover.tsx","./src/app/components/streamtimeline.tsx","./src/app/components/textselector.tsx","./src/app/components/timelinetoolbar.tsx","./src/app/components/transcriptview.tsx","../../node_modules/.pnpm/hls.js@1.6.15/node_modules/hls.js/dist/hls.d.mts","./src/app/components/videoplayer.tsx","./src/app/components/waveformband.tsx","./src/app/concepts/conceptslistcontent.tsx","./src/app/concepts/page.tsx","./src/app/talks/talkslistcontent.tsx","./src/app/concepts/[rkey]/page.tsx","../../node_modules/.pnpm/@chenglou+pretext@0.0.3/node_modules/@chenglou/pretext/dist/analysis.d.ts","../../node_modules/.pnpm/@chenglou+pretext@0.0.3/node_modules/@chenglou/pretext/dist/layout.d.ts","./src/app/concordance/indexcontent.tsx","./src/app/concordance/page.tsx","./src/app/speakers/speakerslistcontent.tsx","./src/app/speakers/page.tsx","./src/app/speakers/[rkey]/page.tsx","./src/app/talks/page.tsx","./src/app/talks/[rkey]/talkcontent.tsx","./src/app/talks/[rkey]/page.tsx","./src/app/tracks/page.tsx","./src/app/tracks/[stream]/trackviewcontent.tsx","./src/app/tracks/[stream]/page.tsx","./.next/types/cache-life.d.ts","./.next/types/validator.ts","./.next/types/app/layout.ts","./.next/types/app/concepts/page.ts","./.next/types/app/concordance/page.ts","./.next/types/app/talks/page.ts","./.next/types/app/tracks/page.ts","./.next/types/app/tracks/[stream]/page.ts"],"fileIdsList":[[101,150,167,168,343,1186],[101,150,167,168,343,1192],[101,150,167,168,343,1170],[101,150,167,168,343,1196],[101,150,167,168,343,1201],[101,150,167,168,343,1199],[101,150,167,168,448,449,450,451],[101,150,167,168],[83,101,150,167,168,495,498,587,1170,1171,1172,1186,1188,1192,1194,1195,1196,1198,1199,1201],[83,101,150,167,168,499,500],[101,150,167,168,499],[101,150,167,168,495,1202],[87,101,150,167,168,482],[87,101,150,167,168,1167],[87,101,150,167,168,970,1167],[87,101,150,167,168,985],[87,101,150,167,168,590],[87,101,150,167,168,482,1168],[87,101,150,167,168,590,591,985],[101,150,167,168,590],[87,101,150,167,168],[87,101,150,167,168,591,970,986,1167,1179],[87,101,150,167,168,590,591],[87,101,150,167,168,591,1182],[87,101,150,167,168,590,985],[101,150,167,168,499,593,1187],[87,101,150,167,168,591,970,1181,1183],[101,150,167,168,593,1185],[87,101,150,167,168,591,970,1181,1183,1190],[101,150,167,168,1191],[101,150,167,168,499,1167,1169],[101,150,167,168,482],[101,150,167,168,593,1193],[101,150,167,168,499,593,1197],[87,101,150,167,168,591,970,1176,1181,1183],[101,150,167,168,593,1187],[101,150,167,168,499,593,1200],[87,101,150,167,168,588,590,591,592,593,1175,1177,1178,1180,1181,1183,1184],[101,150,167,168,472,593],[87,101,150,167,168,969,1166],[101,150,167,168,969],[101,150,167,168,588,980],[101,150,167,168,588,980,982],[101,150,167,168,588],[101,150,167,168,589,980],[87,101,150,167,168,588,589],[101,150,167,168,980,986],[101,150,167,168,526,527],[101,150,167,168,172,585],[101,150,167,168,669,670,773,824,825,829,830,845,948,951,952,954,965],[101,150,167,168,669,948,952,965,966],[101,150,167,168,967],[101,150,167,168,669,670,671,672,673,674,675,676,677,678,679,680,681,682,683,684,685,686,687,688,689,690,691,692,693,694,695,696,697,698,699,700,701,702,703,704,705,706,707,708,709,710,711,712,713,714,715,716,717,718,719,720,721,722,723,724,725,726,727,728,729,730,731,732,733,734,735,736,737,738,739,740,741,742,743,744,745,746,747,748,749,750,751,752,753,754,755,756,757,758,759,760,761,762,763,764,765,766,767,768,769,770,771,772,773,774,775,776,777,778,779,780,781,782,783,784,785,786,787,788,789,790,791,792,793,794,795,796,797,798,799,800,801,802,803,804,805,806,807,808,809,810,811,812,813,814,815,816,817,818,819,820,821,822,823,824,825,826,827,828,829,830,831,832,833,834,835,836,837,838,839,840,841,842,843,844,845,846,847,848,849,850,851,852,853,854,855,856,857,858,859,860,861,862,863,864,865,866,867,868,869,870,871,872,873,874,875,876,877,878,879,880,881,882,883,884,885,886,887,888,889,890,891,892,893,894,895,896,897,898,899,900,901,902,903,904,905,906,907,908,909,910,911,912,913,914,915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,930,931,932,933,934,935,936,937,938,939,940,941,942,943,944,945,946,947],[101,150,167,168,646],[101,150,167,168,646,670,680,699,764,769,770,771,772],[101,150,167,168,669,773],[101,150,167,168,646,670,680,699],[101,150,167,168,646,670,764],[101,150,167,168,646,670],[101,150,167,168,646,670,761],[101,150,167,168,646,670,680,699,762,763,764,765,766,768,769,773],[101,150,167,168,646,670,762,763,764,767],[101,150,167,168,646,670,699,760,762,763,764,766,767,769,773],[101,150,167,168,646,669,670],[101,150,167,168,646,670,699,760],[101,150,167,168,669,768],[101,150,167,168,646,669,670,773],[101,150,167,168,669,670,768],[101,150,167,168,646,670,680],[101,150,167,168,646,670,680,699,760,762,763,764,766,767],[101,150,167,168,646,670,699,760,768,773],[101,150,167,168,669,769],[101,150,167,168,669,670,769],[101,150,167,168,646,670,699,760,769],[101,150,167,168,669],[101,150,167,168,646,670,760],[101,150,167,168,646,670,699,702,773],[101,150,167,168,669,670,765],[101,150,167,168,646,670,699,702,765],[101,150,167,168,669,770],[101,150,167,168,646,669,670,699,773],[101,150,167,168,646,670,768,773],[101,150,167,168,669,847],[101,150,167,168,646,669,670,847],[101,150,167,168,646,669,670,768,847],[101,150,167,168,669,868],[101,150,167,168,646,670,699,773],[101,150,167,168,669,877],[101,150,167,168,646,670,760,767,876],[101,150,167,168,669,670,877],[101,150,167,168,646,669,670,877],[101,150,167,168,646,670,675],[101,150,167,168,669,676],[101,150,167,168,669,675],[101,150,167,168,669,670,676,680],[101,150,167,168,669,690],[101,150,167,168,669,699],[101,150,167,168,646,670,699],[101,150,167,168,646,669,670,676,680,702],[101,150,167,168,646,669,670,704],[101,150,167,168,669,704],[101,150,167,168,646,669],[101,150,167,168,669,744],[101,150,167,168,646,669,670,744],[101,150,167,168,669,897],[101,150,167,168,646,670,675,676,680,699,702,877],[101,150,167,168,669,670,676,680,903],[101,150,167,168,669,903],[101,150,167,168,669,670,903],[101,150,167,168,669,915],[101,150,167,168,669,925],[101,150,167,168,669,929],[101,150,167,168,669,933],[101,150,167,168,646,669,670,676,933],[101,150,167,168,669,937],[101,150,167,168,646,670,773],[101,150,167,168,646,670,903],[101,150,167,168,646,669,670,942],[101,150,167,168,669,942],[101,150,167,168,644,646,658,670,948,949,951,952,953,954,955,956,957,958,959,963,964,966,967,968],[101,150,167,168,670,948],[101,150,167,168,951],[101,150,167,168,948,950,951,960],[101,150,167,168,950,951,960,961,962],[101,150,167,168,948],[101,150,167,168,948,949,950],[101,150,167,168,948,951],[101,150,167,168,948,956],[101,150,167,168,957],[101,150,167,168,607,773,948],[101,150,167,168,607],[101,150,167,168,611,612,613,614,615,616,617,628,629,642,643],[101,150,167,168,641],[101,150,167,168,607,611,627],[101,150,167,168,607,1036,1037,1038],[101,150,167,168,607,1036],[101,150,167,168,1036,1037,1038,1039,1040,1043],[101,150,167,168,1041,1042],[101,150,167,168,1036],[101,150,167,168,1032],[101,150,167,168,998,1031],[101,150,167,168,1034],[101,150,167,168,998,1033],[101,150,167,168,988],[101,150,167,168,607,988,989,990,991,992,993,995,996,997],[101,150,167,168,992],[101,150,167,168,992,994],[101,150,167,168,988,992,995],[101,150,167,168,988,991,992,994,995,996],[101,150,167,168,618,619],[101,150,167,168,618,619,620,621,622,623,625,626],[101,150,167,168,619],[101,150,167,168,618],[101,150,167,168,624],[101,150,167,168,625],[101,150,167,168,608,609,610,645],[101,150,167,168,608],[101,150,167,168,610,644],[101,150,167,168,659,660,661,662],[101,150,167,168,659],[101,150,167,168,644],[101,150,167,168,1131,1162,1163],[101,150,167,168,1035,1162,1163,1164,1165],[101,150,167,168,1143],[101,150,167,168,998,1044,1062,1071,1081,1131,1133,1134,1135,1136,1145,1148,1150,1151,1153,1154,1155,1156,1157,1158,1159,1160,1161],[101,150,167,168,1133],[101,150,167,168,1048,1062,1131],[101,150,167,168,998,1131,1132,1147,1148],[101,150,167,168,998,1062,1071,1081,1131,1133,1135,1143,1144,1145,1146,1147,1148,1150,1151,1156,1157,1158],[101,150,167,168,1131,1135,1143,1145],[101,150,167,168,1062],[101,150,167,168,998,1044,1048,1062,1131,1146,1147,1148,1149],[101,150,167,168,998,1062,1131,1135,1146,1147,1148,1149,1150],[101,150,167,168,1044,1062,1131,1150,1156],[101,150,167,168,998,1132],[101,150,167,168,998,1133],[101,150,167,168,998,1044,1048,1147,1149,1150,1151,1152,1153,1154,1155],[101,150,167,168,998,1048,1149],[101,150,167,168,607,1131,1132],[101,150,167,168,1086,1087,1088],[101,150,167,168,1086,1087,1088,1089,1090],[101,150,167,168,607,1084,1085],[101,150,167,168,607,1086],[101,150,167,168,1082,1083,1084,1085,1086,1087,1088,1089,1090,1091,1092,1093,1094,1095,1096,1097,1098,1099,1100,1101,1102,1103,1104,1105,1106,1107,1108,1109,1110,1111,1112,1113,1114,1115,1116,1117,1118,1119,1120,1121,1122,1123,1124,1125,1126,1127,1128,1129,1130],[101,150,167,168,607,1085,1087],[101,150,167,168,1096,1111],[101,150,167,168,647,648],[101,150,167,168,649,651],[101,150,167,168,649,650],[101,150,167,168,647,648,649,650,652,653,654,655,656,657],[101,150,167,168,630,631],[101,150,167,168,630,632,633,634,635],[101,150,167,168,632,633],[101,150,167,168,630,631,632,633,635,636,637,638,639,640],[101,150,167,168,663,664,666],[101,150,167,168,664],[101,150,167,168,664,665,666,667,668],[101,150,167,168,607,663],[101,150,167,168,663,664],[101,150,167,168,663,664,665],[101,150,167,168,1044,1050,1051,1066],[101,150,167,168,1044,1051,1068],[101,150,167,168,1044,1048,1049,1050],[101,150,167,168,1044],[101,150,167,168,1044,1049,1050],[101,150,167,168,1052,1063,1064,1065],[101,150,167,168,1044,1049],[101,150,167,168,1044,1049,1050,1051,1066,1067,1069,1070],[101,150,167,168,1063,1064],[101,150,167,168,1044,1049,1062],[101,150,167,168,1053,1055],[101,150,167,168,1053,1054,1059],[101,150,167,168,1055],[101,150,167,168,1054],[101,150,167,168,1053,1054,1055,1056,1060,1061],[101,150,167,168,1073,1077],[101,150,167,168,1073,1075,1076],[101,150,167,168,1048,1073],[101,150,167,168,1073,1074,1079],[101,150,167,168,1072,1073,1074,1077,1078,1079,1080],[101,150,167,168,1073],[101,150,167,168,607,1073],[101,150,167,168,1071,1081,1138],[101,150,167,168,1071,1137],[101,150,167,168,1137,1138,1139,1140,1141,1142],[101,150,167,168,1071],[101,150,167,168,1057,1058],[101,150,167,168,1057],[101,150,167,168,1048],[101,150,167,168,1045,1046],[101,150,167,168,1045,1046,1047],[101,150,167,168,1045],[101,150,167,168,1189],[101,150,167,168,573,574],[101,147,148,150,167,168],[101,149,150,167,168],[150,167,168],[101,150,155,167,168,185],[101,150,151,156,161,167,168,170,182,193],[101,150,151,152,161,167,168,170],[96,97,98,101,150,167,168],[101,150,153,167,168,194],[101,150,154,155,162,167,168,171],[101,150,155,167,168,182,190],[101,150,156,158,161,167,168,170],[101,149,150,157,167,168],[101,150,158,159,167,168],[101,150,160,161,167,168],[101,149,150,161,167,168],[101,150,161,162,163,167,168,182,193],[101,150,161,162,163,167,168,177,182,185],[101,143,150,158,161,164,167,168,170,182,193],[101,150,161,162,164,165,167,168,170,182,190,193],[101,150,164,166,167,168,182,190,193],[99,100,101,102,103,104,105,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199],[101,150,161,167,168],[101,150,167,168,169,193],[101,150,158,161,167,168,170,182],[101,150,167,168,171],[101,150,167,168,172],[101,149,150,167,168,173],[101,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199],[101,150,167,168,175],[101,150,167,168,176],[101,150,161,167,168,177,178],[101,150,167,168,177,179,194,196],[101,150,162,167,168],[101,150,161,167,168,182,183,185],[101,150,167,168,184,185],[101,150,167,168,182,183],[101,150,167,168,185],[101,150,167,168,186],[101,147,150,167,168,182,187,193],[101,150,161,167,168,188,189],[101,150,167,168,188,189],[101,150,155,167,168,170,182,190],[101,150,167,168,191],[101,150,167,168,170,192],[101,150,164,167,168,176,193],[101,150,155,167,168,194],[101,150,167,168,182,195],[101,150,167,168,169,196],[101,150,167,168,197],[101,143,150,167,168],[101,143,150,161,163,167,168,173,182,185,193,195,196,198],[101,150,167,168,182,199],[87,101,150,167,168,203,204,205,359],[87,101,150,167,168,203,204],[87,101,150,167,168,204,359],[87,91,101,150,167,168,202,443,491],[87,91,101,150,167,168,201,443,491],[84,85,86,101,150,167,168],[101,150,167,168,529,534,535,537],[101,150,167,168,560,561],[101,150,167,168,535,537,554,555,556],[101,150,167,168,535],[101,150,167,168,535,537,554],[101,150,167,168,535,554],[101,150,167,168,567],[101,150,167,168,530,567,568],[101,150,167,168,530,567],[101,150,167,168,530,536],[101,150,167,168,531],[101,150,167,168,530,531,532,534],[101,150,167,168,530],[101,150,167,168,975,976],[101,150,167,168,975,976,977,978],[101,150,167,168,975,977],[101,150,167,168,975],[101,150,167,168,999,1000,1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1011,1012,1013,1014,1015,1016,1017,1018,1019,1020,1021,1022,1023,1024,1025,1026,1027,1028,1029,1030],[101,150,167,168,999],[101,150,167,168,999,1009],[93,101,150,167,168],[101,150,167,168,446],[101,150,167,168,453],[101,150,167,168,209,223,224,225,227,440],[101,150,167,168,209,248,250,252,253,256,440,442],[101,150,167,168,209,213,215,216,217,218,219,429,440,442],[101,150,167,168,440],[101,150,167,168,224,326,410,419,436],[101,150,167,168,209],[101,150,167,168,206,436],[101,150,167,168,260],[101,150,167,168,259,440,442],[101,150,164,167,168,308,326,355,497],[101,150,164,167,168,319,335,419,435],[101,150,164,167,168,371],[101,150,167,168,423],[101,150,167,168,422,423,424],[101,150,167,168,422],[95,101,150,164,167,168,206,209,213,216,220,221,222,224,228,236,237,364,389,420,440,443],[101,150,167,168,209,226,244,248,249,254,255,440,497],[101,150,167,168,226,497],[101,150,167,168,237,244,306,440,497],[101,150,167,168,497],[101,150,167,168,209,226,227,497],[101,150,167,168,251,497],[101,150,167,168,220,421,428],[101,150,167,168,176,268,436],[101,150,167,168,268,436],[87,101,150,167,168,268],[87,101,150,167,168,327],[101,150,167,168,323,369,436,479,480],[101,150,167,168,416,473,474,475,476,478],[101,150,167,168,415],[101,150,167,168,415,416],[101,150,167,168,217,365,366,367],[101,150,167,168,365,368,369],[101,150,167,168,477],[101,150,167,168,365,369],[87,101,150,167,168,210,467],[87,101,150,167,168,193],[87,101,150,167,168,226,296],[87,101,150,167,168,226],[101,150,167,168,294,298],[87,101,150,167,168,295,445],[87,91,101,150,164,167,168,200,201,202,443,489,490],[101,150,164,167,168],[101,150,164,167,168,213,275,365,375,390,410,425,426,440,441,497],[101,150,167,168,236,427],[101,150,167,168,443],[101,150,167,168,208],[87,101,150,167,168,308,322,334,344,346,435],[101,150,167,168,176,308,322,343,344,345,435,496],[101,150,167,168,337,338,339,340,341,342],[101,150,167,168,339],[101,150,167,168,343],[101,150,167,168,266,267,268,270],[87,101,150,167,168,261,262,263,269],[101,150,167,168,266,269],[101,150,167,168,264],[101,150,167,168,265],[87,101,150,167,168,268,295,445],[87,101,150,167,168,268,444,445],[87,101,150,167,168,268,445],[101,150,167,168,390,432],[101,150,167,168,432],[101,150,164,167,168,441,445],[101,150,167,168,331],[101,149,150,167,168,330],[101,150,167,168,238,276,314,316,318,319,320,321,362,365,435,438,441],[101,150,167,168,238,352,365,369],[101,150,167,168,319,435],[87,101,150,167,168,319,328,329,331,332,333,334,335,336,347,348,349,350,351,353,354,435,436,497],[101,150,167,168,313],[101,150,164,167,168,176,238,239,275,290,320,362,363,364,369,390,410,431,440,441,442,443,497],[101,150,167,168,435],[101,149,150,167,168,224,317,320,364,431,433,434,441],[101,150,167,168,319],[101,149,150,167,168,275,280,309,310,311,312,313,314,315,316,318,435,436],[101,150,164,167,168,280,281,309,441,442],[101,150,167,168,224,364,365,390,431,435,441],[101,150,164,167,168,440,442],[101,150,164,167,168,182,438,441,442],[101,150,164,167,168,176,193,206,213,226,238,239,241,276,277,282,287,290,316,320,365,375,377,380,382,385,386,387,388,389,410,430,431,436,438,440,441,442],[101,150,164,167,168,182],[101,150,167,168,209,210,211,213,218,221,226,244,430,438,439,443,445,497],[101,150,164,167,168,182,193,256,258,260,261,262,263,270,497],[101,150,167,168,176,193,206,248,258,286,287,288,289,316,365,380,389,390,396,399,400,410,431,436,438],[101,150,167,168,220,221,236,364,389,431,440],[101,150,164,167,168,193,210,213,316,394,438,440],[101,150,167,168,307],[101,150,164,167,168,397,398,407],[101,150,167,168,438,440],[101,150,167,168,314,317],[101,150,167,168,316,320,430,445],[101,150,164,167,168,176,242,248,289,380,390,396,399,402,438],[101,150,164,167,168,220,236,248,403],[101,150,167,168,209,241,405,430,440],[101,150,164,167,168,193,440],[101,150,164,167,168,226,240,241,242,253,271,404,406,430,440],[95,101,150,167,168,238,320,409,443,445],[101,150,164,167,168,176,193,213,220,228,236,239,276,282,286,287,288,289,290,316,365,377,390,391,393,395,410,430,431,436,437,438,445],[101,150,164,167,168,182,220,396,401,407,438],[101,150,167,168,231,232,233,234,235],[101,150,167,168,277,381],[101,150,167,168,383],[101,150,167,168,381],[101,150,167,168,383,384],[101,150,164,167,168,213,216,217,275,441],[101,150,164,167,168,176,208,210,238,276,290,320,373,374,410,438,442,443,445],[101,150,164,167,168,176,193,212,217,316,374,437,441],[101,150,167,168,309],[101,150,167,168,310],[101,150,167,168,311],[101,150,167,168,436],[101,150,167,168,257,273],[101,150,164,167,168,213,257,276],[101,150,167,168,272,273],[101,150,167,168,274],[101,150,167,168,257,258],[101,150,167,168,257,291],[101,150,167,168,257],[101,150,167,168,277,379,437],[101,150,167,168,378],[101,150,167,168,258,436,437],[101,150,167,168,376,437],[101,150,167,168,258,436],[101,150,167,168,362],[101,150,167,168,213,218,276,305,308,314,316,320,322,325,356,358,361,365,409,430,438,441],[101,150,167,168,299,302,303,304,323,324,369],[87,101,150,167,168,203,204,205,268,357],[87,101,150,167,168,203,204,205,268,357,360],[101,150,167,168,418],[101,150,167,168,224,281,319,320,331,335,365,409,411,412,413,414,416,417,420,430,435,440],[101,150,167,168,369],[101,150,167,168,373],[101,150,164,167,168,276,292,370,372,375,409,438,443,445],[101,150,167,168,299,300,301,302,303,304,323,324,369,444],[95,101,150,164,167,168,176,193,239,257,258,290,316,320,407,408,410,430,431,440,441,443],[101,150,167,168,281,283,286,431],[101,150,164,167,168,277,440],[101,150,167,168,280,319],[101,150,167,168,279],[101,150,167,168,281,282],[101,150,167,168,278,280,440],[101,150,164,167,168,212,281,283,284,285,440,441],[87,101,150,167,168,365,366,368],[101,150,167,168,243],[87,101,150,167,168,210],[87,101,150,167,168,436],[87,95,101,150,167,168,290,320,443,445],[101,150,167,168,210,467,468],[87,101,150,167,168,298],[87,101,150,167,168,176,193,208,255,293,295,297,445],[101,150,167,168,226,436,441],[101,150,167,168,392,436],[101,150,167,168,365],[87,101,150,162,164,167,168,176,208,244,250,298,443,444],[87,101,150,167,168,201,202,443,491],[87,88,89,90,91,101,150,167,168],[101,150,155,167,168],[101,150,167,168,245,246,247],[101,150,167,168,245],[87,91,101,150,164,166,167,168,176,200,201,202,203,205,206,208,239,343,402,440,442,445,491],[101,150,167,168,455],[101,150,167,168,457],[101,150,167,168,459],[101,150,167,168,461],[101,150,167,168,463,464,465],[101,150,167,168,469],[92,94,101,150,167,168,447,452,454,456,458,460,462,466,470,472,482,483,485,495,496,497,498],[101,150,167,168,471],[101,150,167,168,481],[101,150,167,168,295],[101,150,167,168,484],[101,149,150,167,168,281,283,284,286,334,436,486,487,488,491,492,493,494],[101,150,167,168,200],[101,150,167,168,518],[101,150,167,168,516,518],[101,150,167,168,507,515,516,517,519,521],[101,150,167,168,505],[101,150,167,168,508,513,518,521],[101,150,167,168,504,521],[101,150,167,168,508,509,512,513,514,521],[101,150,167,168,508,509,510,512,513,521],[101,150,167,168,505,506,507,508,509,513,514,515,517,518,519,521],[101,150,167,168,521],[101,150,167,168,503,505,506,507,508,509,510,512,513,514,515,516,517,518,519,520],[101,150,167,168,503,521],[101,150,167,168,508,510,511,513,514,521],[101,150,167,168,512,521],[101,150,167,168,513,514,518,521],[101,150,167,168,506,516],[101,150,167,168,543,552,553],[101,150,167,168,542,543],[101,150,167,168,182,200],[101,150,167,168,523,524],[101,150,167,168,522,525],[101,150,167,168,533],[101,115,119,150,167,168,193],[101,115,150,167,168,182,193],[101,110,150,167,168],[101,112,115,150,167,168,190,193],[101,150,167,168,170,190],[101,110,150,167,168,200],[101,112,115,150,167,168,170,193],[101,107,108,111,114,150,161,167,168,182,193],[101,115,122,150,167,168],[101,107,113,150,167,168],[101,115,136,137,150,167,168],[101,111,115,150,167,168,185,193,200],[101,136,150,167,168,200],[101,109,110,150,167,168,200],[101,115,150,167,168],[101,109,110,111,112,113,114,115,116,117,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,137,138,139,140,141,142,150,167,168],[101,115,130,150,167,168],[101,115,122,123,150,167,168],[101,113,115,123,124,150,167,168],[101,114,150,167,168],[101,107,110,115,150,167,168],[101,115,119,123,124,150,167,168],[101,119,150,167,168],[101,113,115,118,150,167,168,193],[101,107,112,115,122,150,167,168],[101,150,167,168,182],[101,110,115,136,150,167,168,198,200],[101,150,167,168,564,565],[101,150,167,168,564],[101,150,167,168,539],[101,150,161,162,164,165,166,167,168,170,182,190,193,199,200,522,539,540,541,543,544,546,547,548,549,550,551,552,553],[101,150,167,168,539,540,541,545],[101,150,167,168,541],[101,150,167,168,543,553],[101,150,167,168,538,584,972],[101,150,167,168,557,576,577,972],[101,150,167,168,530,537,557,569,570,972],[101,150,167,168,579],[101,150,167,168,558],[101,150,167,168,530,538,557,559,569,578,972],[101,150,167,168,562],[101,150,153,162,167,168,182,530,535,537,553,557,559,562,563,566,569,571,572,575,578,580,581,583,972],[101,150,167,168,557,576,577,578,972],[101,150,167,168,553,582,583],[101,150,167,168,557,559,566,569,571,972],[101,150,167,168,198,572],[101,150,153,162,167,168,182,530,535,537,553,557,558,559,562,563,566,569,570,571,572,575,576,577,578,579,580,581,582,583,972],[101,150,153,162,167,168,182,198,529,530,535,537,538,553,557,558,559,562,563,566,569,570,571,572,575,576,577,578,579,580,581,582,583,971,972,973,974,979],[101,150,167,168,606],[101,150,167,168,597,598],[101,150,167,168,594,595,597,599,600,605],[101,150,167,168,595,597],[101,150,167,168,605],[101,150,167,168,597],[101,150,167,168,594,595,597,600,601,602,603,604],[101,150,167,168,594,595,596]],"fileInfos":[{"version":"c430d44666289dae81f30fa7b2edebf186ecc91a2d4c71266ea6ae76388792e1","affectsGlobalScope":true,"impliedFormat":1},{"version":"45b7ab580deca34ae9729e97c13cfd999df04416a79116c3bfb483804f85ded4","impliedFormat":1},{"version":"3facaf05f0c5fc569c5649dd359892c98a85557e3e0c847964caeb67076f4d75","impliedFormat":1},{"version":"e44bb8bbac7f10ecc786703fe0a6a4b952189f908707980ba8f3c8975a760962","impliedFormat":1},{"version":"5e1c4c362065a6b95ff952c0eab010f04dcd2c3494e813b493ecfd4fcb9fc0d8","impliedFormat":1},{"version":"68d73b4a11549f9c0b7d352d10e91e5dca8faa3322bfb77b661839c42b1ddec7","impliedFormat":1},{"version":"5efce4fc3c29ea84e8928f97adec086e3dc876365e0982cc8479a07954a3efd4","impliedFormat":1},{"version":"feecb1be483ed332fad555aff858affd90a48ab19ba7272ee084704eb7167569","impliedFormat":1},{"version":"ee7bad0c15b58988daa84371e0b89d313b762ab83cb5b31b8a2d1162e8eb41c2","impliedFormat":1},{"version":"27bdc30a0e32783366a5abeda841bc22757c1797de8681bbe81fbc735eeb1c10","impliedFormat":1},{"version":"8fd575e12870e9944c7e1d62e1f5a73fcf23dd8d3a321f2a2c74c20d022283fe","impliedFormat":1},{"version":"2ab096661c711e4a81cc464fa1e6feb929a54f5340b46b0a07ac6bbf857471f0","impliedFormat":1},{"version":"080941d9f9ff9307f7e27a83bcd888b7c8270716c39af943532438932ec1d0b9","affectsGlobalScope":true,"impliedFormat":1},{"version":"2e80ee7a49e8ac312cc11b77f1475804bee36b3b2bc896bead8b6e1266befb43","affectsGlobalScope":true,"impliedFormat":1},{"version":"c57796738e7f83dbc4b8e65132f11a377649c00dd3eee333f672b8f0a6bea671","affectsGlobalScope":true,"impliedFormat":1},{"version":"dc2df20b1bcdc8c2d34af4926e2c3ab15ffe1160a63e58b7e09833f616efff44","affectsGlobalScope":true,"impliedFormat":1},{"version":"515d0b7b9bea2e31ea4ec968e9edd2c39d3eebf4a2d5cbd04e88639819ae3b71","affectsGlobalScope":true,"impliedFormat":1},{"version":"0559b1f683ac7505ae451f9a96ce4c3c92bdc71411651ca6ddb0e88baaaad6a3","affectsGlobalScope":true,"impliedFormat":1},{"version":"0dc1e7ceda9b8b9b455c3a2d67b0412feab00bd2f66656cd8850e8831b08b537","affectsGlobalScope":true,"impliedFormat":1},{"version":"ce691fb9e5c64efb9547083e4a34091bcbe5bdb41027e310ebba8f7d96a98671","affectsGlobalScope":true,"impliedFormat":1},{"version":"8d697a2a929a5fcb38b7a65594020fcef05ec1630804a33748829c5ff53640d0","affectsGlobalScope":true,"impliedFormat":1},{"version":"4ff2a353abf8a80ee399af572debb8faab2d33ad38c4b4474cff7f26e7653b8d","affectsGlobalScope":true,"impliedFormat":1},{"version":"fb0f136d372979348d59b3f5020b4cdb81b5504192b1cacff5d1fbba29378aa1","affectsGlobalScope":true,"impliedFormat":1},{"version":"d15bea3d62cbbdb9797079416b8ac375ae99162a7fba5de2c6c505446486ac0a","affectsGlobalScope":true,"impliedFormat":1},{"version":"68d18b664c9d32a7336a70235958b8997ebc1c3b8505f4f1ae2b7e7753b87618","affectsGlobalScope":true,"impliedFormat":1},{"version":"eb3d66c8327153d8fa7dd03f9c58d351107fe824c79e9b56b462935176cdf12a","affectsGlobalScope":true,"impliedFormat":1},{"version":"38f0219c9e23c915ef9790ab1d680440d95419ad264816fa15009a8851e79119","affectsGlobalScope":true,"impliedFormat":1},{"version":"69ab18c3b76cd9b1be3d188eaf8bba06112ebbe2f47f6c322b5105a6fbc45a2e","affectsGlobalScope":true,"impliedFormat":1},{"version":"a680117f487a4d2f30ea46f1b4b7f58bef1480456e18ba53ee85c2746eeca012","affectsGlobalScope":true,"impliedFormat":1},{"version":"2f11ff796926e0832f9ae148008138ad583bd181899ab7dd768a2666700b1893","affectsGlobalScope":true,"impliedFormat":1},{"version":"4de680d5bb41c17f7f68e0419412ca23c98d5749dcaaea1896172f06435891fc","affectsGlobalScope":true,"impliedFormat":1},{"version":"954296b30da6d508a104a3a0b5d96b76495c709785c1d11610908e63481ee667","affectsGlobalScope":true,"impliedFormat":1},{"version":"ac9538681b19688c8eae65811b329d3744af679e0bdfa5d842d0e32524c73e1c","affectsGlobalScope":true,"impliedFormat":1},{"version":"0a969edff4bd52585473d24995c5ef223f6652d6ef46193309b3921d65dd4376","affectsGlobalScope":true,"impliedFormat":1},{"version":"9e9fbd7030c440b33d021da145d3232984c8bb7916f277e8ffd3dc2e3eae2bdb","affectsGlobalScope":true,"impliedFormat":1},{"version":"811ec78f7fefcabbda4bfa93b3eb67d9ae166ef95f9bff989d964061cbf81a0c","affectsGlobalScope":true,"impliedFormat":1},{"version":"717937616a17072082152a2ef351cb51f98802fb4b2fdabd32399843875974ca","affectsGlobalScope":true,"impliedFormat":1},{"version":"d7e7d9b7b50e5f22c915b525acc5a49a7a6584cf8f62d0569e557c5cfc4b2ac2","affectsGlobalScope":true,"impliedFormat":1},{"version":"71c37f4c9543f31dfced6c7840e068c5a5aacb7b89111a4364b1d5276b852557","affectsGlobalScope":true,"impliedFormat":1},{"version":"576711e016cf4f1804676043e6a0a5414252560eb57de9faceee34d79798c850","affectsGlobalScope":true,"impliedFormat":1},{"version":"89c1b1281ba7b8a96efc676b11b264de7a8374c5ea1e6617f11880a13fc56dc6","affectsGlobalScope":true,"impliedFormat":1},{"version":"74f7fa2d027d5b33eb0471c8e82a6c87216223181ec31247c357a3e8e2fddc5b","affectsGlobalScope":true,"impliedFormat":1},{"version":"d6d7ae4d1f1f3772e2a3cde568ed08991a8ae34a080ff1151af28b7f798e22ca","affectsGlobalScope":true,"impliedFormat":1},{"version":"063600664504610fe3e99b717a1223f8b1900087fab0b4cad1496a114744f8df","affectsGlobalScope":true,"impliedFormat":1},{"version":"934019d7e3c81950f9a8426d093458b65d5aff2c7c1511233c0fd5b941e608ab","affectsGlobalScope":true,"impliedFormat":1},{"version":"52ada8e0b6e0482b728070b7639ee42e83a9b1c22d205992756fe020fd9f4a47","affectsGlobalScope":true,"impliedFormat":1},{"version":"3bdefe1bfd4d6dee0e26f928f93ccc128f1b64d5d501ff4a8cf3c6371200e5e6","affectsGlobalScope":true,"impliedFormat":1},{"version":"59fb2c069260b4ba00b5643b907ef5d5341b167e7d1dbf58dfd895658bda2867","affectsGlobalScope":true,"impliedFormat":1},{"version":"639e512c0dfc3fad96a84caad71b8834d66329a1f28dc95e3946c9b58176c73a","affectsGlobalScope":true,"impliedFormat":1},{"version":"368af93f74c9c932edd84c58883e736c9e3d53cec1fe24c0b0ff451f529ceab1","affectsGlobalScope":true,"impliedFormat":1},{"version":"af3dd424cf267428f30ccfc376f47a2c0114546b55c44d8c0f1d57d841e28d74","affectsGlobalScope":true,"impliedFormat":1},{"version":"995c005ab91a498455ea8dfb63aa9f83fa2ea793c3d8aa344be4a1678d06d399","affectsGlobalScope":true,"impliedFormat":1},{"version":"959d36cddf5e7d572a65045b876f2956c973a586da58e5d26cde519184fd9b8a","affectsGlobalScope":true,"impliedFormat":1},{"version":"965f36eae237dd74e6cca203a43e9ca801ce38824ead814728a2807b1910117d","affectsGlobalScope":true,"impliedFormat":1},{"version":"3925a6c820dcb1a06506c90b1577db1fdbf7705d65b62b99dce4be75c637e26b","affectsGlobalScope":true,"impliedFormat":1},{"version":"0a3d63ef2b853447ec4f749d3f368ce642264246e02911fcb1590d8c161b8005","affectsGlobalScope":true,"impliedFormat":1},{"version":"8cdf8847677ac7d20486e54dd3fcf09eda95812ac8ace44b4418da1bbbab6eb8","affectsGlobalScope":true,"impliedFormat":1},{"version":"8444af78980e3b20b49324f4a16ba35024fef3ee069a0eb67616ea6ca821c47a","affectsGlobalScope":true,"impliedFormat":1},{"version":"3287d9d085fbd618c3971944b65b4be57859f5415f495b33a6adc994edd2f004","affectsGlobalScope":true,"impliedFormat":1},{"version":"b4b67b1a91182421f5df999988c690f14d813b9850b40acd06ed44691f6727ad","affectsGlobalScope":true,"impliedFormat":1},{"version":"df83c2a6c73228b625b0beb6669c7ee2a09c914637e2d35170723ad49c0f5cd4","affectsGlobalScope":true,"impliedFormat":1},{"version":"436aaf437562f276ec2ddbee2f2cdedac7664c1e4c1d2c36839ddd582eeb3d0a","affectsGlobalScope":true,"impliedFormat":1},{"version":"8e3c06ea092138bf9fa5e874a1fdbc9d54805d074bee1de31b99a11e2fec239d","affectsGlobalScope":true,"impliedFormat":1},{"version":"87dc0f382502f5bbce5129bdc0aea21e19a3abbc19259e0b43ae038a9fc4e326","affectsGlobalScope":true,"impliedFormat":1},{"version":"b1cb28af0c891c8c96b2d6b7be76bd394fddcfdb4709a20ba05a7c1605eea0f9","affectsGlobalScope":true,"impliedFormat":1},{"version":"2fef54945a13095fdb9b84f705f2b5994597640c46afeb2ce78352fab4cb3279","affectsGlobalScope":true,"impliedFormat":1},{"version":"ac77cb3e8c6d3565793eb90a8373ee8033146315a3dbead3bde8db5eaf5e5ec6","affectsGlobalScope":true,"impliedFormat":1},{"version":"56e4ed5aab5f5920980066a9409bfaf53e6d21d3f8d020c17e4de584d29600ad","affectsGlobalScope":true,"impliedFormat":1},{"version":"4ece9f17b3866cc077099c73f4983bddbcb1dc7ddb943227f1ec070f529dedd1","affectsGlobalScope":true,"impliedFormat":1},{"version":"0a6282c8827e4b9a95f4bf4f5c205673ada31b982f50572d27103df8ceb8013c","affectsGlobalScope":true,"impliedFormat":1},{"version":"1c9319a09485199c1f7b0498f2988d6d2249793ef67edda49d1e584746be9032","affectsGlobalScope":true,"impliedFormat":1},{"version":"e3a2a0cee0f03ffdde24d89660eba2685bfbdeae955a6c67e8c4c9fd28928eeb","affectsGlobalScope":true,"impliedFormat":1},{"version":"811c71eee4aa0ac5f7adf713323a5c41b0cf6c4e17367a34fbce379e12bbf0a4","affectsGlobalScope":true,"impliedFormat":1},{"version":"51ad4c928303041605b4d7ae32e0c1ee387d43a24cd6f1ebf4a2699e1076d4fa","affectsGlobalScope":true,"impliedFormat":1},{"version":"60037901da1a425516449b9a20073aa03386cce92f7a1fd902d7602be3a7c2e9","affectsGlobalScope":true,"impliedFormat":1},{"version":"d4b1d2c51d058fc21ec2629fff7a76249dec2e36e12960ea056e3ef89174080f","affectsGlobalScope":true,"impliedFormat":1},{"version":"22adec94ef7047a6c9d1af3cb96be87a335908bf9ef386ae9fd50eeb37f44c47","affectsGlobalScope":true,"impliedFormat":1},{"version":"196cb558a13d4533a5163286f30b0509ce0210e4b316c56c38d4c0fd2fb38405","affectsGlobalScope":true,"impliedFormat":1},{"version":"73f78680d4c08509933daf80947902f6ff41b6230f94dd002ae372620adb0f60","affectsGlobalScope":true,"impliedFormat":1},{"version":"c5239f5c01bcfa9cd32f37c496cf19c61d69d37e48be9de612b541aac915805b","affectsGlobalScope":true,"impliedFormat":1},{"version":"8e7f8264d0fb4c5339605a15daadb037bf238c10b654bb3eee14208f860a32ea","affectsGlobalScope":true,"impliedFormat":1},{"version":"782dec38049b92d4e85c1585fbea5474a219c6984a35b004963b00beb1aab538","affectsGlobalScope":true,"impliedFormat":1},{"version":"d6b520432c6ffb434a25b184060fc141f8870d2656894bdb1b0f7352b107e8fc","affectsGlobalScope":true},{"version":"eb5b19b86227ace1d29ea4cf81387279d04bb34051e944bc53df69f58914b788","affectsGlobalScope":true,"impliedFormat":1},{"version":"ac51dd7d31333793807a6abaa5ae168512b6131bd41d9c5b98477fc3b7800f9f","impliedFormat":1},{"version":"87d9d29dbc745f182683f63187bf3d53fd8673e5fca38ad5eaab69798ed29fbc","impliedFormat":1},{"version":"035312d4945d13efa134ae482f6dc56a1a9346f7ac3be7ccbad5741058ce87f3","affectsGlobalScope":true,"impliedFormat":1},{"version":"acd8fd5090ac73902278889c38336ff3f48af6ba03aa665eb34a75e7ba1dccc4","impliedFormat":1},{"version":"d6258883868fb2680d2ca96bc8b1352cab69874581493e6d52680c5ffecdb6cc","impliedFormat":1},{"version":"1b61d259de5350f8b1e5db06290d31eaebebc6baafd5f79d314b5af9256d7153","impliedFormat":1},{"version":"f258e3960f324a956fc76a3d3d9e964fff2244ff5859dcc6ce5951e5413ca826","impliedFormat":1},{"version":"643f7232d07bf75e15bd8f658f664d6183a0efaca5eb84b48201c7671a266979","impliedFormat":1},{"version":"0f6666b58e9276ac3a38fdc80993d19208442d6027ab885580d93aec76b4ef00","impliedFormat":1},{"version":"05fd364b8ef02fb1e174fbac8b825bdb1e5a36a016997c8e421f5fab0a6da0a0","impliedFormat":1},{"version":"631eff75b0e35d1b1b31081d55209abc43e16b49426546ab5a9b40bdd40b1f60","impliedFormat":1},{"version":"6c7176368037af28cb72f2392010fa1cef295d6d6744bca8cfb54985f3a18c3e","affectsGlobalScope":true,"impliedFormat":1},{"version":"ab41ef1f2cdafb8df48be20cd969d875602483859dc194e9c97c8a576892c052","affectsGlobalScope":true,"impliedFormat":1},{"version":"437e20f2ba32abaeb7985e0afe0002de1917bc74e949ba585e49feba65da6ca1","affectsGlobalScope":true,"impliedFormat":1},{"version":"21d819c173c0cf7cc3ce57c3276e77fd9a8a01d35a06ad87158781515c9a438a","impliedFormat":1},{"version":"98cffbf06d6bab333473c70a893770dbe990783904002c4f1a960447b4b53dca","affectsGlobalScope":true,"impliedFormat":1},{"version":"3af97acf03cc97de58a3a4bc91f8f616408099bc4233f6d0852e72a8ffb91ac9","affectsGlobalScope":true,"impliedFormat":1},{"version":"808069bba06b6768b62fd22429b53362e7af342da4a236ed2d2e1c89fcca3b4a","affectsGlobalScope":true,"impliedFormat":1},{"version":"1db0b7dca579049ca4193d034d835f6bfe73096c73663e5ef9a0b5779939f3d0","affectsGlobalScope":true,"impliedFormat":1},{"version":"9798340ffb0d067d69b1ae5b32faa17ab31b82466a3fc00d8f2f2df0c8554aaa","affectsGlobalScope":true,"impliedFormat":1},{"version":"f26b11d8d8e4b8028f1c7d618b22274c892e4b0ef5b3678a8ccbad85419aef43","affectsGlobalScope":true,"impliedFormat":1},{"version":"8e9c23ba78aabc2e0a27033f18737a6df754067731e69dc5f52823957d60a4b6","impliedFormat":1},{"version":"5929864ce17fba74232584d90cb721a89b7ad277220627cc97054ba15a98ea8f","impliedFormat":1},{"version":"763fe0f42b3d79b440a9b6e51e9ba3f3f91352469c1e4b3b67bfa4ff6352f3f4","impliedFormat":1},{"version":"25c8056edf4314820382a5fdb4bb7816999acdcb929c8f75e3f39473b87e85bc","impliedFormat":1},{"version":"c464d66b20788266e5353b48dc4aa6bc0dc4a707276df1e7152ab0c9ae21fad8","impliedFormat":1},{"version":"78d0d27c130d35c60b5e5566c9f1e5be77caf39804636bc1a40133919a949f21","impliedFormat":1},{"version":"c6fd2c5a395f2432786c9cb8deb870b9b0e8ff7e22c029954fabdd692bff6195","impliedFormat":1},{"version":"1d6e127068ea8e104a912e42fc0a110e2aa5a66a356a917a163e8cf9a65e4a75","impliedFormat":1},{"version":"5ded6427296cdf3b9542de4471d2aa8d3983671d4cac0f4bf9c637208d1ced43","impliedFormat":1},{"version":"7f182617db458e98fc18dfb272d40aa2fff3a353c44a89b2c0ccb3937709bfb5","impliedFormat":1},{"version":"cadc8aced301244057c4e7e73fbcae534b0f5b12a37b150d80e5a45aa4bebcbd","impliedFormat":1},{"version":"385aab901643aa54e1c36f5ef3107913b10d1b5bb8cbcd933d4263b80a0d7f20","impliedFormat":1},{"version":"9670d44354bab9d9982eca21945686b5c24a3f893db73c0dae0fd74217a4c219","impliedFormat":1},{"version":"0b8a9268adaf4da35e7fa830c8981cfa22adbbe5b3f6f5ab91f6658899e657a7","impliedFormat":1},{"version":"11396ed8a44c02ab9798b7dca436009f866e8dae3c9c25e8c1fbc396880bf1bb","impliedFormat":1},{"version":"ba7bc87d01492633cb5a0e5da8a4a42a1c86270e7b3d2dea5d156828a84e4882","impliedFormat":1},{"version":"4893a895ea92c85345017a04ed427cbd6a1710453338df26881a6019432febdd","impliedFormat":1},{"version":"c21dc52e277bcfc75fac0436ccb75c204f9e1b3fa5e12729670910639f27343e","impliedFormat":1},{"version":"13f6f39e12b1518c6650bbb220c8985999020fe0f21d818e28f512b7771d00f9","impliedFormat":1},{"version":"9b5369969f6e7175740bf51223112ff209f94ba43ecd3bb09eefff9fd675624a","impliedFormat":1},{"version":"4fe9e626e7164748e8769bbf74b538e09607f07ed17c2f20af8d680ee49fc1da","impliedFormat":1},{"version":"24515859bc0b836719105bb6cc3d68255042a9f02a6022b3187948b204946bd2","impliedFormat":1},{"version":"ea0148f897b45a76544ae179784c95af1bd6721b8610af9ffa467a518a086a43","impliedFormat":1},{"version":"24c6a117721e606c9984335f71711877293a9651e44f59f3d21c1ea0856f9cc9","impliedFormat":1},{"version":"dd3273ead9fbde62a72949c97dbec2247ea08e0c6952e701a483d74ef92d6a17","impliedFormat":1},{"version":"405822be75ad3e4d162e07439bac80c6bcc6dbae1929e179cf467ec0b9ee4e2e","impliedFormat":1},{"version":"0db18c6e78ea846316c012478888f33c11ffadab9efd1cc8bcc12daded7a60b6","impliedFormat":1},{"version":"e61be3f894b41b7baa1fbd6a66893f2579bfad01d208b4ff61daef21493ef0a8","impliedFormat":1},{"version":"bd0532fd6556073727d28da0edfd1736417a3f9f394877b6d5ef6ad88fba1d1a","impliedFormat":1},{"version":"89167d696a849fce5ca508032aabfe901c0868f833a8625d5a9c6e861ef935d2","impliedFormat":1},{"version":"615ba88d0128ed16bf83ef8ccbb6aff05c3ee2db1cc0f89ab50a4939bfc1943f","impliedFormat":1},{"version":"a4d551dbf8746780194d550c88f26cf937caf8d56f102969a110cfaed4b06656","impliedFormat":1},{"version":"8bd86b8e8f6a6aa6c49b71e14c4ffe1211a0e97c80f08d2c8cc98838006e4b88","impliedFormat":1},{"version":"317e63deeb21ac07f3992f5b50cdca8338f10acd4fbb7257ebf56735bf52ab00","impliedFormat":1},{"version":"4732aec92b20fb28c5fe9ad99521fb59974289ed1e45aecb282616202184064f","impliedFormat":1},{"version":"2e85db9e6fd73cfa3d7f28e0ab6b55417ea18931423bd47b409a96e4a169e8e6","impliedFormat":1},{"version":"c46e079fe54c76f95c67fb89081b3e399da2c7d109e7dca8e4b58d83e332e605","impliedFormat":1},{"version":"bf67d53d168abc1298888693338cb82854bdb2e69ef83f8a0092093c2d562107","impliedFormat":1},{"version":"b52476feb4a0cbcb25e5931b930fc73cb6643fb1a5060bf8a3dda0eeae5b4b68","affectsGlobalScope":true,"impliedFormat":1},{"version":"f9501cc13ce624c72b61f12b3963e84fad210fbdf0ffbc4590e08460a3f04eba","affectsGlobalScope":true,"impliedFormat":1},{"version":"e7721c4f69f93c91360c26a0a84ee885997d748237ef78ef665b153e622b36c1","affectsGlobalScope":true,"impliedFormat":1},{"version":"0fa06ada475b910e2106c98c68b10483dc8811d0c14a8a8dd36efb2672485b29","impliedFormat":1},{"version":"33e5e9aba62c3193d10d1d33ae1fa75c46a1171cf76fef750777377d53b0303f","impliedFormat":1},{"version":"2b06b93fd01bcd49d1a6bd1f9b65ddcae6480b9a86e9061634d6f8e354c1468f","impliedFormat":1},{"version":"6a0cd27e5dc2cfbe039e731cf879d12b0e2dded06d1b1dedad07f7712de0d7f4","affectsGlobalScope":true,"impliedFormat":1},{"version":"13f5c844119c43e51ce777c509267f14d6aaf31eafb2c2b002ca35584cd13b29","impliedFormat":1},{"version":"e60477649d6ad21542bd2dc7e3d9ff6853d0797ba9f689ba2f6653818999c264","impliedFormat":1},{"version":"c2510f124c0293ab80b1777c44d80f812b75612f297b9857406468c0f4dafe29","affectsGlobalScope":true,"impliedFormat":1},{"version":"5524481e56c48ff486f42926778c0a3cce1cc85dc46683b92b1271865bcf015a","impliedFormat":1},{"version":"4c829ab315f57c5442c6667b53769975acbf92003a66aef19bce151987675bd1","affectsGlobalScope":true,"impliedFormat":1},{"version":"b2ade7657e2db96d18315694789eff2ddd3d8aea7215b181f8a0b303277cc579","impliedFormat":1},{"version":"9855e02d837744303391e5623a531734443a5f8e6e8755e018c41d63ad797db2","impliedFormat":1},{"version":"4d631b81fa2f07a0e63a9a143d6a82c25c5f051298651a9b69176ba28930756d","impliedFormat":1},{"version":"836a356aae992ff3c28a0212e3eabcb76dd4b0cc06bcb9607aeef560661b860d","impliedFormat":1},{"version":"1e0d1f8b0adfa0b0330e028c7941b5a98c08b600efe7f14d2d2a00854fb2f393","impliedFormat":1},{"version":"41670ee38943d9cbb4924e436f56fc19ee94232bc96108562de1a734af20dc2c","affectsGlobalScope":true,"impliedFormat":1},{"version":"c906fb15bd2aabc9ed1e3f44eb6a8661199d6c320b3aa196b826121552cb3695","impliedFormat":1},{"version":"22295e8103f1d6d8ea4b5d6211e43421fe4564e34d0dd8e09e520e452d89e659","impliedFormat":1},{"version":"58647d85d0f722a1ce9de50955df60a7489f0593bf1a7015521efe901c06d770","impliedFormat":1},{"version":"6b4e081d55ac24fc8a4631d5dd77fe249fa25900abd7d046abb87d90e3b45645","impliedFormat":1},{"version":"a10f0e1854f3316d7ee437b79649e5a6ae3ae14ffe6322b02d4987071a95362e","impliedFormat":1},{"version":"e208f73ef6a980104304b0d2ca5f6bf1b85de6009d2c7e404028b875020fa8f2","impliedFormat":1},{"version":"d163b6bc2372b4f07260747cbc6c0a6405ab3fbcea3852305e98ac43ca59f5bc","impliedFormat":1},{"version":"e6fa9ad47c5f71ff733744a029d1dc472c618de53804eae08ffc243b936f87ff","affectsGlobalScope":true,"impliedFormat":1},{"version":"83e63d6ccf8ec004a3bb6d58b9bb0104f60e002754b1e968024b320730cc5311","impliedFormat":1},{"version":"24826ed94a78d5c64bd857570fdbd96229ad41b5cb654c08d75a9845e3ab7dde","impliedFormat":1},{"version":"8b479a130ccb62e98f11f136d3ac80f2984fdc07616516d29881f3061f2dd472","impliedFormat":1},{"version":"928af3d90454bf656a52a48679f199f64c1435247d6189d1caf4c68f2eaf921f","affectsGlobalScope":true,"impliedFormat":1},{"version":"bceb58df66ab8fb00170df20cd813978c5ab84be1d285710c4eb005d8e9d8efb","affectsGlobalScope":true,"impliedFormat":1},{"version":"3f16a7e4deafa527ed9995a772bb380eb7d3c2c0fd4ae178c5263ed18394db2c","impliedFormat":1},{"version":"933921f0bb0ec12ef45d1062a1fc0f27635318f4d294e4d99de9a5493e618ca2","impliedFormat":1},{"version":"71a0f3ad612c123b57239a7749770017ecfe6b66411488000aba83e4546fde25","impliedFormat":1},{"version":"77fbe5eecb6fac4b6242bbf6eebfc43e98ce5ccba8fa44e0ef6a95c945ff4d98","impliedFormat":1},{"version":"4f9d8ca0c417b67b69eeb54c7ca1bedd7b56034bb9bfd27c5d4f3bc4692daca7","impliedFormat":1},{"version":"814118df420c4e38fe5ae1b9a3bafb6e9c2aa40838e528cde908381867be6466","impliedFormat":1},{"version":"a3fc63c0d7b031693f665f5494412ba4b551fe644ededccc0ab5922401079c95","impliedFormat":1},{"version":"f27524f4bef4b6519c604bdb23bf4465bddcccbf3f003abb901acbd0d7404d99","impliedFormat":1},{"version":"37ba7b45141a45ce6e80e66f2a96c8a5ab1bcef0fc2d0f56bb58df96ec67e972","impliedFormat":1},{"version":"45650f47bfb376c8a8ed39d4bcda5902ab899a3150029684ee4c10676d9fbaee","impliedFormat":1},{"version":"6b039f55681caaf111d5eb84d292b9bee9e0131d0db1ad0871eef0964f533c73","affectsGlobalScope":true,"impliedFormat":1},{"version":"18fd40412d102c5564136f29735e5d1c3b455b8a37f920da79561f1fde068208","impliedFormat":1},{"version":"c8d3e5a18ba35629954e48c4cc8f11dc88224650067a172685c736b27a34a4dc","impliedFormat":1},{"version":"f0be1b8078cd549d91f37c30c222c2a187ac1cf981d994fb476a1adc61387b14","affectsGlobalScope":true,"impliedFormat":1},{"version":"0aaed1d72199b01234152f7a60046bc947f1f37d78d182e9ae09c4289e06a592","impliedFormat":1},{"version":"2b55d426ff2b9087485e52ac4bc7cfafe1dc420fc76dad926cd46526567c501a","impliedFormat":1},{"version":"66ba1b2c3e3a3644a1011cd530fb444a96b1b2dfe2f5e837a002d41a1a799e60","impliedFormat":1},{"version":"7e514f5b852fdbc166b539fdd1f4e9114f29911592a5eb10a94bb3a13ccac3c4","impliedFormat":1},{"version":"5b7aa3c4c1a5d81b411e8cb302b45507fea9358d3569196b27eb1a27ae3a90ef","affectsGlobalScope":true,"impliedFormat":1},{"version":"5987a903da92c7462e0b35704ce7da94d7fdc4b89a984871c0e2b87a8aae9e69","affectsGlobalScope":true,"impliedFormat":1},{"version":"ea08a0345023ade2b47fbff5a76d0d0ed8bff10bc9d22b83f40858a8e941501c","impliedFormat":1},{"version":"47613031a5a31510831304405af561b0ffaedb734437c595256bb61a90f9311b","impliedFormat":1},{"version":"ae062ce7d9510060c5d7e7952ae379224fb3f8f2dd74e88959878af2057c143b","impliedFormat":1},{"version":"8a1a0d0a4a06a8d278947fcb66bf684f117bf147f89b06e50662d79a53be3e9f","affectsGlobalScope":true,"impliedFormat":1},{"version":"358765d5ea8afd285d4fd1532e78b88273f18cb3f87403a9b16fef61ac9fdcfe","impliedFormat":1},{"version":"9f55299850d4f0921e79b6bf344b47c420ce0f507b9dcf593e532b09ea7eeea1","impliedFormat":1},{"version":"f9fd93190acb1ffe0bc0fb395df979452f8d625071e9ffc8636e4dfb86ab2508","impliedFormat":1},{"version":"5f41fd8732a89e940c58ce22206e3df85745feb8983e2b4c6257fb8cbb118493","impliedFormat":1},{"version":"17ed71200119e86ccef2d96b73b02ce8854b76ad6bd21b5021d4269bec527b5f","impliedFormat":1},{"version":"1cfa8647d7d71cb03847d616bd79320abfc01ddea082a49569fda71ac5ece66b","impliedFormat":1},{"version":"bb7a61dd55dc4b9422d13da3a6bb9cc5e89be888ef23bbcf6558aa9726b89a1c","impliedFormat":1},{"version":"413df52d4ea14472c2fa5bee62f7a40abd1eb49be0b9722ee01ee4e52e63beb2","impliedFormat":1},{"version":"db6d2d9daad8a6d83f281af12ce4355a20b9a3e71b82b9f57cddcca0a8964a96","impliedFormat":1},{"version":"829b9e6028b29e6a8b1c01ddb713efe59da04d857089298fa79acbdb3cfcfdef","impliedFormat":1},{"version":"24f8562308dd8ba6013120557fa7b44950b619610b2c6cb8784c79f11e3c4f90","impliedFormat":1},{"version":"5f90b8c733a1bda63e42160b15a2301051e83a6f9d5332a59d16eb12f463270d","impliedFormat":1},{"version":"a86f82d646a739041d6702101afa82dcb935c416dd93cbca7fd754fd0282ce1f","impliedFormat":1},{"version":"ad0d1d75d129b1c80f911be438d6b61bfa8703930a8ff2be2f0e1f8a91841c64","impliedFormat":1},{"version":"ce75b1aebb33d510ff28af960a9221410a3eaf7f18fc5f21f9404075fba77256","impliedFormat":1},{"version":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","impliedFormat":1},{"version":"496bbf339f3838c41f164238543e9fe5f1f10659cb30b68903851618464b98ba","impliedFormat":1},{"version":"5178eb4415a172c287c711dc60a619e110c3fd0b7de01ed0627e51a5336aa09c","impliedFormat":1},{"version":"ca6e5264278b53345bc1ce95f42fb0a8b733a09e3d6479c6ccfca55cdc45038c","impliedFormat":1},{"version":"9e2739b32f741859263fdba0244c194ca8e96da49b430377930b8f721d77c000","impliedFormat":1},{"version":"fb1d8e814a3eeb5101ca13515e0548e112bd1ff3fb358ece535b93e94adf5a3a","impliedFormat":1},{"version":"ffa495b17a5ef1d0399586b590bd281056cee6ce3583e34f39926f8dcc6ecdb5","impliedFormat":1},{"version":"98b18458acb46072947aabeeeab1e410f047e0cacc972943059ca5500b0a5e95","impliedFormat":1},{"version":"361e2b13c6765d7f85bb7600b48fde782b90c7c41105b7dab1f6e7871071ba20","impliedFormat":1},{"version":"c86fe861cf1b4c46a0fb7d74dffe596cf679a2e5e8b1456881313170f092e3fa","impliedFormat":1},{"version":"b6db56e4903e9c32e533b78ac85522de734b3d3a8541bf24d256058d464bf04b","impliedFormat":1},{"version":"24daa0366f837d22c94a5c0bad5bf1fd0f6b29e1fae92dc47c3072c3fdb2fbd5","impliedFormat":1},{"version":"570bb5a00836ffad3e4127f6adf581bfc4535737d8ff763a4d6f4cc877e60d98","impliedFormat":1},{"version":"889c00f3d32091841268f0b994beba4dceaa5df7573be12c2c829d7c5fbc232c","impliedFormat":1},{"version":"65f43099ded6073336e697512d9b80f2d4fec3182b7b2316abf712e84104db00","impliedFormat":1},{"version":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","impliedFormat":1},{"version":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","impliedFormat":1},{"version":"8e609bb71c20b858c77f0e9f90bb1319db8477b13f9f965f1a1e18524bf50881","impliedFormat":1},{"version":"acf5a2ac47b59ca07afa9abbd2b31d001bf7448b041927befae2ea5b1951d9f9","impliedFormat":1},{"version":"8e609bb71c20b858c77f0e9f90bb1319db8477b13f9f965f1a1e18524bf50881","impliedFormat":1},{"version":"d71291eff1e19d8762a908ba947e891af44749f3a2cbc5bd2ec4b72f72ea795f","impliedFormat":1},{"version":"c0480e03db4b816dff2682b347c95f2177699525c54e7e6f6aa8ded890b76be7","impliedFormat":1},{"version":"27ab780875bcbb65e09da7496f2ca36288b0c541abaa75c311450a077d54ec15","impliedFormat":1},{"version":"b620391fe8060cf9bedc176a4d01366e6574d7a71e0ac0ab344a4e76576fcbb8","impliedFormat":1},{"version":"380647d8f3b7f852cca6d154a376dbf8ac620a2f12b936594504a8a852e71d2f","impliedFormat":1},{"version":"208c9af9429dd3c76f5927b971263174aaa4bc7621ddec63f163640cbd3c473c","impliedFormat":1},{"version":"6459054aabb306821a043e02b89d54da508e3a6966601a41e71c166e4ea1474f","impliedFormat":1},{"version":"a23185bc5ef590c287c28a91baf280367b50ae4ea40327366ad01f6f4a8edbc5","impliedFormat":1},{"version":"bb37588926aba35c9283fe8d46ebf4e79ffe976343105f5c6d45f282793352b2","impliedFormat":1},{"version":"002eae065e6960458bda3cf695e578b0d1e2785523476f8a9170b103c709cd4f","impliedFormat":1},{"version":"c83bb0c9c5645a46c68356c2f73fdc9de339ce77f7f45a954f560c7e0b8d5ebb","impliedFormat":1},{"version":"05c97cddbaf99978f83d96de2d8af86aded9332592f08ce4a284d72d0952c391","impliedFormat":1},{"version":"72179f9dd22a86deaad4cc3490eb0fe69ee084d503b686985965654013f1391b","impliedFormat":1},{"version":"2e6114a7dd6feeef85b2c80120fdbfb59a5529c0dcc5bfa8447b6996c97a69f5","impliedFormat":1},{"version":"7b6ff760c8a240b40dab6e4419b989f06a5b782f4710d2967e67c695ef3e93c4","impliedFormat":1},{"version":"c8f004e6036aa1c764ad4ec543cf89a5c1893a9535c80ef3f2b653e370de45e6","impliedFormat":1},{"version":"dd80b1e600d00f5c6a6ba23f455b84a7db121219e68f89f10552c54ba46e4dc9","impliedFormat":1},{"version":"b064c36f35de7387d71c599bfcf28875849a1dbc733e82bd26cae3d1cd060521","impliedFormat":1},{"version":"6a148329edecbda07c21098639ef4254ef7869fb25a69f58e5d6a8b7b69d4236","impliedFormat":1},{"version":"8de9fe97fa9e00ec00666fa77ab6e91b35d25af8ca75dabcb01e14ad3299b150","impliedFormat":1},{"version":"f63ab283a1c8f5c79fabe7ca4ef85f9633339c4f0e822fce6a767f9d59282af2","impliedFormat":1},{"version":"dba114fb6a32b355a9cfc26ca2276834d72fe0e94cd2c3494005547025015369","impliedFormat":1},{"version":"a54c996c8870ef1728a2c1fa9b8eaec0bf4a8001cd2583c02dd5869289465b10","impliedFormat":1},{"version":"3e7efde639c6a6c3edb9847b3f61e308bf7a69685b92f665048c45132f51c218","impliedFormat":1},{"version":"df45ca1176e6ac211eae7ddf51336dc075c5314bc5c253651bae639defd5eec5","impliedFormat":1},{"version":"3754982006a3b32c502cff0867ca83584f7a43b1035989ca73603f400de13c96","impliedFormat":1},{"version":"a30ae9bb8a8fa7b90f24b8a0496702063ae4fe75deb27da731ed4a03b2eb6631","impliedFormat":1},{"version":"f974e4a06953682a2c15d5bd5114c0284d5abf8bc0fe4da25cb9159427b70072","impliedFormat":1},{"version":"50256e9c31318487f3752b7ac12ff365c8949953e04568009c8705db802776fb","impliedFormat":1},{"version":"7d73b24e7bf31dfb8a931ca6c4245f6bb0814dfae17e4b60c9e194a631fe5f7b","impliedFormat":1},{"version":"413586add0cfe7369b64979d4ec2ed56c3f771c0667fbde1bf1f10063ede0b08","impliedFormat":1},{"version":"06472528e998d152375ad3bd8ebcb69ff4694fd8d2effaf60a9d9f25a37a097a","impliedFormat":1},{"version":"50b5bc34ce6b12eccb76214b51aadfa56572aa6cc79c2b9455cdbb3d6c76af1d","impliedFormat":1},{"version":"b7e16ef7f646a50991119b205794ebfd3a4d8f8e0f314981ebbe991639023d0e","impliedFormat":1},{"version":"42c169fb8c2d42f4f668c624a9a11e719d5d07dacbebb63cbcf7ef365b0a75b3","impliedFormat":1},{"version":"a401617604fa1f6ce437b81689563dfdc377069e4c58465dbd8d16069aede0a5","impliedFormat":1},{"version":"e9dd71cf12123419c60dab867d44fbee5c358169f99529121eaef277f5c83531","impliedFormat":1},{"version":"5b6a189ba3a0befa1f5d9cb028eb9eec2af2089c32f04ff50e2411f63d70f25d","impliedFormat":1},{"version":"d6e73f8010935b7b4c7487b6fb13ea197cc610f0965b759bec03a561ccf8423a","impliedFormat":1},{"version":"174f3864e398f3f33f9a446a4f403d55a892aa55328cf6686135dfaf9e171657","impliedFormat":1},{"version":"824c76aec8d8c7e65769688cbee102238c0ef421ed6686f41b2a7d8e7e78a931","impliedFormat":1},{"version":"75b868be3463d5a8cfc0d9396f0a3d973b8c297401d00bfb008a42ab16643f13","impliedFormat":1},{"version":"15a234e5031b19c48a69ccc1607522d6e4b50f57d308ecb7fe863d44cd9f9eb3","impliedFormat":1},{"version":"d682336018141807fb602709e2d95a192828fcb8d5ba06dda3833a8ea98f69e3","impliedFormat":1},{"version":"6124e973eab8c52cabf3c07575204efc1784aca6b0a30c79eb85fe240a857efa","impliedFormat":1},{"version":"0d891735a21edc75df51f3eb995e18149e119d1ce22fd40db2b260c5960b914e","impliedFormat":1},{"version":"3b414b99a73171e1c4b7b7714e26b87d6c5cb03d200352da5342ab4088a54c85","impliedFormat":1},{"version":"4fbd3116e00ed3a6410499924b6403cc9367fdca303e34838129b328058ede40","impliedFormat":1},{"version":"b01bd582a6e41457bc56e6f0f9de4cb17f33f5f3843a7cf8210ac9c18472fb0f","impliedFormat":1},{"version":"0a437ae178f999b46b6153d79095b60c42c996bc0458c04955f1c996dc68b971","impliedFormat":1},{"version":"74b2a5e5197bd0f2e0077a1ea7c07455bbea67b87b0869d9786d55104006784f","impliedFormat":1},{"version":"4a7baeb6325920044f66c0f8e5e6f1f52e06e6d87588d837bdf44feb6f35c664","impliedFormat":1},{"version":"6dcf60530c25194a9ee0962230e874ff29d34c59605d8e069a49928759a17e0a","impliedFormat":1},{"version":"7274fbffbd7c9589d8d0ffba68157237afd5cecff1e99881ea3399127e60572f","impliedFormat":1},{"version":"1a42d2ec31a1fe62fdc51591768695ed4a2dc64c01be113e7ff22890bebb5e3f","impliedFormat":1},{"version":"1a82deef4c1d39f6882f28d275cad4c01f907b9b39be9cbc472fcf2cf051e05b","impliedFormat":1},{"version":"c5426dbfc1cf90532f66965a7aa8c1136a78d4d0f96d8180ecbfc11d7722f1a5","impliedFormat":1},{"version":"65a15fc47900787c0bd18b603afb98d33ede930bed1798fc984d5ebb78b26cf9","impliedFormat":1},{"version":"9d202701f6e0744adb6314d03d2eb8fc994798fc83d91b691b75b07626a69801","impliedFormat":1},{"version":"de9d2df7663e64e3a91bf495f315a7577e23ba088f2949d5ce9ec96f44fba37d","impliedFormat":1},{"version":"c7af78a2ea7cb1cd009cfb5bdb48cd0b03dad3b54f6da7aab615c2e9e9d570c5","impliedFormat":1},{"version":"1ee45496b5f8bdee6f7abc233355898e5bf9bd51255db65f5ff7ede617ca0027","impliedFormat":1},{"version":"0c7c947ff881c4274c0800deaa0086971e0bfe51f89a33bd3048eaa3792d4876","affectsGlobalScope":true,"impliedFormat":1},{"version":"db01d18853469bcb5601b9fc9826931cc84cc1a1944b33cad76fd6f1e3d8c544","affectsGlobalScope":true,"impliedFormat":1},{"version":"a8f8e6ab2fa07b45251f403548b78eaf2022f3c2254df3dc186cb2671fe4996d","affectsGlobalScope":true,"impliedFormat":1},{"version":"fa6c12a7c0f6b84d512f200690bfc74819e99efae69e4c95c4cd30f6884c526e","impliedFormat":1},{"version":"f1c32f9ce9c497da4dc215c3bc84b722ea02497d35f9134db3bb40a8d918b92b","impliedFormat":1},{"version":"b73c319af2cc3ef8f6421308a250f328836531ea3761823b4cabbd133047aefa","affectsGlobalScope":true,"impliedFormat":1},{"version":"e433b0337b8106909e7953015e8fa3f2d30797cea27141d1c5b135365bb975a6","impliedFormat":1},{"version":"15b36126e0089bfef173ab61329e8286ce74af5e809d8a72edcafd0cc049057f","impliedFormat":1},{"version":"ddff7fc6edbdc5163a09e22bf8df7bef75f75369ebd7ecea95ba55c4386e2441","impliedFormat":1},{"version":"106c6025f1d99fd468fd8bf6e5bda724e11e5905a4076c5d29790b6c3745e50c","impliedFormat":1},{"version":"a57b1802794433adec9ff3fed12aa79d671faed86c49b09e02e1ac41b4f1d33a","impliedFormat":1},{"version":"ad10d4f0517599cdeca7755b930f148804e3e0e5b5a3847adce0f1f71bbccd74","impliedFormat":1},{"version":"1042064ece5bb47d6aba91648fbe0635c17c600ebdf567588b4ca715602f0a9d","impliedFormat":1},{"version":"c49469a5349b3cc1965710b5b0f98ed6c028686aa8450bcb3796728873eb923e","impliedFormat":1},{"version":"4a889f2c763edb4d55cb624257272ac10d04a1cad2ed2948b10ed4a7fda2a428","impliedFormat":1},{"version":"7bb79aa2fead87d9d56294ef71e056487e848d7b550c9a367523ee5416c44cfa","impliedFormat":1},{"version":"72d63643a657c02d3e51cd99a08b47c9b020a565c55f246907050d3c8a5e77fb","impliedFormat":1},{"version":"1d415445ea58f8033ba199703e55ff7483c52ac6742075b803bd3e7bbe9f5d61","impliedFormat":1},{"version":"d6406c629bb3efc31aedb2de809bef471e475c86c7e67f3ef9b676b5d7e0d6b2","impliedFormat":1},{"version":"27ff4196654e6373c9af16b6165120e2dd2169f9ad6abb5c935af5abd8c7938c","impliedFormat":1},{"version":"71d8ba39a9e024d9e4bb922464d18542ed8d2c25ee78efa7890c27213cc6e5d3","impliedFormat":1},{"version":"8c030e515014c10a2b98f9f48408e3ba18023dfd3f56e3312c6c2f3ae1f55a16","impliedFormat":1},{"version":"dafc31e9e8751f437122eb8582b93d477e002839864410ff782504a12f2a550c","impliedFormat":1},{"version":"754498c5208ce3c5134f6eabd49b25cf5e1a042373515718953581636491f3c3","impliedFormat":1},{"version":"9c82171d836c47486074e4ca8e059735bf97b205e70b196535b5efd40cbe1bc5","impliedFormat":1},{"version":"f56bdc6884648806d34bc66d31cdb787c4718d04105ce2cd88535db214631f82","impliedFormat":1},{"version":"633d58a237f4bb25ec7d565e4ffa32cecdcee8660ac12189c4351c52557cee9e","impliedFormat":1},{"version":"2e4f37ffe8862b14d8e24ae8763daaa8340c0df0b859d9a9733def0eee7562d9","impliedFormat":1},{"version":"13283350547389802aa35d9f2188effaeac805499169a06ef5cd77ce2a0bd63f","impliedFormat":1},{"version":"ce791f6ea807560f08065d1af6014581eeb54a05abd73294777a281b6dfd73c2","impliedFormat":1},{"version":"6ac6715916fa75a1f7ebdfeacac09513b4d904b667d827b7535e84ff59679aff","impliedFormat":1},{"version":"49f95e989b4632c6c2a578cc0078ee19a5831832d79cc59abecf5160ea71abad","impliedFormat":1},{"version":"9666533332f26e8995e4d6fe472bdeec9f15d405693723e6497bf94120c566c8","impliedFormat":1},{"version":"ce0df82a9ae6f914ba08409d4d883983cc08e6d59eb2df02d8e4d68309e7848b","impliedFormat":1},{"version":"796273b2edc72e78a04e86d7c58ae94d370ab93a0ddf40b1aa85a37a1c29ecd7","impliedFormat":1},{"version":"5df15a69187d737d6d8d066e189ae4f97e41f4d53712a46b2710ff9f8563ec9f","impliedFormat":1},{"version":"e17cd049a1448de4944800399daa4a64c5db8657cc9be7ef46be66e2a2cd0e7c","impliedFormat":1},{"version":"43fa6ea8714e18adc312b30450b13562949ba2f205a1972a459180fa54471018","impliedFormat":1},{"version":"6e89c2c177347d90916bad67714d0fb473f7e37fb3ce912f4ed521fe2892cd0d","impliedFormat":1},{"version":"43ba4f2fa8c698f5c304d21a3ef596741e8e85a810b7c1f9b692653791d8d97a","impliedFormat":1},{"version":"4d4927cbee21750904af7acf940c5e3c491b4d5ebc676530211e389dd375607a","impliedFormat":1},{"version":"72105519d0390262cf0abe84cf41c926ade0ff475d35eb21307b2f94de985778","impliedFormat":1},{"version":"8a97e578a9bc40eb4f1b0ca78f476f2e9154ecbbfd5567ee72943bab37fc156a","impliedFormat":1},{"version":"c857e0aae3f5f444abd791ec81206020fbcc1223e187316677e026d1c1d6fe08","impliedFormat":1},{"version":"ccf6dd45b708fb74ba9ed0f2478d4eb9195c9dfef0ff83a6092fa3cf2ff53b4f","impliedFormat":1},{"version":"2d7db1d73456e8c5075387d4240c29a2a900847f9c1bff106a2e490da8fbd457","impliedFormat":1},{"version":"2b15c805f48e4e970f8ec0b1915f22d13ca6212375e8987663e2ef5f0205e832","impliedFormat":1},{"version":"f22d05663d873ee7a600faf78abb67f3f719d32266803440cf11d5db7ac0cab2","impliedFormat":1},{"version":"d93c544ad20197b3976b0716c6d5cd5994e71165985d31dcab6e1f77feb4b8f2","impliedFormat":1},{"version":"35069c2c417bd7443ae7c7cafd1de02f665bf015479fec998985ffbbf500628c","impliedFormat":1},{"version":"a8b1c79a833ee148251e88a2553d02ce1641d71d2921cce28e79678f3d8b96aa","impliedFormat":1},{"version":"126d4f950d2bba0bd45b3a86c76554d4126c16339e257e6d2fabf8b6bf1ce00c","impliedFormat":1},{"version":"7e0b7f91c5ab6e33f511efc640d36e6f933510b11be24f98836a20a2dc914c2d","impliedFormat":1},{"version":"045b752f44bf9bbdcaffd882424ab0e15cb8d11fa94e1448942e338c8ef19fba","impliedFormat":1},{"version":"2894c56cad581928bb37607810af011764a2f511f575d28c9f4af0f2ef02d1ab","impliedFormat":1},{"version":"0a72186f94215d020cb386f7dca81d7495ab6c17066eb07d0f44a5bf33c1b21a","impliedFormat":1},{"version":"2d3cc2211f352f46ea6b7cf2c751c141ffcdf514d6e7ae7ee20b7b6742da313f","impliedFormat":1},{"version":"c75445151ff8b77d9923191efed7203985b1a9e09eccf4b054e7be864e27923d","impliedFormat":1},{"version":"0aedb02516baf3e66b2c1db9fef50666d6ed257edac0f866ea32f1aa05aa474f","impliedFormat":1},{"version":"fa8a8fbf91ee2a4779496225f0312aac6635b0f21aa09cdafa4283fe32d519c5","affectsGlobalScope":true,"impliedFormat":1},{"version":"0e8aef93d79b000deb6ec336b5645c87de167168e184e84521886f9ecc69a4b5","impliedFormat":1},{"version":"56ccb49443bfb72e5952f7012f0de1a8679f9f75fc93a5c1ac0bafb28725fc5f","impliedFormat":1},{"version":"d90b9f1520366d713a73bd30c5a9eb0040d0fb6076aff370796bc776fd705943","impliedFormat":1},{"version":"05321b823dd3781d0b6aac8700bfdc0c9181d56479fe52ba6a40c9196fd661a8","impliedFormat":1},{"version":"736a8712572e21ee73337055ce15edb08142fc0f59cd5410af4466d04beff0f9","affectsGlobalScope":true,"impliedFormat":1},{"version":"bef86adb77316505c6b471da1d9b8c9e428867c2566270e8894d4d773a1c4dc2","impliedFormat":1},{"version":"de7052bfee2981443498239a90c04ea5cc07065d5b9bb61b12cb6c84313ad4ef","impliedFormat":1},{"version":"a3e7d932dc9c09daa99141a8e4800fc6c58c625af0d4bbb017773dc36da75426","impliedFormat":1},{"version":"43e96a3d5d1411ab40ba2f61d6a3192e58177bcf3b133a80ad2a16591611726d","impliedFormat":1},{"version":"4a2edd238d9104eac35b60d727f1123de5062f452b70ed8e0366cb36387dfdfd","impliedFormat":1},{"version":"ca921bf56756cb6fe957f6af693a35251b134fb932dc13f3dfff0bb7106f80b4","impliedFormat":1},{"version":"fee92c97f1aa59eb7098a0cc34ff4df7e6b11bae71526aca84359a2575f313d8","impliedFormat":1},{"version":"0bd0297484aacea217d0b76e55452862da3c5d9e33b24430e0719d1161657225","impliedFormat":1},{"version":"2ab6d334bcbf2aff3acfc4fd8c73ecd82b981d3c3aa47b3f3b89281772286904","impliedFormat":1},{"version":"d07cbc787a997d83f7bde3877fec5fb5b12ce8c1b7047eb792996ed9726b4dde","impliedFormat":1},{"version":"6ac6715916fa75a1f7ebdfeacac09513b4d904b667d827b7535e84ff59679aff","impliedFormat":1},{"version":"4805f6161c2c8cefb8d3b8bd96a080c0fe8dbc9315f6ad2e53238f9a79e528a6","impliedFormat":1},{"version":"b83cb14474fa60c5f3ec660146b97d122f0735627f80d82dd03e8caa39b4388c","impliedFormat":1},{"version":"f374cb24e93e7798c4d9e83ff872fa52d2cdb36306392b840a6ddf46cb925cb6","impliedFormat":1},{"version":"49179c6a23701c642bd99abe30d996919748014848b738d8e85181fc159685ff","impliedFormat":1},{"version":"b73cbf0a72c8800cf8f96a9acfe94f3ad32ca71342a8908b8ae484d61113f647","impliedFormat":1},{"version":"bae6dd176832f6423966647382c0d7ba9e63f8c167522f09a982f086cd4e8b23","impliedFormat":1},{"version":"20865ac316b8893c1a0cc383ccfc1801443fbcc2a7255be166cf90d03fac88c9","impliedFormat":1},{"version":"c9958eb32126a3843deedda8c22fb97024aa5d6dd588b90af2d7f2bfac540f23","impliedFormat":1},{"version":"461d0ad8ae5f2ff981778af912ba71b37a8426a33301daa00f21c6ccb27f8156","impliedFormat":1},{"version":"e927c2c13c4eaf0a7f17e6022eee8519eb29ef42c4c13a31e81a611ab8c95577","impliedFormat":1},{"version":"fcafff163ca5e66d3b87126e756e1b6dfa8c526aa9cd2a2b0a9da837d81bbd72","impliedFormat":1},{"version":"70246ad95ad8a22bdfe806cb5d383a26c0c6e58e7207ab9c431f1cb175aca657","impliedFormat":1},{"version":"f00f3aa5d64ff46e600648b55a79dcd1333458f7a10da2ed594d9f0a44b76d0b","impliedFormat":1},{"version":"772d8d5eb158b6c92412c03228bd9902ccb1457d7a705b8129814a5d1a6308fc","impliedFormat":1},{"version":"45490817629431853543adcb91c0673c25af52a456479588b6486daba34f68bb","impliedFormat":1},{"version":"802e797bcab5663b2c9f63f51bdf67eff7c41bc64c0fd65e6da3e7941359e2f7","impliedFormat":1},{"version":"8b4327413e5af38cd8cb97c59f48c3c866015d5d642f28518e3a891c469f240e","impliedFormat":1},{"version":"8514c62ce38e58457d967e9e73f128eedc1378115f712b9eef7127f7c88f82ae","impliedFormat":1},{"version":"f1289e05358c546a5b664fbb35a27738954ec2cc6eb4137350353099d154fc62","impliedFormat":1},{"version":"4b20fcf10a5413680e39f5666464859fc56b1003e7dfe2405ced82371ebd49b6","impliedFormat":1},{"version":"1d17ba45cfbe77a9c7e0df92f7d95f3eefd49ee23d1104d0548b215be56945ad","impliedFormat":1},{"version":"f7d628893c9fa52ba3ab01bcb5e79191636c4331ee5667ecc6373cbccff8ae12","impliedFormat":1},{"version":"1d879125d1ec570bf04bc1f362fdbe0cb538315c7ac4bcfcdf0c1e9670846aa6","impliedFormat":1},{"version":"a1ee88010a64e8647d07dba58ec43e6e05851b9ec7a62e4ca2b9c33be5abb2c8","impliedFormat":1},{"version":"46273e8c29816125d0d0b56ce9a849cc77f60f9a5ba627447501d214466f0ff3","impliedFormat":1},{"version":"d663134457d8d669ae0df34eabd57028bddc04fc444c4bc04bc5215afc91e1f4","impliedFormat":1},{"version":"e91f7b1344577a02f051b9b471f33044fef8334a76dc9e1de003d17595a5219b","impliedFormat":1},{"version":"3af3584f79c57853028ef9421ec172539e1fe01853296dc05a9d615ade4ffaf6","impliedFormat":1},{"version":"f82579d87701d639ff4e3930a9b24f4ee13ca74221a9a3a792feb47f01881a9c","impliedFormat":1},{"version":"d7e5d5245a8ba34a274717d085174b2c9827722778129b0081fefd341cca8f55","impliedFormat":1},{"version":"d9d32f94056181c31f553b32ce41d0ef75004912e27450738d57efcd2409c324","impliedFormat":1},{"version":"752513f35f6cff294ffe02d6027c41373adf7bfa35e593dbfd53d95c203635ee","impliedFormat":1},{"version":"6c800b281b9e89e69165fd11536195488de3ff53004e55905e6c0059a2d8591e","impliedFormat":1},{"version":"7d4254b4c6c67a29d5e7f65e67d72540480ac2cfb041ca484847f5ae70480b62","impliedFormat":1},{"version":"1a7e2ea171726446850ec72f4d1525d547ff7e86724cc9e7eec509725752a758","impliedFormat":1},{"version":"8c901126d73f09ecdea4785e9a187d1ac4e793e07da308009db04a7283ec2f37","impliedFormat":1},{"version":"db97922b767bd2675fdfa71e08b49c38b7d2c847a1cc4a7274cb77be23b026f1","impliedFormat":1},{"version":"aab290b8e4b7c399f2c09b957666fc95335eb4522b2dd9ead1bf0cb64da6d6ee","impliedFormat":1},{"version":"94fe3281392e1015b22f39535878610b4fa6f1388dc8d78746be3bc4e4bb8950","impliedFormat":1},{"version":"2652448ac55a2010a1f71dd141f828b682298d39728f9871e1cdf8696ef443fd","impliedFormat":1},{"version":"06c25ddfc2242bd06c19f66c9eae4c46d937349a267810f89783680a1d7b5259","impliedFormat":1},{"version":"120599fd965257b1f4d0ff794bc696162832d9d8467224f4665f713a3119078b","impliedFormat":1},{"version":"5433f33b0a20300cca35d2f229a7fc20b0e8477c44be2affeb21cb464af60c76","impliedFormat":1},{"version":"db036c56f79186da50af66511d37d9fe77fa6793381927292d17f81f787bb195","impliedFormat":1},{"version":"bd4131091b773973ca5d2326c60b789ab1f5e02d8843b3587effe6e1ea7c9d86","impliedFormat":1},{"version":"c7f6485931085bf010fbaf46880a9b9ec1a285ad9dc8c695a9e936f5a48f34b4","impliedFormat":1},{"version":"14f6b927888a1112d662877a5966b05ac1bf7ed25d6c84386db4c23c95a5363b","impliedFormat":1},{"version":"6ac6715916fa75a1f7ebdfeacac09513b4d904b667d827b7535e84ff59679aff","impliedFormat":1},{"version":"0427df5c06fafc5fe126d14b9becd24160a288deff40e838bfbd92a35f8d0d00","impliedFormat":1},{"version":"90c54a02432d04e4246c87736e53a6a83084357acfeeba7a489c5422b22f5c7a","impliedFormat":1},{"version":"49c346823ba6d4b12278c12c977fb3a31c06b9ca719015978cb145eb86da1c61","impliedFormat":1},{"version":"bfac6e50eaa7e73bb66b7e052c38fdc8ccfc8dbde2777648642af33cf349f7f1","impliedFormat":1},{"version":"92f7c1a4da7fbfd67a2228d1687d5c2e1faa0ba865a94d3550a3941d7527a45d","impliedFormat":1},{"version":"f53b120213a9289d9a26f5af90c4c686dd71d91487a0aa5451a38366c70dc64b","impliedFormat":1},{"version":"83fe880c090afe485a5c02262c0b7cdd76a299a50c48d9bde02be8e908fb4ae6","impliedFormat":1},{"version":"0a372c2d12a259da78e21b25974d2878502f14d89c6d16b97bd9c5017ab1bc12","impliedFormat":1},{"version":"57d67b72e06059adc5e9454de26bbfe567d412b962a501d263c75c2db430f40e","impliedFormat":1},{"version":"6511e4503cf74c469c60aafd6589e4d14d5eb0a25f9bf043dcbecdf65f261972","impliedFormat":1},{"version":"ec1ca97598eda26b7a5e6c8053623acbd88e43be7c4d29c77ccd57abc4c43999","impliedFormat":1},{"version":"6e2261cd9836b2c25eecb13940d92c024ebed7f8efe23c4b084145cd3a13b8a6","impliedFormat":1},{"version":"a67b87d0281c97dfc1197ef28dfe397fc2c865ccd41f7e32b53f647184cc7307","impliedFormat":1},{"version":"771ffb773f1ddd562492a6b9aaca648192ac3f056f0e1d997678ff97dbb6bf9b","impliedFormat":1},{"version":"232f70c0cf2b432f3a6e56a8dc3417103eb162292a9fd376d51a3a9ea5fbbf6f","impliedFormat":1},{"version":"a47e6d954d22dd9ebb802e7e431b560ed7c581e79fb885e44dc92ed4f60d4c07","impliedFormat":1},{"version":"f019e57d2491c159d47a107fd90219a1734bdd2e25cd8d1db3c8fae5c6b414c4","impliedFormat":1},{"version":"8a0e762ceb20c7e72504feef83d709468a70af4abccb304f32d6b9bac1129b2c","impliedFormat":1},{"version":"d1c9bf292a54312888a77bb19dba5e2503ad803f5393beafd45d78d2f4fe9b48","impliedFormat":1},{"version":"9252d498a77517aab5d8d4b5eb9d71e4b225bbc7123df9713e08181de63180f6","impliedFormat":1},{"version":"cb8d8ef7b9ce8ed3e6f1c814fcbf3f90dab0cb8863079236784fc350746e27c4","impliedFormat":1},{"version":"35e6379c3f7cb27b111ad4c1aa69538fd8e788ab737b8ff7596a1b40e96f4f90","impliedFormat":1},{"version":"1fffe726740f9787f15b532e1dc870af3cd964dbe29e191e76121aa3dd8693f2","impliedFormat":1},{"version":"3be035da7bee86b4c3abf392e0edaa44fc6e45092995eefe36b39118c8a84068","affectsGlobalScope":true,"impliedFormat":1},{"version":"8f828825d077c2fa0ea606649faeb122749273a353daab23924fe674e98ba44c","impliedFormat":1},{"version":"2896c2e673a5d3bd9b4246811f79486a073cbb03950c3d252fba10003c57411a","impliedFormat":1},{"version":"616775f16134fa9d01fc677ad3f76e68c051a056c22ab552c64cc281a9686790","impliedFormat":1},{"version":"65c24a8baa2cca1de069a0ba9fba82a173690f52d7e2d0f1f7542d59d5eb4db0","impliedFormat":1},{"version":"f9fe6af238339a0e5f7563acee3178f51db37f32a2e7c09f85273098cee7ec49","impliedFormat":1},{"version":"407a06ba04eede4074eec470ecba2784cbb3bf4e7de56833b097dd90a2aa0651","impliedFormat":1},{"version":"77e71242e71ebf8528c5802993697878f0533db8f2299b4d36aa015bae08a79c","impliedFormat":1},{"version":"98a787be42bd92f8c2a37d7df5f13e5992da0d967fab794adbb7ee18370f9849","impliedFormat":1},{"version":"5c96bad5f78466785cdad664c056e9e2802d5482ca5f862ed19ba34ffbb7b3a4","impliedFormat":1},{"version":"81d8603ac527e75cfec72bb9391228b58f161c2b33514a9d814c7f3ebd3ef466","impliedFormat":1},{"version":"5f3dc10ae646f375776b4e028d2bed039a93eebbba105694d8b910feebbe8b9c","impliedFormat":1},{"version":"bb0cd7862b72f5eba39909c9889d566e198fcaddf7207c16737d0c2246112678","impliedFormat":1},{"version":"4545c1a1ceca170d5d83452dd7c4994644c35cf676a671412601689d9a62da35","impliedFormat":1},{"version":"320f4091e33548b554d2214ce5fc31c96631b513dffa806e2e3a60766c8c49d9","impliedFormat":1},{"version":"a2d648d333cf67b9aeac5d81a1a379d563a8ffa91ddd61c6179f68de724260ff","impliedFormat":1},{"version":"d90d5f524de38889d1e1dbc2aeef00060d779f8688c02766ddb9ca195e4a713d","impliedFormat":1},{"version":"a3f41ed1b4f2fc3049394b945a68ae4fdefd49fa1739c32f149d32c0545d67f5","impliedFormat":1},{"version":"bad68fd0401eb90fe7da408565c8aee9c7a7021c2577aec92fa1382e8876071a","impliedFormat":1},{"version":"47699512e6d8bebf7be488182427189f999affe3addc1c87c882d36b7f2d0b0e","impliedFormat":1},{"version":"fec01479923e169fb52bd4f668dbeef1d7a7ea6e6d491e15617b46f2cacfa37d","impliedFormat":1},{"version":"8a8fb3097ba52f0ae6530ec6ab34e43e316506eb1d9aa29420a4b1e92a81442d","impliedFormat":1},{"version":"44e09c831fefb6fe59b8e65ad8f68a7ecc0e708d152cfcbe7ba6d6080c31c61e","impliedFormat":1},{"version":"1c0a98de1323051010ce5b958ad47bc1c007f7921973123c999300e2b7b0ecc0","impliedFormat":1},{"version":"4655709c9cb3fd6db2b866cab7c418c40ed9533ce8ea4b66b5f17ec2feea46a9","impliedFormat":1},{"version":"87affad8e2243635d3a191fa72ef896842748d812e973b7510a55c6200b3c2a4","impliedFormat":1},{"version":"ad036a85efcd9e5b4f7dd5c1a7362c8478f9a3b6c3554654ca24a29aa850a9c5","impliedFormat":1},{"version":"fedebeae32c5cdd1a85b4e0504a01996e4a8adf3dfa72876920d3dd6e42978e7","impliedFormat":1},{"version":"3eecb25bb467a948c04874d70452b14ae7edb707660aac17dc053e42f2088b00","impliedFormat":1},{"version":"cdf21eee8007e339b1b9945abf4a7b44930b1d695cc528459e68a3adc39a622e","impliedFormat":1},{"version":"330896c1a2b9693edd617be24fbf9e5895d6e18c7955d6c08f028f272b37314d","impliedFormat":1},{"version":"1d9c0a9a6df4e8f29dc84c25c5aa0bb1da5456ebede7a03e03df08bb8b27bae6","impliedFormat":1},{"version":"84380af21da938a567c65ef95aefb5354f676368ee1a1cbb4cae81604a4c7d17","impliedFormat":1},{"version":"1af3e1f2a5d1332e136f8b0b95c0e6c0a02aaabd5092b36b64f3042a03debf28","impliedFormat":1},{"version":"30d8da250766efa99490fc02801047c2c6d72dd0da1bba6581c7e80d1d8842a4","impliedFormat":1},{"version":"03566202f5553bd2d9de22dfab0c61aa163cabb64f0223c08431fb3fc8f70280","impliedFormat":1},{"version":"5f0292a40df210ab94b9fb44c8b775c51e96777e14e073900e392b295ca1061b","impliedFormat":1},{"version":"bc9ee0192f056b3d5527bcd78dc3f9e527a9ba2bdc0a2c296fbc9027147df4b2","impliedFormat":1},{"version":"8627ad129bcf56e82adff0ab5951627c993937aa99f5949c33240d690088b803","impliedFormat":1},{"version":"1de80059b8078ea5749941c9f863aa970b4735bdbb003be4925c853a8b6b4450","impliedFormat":1},{"version":"1d079c37fa53e3c21ed3fa214a27507bda9991f2a41458705b19ed8c2b61173d","impliedFormat":1},{"version":"5bf5c7a44e779790d1eb54c234b668b15e34affa95e78eada73e5757f61ed76a","impliedFormat":1},{"version":"5835a6e0d7cd2738e56b671af0e561e7c1b4fb77751383672f4b009f4e161d70","impliedFormat":1},{"version":"5c634644d45a1b6bc7b05e71e05e52ec04f3d73d9ac85d5927f647a5f965181a","impliedFormat":1},{"version":"4b7f74b772140395e7af67c4841be1ab867c11b3b82a51b1aeb692822b76c872","impliedFormat":1},{"version":"27be6622e2922a1b412eb057faa854831b95db9db5035c3f6d4b677b902ab3b7","impliedFormat":1},{"version":"a68d4b3182e8d776cdede7ac9630c209a7bfbb59191f99a52479151816ef9f9e","impliedFormat":99},{"version":"39644b343e4e3d748344af8182111e3bbc594930fff0170256567e13bbdbebb0","impliedFormat":99},{"version":"ed7fd5160b47b0de3b1571c5c5578e8e7e3314e33ae0b8ea85a895774ee64749","impliedFormat":99},{"version":"63a7595a5015e65262557f883463f934904959da563b4f788306f699411e9bac","impliedFormat":1},{"version":"ecbaf0da125974be39c0aac869e403f72f033a4e7fd0d8cd821a8349b4159628","impliedFormat":1},{"version":"4ba137d6553965703b6b55fd2000b4e07ba365f8caeb0359162ad7247f9707a6","impliedFormat":1},{"version":"ceec3c81b2d81f5e3b855d9367c1d4c664ab5046dff8fd56552df015b7ccbe8f","affectsGlobalScope":true,"impliedFormat":1},{"version":"8fac4a15690b27612d8474fb2fc7cc00388df52d169791b78d1a3645d60b4c8b","affectsGlobalScope":true,"impliedFormat":1},{"version":"064ac1c2ac4b2867c2ceaa74bbdce0cb6a4c16e7c31a6497097159c18f74aa7c","impliedFormat":1},{"version":"3dc14e1ab45e497e5d5e4295271d54ff689aeae00b4277979fdd10fa563540ae","impliedFormat":1},{"version":"1d63055b690a582006435ddd3aa9c03aac16a696fac77ce2ed808f3e5a06efab","impliedFormat":1},{"version":"b789bf89eb19c777ed1e956dbad0925ca795701552d22e68fd130a032008b9f9","impliedFormat":1},"85ae5aee75f011967cf2d25cbc342f62d69314e9d925f7f4aa3456fc2cffcca6",{"version":"496898063c834c666510bdb5bb472bcf08e01ca8eef297da101ad12680c8fc93","signature":"435a1e418e8338be3f39614b96b81a9aa2700bc8c27bc6b98f064ff9ce17c363"},{"version":"402e5c534fb2b85fa771170595db3ac0dd532112c8fa44fc23f233bc6967488b","impliedFormat":1},{"version":"7965dc3c7648e2a7a586d11781cabb43d4859920716bc2fdc523da912b06570d","impliedFormat":1},{"version":"90c2bd9a3e72fe08b8fa5982e78cb8dc855a1157b26e11e37a793283c52bf64b","impliedFormat":1},{"version":"a8122fe390a2a987079e06c573b1471296114677923c1c094c24a53ddd7344a2","impliedFormat":1},{"version":"70c2cb19c0c42061a39351156653aa0cf5ba1ecdc8a07424dd38e3a1f1e3c7f4","impliedFormat":1},{"version":"a8fb10fd8c7bc7d9b8f546d4d186d1027f8a9002a639bec689b5000dab68e35c","impliedFormat":1},{"version":"c9b467ea59b86bd27714a879b9ad43c16f186012a26d0f7110b1322025ceaa83","impliedFormat":1},{"version":"57ea19c2e6ba094d8087c721bac30ff1c681081dbd8b167ac068590ef633e7a5","impliedFormat":1},{"version":"cba81ec9ae7bc31a4dc56f33c054131e037649d6b9a2cfa245124c67e23e4721","impliedFormat":1},{"version":"ad193f61ba708e01218496f093c23626aa3808c296844a99189be7108a9c8343","impliedFormat":1},{"version":"a0544b3c8b70b2f319a99ea380b55ab5394ede9188cdee452a5d0ce264f258b2","impliedFormat":1},{"version":"8c654c17c334c7c168c1c36e5336896dc2c892de940886c1639bebd9fc7b9be4","impliedFormat":1},{"version":"6a4da742485d5c2eb6bcb322ae96993999ffecbd5660b0219a5f5678d8225bb0","impliedFormat":1},{"version":"c65ca21d7002bdb431f9ab3c7a6e765a489aa5196e7e0ef00aed55b1294df599","impliedFormat":1},{"version":"c8fc655c2c4bafc155ceee01c84ab3d6c03192ced5d3f2de82e20f3d1bd7f9fa","impliedFormat":1},{"version":"be5a7ff3b47f7e553565e9483bdcadb0ca2040ac9e5ec7b81c7e115a81059882","impliedFormat":1},{"version":"1a93f36ecdb60a95e3a3621b561763e2952da81962fae217ab5441ac1d77ffc5","impliedFormat":1},{"version":"2a771d907aebf9391ac1f50e4ad37952943515eeea0dcc7e78aa08f508294668","impliedFormat":1},{"version":"0146fd6262c3fd3da51cb0254bb6b9a4e42931eb2f56329edd4c199cb9aaf804","impliedFormat":1},{"version":"183f480885db5caa5a8acb833c2be04f98056bdcc5fb29e969ff86e07efe57ab","impliedFormat":99},{"version":"b558c9a18ea4e6e4157124465c3ef1063e64640da139e67be5edb22f534f2f08","impliedFormat":1},{"version":"01374379f82be05d25c08d2f30779fa4a4c41895a18b93b33f14aeef51768692","impliedFormat":1},{"version":"b0dee183d4e65cf938242efaf3d833c6b645afb35039d058496965014f158141","impliedFormat":1},{"version":"c0bbbf84d3fbd85dd60d040c81e8964cc00e38124a52e9c5dcdedf45fea3f213","impliedFormat":1},{"version":"1dacb6ae2c0d095c0c085032f1f918cbb29f27f1f433c0374935347a0d99bb5b","impliedFormat":1},{"version":"dabb467c756ac5fa436cdbc46878550c83127d05a6faa22e739f28e48c14519d","signature":"f65ce75c9085571e6321abf2bf9833709f4897e381f89e9925521833dbb7ab16"},{"version":"04471dc55f802c29791cc75edda8c4dd2a121f71c2401059da61eff83099e8ab","impliedFormat":99},{"version":"5c54a34e3d91727f7ae840bfe4d5d1c9a2f93c54cb7b6063d06ee4a6c3322656","impliedFormat":99},{"version":"db4da53b03596668cf6cc9484834e5de3833b9e7e64620cf08399fe069cd398d","impliedFormat":99},{"version":"ac7c28f153820c10850457994db1462d8c8e462f253b828ad942a979f726f2f9","impliedFormat":99},{"version":"f9b028d3c3891dd817e24d53102132b8f696269309605e6ed4f0db2c113bbd82","impliedFormat":99},{"version":"fb7c8d90e52e2884509166f96f3d591020c7b7977ab473b746954b0c8d100960","impliedFormat":99},{"version":"0bff51d6ed0c9093f6955b9d8258ce152ddb273359d50a897d8baabcb34de2c4","impliedFormat":99},{"version":"ef13c73d6157a32933c612d476c1524dd674cf5b9a88571d7d6a0d147544d529","impliedFormat":99},{"version":"13918e2b81c4288695f9b1f3dcc2468caf0f848d5c1f3dc00071c619d34ff63a","impliedFormat":99},{"version":"120a80aa556732f684db3ed61aeff1d6671e1655bd6cba0aa88b22b88ac9a6b1","affectsGlobalScope":true,"impliedFormat":99},{"version":"a7ca8df4f2931bef2aa4118078584d84a0b16539598eaadf7dce9104dfaa381c","impliedFormat":1},{"version":"10073cdcf56982064c5337787cc59b79586131e1b28c106ede5bff362f912b70","impliedFormat":99},{"version":"72950913f4900b680f44d8cab6dd1ea0311698fc1eefb014eb9cdfc37ac4a734","impliedFormat":1},{"version":"151ff381ef9ff8da2da9b9663ebf657eac35c4c9a19183420c05728f31a6761d","impliedFormat":1},{"version":"ee70b8037ecdf0de6c04f35277f253663a536d7e38f1539d270e4e916d225a3f","affectsGlobalScope":true,"impliedFormat":1},{"version":"a660aa95476042d3fdcc1343cf6bb8fdf24772d31712b1db321c5a4dcc325434","impliedFormat":1},{"version":"36977c14a7f7bfc8c0426ae4343875689949fb699f3f84ecbe5b300ebf9a2c55","impliedFormat":1},{"version":"ff0a83c9a0489a627e264ffcb63f2264b935b20a502afa3a018848139e3d8575","impliedFormat":99},{"version":"161c8e0690c46021506e32fda85956d785b70f309ae97011fd27374c065cac9b","affectsGlobalScope":true,"impliedFormat":1},{"version":"f582b0fcbf1eea9b318ab92fb89ea9ab2ebb84f9b60af89328a91155e1afce72","impliedFormat":1},{"version":"960bd764c62ac43edc24eaa2af958a4b4f1fa5d27df5237e176d0143b36a39c6","affectsGlobalScope":true,"impliedFormat":1},{"version":"4ec16d7a4e366c06a4573d299e15fe6207fc080f41beac5da06f4af33ea9761e","impliedFormat":1},{"version":"59f8dc89b9e724a6a667f52cdf4b90b6816ae6c9842ce176d38fcc973669009e","affectsGlobalScope":true,"impliedFormat":1},{"version":"e4af494f7a14b226bbe732e9c130d8811f8c7025911d7c58dd97121a85519715","impliedFormat":1},{"version":"47416e41b1af81e53e8c3cc5bf909d47ff632a7b6eddfe7ff43d187b4dcca047","impliedFormat":99},{"version":"45cec9a1ba6549060552eead8959d47226048e0b71c7d0702ae58b7e16a28912","impliedFormat":99},{"version":"6907b09850f86610e7a528348c15484c1e1c09a18a9c1e98861399dfe4b18b46","impliedFormat":99},{"version":"12deea8eaa7a4fc1a2908e67da99831e5c5a6b46ad4f4f948fd4759314ea2b80","impliedFormat":99},{"version":"f0a8b376568a18f9a4976ecb0855187672b16b96c4df1c183a7e52dc1b5d98e8","impliedFormat":99},{"version":"8124828a11be7db984fcdab052fd4ff756b18edcfa8d71118b55388176210923","impliedFormat":99},{"version":"092944a8c05f9b96579161e88c6f211d5304a76bd2c47f8d4c30053269146bc8","impliedFormat":99},{"version":"b34b5f6b506abb206b1ea73c6a332b9ee9c8c98be0f6d17cdbda9430ecc1efab","impliedFormat":99},{"version":"75d4c746c3d16af0df61e7b0afe9606475a23335d9f34fcc525d388c21e9058b","impliedFormat":99},{"version":"fa959bf357232201c32566f45d97e70538c75a093c940af594865d12f31d4912","impliedFormat":99},{"version":"d2c52abd76259fc39a30dfae70a2e5ce77fd23144457a7ff1b64b03de6e3aec7","impliedFormat":99},{"version":"e6233e1c976265e85aa8ad76c3881febe6264cb06ae3136f0257e1eab4a6cc5a","impliedFormat":99},{"version":"f73e2335e568014e279927321770da6fe26facd4ac96cdc22a56687f1ecbb58e","impliedFormat":99},{"version":"317878f156f976d487e21fd1d58ad0461ee0a09185d5b0a43eedf2a56eb7e4ea","impliedFormat":99},{"version":"324ac98294dab54fbd580c7d0e707d94506d7b2c3d5efe981a8495f02cf9ad96","impliedFormat":99},{"version":"9ec72eb493ff209b470467e24264116b6a8616484bca438091433a545dfba17e","impliedFormat":99},{"version":"d6ee22aba183d5fc0c7b8617f77ee82ecadc2c14359cc51271c135e23f6ed51f","impliedFormat":99},{"version":"49747416f08b3ba50500a215e7a55d75268b84e31e896a40313c8053e8dec908","impliedFormat":99},{"version":"81e634f1c5e1ca309e7e3dc69e2732eea932ef07b8b34517d452e5a3e9a36fa3","impliedFormat":99},{"version":"34f39f75f2b5aa9c84a9f8157abbf8322e6831430e402badeaf58dd284f9b9a6","impliedFormat":99},{"version":"427fe2004642504828c1476d0af4270e6ad4db6de78c0b5da3e4c5ca95052a99","impliedFormat":1},{"version":"2eeffcee5c1661ddca53353929558037b8cf305ffb86a803512982f99bcab50d","impliedFormat":99},{"version":"9afb4cb864d297e4092a79ee2871b5d3143ea14153f62ef0bb04ede25f432030","affectsGlobalScope":true,"impliedFormat":99},{"version":"891694d3694abd66f0b8872997b85fd8e52bc51632ce0f8128c96962b443189f","impliedFormat":99},{"version":"69bf2422313487956e4dacf049f30cb91b34968912058d244cb19e4baa24da97","impliedFormat":99},{"version":"971a2c327ff166c770c5fb35699575ba2d13bba1f6d2757309c9be4b30036c8e","impliedFormat":99},{"version":"4f45e8effab83434a78d17123b01124259fbd1e335732135c213955d85222234","impliedFormat":99},{"version":"7bd51996fb7717941cbe094b05adc0d80b9503b350a77b789bbb0fc786f28053","impliedFormat":99},{"version":"b62006bbc815fe8190c7aee262aad6bff993e3f9ade70d7057dfceab6de79d2f","impliedFormat":99},{"version":"13497c0d73306e27f70634c424cd2f3b472187164f36140b504b3756b0ff476d","impliedFormat":99},{"version":"a23a08b626aa4d4a1924957bd8c4d38a7ffc032e21407bbd2c97413e1d8c3dbd","impliedFormat":99},{"version":"c320fe76361c53cad266b46986aac4e68d644acda1629f64be29c95534463d28","impliedFormat":99},{"version":"7bbff6783e96c691a41a7cf12dd5486b8166a01b0c57d071dbcfca55c9525ec4","impliedFormat":99},{"version":"3aca5b7f6e76a762ed7ee9596a6dd9e0678a9908b055b4c44a0555096fc1ed9e","signature":"4b96dd19fd2949d28ce80e913412b0026dc421e5bf6c31d87c7b5eb11b5753b4"},{"version":"7bb9b7b5c580ebde3f2839818dc5f49053a4bc693088af3a30c6ca1b69042bfb","signature":"0a996bc5648f30c52e845d7da69010a87f8fb57987d8e9c943b58d8013286049"},{"version":"3e0600317b706f47f709979812e601b97c7b12d64079c36f3575772ffe4fe2f8","signature":"a43d90a5c8e7a34db9b75dfe22cb4bd54ca43c51b2f24dbe6c67f28501cf1c58"},{"version":"3cbe6707a9e935f5b798d42bfb5dfa8af06707ad9a145691f66f48448cfcb383","signature":"645c81e86b6da1969b258ea73b11aeaf1d1cb9ec3faff28014de22a4357690cf"},{"version":"98d1be0fc23bc9882bdee4f8f323183115322b4ecb6a1ebafc689ea3205acc59","signature":"d336d46c96f79d17be4b81f7fac76937f18964b282c05256640e98bfd973c830"},{"version":"7749949e4261420989f255c30de9454b9c8f944a3dadff68d7eca91c233d2c9b","signature":"13b1a2180942a338fa3899781c2861493613b5b374803e17fa935c784b49a4a9"},{"version":"f3f0696393d4bb80e22fba11c1a7d447b18baa1f7d0f4d2e2af5a902faf3f9d8","signature":"73d048af9f177612fb2e7f59a6623a14e9608311059928af1d5c10139d4576bc"},{"version":"74946ef6928945934a528cec504cc4ee73665c9c18707a877122a5256fc896f5","signature":"e35db0faf36c8c332f6429ed35934faea6a0a25249c2b86e1e0217ce346cbd12"},{"version":"d3cfde44f8089768ebb08098c96d01ca260b88bccf238d55eee93f1c620ff5a5","impliedFormat":1},{"version":"293eadad9dead44c6fd1db6de552663c33f215c55a1bfa2802a1bceed88ff0ec","impliedFormat":1},{"version":"833e92c058d033cde3f29a6c7603f517001d1ddd8020bc94d2067a3bc69b2a8e","impliedFormat":1},{"version":"08b2fae7b0f553ad9f79faec864b179fc58bc172e295a70943e8585dd85f600c","impliedFormat":1},{"version":"f12edf1672a94c578eca32216839604f1e1c16b40a1896198deabf99c882b340","impliedFormat":1},{"version":"e3498cf5e428e6c6b9e97bd88736f26d6cf147dedbfa5a8ad3ed8e05e059af8a","impliedFormat":1},{"version":"dba3f34531fd9b1b6e072928b6f885aa4d28dd6789cbd0e93563d43f4b62da53","impliedFormat":1},{"version":"f672c876c1a04a223cf2023b3d91e8a52bb1544c576b81bf64a8fec82be9969c","impliedFormat":1},{"version":"e4b03ddcf8563b1c0aee782a185286ed85a255ce8a30df8453aade2188bbc904","impliedFormat":1},{"version":"2329d90062487e1eaca87b5e06abcbbeeecf80a82f65f949fd332cfcf824b87b","impliedFormat":1},{"version":"25b3f581e12ede11e5739f57a86e8668fbc0124f6649506def306cad2c59d262","impliedFormat":1},{"version":"4fdb529707247a1a917a4626bfb6a293d52cd8ee57ccf03830ec91d39d606d6d","impliedFormat":1},{"version":"a9ebb67d6bbead6044b43714b50dcb77b8f7541ffe803046fdec1714c1eba206","impliedFormat":1},{"version":"5780b706cece027f0d4444fbb4e1af62dc51e19da7c3d3719f67b22b033859b9","impliedFormat":1},{"version":"cb1f8036f8f9c69cd27d53813b9adaa23b57cdc536c4089a8a0854c575cdd0b1","impliedFormat":1},{"version":"dfe290c5346b0014184b26f6a2150929727138c7da0f41922418f22a6f05c020","impliedFormat":1},{"version":"85c7009d9d3253ab5f36f4d62309136fa74d87f9097cbcf7885db7d286364b16","impliedFormat":1},{"version":"3db4bf7c73ec7f427c255b25dc2482c61943e2c29e1fb9e77d61b4ef1528ba52","impliedFormat":1},{"version":"304c574c4c392ec7cc96c4d800a853e705daa2062a4b24f7fc0795c1371eba39","impliedFormat":1},{"version":"0711cd64e19e00917238c4996c97ba0f69380135cdebdec69d27fbe71419826d","impliedFormat":1},{"version":"e165bf9cb5815b38a14cb5dbbff3f83b48b207b46cc7f448896bfc69b2dbe6a1","impliedFormat":1},{"version":"85bada258ba9e8ab7a28fb31c1387b5d6f36aacede9197a9224c7ac4d0c7afc4","impliedFormat":1},{"version":"4eb0ed5e5864eb77abb73452e6e2c8b584825afa75d72dda4a9996f3f8d160cb","impliedFormat":1},{"version":"5f35327c612000cef210e8066e8a081258adcf5b5ea5a20395b2a575c081104b","impliedFormat":1},{"version":"8f25dc8cea6689735bfb730f446fb62592150a32f3a75fce4b2c23237e057fc9","impliedFormat":1},{"version":"26cec5bfef392a4c36c1995bc96abbe0ca3e02577bf7c23638326e1deb694d83","impliedFormat":1},{"version":"73043405ac8b8a85412e24223525cf8542b72e1b7201bbcb7a9bb87e4699c109","impliedFormat":1},{"version":"76a9454e36c6dcbe0cb45fa47df11294474e4f56ae57fc5b1ea66031392e5021","impliedFormat":1},{"version":"ed4959e66a9254e26976fc8ae88e458b0b05ae16841f2c57adf3e19e686a0d6a","impliedFormat":1},{"version":"a789d89d816ef995ed356886b1388a09543e4a801adb311e75c755b5338dc3e6","impliedFormat":1},{"version":"7ed4d5512e1a7c276aa547ebaccba714d9984ec1669b5130a039753058275881","impliedFormat":1},{"version":"fcef4bd9130dc41bcc30da1779f3ebd62cd6f90b31318b73c7e3d25a8c33b9c4","impliedFormat":1},{"version":"b593f3100ecf48e39d8f1a2fc49373c56c8e6ac312af4594020c96f650769836","impliedFormat":1},{"version":"9527492b74946dac2d980a584bf7061dad2d48a0e8ac21c62444ffc94388d984","impliedFormat":1},{"version":"d7eb49400d3852943d03d34caaed4c670ba35aaa309c9c20b8a0db48dd77d3c4","impliedFormat":1},{"version":"3ccffc1aa34b00b09df345cbb494ba545aec52aab5741fc863e174cb8b2285cc","impliedFormat":1},{"version":"ec4acd6c65b2f3466cdaeacd5d630e1bfb558066499720dd0828fe0e73799683","impliedFormat":1},{"version":"eee31fee7d4112a523b6ed43967b1d458a1d3c3ad22607eb6bbb3f6e6a4bebf5","impliedFormat":1},{"version":"958266dfbad20d8a14a9c12a53d8d4640de211f3b287fb543839a50d95b0e9e3","impliedFormat":1},{"version":"72b62e78c48f06790526fb910199291450f355031d12b5a91233eaf0295e418e","impliedFormat":1},{"version":"33a3038cb23270db88281ff2ada83b26acc68f6e5984d66934bef19554347f1f","impliedFormat":1},{"version":"74720f66db4cc64aa195dd49d0439b9d5a339e558ae02d24bd0d39db0bbccfaf","impliedFormat":1},{"version":"2d5004701e2a8fc6d827dab5223481f68da96ec4732fe32e7e918c01a8a7a61a","impliedFormat":1},{"version":"0934b6143a95cd1c43feda2fa2c8c17379ec6f4dc3e3e9e5fd561d76cec17739","impliedFormat":1},{"version":"cfdafb61973717bee7c31a4c8eed91af04c476b4167be1340103a79dd0532de1","impliedFormat":1},{"version":"cfd663d0b2006e5795fa3b1952653dc5f5d323fc0149a9c38cda3201e1a61b73","impliedFormat":1},{"version":"9e622274dae946c2702eea53bf9018eccd2a51cb11947cfd9e81ef3bda017eb3","impliedFormat":1},{"version":"002108b90ff7e9e87a9aacec121b058cd9abb892ee54a799b6c8317ef8bfd72b","impliedFormat":1},{"version":"b8f48caba09cfffaeab5e762b0e731c47e529d9f19ab64eb3dd46fa389e16406","impliedFormat":1},{"version":"32a82ad869e2b34ed784f6f7e6f630eb6bfcbcf202e6afd7db92748001907411","impliedFormat":1},{"version":"0a48ca6a980592f75892a113d541052da384c39038a0896565f2ee3dd38e0ceb","impliedFormat":1},{"version":"85b36a92544cc714725c43fe08e7da5e39dba751a9f80aa2d8ce6d8b667615e0","impliedFormat":1},{"version":"5754a019a1c1d6675966dc9f3736f3a1e646676ea262579fcc9dc676b4c269e0","impliedFormat":1},{"version":"ec4acd6c65b2f3466cdaeacd5d630e1bfb558066499720dd0828fe0e73799683","impliedFormat":1},{"version":"f227ccf65cd58641e192d41861ba64b310a981e9bfaeea22c08eff201300f6f3","impliedFormat":1},{"version":"b46f91ec07ec2882258d985037d4b45cede03326de6e1a57935cfef9e58a0c1e","impliedFormat":1},{"version":"4d828dd54c61e3436a3f0733f1c4d119828bf420740de7deacfe605519c3fe59","impliedFormat":1},{"version":"33a3038cb23270db88281ff2ada83b26acc68f6e5984d66934bef19554347f1f","impliedFormat":1},{"version":"9571c4af5c4e96120b86db94167847d583def98675ce1134faaf2a65de98ae94","impliedFormat":1},{"version":"427e9515091a96a82217de1dcb2b5fa0ff09cacf7c1359fae28050903fcfe1f8","affectsGlobalScope":true,"impliedFormat":1},{"version":"cfdafb61973717bee7c31a4c8eed91af04c476b4167be1340103a79dd0532de1","impliedFormat":1},{"version":"74720f66db4cc64aa195dd49d0439b9d5a339e558ae02d24bd0d39db0bbccfaf","impliedFormat":1},{"version":"cfd663d0b2006e5795fa3b1952653dc5f5d323fc0149a9c38cda3201e1a61b73","impliedFormat":1},{"version":"9e622274dae946c2702eea53bf9018eccd2a51cb11947cfd9e81ef3bda017eb3","impliedFormat":1},{"version":"002108b90ff7e9e87a9aacec121b058cd9abb892ee54a799b6c8317ef8bfd72b","impliedFormat":1},{"version":"0b6e86f4022fd9587b9987d5753aa2acdb05dd96b40576cc1db0734b2683a33d","impliedFormat":1},{"version":"dfe290c5346b0014184b26f6a2150929727138c7da0f41922418f22a6f05c020","impliedFormat":1},{"version":"2ecf1fb584b8762acab872e26630c3588587ee8cb3761638d4e8f96726a1b9be","impliedFormat":1},{"version":"84695653be49f0ee6685ad56fd3025f6f2935f834cc736b6ebe18f4ba35c2036","impliedFormat":1},{"version":"5754a019a1c1d6675966dc9f3736f3a1e646676ea262579fcc9dc676b4c269e0","impliedFormat":1},{"version":"13e8a533b3f6fa9a49bb77daef2cdfd4e8ab78887b68210ed0d4357c5cb7260e","impliedFormat":1},{"version":"436a4e249d1e2e7b5b599de2f13088c5b2a181e2e7a69b3fb83bbb3fe4c58c0f","impliedFormat":1},{"version":"6733f45a5cf9c190bf55c36a71eb7226258c32c422fdbd9bdcf712d60f29f914","impliedFormat":1},{"version":"f384f32f37497419f864977504318a703ff9974d7484e1e00f15a7c27ded4beb","impliedFormat":1},{"version":"3b79dcddcd327a1adf18eedbd1e71975e5526482207640afdcecb82631713df1","impliedFormat":1},{"version":"cbd591f32d67e0168030d8ac63fe9f5305e3b12dc66eff11388b017799e3fdcc","impliedFormat":1},{"version":"e00793ecb619340557aacc35f3f2810434bf55a070a8ee2548bfe7e58cd691d8","impliedFormat":1},{"version":"c380eccd51906944bccb84d9339172351d7d3032cc6109e8f2cd7b49f6a4074f","impliedFormat":1},{"version":"e0f6a5c6df80ac903fcbf81d8e2031509d99f84da6a02cc0c3f07a2e2f0bb69d","impliedFormat":1},{"version":"7b67e92e550658a3400740cd2c6c0694f425d4b38670784f1dad742a58aad5fe","impliedFormat":1},{"version":"69922c21d6e04d08496a75cfe979d1b42e5c4dada2dc1fabe7d3d85dc5c9be9b","impliedFormat":1},{"version":"b297245ccf3ec72e4b413e21ec6720d03ded5f5d208883592161d584fda3b1bd","impliedFormat":1},{"version":"976245df09b78e9f693eeaadcc6f24ec9837ee1fe61dc2124bbfd3d61e988d1b","impliedFormat":1},{"version":"4d12a68269f94c046f5865ac57369536ed2ebde3ab27545e82b728463dad3bf4","impliedFormat":1},{"version":"5bfbec6f4a9e5c3dbbeceaee7e9ab62d792b86bbba4098b7617ac04ad922088c","impliedFormat":1},{"version":"1e09d3ba318b6b09b888d96a43c57fee2fbf886eeeff0aad41e8f4386741c4d8","impliedFormat":1},{"version":"3bc93d58fd6910e6efb7db1d77f98f6c99e85576c920b5de973cc034a9f76728","impliedFormat":1},{"version":"8a1ec29f23543d9ddaaa883ada4325a418ed92bf09efc5f02771c51cbae253ae","impliedFormat":1},{"version":"df0e194edb86a119b1f021f9d5ee07fa689b2ebe703f2f29aaf436d3d3546e21","impliedFormat":1},{"version":"15c445f430445ebf6bfbc107ddbd94c5a1f6a1f07a3e03804478311358c9a6bc","impliedFormat":1},{"version":"0e2b2d160948defe907e86c937c6cc72593e2860183efebfb468942acaf4489e","impliedFormat":1},{"version":"8fc1ddf85214631bd866863970b8461ce0a176082862195cc46719f690fe1e43","impliedFormat":1},{"version":"0f70fe3235108c8fe062e36f9926e7683e3f9e46072d0940ace9a18e63a39479","impliedFormat":1},{"version":"36a8c33d093e1bc26ef5e87574b2a42d663a784355e0b9e1e94097847982d59a","impliedFormat":1},{"version":"60de2aba74b5b3f4293675e513f2c718c4cd074d77682e3b34f5233280497ef8","impliedFormat":1},{"version":"4eb134c8bd84bdfca82f233e659890b7dc9d1c471dae2ede990ffd1811e7f402","impliedFormat":1},{"version":"ae3e6bdeb49784a5a4af737bd6192035d02daf9cb4d21346ec572c2e5e180ff4","impliedFormat":1},{"version":"2eb2c6e8c9530e6807316bc0b863b7228c5e9ed3f69d9257c99185146499f0e2","impliedFormat":1},{"version":"d9c326e2b89124e3444439c75d0ac329b775ba89eba2486000780537b38430fb","impliedFormat":1},{"version":"48abb94feb786107ae4e934c60f3953230033f8d0dd5879245f2f7834f08a648","impliedFormat":1},{"version":"9682f9ab43c4b22a42960d6fb30d83876678cfa2b6f989478531488b5fbf5e8f","impliedFormat":1},{"version":"b813061d28e68084d190f0fda9509a64d156473db3ab696e5b28de0f05af7205","impliedFormat":1},{"version":"c9eef8879eac553d9482a84d60f183aca06dda7450dd1a776f5bc26dff38d636","impliedFormat":1},{"version":"b975867b8f5e0dbb461e4d29340561df8238fe42aa3132403086c1066d97f09f","impliedFormat":1},{"version":"75b4ff3600baa5111e336bf63bf1ce5ed1f6a3261e880de04d99abbe2b0550d8","impliedFormat":1},{"version":"7d8d645a484a708b37ca2dc8b192bc5a687a2bb3da7fe300c7f31cd80be591b4","impliedFormat":1},{"version":"d68165735d6bfc43cdc59e2acc0a3b0873b34525d71b1c266c7c6fba237926af","impliedFormat":1},{"version":"d22fad3dbd720f40e76e466d2df066005e11aeff2d1afd31e6de7a4385905eaf","impliedFormat":1},{"version":"219a5ba6fce5cd56ded80cd38a9061a8284a22400f80cdb7e78128f44e1e82ae","impliedFormat":1},{"version":"4eb343113cace665dea18eb3902f10785d2b95b3fe27c4b17833733c8c5766a9","impliedFormat":1},{"version":"0459512bf4737c1c50d71ff66370a0613fe58c42888ebd70ea5cb0df2b55e16a","impliedFormat":1},{"version":"14f588f95f40f3bedeb7a40b47e0cbe8d2326e3a88647766872403ed9c9809de","impliedFormat":1},{"version":"1848ed70143118527b8d9f44c42ad3af6304cb6e1cfcb3b0f7e4b2f1abfeb66e","impliedFormat":1},{"version":"ffbd00f89064a9963f9c790b9828c74caffc37c817f27954e3f58ccdcbf6b4ee","impliedFormat":1},{"version":"f50495adbdad305534adc331c1616d60fae4862a491433b02f60688399387193","impliedFormat":1},{"version":"3b385547db42cce98dcabd9dc9c6fe23c580807ae8d250fcb5789e505a988dda","impliedFormat":1},{"version":"0618d4380d763a72a1dba237b163c6cf2e087e3b845b2ad83700affccbb80082","impliedFormat":1},{"version":"08d9d00a2a86597cab6dd27fe19ab0ceea6010a86c74f806b00857242ddd047c","impliedFormat":1},{"version":"1ed02e88ae4a0022b5b2abde292fc349bca71815248a607d00f3d1960500544f","impliedFormat":1},{"version":"3d0874bcc16917437655ecb436f3d44920baf428b914aa456617454294f9ffc3","impliedFormat":1},{"version":"b478a4e6bd2d39ded7cbe64dcacbf999734828267c67490c167271dd32af3b23","impliedFormat":1},{"version":"d9c326e2b89124e3444439c75d0ac329b775ba89eba2486000780537b38430fb","impliedFormat":1},{"version":"250c5905bf19aefd93d4172b2d0ca4f9dd5e00d1ce6b4b2e4ccefe21ff728c86","impliedFormat":1},{"version":"6ddf24f9ecaac66bff4cedcb7d03865f340e75598400d265b00e29f0c6406b80","impliedFormat":1},{"version":"5330f4f848654078d37780010652b49115d9f89896a3401703ea3cf0baa8cf04","impliedFormat":1},{"version":"ef1364efe7d2d72b53e021336a601beb05b4050181354d58be8fa023d4dd20a7","impliedFormat":1},{"version":"609d234ca974cd849d39b6e3f52e3eecb879142a6ef0f2bc9f4ce97e81452d11","impliedFormat":1},{"version":"5af232c60b98d7fcc0e1025cb18f7b8037fe3eae1c8a372269e0f1b99c9fef4a","impliedFormat":1},{"version":"2caee401eb12d2302cd30ca71484fd49179a570863f31ae95acc35b76ec6bfbd","impliedFormat":1},{"version":"e02922a03c6b317ffee8c7bacd9290e094371ff76a7728c53785a55c37b55f69","impliedFormat":1},{"version":"2a7043737e1d8d80ecd74d646fb4446d149ccad99b8625f01f1e32e81b594ad1","impliedFormat":1},{"version":"d9c326e2b89124e3444439c75d0ac329b775ba89eba2486000780537b38430fb","impliedFormat":1},{"version":"47d88349632322b02448baa8671242ef999652300a86e044b957d084e590b3ef","impliedFormat":1},{"version":"fb7729535e349f99937d227817f21bf587ed3ae716c5bce33edca0cf204914bf","impliedFormat":1},{"version":"d287a83521026c13e7f0c26fe93ec1f8d996ae9846b187af45493b4d3e75eaf5","impliedFormat":1},{"version":"bf73c3a606a90a0e0fdf16784a45b67cdf9818f2a38d06c84fb56288ed911041","impliedFormat":1},{"version":"af107421a701786800dc523275bb847823c97dea400dc96b12fa59df8a9e9436","impliedFormat":1},{"version":"3c3eb531c13b6ae3d0d038f07a28ad1260b0fa249df7fa1caa434a047b88fa0a","impliedFormat":1},{"version":"d9c326e2b89124e3444439c75d0ac329b775ba89eba2486000780537b38430fb","impliedFormat":1},{"version":"d9c326e2b89124e3444439c75d0ac329b775ba89eba2486000780537b38430fb","impliedFormat":1},{"version":"803def89d1c799f619a300cd57853b7956bce6e76305d0aad806ef89a022dbb9","impliedFormat":1},{"version":"c53164284974ac89d51386ac9a5bb18c34477ae1f39d410013ea44763c2b9206","impliedFormat":1},{"version":"89f0ba5074e15ef17ad5cd4199aaa6a8a047496a70ca1843d54c613e0603c865","impliedFormat":1},{"version":"428554d1b6bd039eff68ed3ee14942908ae8146f219b238da2f653ac2ac2f861","impliedFormat":1},{"version":"ee0dc9004728daa40b27f979568954414a38dfbe24606001e700b3bfe72c2db8","impliedFormat":1},{"version":"37c762ab5356af4ca3e6546c54150224ce5012325041a85b2e6f3710cbd7a1f9","impliedFormat":1},{"version":"73e01307cfd6334a483b80a2aec03c0d07caa9eadac8aabe5ef7e9665fe15c59","impliedFormat":1},{"version":"fd3c1ccea875d68afc590962ee38f0260998bcc8dd001e8da68fc96c3d1b0ef5","impliedFormat":1},{"version":"faaeaf97593e09f191316a820953400b98ff53c778ad9ce888b93389f41ae5e3","impliedFormat":1},{"version":"14bd37fc13e1cb4595d490ebc90d2a4752b9043a745079662232ee3492b12ec6","impliedFormat":1},{"version":"2592f6ae20b3c3953fdf29a5be55d59929ae54d43ac4b208254307904e97db01","impliedFormat":1},{"version":"2997e9f7087398a4e44d6a0aed6f45a7aa9a0df99e653eedd37e2bf434feab26","impliedFormat":1},{"version":"10182b6a50cc485aa657eb4db9f783a3781897a5c2a1a9fe83e0f55d9e34fd95","impliedFormat":1},{"version":"4b4ca97d1f43f99ac609c2b2d1a4629854fcfb411b9ae640b9a3e06a74a70a8e","impliedFormat":1},{"version":"b31bb5cfb4285544ea7c5f86948df4b0ae4b7457bce668bcadf6ae665196db0e","impliedFormat":1},{"version":"3ece3336776791bfa8209355870b04629b46a7e574c8b101ddd98bf1a66751d5","impliedFormat":1},{"version":"f14037babbdeeac50e775ed72ef141dcd6565e78445c577cb95254024834fbea","impliedFormat":1},{"version":"a93fd929cd40ba2a5940d3639837645f8b21bba2a41c192796b12adc959d7776","impliedFormat":1},{"version":"ccfc9213fa3abbf42ecd7a0a3864cca0b17e77e485837a819a5272a2101a9268","impliedFormat":1},{"version":"b19aac4a14edfad05beb451bae30492b76f00ee4ecf79c9bbdd3334c13f68d8e","impliedFormat":1},{"version":"9c9f3389cf8e2369db03ff255c178f0f0f952fec8b672a738ed681c850342a4b","impliedFormat":1},{"version":"67d029c07b26107415ef6fc6e5f9e839767dbf91fe252c847cfeb7f0292cd8c0","impliedFormat":1},{"version":"5b527764483b100cc496c78e1d6fdd398117ed33ca9afc33f4941a4ee484ad5a","impliedFormat":1},{"version":"b91db5b602d5a13bef17751f95ebacf0054164660378c78306fa41f9d871d2d1","impliedFormat":1},{"version":"d0ad7cbec66adb43a08ab426aa6f22590e2183fc8faadd556d2ccb3e930e9941","impliedFormat":1},{"version":"6d7d868af595e9ec3d7d1334d751e0ec7da622df213d676dd25ba000394c22c4","impliedFormat":1},{"version":"9b54e2b3ebc2bd20c5b2e7cc0ca5a1173720b7df0ea4f36be8a173ff4648b34e","impliedFormat":1},{"version":"72b3a0765eb1e90558baee690f559cc2588b9a127ac33eb254b3efe73ac3e1c9","impliedFormat":1},{"version":"98be5603c4f3dac1335ff3e527f41d4fafeed14e2f3d013239d977ed657e693b","impliedFormat":1},{"version":"cc701f24f92ec8e6f852b97d776b1ae0f25bd2b669fcc8694898c3f2d555c8c0","impliedFormat":1},{"version":"26d573d47d7a3a228f510bec272aaa275350cebd9d2ecbaed90a4effc6e557c0","impliedFormat":1},{"version":"4b4fe975f117be911361c11924c5f4837c264e72f500e328dd1bb9e830443767","impliedFormat":1},{"version":"a537c671ffdc208d6b9c57caa97c1913da4c7cc2d1115f013fb2f7a6f95d1471","impliedFormat":1},{"version":"bafbd6ddff858792855ae5e1bb51a0b2c5a6e0dedb45b2cd892c357722ac3508","impliedFormat":1},{"version":"ea41963e99d0311c2ae979e8f5cd5c8caa9139f93c61a80fead4652e61677e3c","impliedFormat":1},{"version":"5ae06496f79ffffed758ae9c827a9948f5305839b7ff84e1b920ba1f5fa24d5c","impliedFormat":1},{"version":"9a869954197de6d2f2ceb6971856396e082cf7d0f8b58335d1109b0aa84c8bde","impliedFormat":1},{"version":"3054b2d41619ab80be976f6422b4220c7125f30f19a7dfcd282ee1fcee4458c5","impliedFormat":1},{"version":"edec72c09ee9bdb97f1001d5ca3793a7df71e53a6122579c0de98726b8a69e7a","impliedFormat":1},{"version":"8db830f5cb44fbd450010601c02b5225d9b69fb4e0565ae6a69f5ed441d350ed","impliedFormat":1},{"version":"af1066f19969a40c06a064168ea271d466ef8911b70e38db0241147c0f9b1534","impliedFormat":1},{"version":"48f1679dc3ea2f380b04b2c2256092a9a31b30edd5b52a8fd1260341696a2e5c","impliedFormat":1},{"version":"8129c7fa5e0b91362d8484fcfc853ea2de354497ef0ef656707dc251b47d30d2","impliedFormat":1},{"version":"7d99bf795b8a2080c5acbaec7648dce0aa014f61654363cbb8da631e158813ca","impliedFormat":1},{"version":"38c2d29872995e0eba3cc77ec7714be7c8714024a56d0698c0ccdfebc8b34333","impliedFormat":1},{"version":"b17dfe247aa0111c3ca2eadf2165b50833f6b2b64ef7b66319b5f30b6ecb316a","impliedFormat":1},{"version":"e4714e134970d7a51f7ec1b4e91747058e7fb77daad7a18702a5383d499b633a","impliedFormat":1},{"version":"c9fd408bd5813a02a9e30f0a1f85221e0f13f9f46d1405c3b0717c749fbb6c89","impliedFormat":1},{"version":"e7f8905bc9f71122a3ea5eb210256b206893bfd80101c5f4bab9855117a0ac80","impliedFormat":1},{"version":"f087db095dab80bddce2d43ae95d603f7bba06201a16bdee5b028ceded4899c0","impliedFormat":1},{"version":"6f85468ab5d8d3e9c6653f1a55a43a03bde345a48d50918f53a334f738295ad4","impliedFormat":1},{"version":"4d5a81f83f85d33f21fe6bb37652841db2ba290b94f52f60e5352996e1cfdc1f","impliedFormat":1},{"version":"d698b3f9912dc7ac5a7039530413f6ccc44945b431c3370885bfae8370430c0b","impliedFormat":1},{"version":"f2d82744b9d0b4dc459588b995832c047bfbccaed5fdd2907cf69af10d3360ec","impliedFormat":1},{"version":"576bf26ab310f0d948285920746ff9ab299d8515f84368fdd94b867fa932570c","impliedFormat":1},{"version":"49c3d2fea73d85b4024a3b4cbfd4c086d85a5a1a4c8920f23c40e6c81b7446dc","impliedFormat":1},{"version":"2d0e15690b38b53346045a15e9e1359509aa2c24170039abc50faefbc6b002e7","impliedFormat":1},{"version":"cacf5c0c429c4beddd0858f77bf68a918ceb0896802793a9e62736c7313b198a","impliedFormat":1},{"version":"9e3e5c5a74925a0aea9c786095c04f1348e75988f1066660fb0d045de83cb486","impliedFormat":1},{"version":"1035c6b42fbacc428e6c6b10f5c11ca567a9150e6017e6e5829d72ea1aa70cad","impliedFormat":1},{"version":"590f44dd7425356e40db71a9063fb7605fa5817ca2090000491111e0f535c540","impliedFormat":1},{"version":"0e8b0e62026c9166bec95ead366d2cbd01e0086582cb59a01301054731cf9eb1","impliedFormat":1},{"version":"3f588900bc393edd5d39d66e55cf73d54e64616bb10e16aabb69308b527e63da","impliedFormat":1},{"version":"549049e4aa464cceb66f0bc4525e7466b26f9d6db45d1a89129b2fb042270284","impliedFormat":1},{"version":"66889f57294f06e1c0a891a2af5298d1aff23861e3290c697b5f3eb2e5f8da23","impliedFormat":1},{"version":"9e9b4741ad5e7228a62961357dc596dd12f94569c03b515d6aa80adf51b64778","impliedFormat":1},{"version":"8b0990d1eb332f973044a845912d182ebc6ab87fac6ea52fa984452feac91816","impliedFormat":1},{"version":"abdba7845ee011022e227abecd75cbe599b43f3d5ea57bad547c1ae2a564af2c","impliedFormat":1},{"version":"1d57d1aa30f5f99aa31bdfa469804afb8420390d3a77b94c4f0aa285d5dc2401","impliedFormat":1},{"version":"49a01bb34f6651d5f33143d8d90653de8369b3c354cf56d33130c7f7fbd7c4da","impliedFormat":1},{"version":"d433831ee2ac9c9291290323bde0ef405ccb999de68c97a5428488f424508cd6","impliedFormat":1},{"version":"e1f419783736d84f773c9a7a47d3c8ba9884b75d01a950061f2556170bb51ba8","impliedFormat":1},{"version":"24f0897ddb49d344daf653ccb10655c0f345f59c9265dfb42984ffbcaf35c189","impliedFormat":1},{"version":"01696b6221d4bf20aea3ebe7717e2698a65fe6c5d8c163bc005d0741f031275e","impliedFormat":1},{"version":"16091fc8e371ecfe5e676673930fa06ed3664c4949d47a55e749609066bd25ca","impliedFormat":1},{"version":"38bada6c35d518359a6a7720b1dd7eea522873c4cb70bef80585e6f184e3be8c","impliedFormat":1},{"version":"d079bebca6469ebb44340b0c5458f14be6aa8ed9be2347bb9374d89f9b2a48a1","impliedFormat":1},{"version":"38bada6c35d518359a6a7720b1dd7eea522873c4cb70bef80585e6f184e3be8c","impliedFormat":1},{"version":"27302c5f42cf901cdc4206f8243b8cbe2ab3326d043e201086a354cc0d36f066","impliedFormat":1},{"version":"6233d61f7d2db398c5a1aa699ce306c32ea9aed3a7351f07f15e2133be0f1a1e","impliedFormat":1},{"version":"6233d61f7d2db398c5a1aa699ce306c32ea9aed3a7351f07f15e2133be0f1a1e","impliedFormat":1},{"version":"b43c0bcd2b1c1772aa7f7e04276b6e4674edb44faae05ed04c03dc573439ad08","impliedFormat":1},{"version":"6799fe20fd9575bac4a4131a05ea5f6e8b96e9c8c5eacd65aa1e3a2e3ae4a6e3","impliedFormat":1},{"version":"c3202f06147190991108fb9f3c574d5c2dd2b7b21fcb2c3bb9692472161a46e1","impliedFormat":1},{"version":"523fa4399cdc798164636b07a8b8f5f31c3ed7fb73b96df0d4d84f7f7e59fd6c","impliedFormat":1},{"version":"ba62fdf8d36f79a237de7d6d3f9c60bf3104af8e29c4de86af66b069cf857cda","impliedFormat":1},{"version":"95ce2a6f4e50fbfc542a287f9697c196e962dd89e554b5b7e69e07a5bcdeec93","impliedFormat":1},{"version":"47927e7a2e0a90119cefd0dcb79fa33738470d4c044de62f9030208fad91ea6e","impliedFormat":1},{"version":"429445903ca521abb9ca988d76f04e42792e28764acf3f4f494f3ca66c584e13","impliedFormat":1},{"version":"8b57b9ee66d3ef2c6674ad59be788cec9e95f5e974a4c7b5576627bea555da79","impliedFormat":1},{"version":"97f7424a7d768cd76302507d2ca5169105d26f0c92fe6f47e90bba843e400672","impliedFormat":1},{"version":"6911553948a0327a55b1cfea76ab9a4da2b4b13b7040fce08758eb84ba09c5ce","impliedFormat":1},{"version":"d720bad723bd8d6dbb04f76118c0b90c44b8b5bc4e5ec3fd3408b076153f2ace","impliedFormat":1},{"version":"7fcd666aff2087ccbad00794d2c8b92341190bf603661bc53ce0c848a8898d26","impliedFormat":1},{"version":"64c39c750a8556d514709f6f72e3acec60b8dc8a39045aa4102d81f5797f1b6f","impliedFormat":1},{"version":"97f7424a7d768cd76302507d2ca5169105d26f0c92fe6f47e90bba843e400672","impliedFormat":1},{"version":"6911553948a0327a55b1cfea76ab9a4da2b4b13b7040fce08758eb84ba09c5ce","impliedFormat":1},{"version":"d720bad723bd8d6dbb04f76118c0b90c44b8b5bc4e5ec3fd3408b076153f2ace","impliedFormat":1},{"version":"3db86af32ed40cc024a705f5bdbd2f851ea68e68cf9f779f0b2e4b7a332a7c55","impliedFormat":1},{"version":"c249089e61536ac3fdea7344280f4e3ade979f510b8c79ea23dbedab33df5360","impliedFormat":1},{"version":"3efe8e2b11ed4c737c5f1716759329c2859e83409b7ddf1514c10a2a267c2f33","impliedFormat":1},{"version":"285c3fcb2cdc80a125297403f9248f00a8b705f7e3aa1ccdb11f73f6add72394","impliedFormat":1},{"version":"dc871fa2f1ff416dbb5948ba7c69e143a9062d45c0620f618bd3d6936b9429bd","impliedFormat":1},{"version":"f05ce5c3ab663ed93097b98229f7e3ac3f3c98b7f6076cf29232bd090702efe0","impliedFormat":1},{"version":"f30b367468119582fc0a19466de8615998e15bd2f2c0ec4c33e9826cbcef8ee7","impliedFormat":1},{"version":"026e2ceda497ebdb829d810e5d8c018838412d4b9b16c52d1ef521f27f4a7cef","impliedFormat":1},{"version":"eb20bcc78034839e75de88f72cbb31a51a099201c72bbc563910933c0dedbb35","impliedFormat":1},{"version":"bd7107d42df22463ee116e095ea51a10fa3cc6be719043cf24c41189d07b09e0","impliedFormat":1},{"version":"9bea8564c9d245b0043916cd3267e63fc8b63c3ee3ab45b91214da7d59296500","impliedFormat":1},{"version":"6f384d5fdd6d5b427cd30e22d2998a9ef0c9abfcc92d3e3221d6082e6ae49241","impliedFormat":1},{"version":"26b7da74bac1b95dbba09430b2a2d2a313dd2a4ae4eb0d21c37d0133560167db","impliedFormat":1},{"version":"c4fcda5921f7b3d759116533f53757244c33f673666980c34934c4746ec75276","impliedFormat":1},{"version":"d1b6c97f6c075043a84c0ff906a4bea9bd689dc4d4fb798908b5dd16b9fe84ab","impliedFormat":1},{"version":"6b27a4157ebe97ae97dd63c13b6861036b2c9a6973e83fb636724f556ad4f814","impliedFormat":1},{"version":"6d2406b7484df398062c6d0a88bd4e71b3d6339aa079b785676f25e677f8cf5a","impliedFormat":1},{"version":"5209d0af91f77915c6552c7eed807a416131c19734d0264a81bf6e782f667fec","impliedFormat":1},{"version":"5130b0078e3616e4e1fe375c044d0a2c0d8eb99b477cc6e2037e881b0eb4664a","impliedFormat":1},{"version":"2863d27262545b9fb5d30d88c26b26fd1a54cacb07d89ea048eaa068c9a12e0b","impliedFormat":1},{"version":"07fca2cd875b20e85679790c59059b28cccff059c0059d67b5890f508a3a2e60","impliedFormat":1},{"version":"01248b7e8d551298920ad0f9480727bab67451214a5967b13e57f3f339e0f483","impliedFormat":1},{"version":"9673acf0ad66b0f381c223d8315eaca2705dbc4a70ec66ee7e74f76b979967b7","impliedFormat":1},{"version":"21e4632cce155fd43d83f80b068ba6509327a2746266147bcc28d8d9356164dd","impliedFormat":1},{"version":"7c5bddae9b801a72006e3f9bc294e82b728ec7da9c4df84946fb09c20c79923b","impliedFormat":1},{"version":"502e95eac78518007547ce992e054027be6782b08ae6a894a4f34b8fd181edc7","impliedFormat":1},{"version":"6c9d79d814d1f2be36ddd8e0eaef8a0996caf3bd249f0f97e290c8cc5445e632","impliedFormat":1},{"version":"4464b4ce8828c885c068acaa2a6e3ee7726cdb470377999fcf4af2e5bbe91b41","impliedFormat":1},{"version":"1f7fc42238e1f3c6b03b96002005a2ffd057e16f334ae9c1499ce3db02047e1f","impliedFormat":1},{"version":"02253965788d57f8b948175eac6ac874c3c9ff36404e9eb2c3eee2f3fd6298b5","impliedFormat":1},{"version":"6178abc2f31f50d5b0fb8c1877ed4e3c1af2412619f5825588099b254bae7090","impliedFormat":1},{"version":"742126ff1ca779a40038998d3c92bf0edb69cb1af8f3da6d8090705392c92afb","impliedFormat":1},{"version":"16b2edd77efe81e51069427a5edf2f96115a05a7e1169852f39f0c3ddb285266","impliedFormat":1},{"version":"59c1d976a5cb3b8e47a79e00db4b28532da67f46f6044d0ff34718ce68843976","impliedFormat":1},{"version":"43af042220029f253356622d5a2977e263036861414f20ea2ed502746c891434","impliedFormat":1},{"version":"9176ff1ca320c9735003e9caec7a5f722976e943b2043c58106170406df8614b","impliedFormat":1},{"version":"df9342677f9aa42b3d879bbb9daf7584c0d6f63cdfa49e9d009d80adf8d490d6","impliedFormat":1},{"version":"b2a585472d160d95a13cf17fe373959fd892cc78c96436545754a5dc7defeed7","impliedFormat":1},{"version":"24de25465e109f08469b8c56791bc1d75aab7c87d27c026879c22cde97e3297a","impliedFormat":1},{"version":"87d50c6588751a6d4692f0dd0186ad8c0d591253f2e21fbf3c5f962f21b8c8b2","impliedFormat":1},{"version":"ec2779b18cf625e277642b2a09b4e6104bd90f2765b2fb36a97115b0a9a4871d","impliedFormat":1},{"version":"09b2592b11a0ed66c442c314d11290bc550e4358fadbf5f9647a404c11399cab","impliedFormat":1},{"version":"50b49b549fc393ffc61aac1171bf12cc46f6eda3d3082cd1876d14758edd606e","impliedFormat":1},{"version":"6657c0cf3308ac450633a08f7835765cce67a13c409d6a09d2fe19e66f5252fe","impliedFormat":1},{"version":"1abdbe2031378fb1f7883ba0d60a2cda3e0ce42a60402d356e115b00850e2d53","impliedFormat":1},{"version":"023554b09495d4e4594b8ed70fefb8329a562d364769ec62db8844c96e69dfc5","impliedFormat":1},{"version":"8b3fbc2adaf95c5b68d11eefff5965c7024f40d4b21a6d0263e5caefd637209b","impliedFormat":1},{"version":"cd32b6ba989eedad32612bd49643ba71bd83e3cc78c066d857d8db8273680ccc","impliedFormat":1},{"version":"b5a4495bb01dadf0d320ae0987d6ad9a7d9270f4e0fb31b35497f8e3ad02fe35","impliedFormat":1},{"version":"8306e2999f7af8d69e238629596c936362ddbfd27a0859d0102261c582952664","impliedFormat":1},{"version":"07f39e8c121c4ad995bc5b648d95e3029cf1de7948bb8f52242d1c9571bde8e3","impliedFormat":1},{"version":"9569532b4674ce1c66f59ed98a1139484ce10599ec31e7d1fe306e326d784ed3","impliedFormat":1},{"version":"eceb1d0beebbdaae0b41b0c80856764f4932660d45f875954f491e09a34c0d7a","impliedFormat":1},{"version":"ec4ec23de9c89c96e96e31c88975a98ecbe94638d0f7fa9b93d5b8fc6d02a79f","impliedFormat":1},{"version":"ed028d7023163d03c9547d64e642ed39e6dc544e1f4bc00715c997d9daa1e98b","impliedFormat":1},{"version":"51f5665aeb2774990b3b0eab4fc39ceb53e674e4b5fa88d1e6d64dfbca36c636","impliedFormat":1},{"version":"e6f2dbd92a37874ceb4a65a9cfa393f216a215a58a6baf0128e2fa5a3098603f","impliedFormat":1},{"version":"cef4fe0e1c6eb9b0e14a23201ff3b5edabe329aabca23a14e178108c49be8752","impliedFormat":1},{"version":"d544a24aef3010d12aeadcc7813c9b4ec02ca2447262cda7d561f31e8ab4ab4a","impliedFormat":1},{"version":"51f5665aeb2774990b3b0eab4fc39ceb53e674e4b5fa88d1e6d64dfbca36c636","impliedFormat":1},{"version":"4ba3b22edd355ae3316dabb362a7e41c8bfe2a22818cb9b4e0abfb26a9618a48","impliedFormat":1},{"version":"8015f3c46a39b4cb2ada00f4acd5c21b33b90aad98b7a44e311c53b74e444695","impliedFormat":1},{"version":"7019c88002c488be672c19ad13def90a2edbcd699d423240d601b79a76599866","impliedFormat":1},{"version":"4757254beac0f2a34c1625f950279c82185de944e1ff81c5ef9bb9279d6e492b","impliedFormat":1},{"version":"924d65cd98350be913955cae8c89ea19ecaf5cbcc10b6c6252d2fcb2ab7b3518","impliedFormat":1},{"version":"afb80020cf49bfbd5f08a60737e4f0c84dd819193f8adcbbe6f7d7a96b3852be","impliedFormat":1},{"version":"fc74a81d71ecfe1926214c4fc172f540e51a15bae98616278d165f33846f1fc1","impliedFormat":1},{"version":"bb697f2636d63cf2960bbf91a65744b705ae32c786d9d9934607e587fcffdb8b","impliedFormat":1},{"version":"0a8259e9ef9e33557e7fd4763bc871581b7ffbea5d6d6de7bee8cccb57c68db3","impliedFormat":1},{"version":"7c307c4ca0a07f8ef7b9bd8c5b7b0e48f894203b2d543b5848f471914633ac5a","impliedFormat":1},{"version":"786426518b5c3582c00528444c0562fd1b995464cd67be7095944bcda8ab7677","impliedFormat":1},{"version":"064070134a2e8ea83dd3f9d5b40c41431315cbb660333370aed8e77bf2da6b08","impliedFormat":1},{"version":"3453583e8f126b7d1d19d311ee10ffee609a2167b05bddb96c370fbea40e87ba","impliedFormat":1},{"version":"ae76aca56117673e501c7e5cab55e31eea3344aba6324407164bf2729770a598","impliedFormat":1},{"version":"6fac972fb851716995eef39678b2055bafc802b57bd94ccfae263c263213ec0c","impliedFormat":1},{"version":"7a7eeb228a832cd49484d1192db993dd120a2202fec9dead9411d5781b608660","impliedFormat":1},{"version":"486157b5283f5679b3c422dd4c9bd4e3f215ba41736019f5b61508852d2e4c8b","impliedFormat":1},{"version":"325379e60d8e0465149fb0ef9812a9eb1a12982b5cc16aeab90067360044f289","impliedFormat":1},{"version":"b418f0bdbf8c35aee9b89fda32b04f53decd9c7481b6f871692458f1be97b462","impliedFormat":1},{"version":"1d8f51a4eaea84b7908e26d87d3d0abcbc3eb78ff8ec86c1c0f311075d4d245c","impliedFormat":1},{"version":"2189bc92169eacac269706b342b75c0f0c089fb35b053ec30962b4dd483b5ec0","impliedFormat":1},{"version":"b97c3f409bdedf9ac0852f3a4f5ee1827f7d75d686efc2ee38c47cc175b2a1e9","impliedFormat":1},{"version":"05cd813328106c081a3f13fc3f9a4781bc0f756f5655279123306501d093aa44","impliedFormat":1},{"version":"4aa9a7d7480f1f844e42c189ae4e101e6e42dc488b0ccbf077a5c9a9f70d97a3","impliedFormat":1},{"version":"6a11946ceb52ef7e4885c245b0a6b2e7a5b3ef90e0cbf8e480639f2b82aba681","impliedFormat":1},{"version":"a49ca8bfdf9affced255ecdb77cc23e2b4cb6d52c8ff2f777026d300083c14f4","impliedFormat":1},{"version":"2a98d6fe953220a7a1ae8dba58aa5bc28d8d6cd9fa1f166199c2c1116ecd3c38","impliedFormat":1},{"version":"466aad8a0d48efb91dfae2570478ef8eae643657d4f6547e3013967bf3db4ffe","impliedFormat":1},{"version":"26054f90788c0e761b748411a6fb223bb61ec680041eb2eddd39cd970f4fcd39","impliedFormat":1},{"version":"e251b6550b56f8f8c838f8ddd4990bc60fec06d9c99527a080c619dcafdf02aa","impliedFormat":1},{"version":"36ca919dfeab1d304e60d703956d899087212701c175ab574eca3d54b0a9ff2f","impliedFormat":1},{"version":"ae98194239f1570466d7bfd8835cdae1343ffa8969bcaeca6f7237bbbbaea2a6","impliedFormat":1},{"version":"ee9b869e0409f0bf6857d4a2e02b64c2554071fb76f9cc3c3555d1dde25b5a18","impliedFormat":1},{"version":"2efd52338da3ff5711cc72e5b73a7b2be30ef4131301f3802eea0b9b98eeccc4","impliedFormat":1},{"version":"c9639824974e1515a9d4a0befc673eb3a396529362331ce3bbddd79cbb2716a5","impliedFormat":1},{"version":"20082c0404595cd12f067e44d592ccc88d818eb09cc1c4e4a129fc3f7636a643","impliedFormat":1},{"version":"f81f66f5bd361fc82717f591971666bca517a7a6f2e202963097cb5cfa507a64","impliedFormat":1},{"version":"53fbde0efcc4a821f2dba6d6ea27e1a80d7da02fbb367d9f73eb944516785f13","impliedFormat":1},{"version":"a90b15539d910b1560c4ab715fb7330e175e591d01e7e31b2c9bfda65de938f1","impliedFormat":1},{"version":"6a36da368780386326462d6f48f47222cbde9a00fbfaa0f855034ac6751c8f85","impliedFormat":1},{"version":"861f698c8bfd16f1acaff2ae370bed396b9dd4a0a8aa790be6d93be2f542d55a","impliedFormat":1},{"version":"60aec83c734c6445d2dfc2eb1ec3ce22d4addd3999c05046483ebf64f36566d6","impliedFormat":1},{"version":"cfbe384795dee8102f2fcfac7126e07f55e7d343fafc887cc08051f01165168a","impliedFormat":1},{"version":"09cb1355bcecf2cc77e2f01b439497afc40d11e614d1efed532dc706dcdef335","impliedFormat":1},{"version":"51afdbccecc8375ebe5d89095d15fd07b1111c2e42d092df3b1b3a78aadf9098","impliedFormat":1},{"version":"82b276fcb52e5a460b21290cefa1ec98268466215276a7b4fb9cb44cde5315b4","impliedFormat":1},{"version":"d2cb3dc749548c173c0c135b3c8abc02dfb088d3559eb9bac31c8a5f58125d29","impliedFormat":1},{"version":"c15e99f7d8fa0717ea26d36af76f371f066372c581312d8d28f3a47b553c67a4","impliedFormat":1},{"version":"2d844d3589f04bf3b3f53216b72271312acb459d4ed70f603e52da034fe594af","impliedFormat":1},{"version":"ce30a913ea003516f6dd959ca623550da569fc1af7660f17c4cf53d9f28b826a","impliedFormat":1},{"version":"44cec0d12d632b7bb943fd681c23ddc1b031078b28697358ec2cae7f99bf8a92","impliedFormat":1},{"version":"839abd29c3fef0c2777be53ebf099e545718779ff76ef31120f6436e2448fada","impliedFormat":1},{"version":"7ec31d0f2e40ef288d68b8afe023f38c033a32a4cfde5541e75a4ab4da1ad499","impliedFormat":1},{"version":"e413696188f357020e920078f8a04bdf8752bba0b21ba61ea4b7a0ca066da22d","impliedFormat":1},{"version":"868867a0ba768c46a5a72043814d18e89370d479fc34f3c0d9c22fe81c1ca23f","impliedFormat":1},{"version":"3003540eb4037023bc605b9560f65bb93ec37f4c28ffa65b38552b68d3bd8f32","impliedFormat":1},{"version":"fcd8e7548a5bd2715a1c47611af7b2d0fb870589917876e18305cf4d35fbbae3","impliedFormat":1},{"version":"a3c1743275c71b8bd46a2bd63c1d9a7a90be4ce373ead58654ce8653acf7dd70","impliedFormat":1},{"version":"d0e562fbc98b25a154ddfca69fdf86c18ae6c09545a1166a609224e399fe3474","impliedFormat":1},{"version":"59d95dde3c75f13bbdff4842f35993b96b54509e423421534881f62377a28102","impliedFormat":1},{"version":"518012d5a74b0973d64e5e59577c094dfcf71d14ef5ae07d9610fb83d36f6acf","impliedFormat":1},{"version":"8f6ac9f91fa905a021fa8702f621680d56849deffd3b1ba170ccf7dda3a8bafd","impliedFormat":1},{"version":"b23709afde997019d6b35ceafd5f68103ce55ac1cb6988d439e7624f3db69f99","impliedFormat":1},{"version":"1b173650e2ec1b05d89d6bb5d8eea3d9b4ff32c51d0368c4c8c235259b36522f","impliedFormat":1},{"version":"25f7bb52ffdb36ca9ad22a7bf134e9fe0fdf79fffe7d37ccd656c8bfeca394ef","impliedFormat":1},{"version":"5c99dd66b0a3fc5a0afef3c352e1c63e6f889964d51e0906ff25b04ea83d1a57","impliedFormat":1},{"version":"5bf185675b60707802daa0d6d2b495c24ccc6dc98fc2e388a0b5c7f6da1d999d","impliedFormat":1},{"version":"fd93d73895c75a7b2e5a83820955edcbd64934c72236598a68d12b20ffb7b25d","impliedFormat":1},{"version":"0d7cd779405f2cbdba626fa1353419bc5cc85c497782a5381d2b363f523e3701","impliedFormat":1},{"version":"b0ae7203c5b50f8b368e007532a19cf5a0a51ed6d2bb7549b56e7f41ed2ebd82","impliedFormat":1},{"version":"2fd2392d984c25633d5738fc80ac2449faadfc867ed89274884da1771752b091","impliedFormat":1},{"version":"415ead3b5b34239b5fafd4dff7d92e3a99b5887b4bda47d803782d5fa2366e7c","impliedFormat":1},{"version":"a1ad2126f33bd34ebc21b97c04e496773f564bf842b9a24ed0d9e41e19fcf600","impliedFormat":1},{"version":"98ce3d77d663139a7c20fd506354b13628157092995d76d60c55a73e35d505fb","impliedFormat":1},{"version":"6549a1e655ad2265e294e57622b077f16c8ad74c820697c88fafe454cf743770","impliedFormat":1},{"version":"4655832f525f00b8796f42b0e73807d62fe7c5863890478781a5a7520b093404","impliedFormat":1},{"version":"4b71432f437f48272e6879cca65f2510e01419527f658846c0c65f3cfb6bb5b7","impliedFormat":1},{"version":"64fb1bbd008a55ddb5737c80d246a60cc4863751f8079670a3c3caaba79699e1","impliedFormat":1},{"version":"a4696fa234d9c6342e5103362ba4aa9e5bbc8179e132c240bf9fc388f09d9236","signature":"0e6b78bcd048d61224795ce4458f5138cb0ae8f3832437e697036c65603d0538"},{"version":"bf7a2d0f6d9e72d59044079d61000c38da50328ccdff28c47528a1a139c610ec","impliedFormat":99},{"version":"e58c0b5226aff07b63be6ac6e1bec9d55bc3d2bda3b11b9b68cccea8c24ae839","affectsGlobalScope":true,"impliedFormat":99},{"version":"5a88655bf852c8cc007d6bc874ab61d1d63fba97063020458177173c454e9b4a","impliedFormat":99},{"version":"7e4dfae2da12ec71ffd9f55f4641a6e05610ce0d6784838659490e259e4eb13c","impliedFormat":99},{"version":"c30a41267fc04c6518b17e55dcb2b810f267af4314b0b6d7df1c33a76ce1b330","impliedFormat":1},{"version":"72422d0bac4076912385d0c10911b82e4694fc106e2d70added091f88f0824ba","impliedFormat":1},{"version":"da251b82c25bee1d93f9fd80c5a61d945da4f708ca21285541d7aff83ecb8200","impliedFormat":1},{"version":"64db14db2bf37ac089766fdb3c7e1160fabc10e9929bc2deeede7237e4419fc8","impliedFormat":1},{"version":"98b94085c9f78eba36d3d2314affe973e8994f99864b8708122750788825c771","impliedFormat":1},{"version":"13573a613314e40482386fe9c7934f9d86f3e06f19b840466c75391fb833b99b","impliedFormat":99},{"version":"64c18db93d238750fffddbefab86ba3475686afd50ae44748b73a8d280c1a9cb","signature":"8e609bb71c20b858c77f0e9f90bb1319db8477b13f9f965f1a1e18524bf50881"},{"version":"b47bff28e5e91082a4b08cd9bd83a788596bf28218bb75476260acac6844ff3b","signature":"a5f04e1e0258c0d0c50c2121b702f32d34e6ea0c0018798f58a810e24aa1a6a2"},{"version":"44e7cd3ada74ce6f1c3f462e07cca990691d1188cebf04c77de3028c6f3e2703","signature":"8e609bb71c20b858c77f0e9f90bb1319db8477b13f9f965f1a1e18524bf50881"},{"version":"6542e1e73662ce0b0efca7c3860ddd4c577a3fb6d4896066bf363d090488a606","signature":"8e609bb71c20b858c77f0e9f90bb1319db8477b13f9f965f1a1e18524bf50881"},{"version":"3c3174c0432ee84e2c715c2fd6a9d2eca247d767acab85543a92ff34a37f18e7","signature":"3450bd5107d2b9c131247a65d4407b59178e6a14417076cb44fe01d6d456ecf5"},{"version":"3b675a8e4d9e18ff68a3ac28fe2a0dfa71c8e6c95c243da42d351d87ecdac662","signature":"c10b61e6f8088a9d1aa37f91001d5d07fb618d814f6abcad27334d0d78cbd6f5"},{"version":"5ba99133cee6fd93c5a2845364de6f770c1bae05dd778f9d568427ef972209ba","signature":"8e609bb71c20b858c77f0e9f90bb1319db8477b13f9f965f1a1e18524bf50881"},{"version":"63ff6dc64ef576df79545bbaa963d23cf124e8ad0bab7b20d08152ee04b6342a","impliedFormat":1},{"version":"2f6cb703e70a0c84b7e1c4f04573144d9779e4812d295ee1336c33c8c619d598","impliedFormat":1},{"version":"1667c652b307c2827c64ce3bbb2e635345c55a92c3d4abd7253e56869f5a7e61","impliedFormat":1},{"version":"ec291aef6983ef8c26e982c82b110aa39aa30e952991f8965f25bac02b5c6d47","impliedFormat":1},{"version":"8008ef47146c0fae2f633ffc92fec12ce1c3d3cde21446fe9d2966cab9cbbfa5","impliedFormat":1},{"version":"0f6ccb7b3426efd6222202f72b7c651f62ef6c9f0a77f6cc87db1bc4e4b48805","impliedFormat":1},{"version":"d5b0e01b58aab75223f97953afba894bb2e73cf935d6aedc85d54aca0115cc36","impliedFormat":1},{"version":"19b744a6fe628b476011906b02b5fbf579aaa1fff5dd039de5e3637c5bdf2928","impliedFormat":1},{"version":"192c70866ca70b0edbb78e05bdcdd6052262aa8cc7dcd3df28607646775e5bc3","impliedFormat":1},{"version":"d8710b3620c0301e1d0c8477bfeaf6e074ae31c517bc7aac55c05db3ffd11832","impliedFormat":1},{"version":"487c1324f90d0a25cd10eef3225f966100c2f403c334090f1540fed30d118124","impliedFormat":1},{"version":"7bb53546e9bd6e3f22804497a41d4b885674e7b15b7d64c7d3f83722dfd2b456","impliedFormat":1},{"version":"4083e6d84bfe72b0835b600185c7b7ce321da3d6053f866859185eefc161e7a0","impliedFormat":1},{"version":"b883e245dc30c73b655ffe175712cac82981fc999d6284685f0ed7c1dac8aa6f","impliedFormat":1},{"version":"626e3504b81883fa94578c2a97eff345fadc5eae17a57c39f585655eef5b8272","impliedFormat":1},{"version":"e9a15eeba29ceb0ee109dd5e0282d2877d8165d87251f2ea9741a82685a25c61","impliedFormat":1},{"version":"c6cb06cc021d9149301f3c51762a387f9d7571feed74273b157d934c56857fac","impliedFormat":1},{"version":"cd7c133395a1c72e7c9e546f62292f839819f50a8aa46050f8588b63ef56df88","impliedFormat":1},{"version":"196f5f74208ce4accea017450ed2abc9ce4ab13c29a9ea543db4c2d715a19183","impliedFormat":1},{"version":"4687c961ab2e3107379f139d22932253afb7dd52e75a18890e70d4a376cdf5d9","impliedFormat":1},{"version":"ae8cfe2e3bdef3705fc294d07869a0ab8a52d9b623d1cc0482b6fc2be262b015","impliedFormat":1},{"version":"94c8e9c00244bbf1c868ca526b12b4db1fab144e3f5e18af3591b5b471854157","impliedFormat":1},{"version":"827d576995f67a6205c0f048ae32f6a1cf7bda9a7a76917ab286ef11d7987fd7","impliedFormat":1},{"version":"cb5dc83310a61d2bb351ddcdcaa6ec1cf60cc965d26ce6f156a28b4062e96ab2","impliedFormat":1},{"version":"0091cb2456a823e123fe76faa8b94dea81db421770d9a9c9ade1b111abe0fcd1","impliedFormat":1},{"version":"034d811fd7fb2262ad35b21df0ecab14fdd513e25dbf563572068e3f083957d9","impliedFormat":1},{"version":"298bcc906dd21d62b56731f9233795cd11d88e062329f5df7cdb4e499207cdd4","impliedFormat":1},{"version":"f7e64be58c24f2f0b7116bed8f8c17e6543ddcdc1f46861d5c54217b4a47d731","impliedFormat":1},{"version":"966394e0405e675ca1282edbfa5140df86cb6dc025e0f957985f059fe4b9d5d6","impliedFormat":1},{"version":"b0587deb3f251b7ad289240c54b7c41161bb6488807d1f713e0a14c540cbcaee","impliedFormat":1},{"version":"4254aab77d0092cab52b34c2e0ab235f24f82a5e557f11d5409ae02213386e29","impliedFormat":1},{"version":"19db45929fad543b26b12504ee4e3ff7d9a8bddc1fc3ed39723c2259e3a4590f","impliedFormat":1},{"version":"b21934bebe4cd01c02953ab8d17be4d33d69057afdb5469be3956e84a09a8d99","impliedFormat":1},{"version":"b2b734c414d440c92a17fd409fa8dac89f425031a6fc7843bac765c6c174d1ca","impliedFormat":1},{"version":"239f39e8ad95065f5188a7acd8dbefbbbf94d9e00c460ffdc331e24bc1f63a54","impliedFormat":1},{"version":"d44f78893cb79e00e16a028e3023a65c1f2968352378e8e323f8c8f88b8da495","impliedFormat":1},{"version":"32afc9daae92391cb4efeb0d2dac779dc0fb17c69be0eb171fd5ed7f7908eeb4","impliedFormat":1},{"version":"b835c6e093ad9cda87d376c248735f7e4081f64d304b7c54a688f1276875cbf0","impliedFormat":1},{"version":"a9eabe1d0b20e967a18758a77884fbd61b897d72a57ddd9bf7ea6ef1a3f4514b","impliedFormat":1},{"version":"64c5059e7d7a80fe99d7dad639f3ba765f8d5b42c5b265275d7cd68f8426be75","impliedFormat":1},{"version":"05dc1970dc02c54db14d23ff7a30af00efbd7735313aa8af45c4fd4f5c3d3a33","impliedFormat":1},{"version":"a0caf07fe750954ad4cf079c5cf036be2191a758c2700424085ffde6af60d185","impliedFormat":1},{"version":"1ea59d0d71022de8ea1c98a3f88d452ad5701c7f85e74ddaa0b3b9a34ed0e81c","impliedFormat":1},{"version":"eab89b3aa37e9e48b2679f4abe685d56ac371daa8fbe68526c6b0c914eb28474","impliedFormat":1},{"version":"8ec83fc8f345a4f5011dd9ea16a10aadc1fab5c5bab6215451f0027a05cd627b","impliedFormat":1},{"version":"64456bf67e3e27ee199ebf28b90105f293c479dcdbb1720c041f9f54b2447f67","impliedFormat":1},{"version":"08953b65d641e31c0cb7a5e9cf82657f0d06113cbbdf63c7bef19ddab3c5f38b","impliedFormat":1},{"version":"6b75f3cb3254ed2ebde6f7c9487711bd498406d86310033f5b705655016d3086","impliedFormat":1},{"version":"65edde03abcb84048a8782670a52e027d2864090827fb9f6a593df442b9a7552","impliedFormat":1},{"version":"83eaf9842aaec8f93fa3dfd2f5ff82af72aa07de1855c5e405d52cb5ddbd0561","impliedFormat":1},{"version":"58961616c80eb882f198633f36128267882f1e38ce5d1acf21893726218d6f4e","impliedFormat":1},{"version":"4e50de679406cabd9ef284e0b6fa8b2e190bb00b3a1beb70afb2f85dd21b09c8","impliedFormat":1},{"version":"2e812554c576fa240ffaa71d0ca5259181cfb00cab70c5c1f78eb7d8e3330e44","impliedFormat":1},{"version":"fe59811a5b7433b873afe7ea9024f0fdf8626b7523e8df26f53d17f652f66eae","impliedFormat":1},{"version":"6605e78846265f409ef1ff82eaa6b4c11ab50ef2e6eb634982506cafce5e2c5b","impliedFormat":1},{"version":"a09dee614aa1423e888a527e4bf11ada691427416a3af8911b5b5f9ecf21ebc7","impliedFormat":1},{"version":"ab9467ccc825bce823575de19bda4c744a7079455a9aee79e2d5b28a127df558","impliedFormat":1},{"version":"cdffa4d1d8670f17245f6ff2afcbe07947467c55b44387d43ed58e7b4744a139","impliedFormat":1},{"version":"6e35ffd1ead2afed3c2c6a46e878022ba579c202a38fe4d7a32a7bf33ae276f0","impliedFormat":1},{"version":"4026aa06fee0b478cec95e4dfdbef51aebb5e204ea4f1597c8439883a45b3cd8","impliedFormat":1},{"version":"d14bf272185fece955d0b9d8977cd34ad8ccdfedb7b7c40b5b3355111a07cfb7","impliedFormat":1},{"version":"0856233bdf7a3f9f2d8da63236e81b759a409b7e371e94b57619401e80703a0f","impliedFormat":1},{"version":"779007337a0ce855eaef8fae082043a48ea00ccbafc5fd182bae4d94a1ea8d46","impliedFormat":1},{"version":"dc18423f1519fb93f4fbba99cd139237736702fd8c6aebc5e4646dd7f0cfd1fa","impliedFormat":1},{"version":"fe0e84cad25365bd7cd69e6a022e2e0dc921bbbca793b1f72a9099ef129425b4","impliedFormat":1},{"version":"bb5ac364cae40e941865a0413a868a3d0feec1d5f1b80045d352d5df9f57bdbb","impliedFormat":1},{"version":"d270126e54ce74bc28448b9879e4e034cf1b6a412a0b3ee8cbf3c8ed13ef6550","impliedFormat":1},{"version":"8f01a3f96136b81ab57882f99b1153162f23601bb4fc4e698e742d46255757f1","impliedFormat":1},{"version":"e565c4c402e75e639dbbe62457e6630d265f13076be4557ebecc50c4a14bac39","impliedFormat":1},{"version":"5971d32a8fbc962d3b56f68c24b1cbb071be5a03a9febb4d6ee7787990249e60","impliedFormat":1},{"version":"bf7c5173ecbd23b2642a23eb37607b4a9e8c533c3beed32cb28fe777cdc913ad","impliedFormat":1},{"version":"1ddd5fa2d7f7857f05e263b108bd6713525a553b3b63fa36310f24356e7480bd","impliedFormat":1},{"version":"345dc25bfa274a8086b0cdfa65dec6ed9ce34dc53c19f36f10d0d3ce4270938f","impliedFormat":1},{"version":"33ba37fbce1b78c28e860fb312b6284587b0224640bf8233cca69ebbb78b1629","impliedFormat":1},{"version":"ab4ec5d270e1b668b58c02984e3b108f28521d6c0e3ef5226306d1548e88f19b","impliedFormat":1},{"version":"e3f92a43b3990ccee0f634b38021c7267dfbd2f831ceb82806cd86fd9b970aa2","impliedFormat":1},{"version":"ee6971c95c495d2e746251a3a4edebaa9f3d1f2e3f6d4b5cdd210b8e3a36e097","impliedFormat":1},{"version":"93cfb20661b6e888148813f15c85f7b0c88fac9f01ac8d42e28f2c9bfef44aa6","impliedFormat":1},{"version":"0b5d14c81c906ba9dd283d8fbb0d3c5cdf98339688fc4eed0b10ba2e07cef7b2","impliedFormat":1},{"version":"2a25deb835ad5c88aba7f0148e4fa58d0989f45570dddb5811e327e1eaeed4ad","impliedFormat":1},{"version":"8eaa99fa1669a382ec159ce60f9f1d81959a994debeb8ff6e167e87bd59b68a6","impliedFormat":1},{"version":"68abc9d3fdc5cd30079d5aa79aee3fe335e97fd2465a6e0d97a911ed5f126be7","impliedFormat":1},{"version":"a09dee614aa1423e888a527e4bf11ada691427416a3af8911b5b5f9ecf21ebc7","impliedFormat":1},{"version":"295048b3b1f5d88d6b4ed98f5db01205424f5c87053fd39f86dffceee7bdf1aa","impliedFormat":1},{"version":"a91b73ce817b20437417d24221dce06c13e94f868abeb926eb859649b96d4dd2","impliedFormat":1},{"version":"52937dcd1b720c242993e82d765a4493378dd92d1af840d1f1c2d505a8d8fb52","impliedFormat":1},{"version":"9e51f0a6a0e89504afafcb32d2723f09f8898f6a7dcf92dc6cb90fa173492b98","impliedFormat":1},{"version":"d7c447aaf48a7dc6f2c05de54b6f69fef43d470db301a578563b6743a8af6c5b","impliedFormat":1},{"version":"9072df8167c523cb92a0ade4494b84ba744ed3b0779b690d6671a8febb130d6d","impliedFormat":1},{"version":"9146d34a054ad4e3b4c3f53f64d4c106e643f41209bf05b94d95b593bd6c76c0","impliedFormat":1},{"version":"ac26beae2bf3f2c845b7ffad4f55328ed160dd0f463a58372704fa7a6c27f793","impliedFormat":1},{"version":"ac20be3a60ff3c03777c81b858e6c78784352ef7aaf798fd34b8cf2e29b38ed0","impliedFormat":1},{"version":"97fd4e7d6ae8ba1f2594f1caf41cbc1be95029783f973d87525b246c6e95f0a7","impliedFormat":1},{"version":"1d6791c65ea98d1541f74ad5e213b75982384b6ae5a4057bcb41466961709bb5","impliedFormat":1},{"version":"281cc4fead96675e77eb85d6f5208a514500188b2fbda2935134da18c77ff5c9","impliedFormat":1},{"version":"82c726b64759224520bb3c187cd3494f7731a9244573445d917122b22fa41f8b","impliedFormat":1},{"version":"e459ce3fb3308c97e106f748a151e6ce78ebd11a09551b2d02a3c088dfd1d7d5","impliedFormat":1},{"version":"6a50ed407459f72bde387960e0260a325644cd0ca3bf3e2bcadcc2bd970afa40","impliedFormat":1},{"version":"c99ebe0198a5e793ef35564e012aaca09d2cc13203ae3cd47516f2f15f0062cb","impliedFormat":1},{"version":"906fec947a3ff4f891c58406b56a23d839d374b2b3351e1591086493e3acd76c","impliedFormat":1},{"version":"5257b83697b5aa5fd2592133315a38682928bc663c874324541a22395d758ac4","impliedFormat":1},{"version":"ccb70257fea5c213e4ea55e37ded0acd02bcaf55743a96c46add9bbe29262abe","impliedFormat":1},{"version":"f8c3bd231d511bded4ad4b3ebfa29d26c45529e5dfee3c1a767004953889d206","impliedFormat":1},{"version":"6bcfd8bd7a995605a557c3d4578056038f16cc3d128a6e5ca25bd7d948563a70","impliedFormat":1},{"version":"e74145e707933003eeb6613b8eb7d0880ddaeb1fbc47642694da119279e26b98","impliedFormat":1},{"version":"72be37952168ab433b352d5ec8f51b73aa64c9ebf2dc5538cadb02c6d47e01cb","impliedFormat":1},{"version":"727950dfc1b8ea42553aa73d4070d302db0a72b6cba269e4ff330561f90e1ac1","impliedFormat":1},{"version":"387751c30bb534d0c2cdca023a75b77c4859ec4b16f874e498d69213ee40efc7","impliedFormat":1},{"version":"39c4884d89bf2b8ea56944dc1d4f68fd605b9731a542394d3f168149440daf3f","impliedFormat":1},{"version":"bb7e593672a1ba37acfeda32959bb875b0c1b99b42ac7d2d16ecd90112444ea3","impliedFormat":1},{"version":"5b2ac30cc8aaf9d0e6b97e0ac8e88c48b0132937743b7865fc605cec8257cd02","impliedFormat":1},{"version":"db63de117cdb3bf857512198f988577498e16b8069f27099ab8fb71f5e5f9faf","impliedFormat":1},{"version":"7ebba6429a982ba3ee14d2f0e6f65596171ec96a5bcdecc963a3521f19718374","impliedFormat":1},{"version":"d1d18efda8252075a82a6d3e6c373e144322b1bf1a018ec831aec2a34cfc6384","impliedFormat":1},{"version":"2e8415a4268001bfce5672f1fca8b5f45474b82b2cf082693502376d1de22f02","impliedFormat":1},{"version":"25c16b6d66a09258a2cedd5a68a3524b85f0abc362bf5cb92841f2a87d08f8b3","impliedFormat":1},{"version":"e3f4430a9aa0d8cbb580de46fdc9eae49137275a62e5129e916d3aa03f1f7c81","impliedFormat":1},{"version":"8fdf0d718f6a6cc522c6b9d187fb5ccbdbbc4f36d5c5f53cf868ddc8cb619fc0","impliedFormat":1},{"version":"ffd8da17fc910d12f14597471210e28e57ff745271c0c9448ecbc28b13fda608","impliedFormat":1},{"version":"d08347843fa76bb14ba0e003803278711515b04c2f0ab0bf0a14baa89acfe3b9","impliedFormat":1},{"version":"14a56bbcee52b698f1907c3d9428b2d9bef8ea611ddd6f5f76af3f601d9c6c6d","impliedFormat":1},{"version":"540e084b06df30a4e27b271bc2163c8f88b3d181c18497173f8ab3c6218107b5","impliedFormat":1},{"version":"75739fdfe4274aa1603b8c3e08ab21d2465ba4fa598912aa447590af2ebe35a7","impliedFormat":1},{"version":"60387bc1f3a8ac59f3cecd4e37ae632852982b9d0a37849b113502f96abad4dd","impliedFormat":1},{"version":"448088258817dcfac1af44820f02268d3a733fba3165a4df27eeadbec2416064","impliedFormat":1},{"version":"f838227553bed5ea4557c9eb3a3782ac2e9395c01918223f087f0b760eb726b8","impliedFormat":1},{"version":"1a44297617788065c56ecac49d14a27d61b3c8b6dd93044d40afc8283cfa3706","impliedFormat":1},{"version":"5dc248f7d6c401a87b4468922af2cedb4efa98f0ac10f7f0547cf13988f99e48","impliedFormat":1},{"version":"8c9947d347d356d81a062232ae1ff2afaf97b702d4bb9f5d1781d101aa52b1ae","impliedFormat":1},{"version":"30d4b608895479c30604878dd6a4d31dddc0cfb64189b71833fc2ecc2be4abc6","impliedFormat":1},{"version":"939bfbbc861cbe104793567d5505609012a0ce84901a9c044e282d180981982d","impliedFormat":1},{"version":"88069fbc0eaf70d82d1439504a0cada34250d761b65de8ff350a778e3fb3063d","impliedFormat":1},{"version":"da592d0fdb1a2897803ccb0f949320dfeb76dad033fec0f8d5d6933fddfa0f4b","impliedFormat":1},{"version":"7be3fe0dd8fd7e3a6296c2a0b9e017b8dec496e461d46d6ba66925d8b0d778cf","impliedFormat":1},{"version":"7b32a09d43a93680b366cc7a7637c884e1dd817e3939f413c5aa0cdad914afeb","impliedFormat":1},{"version":"1a5a65d70494b82429b5bd78ce6cdf73037b10e7342ecd825a660b11ff72d630","impliedFormat":1},{"version":"511bf2e95b882104430ced0c627834fa54df8070c50829201dfa012dc6058009","impliedFormat":1},{"version":"d8a711cb6e0725f842cbe33ba8aa2bc7bdda76431d86e471a7ff7aea7163f323","impliedFormat":1},{"version":"73473a5f6064e3d8bd29185a6a3b88b6ac5916b901a17fa66d7cea50f98ee856","impliedFormat":1},{"version":"f339feba19bec1ecf5861b9bf95290b5f97a33f996e7fc848975eb18b32c8f5f","impliedFormat":1},{"version":"fc5b3fbd60f681038a883b3b0a1d114684b36d8350e24d9fd2c7d5a6ffd2ac2b","impliedFormat":1},{"version":"f95cad3d309ede51f10e1aa0c2c7821a41193fa10de7712c8166663225aec4d0","impliedFormat":1},{"version":"7624531047fba888b685932752f3ef5c2738e034303c93579fd811349006ece7","impliedFormat":1},{"version":"d7f3939e0ff0c8aa52c8165c9385b481ffee240537464459822533c22f67815a","impliedFormat":1},{"version":"37fd6df68a4992adf9489418c96777874ef425ad884f9df004f92e29626bc53e","impliedFormat":1},{"version":"45182be842c1c6809296c46f24fd45a1fd6298f7b4b84a414436fd2ad5827d4e","impliedFormat":1},{"version":"ab9f456f60347c8ed06a7bf3ebbd54162184e9cbf6dc2f43127ff631ce74757d","impliedFormat":1},{"version":"b46bc135f59ad7cbda10236d127679fb92c9b4665e082b87f801125b86a79c2c","impliedFormat":1},{"version":"a8dd5ff55b15c2966589edf335832b73f09e1a4dd6c3d5e75a99384f3ff364f4","impliedFormat":1},{"version":"7693e2ee55c5df4b0940f1c66d86b5fb5e9224b8bbe849a43f0468ace0d16e8e","impliedFormat":1},{"version":"a8a1481056c587c8e257bf519a23c4f600ee764a627268a969791c6ab995144f","impliedFormat":1},{"version":"787b0bd0ef9dd83b7bc898b7f831ddf71862652017a336c22bdb23244f89bf36","impliedFormat":1},{"version":"81521858f1817c1ae701537adbd3dcf3254bf9857a83856a2f4ea573b6cab85f","impliedFormat":1},{"version":"db3eb26b69a3b3574d17b87c447c4f560828d9230a1c2fb1ca8eeed1f61b2957","impliedFormat":1},{"version":"e412ec3e685a55847d85bf04e9332e5af82e28dc92c778184038d0bfc695283e","impliedFormat":1},{"version":"60fd4af8ecad9bb99dd1b29ee1b69e9714263b11bc0b504b9d7beb164d7a1a35","impliedFormat":1},{"version":"f7ebd3c4e33524de1e4924028c22946b7fb95788d4e0c13d72545b76e5b464b6","impliedFormat":1},{"version":"486ca4fa9d5c0a5c01472a81a7ce51a76dc3ab86de70164bc0e5ad99859eb9eb","impliedFormat":1},{"version":"d1305eb5d7fa2ba5a60d6ad2de0e036d15588d49a88c0f92f3956bcd4700f104","impliedFormat":1},{"version":"e5dfe656913c2450a17c62988011b9d821edb4fea05dbd602675e3aa7c9d73f6","impliedFormat":1},{"version":"da88233ec70b4ac49df88c8345d0df8b1309c53d5df0017cf668876c0785680a","impliedFormat":1},{"version":"92407620ad81bb95c91a6cdac78a769fc155e12fef59468eb0882aed9b733a9e","impliedFormat":1},{"version":"b07349b94e69b9e9bb67499fea99bd1fa6e9d9df2a8b571b9941287455c76ed3","impliedFormat":1},{"version":"19bdc305c904559ed5d4c367ac50dbe9fede36557abc2d023e6228690e6fb207","impliedFormat":1},{"version":"2ad274d45e2a9dc66915b1806c3c02b065889e32a487dee5af20ed9bd53c9d6a","impliedFormat":1},{"version":"d4ae12fd53be33b90aeda73d73f644337b7623fb0e60b69ad32c526dbf785a5a","impliedFormat":1},{"version":"da7476aaf1035c16565fb8402a2704cc8c8e3d7cb39180120bb3711525d0ab8b","impliedFormat":1},{"version":"99030f98187f417f3b9ef1e4110e7c9ca1ab6ed98b6e12e6130d168f943be079","impliedFormat":1},{"version":"6489a56dd93d8cecfe86e21c25aada578281973cbd41910e9cfc975a51963904","impliedFormat":1},{"version":"8967ae64c201c0c563070d526b1d9a9f46b417523a62433699f2e2048b4d82ed","impliedFormat":1},{"version":"521bb8058e97d1dbc36c06f94b95cd87f4b7f39b9a443f64cc483492048375da","impliedFormat":1},{"version":"f74437df66cbcae00ed3b71ae771fe998edd4f30f28cf8b917070cdbb060e7bb","impliedFormat":1},{"version":"fa8b0784e57a825ac298e89a5c43ac4ec88b8dbde74f9bef87c38f891fc2e162","impliedFormat":1},{"version":"738634e0df0b2c4a4ba1b2969e3de2a7661b1f19d0001eda6fa53e4ca6e0b788","impliedFormat":1},{"version":"8fac9df67977bcd5a0036bff1ce0d7eacf190ebe2fe93c073d0ecfb93934799d","impliedFormat":1},{"version":"33113406bbee152d17b1f11f75e220af79a971c229e2dddf7239bcde6eedb591","impliedFormat":1},{"version":"4e3eb4be1bc777e2c2babde44132c9b36e3f85ecc50de28321a75cc936f03508","impliedFormat":1},{"version":"25fa594d7e17d731fd20195af7569bf71e087ec5b724c7cbd406777f37b601b1","impliedFormat":1},{"version":"84dbb23aa064c4ee274e831ccaaf0162346a93cff5c95aedebf71b883543c9d7","impliedFormat":1},{"version":"592ef2afa2e3332d7e982d134b0149356ebf7ed61b43d56ca6dd4c063cb71a62","signature":"36aa37b82a71d1451256ab107a5714dcd7b0e73775db33a779dcdd703047b47e"},{"version":"7457091c71c795629e6608f0d2b7132d5a82b514fca5dd19200590646ebfdd0d","signature":"4be0cf8d79dd3d065e03d5d0b3544fe7ef55a07d0f337b0e0d75399d6e8edeec"},{"version":"033183f3e07c8123da9036b2230e7a0d982655ae5f9f3fedd32431140b5ab6c5","signature":"03b14e671dda7f9d14bce7589a9fd9df1955232fc2f9a386e8f348dce096e5aa"},{"version":"bad9cb35ff53dc90f58f570223ced376f650eac46df68e0c663f8838eddf7b9d","signature":"d50234446709c93924529c0508fb514f3a19916424febb911dd43644b268c3ce"},{"version":"0b88bf253914e4480466ccdfbc9bae5d8891c9e2a20ace102059ee01d3ae4582","signature":"f5b5d4d2565e15fa4ea35249f6dfac49afe8d18383b09d6f2732010ea11ff387"},{"version":"abcb770e2d0739e7e135836d444bb51e40409727319104aaa7c2237c469c4c83","signature":"8b9f4974d96b0ed131f8d6fc666e5c48990c24ad021734f546d6acab6d743828"},{"version":"5b34f838294309cf3e868c2277fafb006da9395020b1e609bd80d799e2f685f5","signature":"02cc2e63ce9e2b48aa02c06d8de191fb2f2497bd814ecc3058cc817dbbed7e12"},{"version":"c31dc8d99fbff90dc21e03688efc95e3bc7633531f7c1429de53d9810039394d","signature":"1642157a7dc01181a6ec5fae4a1235322df48321e48dfe753b95436a283e1927"},"318d2da3978dfe9ad88ecd5442a3694764b5c915d02c3eb0456dd7c74fc90109",{"version":"ba877158db20e6494d6306b52e58cc9fec61bca0f168e0613724d4d208382871","signature":"0997461569544422e239d876edc79a9d7d13056f2f8e38b1db886fd508f1d6ee"},"9b766ef6750ed26ef5f53599e619fd04c29105d81cc28716279d1691bc48fa55",{"version":"8857f241d76c5cbcd144fbffb3d17a433887ce85410a6438549b54461d70fc13","signature":"b3929979c35152e2c0d667d240d8cd0f88443e94aa8c457aa6f0455b0fbfd607"},{"version":"d142090eda68447039a260082d250740ccd84e9ddcfe8327f6087f8ab1469f34","signature":"7bb2c604bc7416a7e0dea2042821bdfa0016763660d480dde967602b8dcedeb0"},{"version":"96ec71bbb3f94ee8d8f5e97a7b720bee69e6ab17e5afd23cd3ddc680de03b5a9","signature":"3168d333ebf0629d346dd4a4ba94270dfc111be0e9ffec6808bf94362db2a274"},{"version":"c2c52da0c2c747df890825dc63cb7a61d511b2836cd7b18c0ddd0403c228bd25","signature":"22d17a4242f014f1936d6e194ce4b67598fc1e3e19f05404665973f6c3e612e3"},{"version":"853bece6815b265980b443f83d4ed245ffcccce293aa60dc1bce18aeaec827c8","impliedFormat":99},{"version":"9056fd2f4260a4450954e3e2a7e452ce343b8ee5dd2d8eb9162cc3ac6f815164","signature":"c7c0d5aac178defd5257116d30fcbafc866c7d30b539ae34d67f2af4a60a8d5a"},"71467450570e5dbff1c30766967804ec100d254e471ae7d737c6ac17dd28eab5",{"version":"21bccfc7ed64517768bbb5867fee35ef26e23af2ba0227081c49685ee5bcbf99","signature":"eac8fa25389b9e19a88d3240a2a2a9018f6b6b5a3117007041eb246c4cf0243a"},{"version":"25d287ce4f272889cb18d1a4a1bbbce4510f61a54e3161c36af6e8861974892c","signature":"3163779e52856fd99d3ca639d6e67f993cc57627d5ea929ab6481a98bd5cad24"},{"version":"b50f7438df1d20b5fd5f86aef67c361b7cc541d3efbb233025b069bc02e465c6","signature":"80016cbb5870f8f650a509ef53a186a36089766d3426d3f884276e8502b9aa4d"},{"version":"7cb98bd432df5f315874f66285c8d9ab37ba1fd15fe3892c74135c8284fd066b","signature":"a3b22789c3ad2309c354d06fd13a3ae1b69cc32a57b39ced004e3a9c0435ddcf"},{"version":"68941aafaa2db7181b9ef62e21afc8648596fc4c30eec8e6e2e9af0c8af96739","impliedFormat":99},{"version":"a2f54ab67759f89cc2101fb1d0008e9ea88b2398e2f5808befbc7406ebfe7d45","impliedFormat":99},{"version":"21cf3fc93e67812e34cc6459f378ee169fec5c72d9b73fc75a4fd994ac97d619","signature":"d1b225ce055322c95052c7b45e5f593af90ec1e109b02f7d86a5021f06629803"},{"version":"1ecdc2c8e2b97cd89ebfdc0944c6070bb6af493839c85c8f7d072c6a341ca71f","signature":"20a4889dcdfbfb38e094af503d9764d3dbb68992c42ac620abbe46849766417f"},{"version":"c03f8af8b1acedcd04e899dc11d6f2ce3697aa415e287f217489ba19f5487275","signature":"d8a4f999cc0695d21b3c05450f769c8eb116dabcc84f862437ca63a55675156f"},{"version":"1816a3ab1770ca4e6de9b495267f0b21da3c24d26fd9e20b6833e600acbec1ba","signature":"2342f0f37d8ab3d926a01afa21fc82f0ce50dd243ea018c109f04290dc3955dd"},{"version":"c4d6c4265d1f73ef06c8a5573800425fcfe2f9a669c12d83140327443c9d74a1","signature":"bd9babe770cb24f4ab34f7f3636cf5bbf11308122fab291027d61d2ee1eac2b1"},{"version":"9d47cb4a30bf1d6c2b11624bd258e2be4684585f8b3d876bf758556adf79cf91","signature":"2af59c137264af8b0a67836fd2d4bc54d08274ca98d349b3b2dc6c342e10ce71"},{"version":"d60284fe6e9dc8aac493ee69cfc4b5e89f2c2ed9e21c7e46ea40a3dba29d6cfa","signature":"dadfe66204b0f5dbd8a551a5c613bf3833981afea20be8bd92303a9a96d261b8"},{"version":"457ee66ec0b4409c36fba9e8d21df74cb14d416831fea90cac5165ec3c5018d0","signature":"eb0793356ed53d5a677eb5c91488c9b1f3b313f9372f8285485377576cbc0cff"},{"version":"97a1606cb8ff2f4a9f5baaca79bd97cd4cc09e0385adc7c94b983c93fc402198","signature":"999da91586584b1c82a03997d2091af216ec545e026f7c0b1e34164f91d5f518"},{"version":"793f46a4ecc867e93430e89e521d580e9aabf0caae9c6e9a3eff5bb37169f6ae","signature":"b32053bb17f2f48d828886c94e95cb90aa57ab460d0b6e8e3cd80e510a32e836"},"9e9ef6e94394dfa6b14df3e05316b7391c7b2f74f212c417e2cadb10bcfc27bd","2552a31fad45a9ed1bde87e51b038dc0e786cd364b597162263abbf57018949b","71b9f0ab8a0c41cfe30aadc2b730b4e632ba491de9956cc01a64b24cec734073",{"version":"ee2e5aaba8b9e0c9ca71588f65a54392eab7a8236c5b8d3f194559e50ae55ae4","signature":"89b0f68f8f0b901f9dfff2b9e7255520283a783d6af7f2bc2953d771232317a2"},{"version":"71854cacb74a79b59d694b0e3b2130d413d47e4bb5d2c3844088e6fa68e59729","signature":"89b0f68f8f0b901f9dfff2b9e7255520283a783d6af7f2bc2953d771232317a2"},{"version":"8c54bb3251674e8ac615345ae28bb6dcc01d0528786ab77ce073090c7c0e39e0","signature":"89b0f68f8f0b901f9dfff2b9e7255520283a783d6af7f2bc2953d771232317a2"},{"version":"f15a35f0b0030d0827d03a0ede3bbbc8696fdd90dd7cd6e90d07a1f2dad085f2","signature":"89b0f68f8f0b901f9dfff2b9e7255520283a783d6af7f2bc2953d771232317a2"},{"version":"09ced0ee0b5fc680a5e1833e3636eb7fb2796991d230ec13745cbbcb08ce76ed","signature":"89b0f68f8f0b901f9dfff2b9e7255520283a783d6af7f2bc2953d771232317a2"},"9033876b1f4e2c37404a5af347dc3466e71eadeaae950dd376f7c2f20e160dc8"],"root":[83,501,502,528,[586,593],970,[981,987],[1167,1181],[1183,1188],[1191,1209]],"options":{"allowJs":true,"esModuleInterop":true,"jsx":1,"module":99,"skipLibCheck":true,"strict":true,"target":4},"referencedMap":[[1205,1],[1206,2],[1204,3],[1207,4],[1209,5],[1208,6],[1202,7],[83,8],[1203,9],[501,10],[502,11],[587,12],[1172,13],[1168,14],[1173,15],[1174,16],[1175,17],[1169,18],[1176,15],[1177,17],[1178,19],[1179,14],[1180,20],[591,21],[1181,22],[592,23],[1183,24],[1184,25],[1188,26],[1185,27],[1186,28],[1191,29],[1192,30],[1170,31],[1171,32],[1195,26],[1194,33],[1193,27],[1198,34],[1197,35],[1196,36],[1187,35],[1201,37],[1200,38],[1199,39],[593,8],[1167,40],[970,41],[981,42],[588,8],[983,43],[982,44],[984,45],[589,8],[590,46],[985,8],[987,47],[986,8],[528,48],[586,49],[966,50],[967,51],[968,52],[948,53],[955,54],[773,55],[774,56],[775,56],[776,56],[777,56],[778,57],[779,56],[780,56],[781,56],[782,58],[761,59],[764,59],[762,60],[767,61],[766,62],[763,60],[768,63],[783,64],[784,65],[785,66],[786,66],[787,66],[788,66],[789,66],[790,66],[791,66],[792,67],[793,66],[794,66],[795,68],[796,66],[797,56],[798,66],[799,66],[800,69],[801,70],[772,59],[802,69],[803,66],[804,66],[771,59],[805,59],[769,71],[806,59],[807,72],[808,56],[809,56],[810,56],[811,56],[812,72],[813,72],[814,72],[815,72],[816,56],[817,73],[818,72],[819,72],[820,56],[821,74],[822,59],[823,59],[824,75],[825,75],[826,75],[827,72],[828,76],[829,75],[830,75],[831,75],[832,59],[765,77],[833,78],[834,79],[835,59],[770,59],[836,80],[837,75],[838,56],[839,81],[840,80],[841,75],[842,80],[843,75],[844,75],[845,75],[760,59],[846,64],[847,82],[848,83],[849,64],[850,66],[851,84],[852,85],[853,66],[854,75],[855,72],[856,75],[857,56],[858,75],[859,83],[860,64],[861,83],[862,83],[863,83],[864,83],[865,83],[866,83],[867,83],[868,59],[869,86],[870,75],[871,86],[872,59],[876,87],[873,75],[874,75],[875,75],[878,88],[877,89],[879,88],[880,88],[881,88],[882,88],[883,90],[884,90],[885,75],[886,88],[887,88],[888,88],[889,88],[890,91],[891,88],[892,75],[893,88],[894,64],[895,90],[896,75],[676,92],[671,75],[672,75],[673,75],[674,75],[677,93],[678,93],[679,94],[681,95],[682,93],[683,75],[684,75],[685,75],[686,75],[687,75],[688,95],[690,59],[689,75],[691,96],[692,75],[693,75],[694,75],[695,96],[696,75],[697,75],[698,75],[699,59],[700,97],[946,98],[701,59],[703,99],[702,8],[705,100],[706,101],[704,59],[707,101],[708,75],[709,75],[710,75],[711,64],[712,64],[713,101],[680,59],[714,102],[715,75],[716,75],[717,75],[718,75],[719,64],[720,75],[721,64],[722,75],[723,75],[675,59],[724,75],[725,75],[726,64],[727,94],[728,75],[729,75],[730,64],[731,75],[732,75],[733,75],[734,75],[735,75],[736,75],[737,75],[738,75],[739,75],[744,8],[740,75],[741,75],[742,75],[743,75],[745,103],[746,75],[747,75],[748,75],[749,75],[750,75],[751,104],[752,64],[753,64],[754,75],[755,75],[947,59],[756,75],[757,75],[758,97],[759,75],[898,105],[897,59],[899,75],[900,105],[901,105],[902,64],[903,106],[904,107],[905,108],[906,108],[907,109],[908,108],[909,108],[910,109],[911,108],[912,108],[913,108],[914,108],[916,110],[915,59],[917,110],[918,110],[919,110],[920,110],[921,64],[922,75],[925,59],[923,75],[924,75],[926,111],[927,111],[928,111],[929,59],[930,112],[931,75],[932,112],[933,59],[934,113],[935,114],[936,93],[938,115],[937,116],[939,75],[940,115],[941,115],[942,117],[943,118],[944,119],[945,64],[670,54],[953,8],[969,120],[964,121],[949,122],[961,123],[963,124],[950,125],[951,126],[960,122],[962,127],[957,128],[958,129],[956,8],[959,8],[965,75],[952,127],[954,130],[613,8],[614,8],[611,8],[643,131],[644,132],[616,8],[617,8],[642,133],[615,8],[629,8],[628,134],[612,8],[1039,135],[1037,136],[1040,8],[1036,131],[1044,137],[1043,138],[1041,139],[1042,139],[1038,8],[1033,140],[1032,141],[1035,142],[1034,143],[989,144],[990,8],[998,145],[988,131],[991,131],[993,146],[995,147],[992,131],[996,148],[997,149],[994,131],[620,150],[618,8],[627,151],[621,152],[622,8],[619,153],[623,8],[624,8],[625,154],[626,155],[610,131],[646,156],[609,157],[645,158],[608,131],[661,131],[663,159],[660,160],[662,161],[659,131],[1164,162],[1165,8],[1166,163],[1163,8],[1152,8],[1153,8],[1154,8],[1155,8],[1144,164],[1162,165],[1134,166],[1135,167],[1136,8],[1149,168],[1159,169],[1145,167],[1160,8],[1146,170],[1161,171],[1150,172],[1151,173],[1157,174],[1133,175],[1147,176],[1156,177],[1158,178],[1148,179],[1132,8],[1089,180],[1091,181],[1092,8],[1086,182],[1093,183],[1082,8],[1131,184],[1094,131],[1095,131],[1096,131],[1097,131],[1098,131],[1099,131],[1100,131],[1101,131],[1102,131],[1103,131],[1104,131],[1105,131],[1106,131],[1088,185],[1107,131],[1090,131],[1108,131],[1109,8],[1110,131],[1112,186],[1113,131],[1114,131],[1115,131],[1116,131],[1117,131],[1087,131],[1118,131],[1119,131],[1120,131],[1121,131],[1122,131],[1085,131],[1123,131],[1124,131],[1125,131],[1111,131],[1126,131],[1127,131],[1128,131],[1129,131],[1130,131],[1083,131],[1084,8],[649,187],[652,188],[651,189],[653,8],[647,8],[648,8],[658,190],[654,8],[650,8],[655,8],[656,8],[657,8],[632,191],[636,192],[634,193],[637,8],[630,8],[631,8],[641,194],[638,8],[633,8],[635,8],[639,8],[640,8],[667,195],[665,196],[669,197],[664,198],[668,199],[666,200],[1067,201],[1069,202],[1051,203],[1049,204],[1052,205],[1066,206],[1050,207],[1071,208],[1070,209],[1063,210],[1064,210],[1065,8],[1053,8],[1056,211],[1060,212],[1061,213],[1055,214],[1062,215],[1054,8],[1078,216],[1077,217],[1079,218],[1080,219],[1072,8],[1081,220],[1075,221],[1076,221],[1073,204],[1074,222],[1139,223],[1137,8],[1140,223],[1141,8],[1138,224],[1143,225],[1142,226],[1059,227],[1058,228],[1057,8],[1068,229],[1047,230],[1048,231],[1046,232],[1045,8],[1189,8],[1190,233],[250,8],[527,8],[575,234],[573,8],[542,8],[147,235],[148,235],[149,236],[101,237],[150,238],[151,239],[152,240],[96,8],[99,241],[97,8],[98,8],[153,242],[154,243],[155,244],[156,245],[157,246],[158,247],[159,247],[160,248],[161,249],[162,250],[163,251],[102,8],[100,8],[164,252],[165,253],[166,254],[200,255],[167,256],[168,8],[169,257],[170,258],[171,259],[172,260],[173,261],[174,262],[175,263],[176,264],[177,265],[178,265],[179,266],[180,8],[181,267],[182,268],[184,269],[183,270],[185,271],[186,272],[187,273],[188,274],[189,275],[190,276],[191,277],[192,278],[193,279],[194,280],[195,281],[196,282],[197,283],[103,8],[104,8],[105,8],[144,284],[145,8],[146,8],[198,285],[199,286],[86,8],[204,287],[359,21],[205,288],[203,21],[360,289],[201,290],[202,291],[84,8],[87,292],[357,21],[268,21],[538,293],[562,294],[560,8],[561,8],[530,8],[557,295],[554,296],[555,297],[576,298],[567,8],[570,299],[569,300],[581,300],[568,301],[529,8],[537,302],[556,302],[532,303],[535,304],[563,303],[536,305],[531,8],[574,8],[106,8],[85,8],[547,8],[977,306],[979,307],[978,308],[976,309],[975,8],[1182,8],[1031,310],[1000,311],[1010,311],[1001,311],[1011,311],[1002,311],[1003,311],[1018,311],[1017,311],[1019,311],[1020,311],[1012,311],[1004,311],[1013,311],[1005,311],[1014,311],[1006,311],[1008,311],[1016,312],[1009,311],[1015,312],[1021,312],[1007,311],[1022,311],[1027,311],[1028,311],[1023,311],[999,8],[1029,8],[1025,311],[1024,311],[1026,311],[1030,311],[94,313],[447,314],[452,7],[454,315],[226,316],[254,317],[430,318],[249,319],[237,8],[218,8],[224,8],[420,320],[285,321],[225,8],[389,322],[259,323],[260,324],[356,325],[417,326],[372,327],[424,328],[425,329],[423,330],[422,8],[421,331],[256,332],[227,333],[306,8],[307,334],[222,8],[238,335],[228,336],[290,335],[287,335],[211,335],[252,337],[251,8],[429,338],[439,8],[217,8],[332,339],[333,340],[327,21],[475,8],[335,8],[336,341],[328,342],[481,343],[479,344],[474,8],[416,345],[415,8],[473,346],[329,21],[368,347],[366,348],[476,8],[480,8],[478,349],[477,8],[367,350],[468,351],[471,352],[297,353],[296,354],[295,355],[484,21],[294,356],[279,8],[487,8],[490,8],[489,21],[491,357],[207,8],[426,358],[427,359],[428,360],[240,8],[216,361],[206,8],[348,21],[209,362],[347,363],[346,364],[337,8],[338,8],[345,8],[340,8],[343,365],[339,8],[341,366],[344,367],[342,366],[223,8],[214,8],[215,335],[269,368],[270,369],[267,370],[265,371],[266,372],[262,8],[354,341],[374,341],[446,373],[455,374],[459,375],[433,376],[432,8],[282,8],[492,377],[442,378],[330,379],[331,380],[322,381],[312,8],[353,382],[313,383],[355,384],[350,385],[349,8],[351,8],[365,386],[434,387],[435,388],[315,389],[319,390],[310,391],[412,392],[441,393],[289,394],[390,395],[212,396],[440,397],[208,319],[263,8],[271,398],[401,399],[261,8],[400,400],[95,8],[395,401],[239,8],[308,402],[391,8],[213,8],[272,8],[399,403],[221,8],[277,404],[318,405],[431,406],[317,8],[398,8],[264,8],[403,407],[404,408],[219,8],[406,409],[408,410],[407,411],[242,8],[397,396],[410,412],[396,413],[402,414],[230,8],[233,8],[231,8],[235,8],[232,8],[234,8],[236,415],[229,8],[382,416],[381,8],[387,417],[383,418],[386,419],[385,419],[388,417],[384,418],[276,420],[375,421],[438,422],[494,8],[463,423],[465,424],[314,8],[464,425],[436,387],[493,426],[334,387],[220,8],[316,427],[273,428],[274,429],[275,430],[305,431],[411,431],[291,431],[376,432],[292,432],[258,433],[257,8],[380,434],[379,435],[378,436],[377,437],[437,438],[326,439],[362,440],[325,441],[358,442],[361,443],[419,444],[418,445],[414,446],[371,447],[373,448],[370,449],[409,450],[364,8],[451,8],[363,451],[413,8],[278,452],[311,358],[309,453],[280,454],[283,455],[488,8],[281,456],[284,456],[449,8],[448,8],[450,8],[486,8],[286,457],[324,21],[93,8],[369,458],[255,8],[244,459],[320,8],[457,21],[467,460],[304,21],[461,341],[303,461],[444,462],[302,460],[210,8],[469,463],[300,21],[301,21],[293,8],[243,8],[299,464],[298,465],[241,466],[321,264],[288,264],[405,8],[393,467],[392,8],[453,8],[352,468],[323,21],[445,469],[88,21],[91,470],[92,471],[89,21],[90,8],[253,472],[248,473],[247,8],[246,474],[245,8],[443,475],[456,476],[458,477],[460,478],[462,479],[466,480],[500,481],[470,481],[499,482],[472,483],[482,484],[483,485],[485,486],[495,487],[498,361],[497,8],[496,488],[519,489],[517,490],[518,491],[506,492],[507,490],[514,493],[505,494],[510,495],[520,8],[511,496],[516,497],[522,498],[521,499],[504,500],[512,501],[513,502],[508,503],[515,489],[509,504],[544,505],[543,506],[394,507],[503,8],[525,508],[524,8],[523,8],[526,509],[577,8],[533,8],[534,510],[81,8],[82,8],[13,8],[14,8],[16,8],[15,8],[2,8],[17,8],[18,8],[19,8],[20,8],[21,8],[22,8],[23,8],[24,8],[3,8],[25,8],[26,8],[4,8],[27,8],[31,8],[28,8],[29,8],[30,8],[32,8],[33,8],[34,8],[5,8],[35,8],[36,8],[37,8],[38,8],[6,8],[42,8],[39,8],[40,8],[41,8],[43,8],[7,8],[44,8],[49,8],[50,8],[45,8],[46,8],[47,8],[48,8],[8,8],[54,8],[51,8],[52,8],[53,8],[55,8],[9,8],[56,8],[57,8],[58,8],[60,8],[59,8],[61,8],[62,8],[10,8],[63,8],[64,8],[65,8],[11,8],[66,8],[67,8],[68,8],[69,8],[70,8],[1,8],[71,8],[72,8],[12,8],[76,8],[74,8],[79,8],[78,8],[73,8],[77,8],[75,8],[80,8],[122,511],[132,512],[121,511],[142,513],[113,514],[112,515],[141,488],[135,516],[140,517],[115,518],[129,519],[114,520],[138,521],[110,522],[109,488],[139,523],[111,524],[116,525],[117,8],[120,525],[107,8],[143,526],[133,527],[124,528],[125,529],[127,530],[123,531],[126,532],[136,488],[118,533],[119,534],[128,535],[108,536],[131,527],[130,525],[134,8],[137,537],[579,538],[565,539],[566,538],[564,8],[540,540],[553,541],[546,542],[541,540],[539,8],[545,543],[551,8],[549,8],[550,8],[548,8],[552,544],[585,545],[578,546],[571,547],[580,548],[559,549],[972,550],[973,551],[582,552],[974,553],[583,554],[572,555],[971,556],[584,557],[980,558],[558,8],[607,559],[599,560],[606,561],[601,8],[602,8],[600,562],[603,563],[594,8],[595,8],[596,559],[598,564],[604,8],[605,565],[597,566]],"affectedFilesPendingEmit":[1205,1206,1204,1207,1209,1208,1203,502,587,1172,1168,1173,1174,1175,1169,1176,1177,1178,1179,1180,591,1181,592,1183,1184,1188,1185,1186,1191,1192,1170,1171,1195,1194,1193,1198,1197,1196,1187,1201,1200,1199,593,1167,970,981,588,983,982,984,589,590,985,987,986,528,586],"version":"5.9.3"} 1 + {"fileNames":["../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es5.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2015.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2016.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2017.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2018.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2019.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2020.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2021.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2022.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2023.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2024.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.esnext.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.dom.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.dom.iterable.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2015.core.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2015.collection.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2015.generator.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2015.iterable.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2015.promise.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2015.proxy.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2015.reflect.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2015.symbol.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2015.symbol.wellknown.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2016.array.include.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2016.intl.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2017.arraybuffer.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2017.date.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2017.object.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2017.sharedmemory.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2017.string.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2017.intl.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2017.typedarrays.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2018.asyncgenerator.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2018.asynciterable.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2018.intl.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2018.promise.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2018.regexp.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2019.array.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2019.object.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2019.string.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2019.symbol.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2019.intl.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2020.bigint.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2020.date.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2020.promise.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2020.sharedmemory.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2020.string.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2020.symbol.wellknown.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2020.intl.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2020.number.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2021.promise.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2021.string.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2021.weakref.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2021.intl.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2022.array.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2022.error.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2022.intl.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2022.object.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2022.string.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2022.regexp.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2023.array.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2023.collection.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2023.intl.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2024.arraybuffer.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2024.collection.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2024.object.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2024.promise.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2024.regexp.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2024.sharedmemory.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2024.string.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.esnext.array.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.esnext.collection.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.esnext.intl.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.esnext.disposable.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.esnext.promise.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.esnext.decorators.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.esnext.iterator.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.esnext.float16.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.esnext.error.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.esnext.sharedmemory.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.decorators.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.decorators.legacy.d.ts","./.next/types/routes.d.ts","../../node_modules/.pnpm/@types+react@18.3.28/node_modules/@types/react/global.d.ts","../../node_modules/.pnpm/csstype@3.2.3/node_modules/csstype/index.d.ts","../../node_modules/.pnpm/@types+prop-types@15.7.15/node_modules/@types/prop-types/index.d.ts","../../node_modules/.pnpm/@types+react@18.3.28/node_modules/@types/react/index.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/styled-jsx/types/css.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/styled-jsx/types/macro.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/styled-jsx/types/style.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/styled-jsx/types/global.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/styled-jsx/types/index.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/shared/lib/amp.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/amp.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/get-page-files.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/compatibility/disposable.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/compatibility/indexable.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/compatibility/iterators.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/compatibility/index.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/globals.typedarray.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/buffer.buffer.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/globals.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/web-globals/abortcontroller.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/web-globals/domexception.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/web-globals/events.d.ts","../../node_modules/.pnpm/buffer@5.7.1/node_modules/buffer/index.d.ts","../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/header.d.ts","../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/readable.d.ts","../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/file.d.ts","../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/fetch.d.ts","../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/formdata.d.ts","../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/connector.d.ts","../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/client.d.ts","../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/errors.d.ts","../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/dispatcher.d.ts","../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/global-dispatcher.d.ts","../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/global-origin.d.ts","../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/pool-stats.d.ts","../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/pool.d.ts","../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/handlers.d.ts","../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/balanced-pool.d.ts","../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/agent.d.ts","../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/mock-interceptor.d.ts","../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/mock-agent.d.ts","../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/mock-client.d.ts","../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/mock-pool.d.ts","../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/mock-errors.d.ts","../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/proxy-agent.d.ts","../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/env-http-proxy-agent.d.ts","../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/retry-handler.d.ts","../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/retry-agent.d.ts","../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/api.d.ts","../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/interceptors.d.ts","../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/util.d.ts","../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/cookies.d.ts","../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/patch.d.ts","../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/websocket.d.ts","../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/eventsource.d.ts","../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/filereader.d.ts","../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/diagnostics-channel.d.ts","../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/content-type.d.ts","../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/cache.d.ts","../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/index.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/web-globals/fetch.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/web-globals/navigator.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/web-globals/storage.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/assert.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/assert/strict.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/async_hooks.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/buffer.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/child_process.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/cluster.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/console.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/constants.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/crypto.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/dgram.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/diagnostics_channel.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/dns.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/dns/promises.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/domain.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/events.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/fs.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/fs/promises.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/http.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/http2.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/https.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/inspector.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/inspector.generated.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/module.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/net.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/os.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/path.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/perf_hooks.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/process.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/punycode.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/querystring.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/readline.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/readline/promises.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/repl.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/sea.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/sqlite.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/stream.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/stream/promises.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/stream/consumers.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/stream/web.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/string_decoder.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/test.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/timers.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/timers/promises.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/tls.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/trace_events.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/tty.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/url.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/util.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/v8.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/vm.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/wasi.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/worker_threads.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/zlib.d.ts","../../node_modules/.pnpm/@types+node@22.19.15/node_modules/@types/node/index.d.ts","../../node_modules/.pnpm/@types+react@18.3.28/node_modules/@types/react/canary.d.ts","../../node_modules/.pnpm/@types+react@18.3.28/node_modules/@types/react/experimental.d.ts","../../node_modules/.pnpm/@types+react-dom@18.3.7_@types+react@18.3.28/node_modules/@types/react-dom/index.d.ts","../../node_modules/.pnpm/@types+react-dom@18.3.7_@types+react@18.3.28/node_modules/@types/react-dom/canary.d.ts","../../node_modules/.pnpm/@types+react-dom@18.3.7_@types+react@18.3.28/node_modules/@types/react-dom/experimental.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/lib/fallback.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/compiled/webpack/webpack.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/config.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/lib/load-custom-routes.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/shared/lib/image-config.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/build/webpack/plugins/subresource-integrity-plugin.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/body-streams.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/lib/cache-control.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/lib/setup-exception-listeners.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/lib/worker.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/lib/constants.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/client/components/app-router-headers.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/build/rendering-mode.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/lib/router-utils/build-prefetch-segment-data-route.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/require-hook.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/lib/experimental/ppr.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/build/webpack/plugins/app-build-manifest-plugin.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/lib/page-types.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/build/segment-config/app/app-segment-config.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/build/segment-config/pages/pages-segment-config.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/build/analysis/get-page-static-info.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/build/webpack/loaders/get-module-build-info.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/build/webpack/plugins/middleware-plugin.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/node-polyfill-crypto.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/node-environment-baseline.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/node-environment-extensions/error-inspect.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/node-environment-extensions/random.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/node-environment-extensions/date.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/node-environment-extensions/web-crypto.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/node-environment-extensions/node-crypto.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/node-environment.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/build/page-extensions-type.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/build/webpack/plugins/flight-manifest-plugin.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/instrumentation/types.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/lib/coalesced-function.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/shared/lib/router/utils/middleware-route-matcher.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/lib/router-utils/types.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/shared/lib/modern-browserslist-target.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/shared/lib/constants.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/trace/types.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/trace/trace.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/trace/shared.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/trace/index.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/build/load-jsconfig.d.ts","../../node_modules/.pnpm/@next+env@15.5.14/node_modules/@next/env/dist/index.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/build/webpack/plugins/telemetry-plugin/use-cache-tracker-utils.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/build/webpack/plugins/telemetry-plugin/telemetry-plugin.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/telemetry/storage.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/build/build-context.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/shared/lib/bloom-filter.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/build/webpack-config.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/route-kind.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/route-definitions/route-definition.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/build/swc/generated-native.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/build/swc/types.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/dev/parse-version-info.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/next-devtools/shared/types.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/dev/dev-indicator-server-state.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/lib/parse-stack.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/next-devtools/server/shared.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/next-devtools/shared/stack-frame.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/next-devtools/dev-overlay/utils/get-error-by-type.d.ts","../../node_modules/.pnpm/@types+react@18.3.28/node_modules/@types/react/jsx-runtime.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/next-devtools/dev-overlay/container/runtime-error/render-error.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/next-devtools/dev-overlay/shared.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/dev/hot-reloader-types.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/lib/cache-handlers/types.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/response-cache/types.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/resume-data-cache/cache-store.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/resume-data-cache/resume-data-cache.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/render-result.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/lib/i18n-provider.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/web/next-url.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/compiled/@edge-runtime/cookies/index.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/web/spec-extension/cookies.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/web/spec-extension/request.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/after/builtin-request-context.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/web/spec-extension/fetch-event.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/web/spec-extension/response.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/build/segment-config/middleware/middleware-config.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/web/types.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/build/webpack/plugins/pages-manifest-plugin.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/shared/lib/router/utils/parse-url.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/base-http/node.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/build/webpack/plugins/next-font-manifest-plugin.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/route-definitions/locale-route-definition.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/route-definitions/pages-route-definition.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/shared/lib/mitt.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/client/with-router.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/client/router.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/client/route-loader.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/client/page-loader.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/shared/lib/router/router.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/shared/lib/router-context.shared-runtime.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/shared/lib/loadable-context.shared-runtime.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/shared/lib/loadable.shared-runtime.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/shared/lib/image-config-context.shared-runtime.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/shared/lib/hooks-client-context.shared-runtime.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/shared/lib/head-manager-context.shared-runtime.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/route-definitions/app-page-route-definition.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/build/webpack/loaders/metadata/types.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/build/webpack/loaders/next-app-loader/index.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/lib/app-dir-module.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/web/spec-extension/adapters/request-cookies.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/async-storage/draft-mode-provider.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/web/spec-extension/adapters/headers.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/app-render/cache-signal.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/app-render/dynamic-rendering.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/request/fallback-params.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/app-render/work-unit-async-storage-instance.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/response-cache/index.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/lib/lazy-result.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/lib/implicit-tags.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/app-render/work-unit-async-storage.external.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/shared/lib/deep-readonly.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/shared/lib/router/utils/parse-relative-url.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/app-render/app-render.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/shared/lib/server-inserted-html.shared-runtime.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/shared/lib/amp-context.shared-runtime.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/route-modules/app-page/vendored/contexts/entrypoints.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/route-modules/app-page/module.compiled.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/client/components/error-boundary.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/client/components/layout-router.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/client/components/render-from-template-context.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/app-render/action-async-storage-instance.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/app-render/action-async-storage.external.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/client/components/client-page.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/client/components/client-segment.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/request/search-params.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/client/components/hooks-server-context.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/client/components/http-access-fallback/error-boundary.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/lib/metadata/types/alternative-urls-types.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/lib/metadata/types/extra-types.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/lib/metadata/types/metadata-types.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/lib/metadata/types/manifest-types.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/lib/metadata/types/opengraph-types.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/lib/metadata/types/twitter-types.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/lib/metadata/types/metadata-interface.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/lib/metadata/types/resolvers.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/lib/metadata/types/icons.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/lib/metadata/resolve-metadata.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/lib/metadata/metadata.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/lib/framework/boundary-components.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/app-render/rsc/preloads.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/app-render/rsc/postpone.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/app-render/rsc/taint.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/shared/lib/segment-cache/segment-value-encoding.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/app-render/collect-segment-data.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/next-devtools/userspace/app/segment-explorer-node.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/app-render/entry-base.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/build/templates/app-page.d.ts","../../node_modules/.pnpm/@types+react@18.3.28/node_modules/@types/react/jsx-dev-runtime.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/route-modules/app-page/vendored/rsc/entrypoints.d.ts","../../node_modules/.pnpm/@types+react-dom@18.3.7_@types+react@18.3.28/node_modules/@types/react-dom/client.d.ts","../../node_modules/.pnpm/@types+react-dom@18.3.7_@types+react@18.3.28/node_modules/@types/react-dom/server.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/route-modules/app-page/vendored/ssr/entrypoints.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/route-modules/app-page/module.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/web/adapter.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/use-cache/cache-life.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/app-render/types.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/client/components/router-reducer/router-reducer-types.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/client/flight-data-helpers.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/client/components/router-reducer/fetch-server-response.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/shared/lib/app-router-context.shared-runtime.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/route-modules/pages/vendored/contexts/entrypoints.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/route-modules/pages/module.compiled.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/build/templates/pages.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/route-modules/pages/module.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/next-devtools/userspace/pages/pages-dev-overlay-setup.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/render.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/route-definitions/pages-api-route-definition.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/route-matches/pages-api-route-match.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/route-matchers/route-matcher.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/route-matcher-providers/route-matcher-provider.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/route-matcher-managers/route-matcher-manager.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/normalizers/normalizer.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/normalizers/locale-route-normalizer.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/normalizers/request/pathname-normalizer.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/normalizers/request/suffix.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/normalizers/request/rsc.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/normalizers/request/prefetch-rsc.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/normalizers/request/next-data.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/normalizers/request/segment-prefix-rsc.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/build/static-paths/types.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/base-server.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/lib/async-callback-set.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/shared/lib/router/utils/route-regex.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/shared/lib/router/utils/route-matcher.d.ts","../../node_modules/.pnpm/sharp@0.34.5/node_modules/sharp/lib/index.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/image-optimizer.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/next-server.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/lib/types.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/lib/lru-cache.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/lib/dev-bundler-service.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/dev/static-paths-worker.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/dev/next-dev-server.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/next.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/lib/render-server.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/lib/router-server.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/shared/lib/router/utils/path-match.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/lib/router-utils/filesystem.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/lib/router-utils/setup-dev-bundler.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/lib/router-utils/router-server-context.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/route-modules/route-module.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/load-components.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/route-definitions/app-route-route-definition.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/async-storage/work-store.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/web/http.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/route-modules/app-route/shared-modules.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/client/components/redirect-status-code.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/client/components/redirect-error.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/build/templates/app-route.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/route-modules/app-route/module.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/route-modules/app-route/module.compiled.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/build/segment-config/app/app-segments.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/build/utils.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/build/turborepo-access-trace/types.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/build/turborepo-access-trace/result.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/build/turborepo-access-trace/helpers.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/build/turborepo-access-trace/index.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/export/routes/types.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/export/types.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/export/worker.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/build/worker.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/build/index.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/lib/incremental-cache/index.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/after/after.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/after/after-context.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/app-render/work-async-storage-instance.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/app-render/work-async-storage.external.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/request/params.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/route-matches/route-match.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/request-meta.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/cli/next-test.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/config-shared.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/base-http/index.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/api-utils/index.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/types.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/shared/lib/html-context.shared-runtime.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/shared/lib/utils.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/pages/_app.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/app.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/web/spec-extension/unstable-cache.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/web/spec-extension/revalidate.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/web/spec-extension/unstable-no-store.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/use-cache/cache-tag.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/cache.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/shared/lib/runtime-config.external.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/config.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/pages/_document.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/document.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/shared/lib/dynamic.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dynamic.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/pages/_error.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/error.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/shared/lib/head.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/head.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/request/cookies.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/request/headers.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/request/draft-mode.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/headers.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/shared/lib/get-img-props.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/client/image-component.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/shared/lib/image-external.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/image.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/client/link.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/link.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/client/components/redirect.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/client/components/not-found.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/client/components/forbidden.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/client/components/unauthorized.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/client/components/unstable-rethrow.server.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/client/components/unstable-rethrow.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/client/components/navigation.react-server.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/client/components/unrecognized-action-error.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/client/components/navigation.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/navigation.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/router.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/client/script.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/script.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/web/spec-extension/user-agent.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/compiled/@edge-runtime/primitives/url.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/web/spec-extension/image-response.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/compiled/@vercel/og/satori/index.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/compiled/@vercel/og/emoji/index.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/compiled/@vercel/og/types.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/after/index.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/request/root-params.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/request/connection.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/server.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/types/global.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/types/compiled.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/types.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/index.d.ts","../../node_modules/.pnpm/next@15.5.14_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/image-types/global.d.ts","./next-env.d.ts","./next.config.ts","../../node_modules/.pnpm/source-map-js@1.2.1/node_modules/source-map-js/source-map.d.ts","../../node_modules/.pnpm/postcss@8.5.8/node_modules/postcss/lib/previous-map.d.ts","../../node_modules/.pnpm/postcss@8.5.8/node_modules/postcss/lib/input.d.ts","../../node_modules/.pnpm/postcss@8.5.8/node_modules/postcss/lib/css-syntax-error.d.ts","../../node_modules/.pnpm/postcss@8.5.8/node_modules/postcss/lib/declaration.d.ts","../../node_modules/.pnpm/postcss@8.5.8/node_modules/postcss/lib/root.d.ts","../../node_modules/.pnpm/postcss@8.5.8/node_modules/postcss/lib/warning.d.ts","../../node_modules/.pnpm/postcss@8.5.8/node_modules/postcss/lib/lazy-result.d.ts","../../node_modules/.pnpm/postcss@8.5.8/node_modules/postcss/lib/no-work-result.d.ts","../../node_modules/.pnpm/postcss@8.5.8/node_modules/postcss/lib/processor.d.ts","../../node_modules/.pnpm/postcss@8.5.8/node_modules/postcss/lib/result.d.ts","../../node_modules/.pnpm/postcss@8.5.8/node_modules/postcss/lib/document.d.ts","../../node_modules/.pnpm/postcss@8.5.8/node_modules/postcss/lib/rule.d.ts","../../node_modules/.pnpm/postcss@8.5.8/node_modules/postcss/lib/node.d.ts","../../node_modules/.pnpm/postcss@8.5.8/node_modules/postcss/lib/comment.d.ts","../../node_modules/.pnpm/postcss@8.5.8/node_modules/postcss/lib/container.d.ts","../../node_modules/.pnpm/postcss@8.5.8/node_modules/postcss/lib/at-rule.d.ts","../../node_modules/.pnpm/postcss@8.5.8/node_modules/postcss/lib/list.d.ts","../../node_modules/.pnpm/postcss@8.5.8/node_modules/postcss/lib/postcss.d.ts","../../node_modules/.pnpm/postcss@8.5.8/node_modules/postcss/lib/postcss.d.mts","../../node_modules/.pnpm/tailwindcss@3.4.19_tsx@4.21.0/node_modules/tailwindcss/types/generated/corepluginlist.d.ts","../../node_modules/.pnpm/tailwindcss@3.4.19_tsx@4.21.0/node_modules/tailwindcss/types/generated/colors.d.ts","../../node_modules/.pnpm/tailwindcss@3.4.19_tsx@4.21.0/node_modules/tailwindcss/types/config.d.ts","../../node_modules/.pnpm/tailwindcss@3.4.19_tsx@4.21.0/node_modules/tailwindcss/types/index.d.ts","../../node_modules/.pnpm/@tailwindcss+typography@0.5.19_tailwindcss@3.4.19_tsx@4.21.0_/node_modules/@tailwindcss/typography/src/index.d.ts","./tailwind.config.ts","../../node_modules/.pnpm/@vitest+spy@3.2.4/node_modules/@vitest/spy/dist/index.d.ts","../../node_modules/.pnpm/@vitest+pretty-format@3.2.4/node_modules/@vitest/pretty-format/dist/index.d.ts","../../node_modules/.pnpm/@vitest+utils@3.2.4/node_modules/@vitest/utils/dist/types.d.ts","../../node_modules/.pnpm/@vitest+utils@3.2.4/node_modules/@vitest/utils/dist/helpers.d.ts","../../node_modules/.pnpm/tinyrainbow@2.0.0/node_modules/tinyrainbow/dist/index-8b61d5bc.d.ts","../../node_modules/.pnpm/tinyrainbow@2.0.0/node_modules/tinyrainbow/dist/node.d.ts","../../node_modules/.pnpm/@vitest+utils@3.2.4/node_modules/@vitest/utils/dist/index.d.ts","../../node_modules/.pnpm/@vitest+utils@3.2.4/node_modules/@vitest/utils/dist/types.d-bcelap-c.d.ts","../../node_modules/.pnpm/@vitest+utils@3.2.4/node_modules/@vitest/utils/dist/diff.d.ts","../../node_modules/.pnpm/@vitest+expect@3.2.4/node_modules/@vitest/expect/dist/index.d.ts","../../node_modules/.pnpm/vite@7.3.1_@types+node@22.19.15_jiti@1.21.7_tsx@4.21.0/node_modules/vite/types/hmrpayload.d.ts","../../node_modules/.pnpm/vite@7.3.1_@types+node@22.19.15_jiti@1.21.7_tsx@4.21.0/node_modules/vite/dist/node/chunks/modulerunnertransport.d.ts","../../node_modules/.pnpm/vite@7.3.1_@types+node@22.19.15_jiti@1.21.7_tsx@4.21.0/node_modules/vite/types/customevent.d.ts","../../node_modules/.pnpm/@types+estree@1.0.8/node_modules/@types/estree/index.d.ts","../../node_modules/.pnpm/rollup@4.60.1/node_modules/rollup/dist/rollup.d.ts","../../node_modules/.pnpm/rollup@4.60.1/node_modules/rollup/dist/parseast.d.ts","../../node_modules/.pnpm/vite@7.3.1_@types+node@22.19.15_jiti@1.21.7_tsx@4.21.0/node_modules/vite/types/hot.d.ts","../../node_modules/.pnpm/vite@7.3.1_@types+node@22.19.15_jiti@1.21.7_tsx@4.21.0/node_modules/vite/dist/node/module-runner.d.ts","../../node_modules/.pnpm/esbuild@0.27.4/node_modules/esbuild/lib/main.d.ts","../../node_modules/.pnpm/vite@7.3.1_@types+node@22.19.15_jiti@1.21.7_tsx@4.21.0/node_modules/vite/types/internal/terseroptions.d.ts","../../node_modules/.pnpm/vite@7.3.1_@types+node@22.19.15_jiti@1.21.7_tsx@4.21.0/node_modules/vite/types/internal/csspreprocessoroptions.d.ts","../../node_modules/.pnpm/vite@7.3.1_@types+node@22.19.15_jiti@1.21.7_tsx@4.21.0/node_modules/vite/types/internal/lightningcssoptions.d.ts","../../node_modules/.pnpm/vite@7.3.1_@types+node@22.19.15_jiti@1.21.7_tsx@4.21.0/node_modules/vite/types/importglob.d.ts","../../node_modules/.pnpm/vite@7.3.1_@types+node@22.19.15_jiti@1.21.7_tsx@4.21.0/node_modules/vite/types/metadata.d.ts","../../node_modules/.pnpm/vite@7.3.1_@types+node@22.19.15_jiti@1.21.7_tsx@4.21.0/node_modules/vite/dist/node/index.d.ts","../../node_modules/.pnpm/@vitest+runner@3.2.4/node_modules/@vitest/runner/dist/tasks.d-cksck4of.d.ts","../../node_modules/.pnpm/@vitest+runner@3.2.4/node_modules/@vitest/runner/dist/types.d.ts","../../node_modules/.pnpm/@vitest+utils@3.2.4/node_modules/@vitest/utils/dist/error.d.ts","../../node_modules/.pnpm/@vitest+runner@3.2.4/node_modules/@vitest/runner/dist/index.d.ts","../../node_modules/.pnpm/vitest@3.2.4_@types+node@22.19.15_jiti@1.21.7_tsx@4.21.0/node_modules/vitest/optional-types.d.ts","../../node_modules/.pnpm/vitest@3.2.4_@types+node@22.19.15_jiti@1.21.7_tsx@4.21.0/node_modules/vitest/dist/chunks/environment.d.cl3nlxbe.d.ts","../../node_modules/.pnpm/@vitest+mocker@3.2.4_vite@7.3.1_@types+node@22.19.15_jiti@1.21.7_tsx@4.21.0_/node_modules/@vitest/mocker/dist/registry.d-d765pazg.d.ts","../../node_modules/.pnpm/@vitest+mocker@3.2.4_vite@7.3.1_@types+node@22.19.15_jiti@1.21.7_tsx@4.21.0_/node_modules/@vitest/mocker/dist/types.d-d_arzrdy.d.ts","../../node_modules/.pnpm/@vitest+mocker@3.2.4_vite@7.3.1_@types+node@22.19.15_jiti@1.21.7_tsx@4.21.0_/node_modules/@vitest/mocker/dist/index.d.ts","../../node_modules/.pnpm/@vitest+utils@3.2.4/node_modules/@vitest/utils/dist/source-map.d.ts","../../node_modules/.pnpm/vite-node@3.2.4_@types+node@22.19.15_jiti@1.21.7_tsx@4.21.0/node_modules/vite-node/dist/trace-mapping.d-dlvdeqop.d.ts","../../node_modules/.pnpm/vite-node@3.2.4_@types+node@22.19.15_jiti@1.21.7_tsx@4.21.0/node_modules/vite-node/dist/index.d-dgmxd2u7.d.ts","../../node_modules/.pnpm/vite-node@3.2.4_@types+node@22.19.15_jiti@1.21.7_tsx@4.21.0/node_modules/vite-node/dist/index.d.ts","../../node_modules/.pnpm/@vitest+snapshot@3.2.4/node_modules/@vitest/snapshot/dist/environment.d-dhdq1csl.d.ts","../../node_modules/.pnpm/@vitest+snapshot@3.2.4/node_modules/@vitest/snapshot/dist/rawsnapshot.d-lfsmjfud.d.ts","../../node_modules/.pnpm/@vitest+snapshot@3.2.4/node_modules/@vitest/snapshot/dist/index.d.ts","../../node_modules/.pnpm/@vitest+snapshot@3.2.4/node_modules/@vitest/snapshot/dist/environment.d.ts","../../node_modules/.pnpm/vitest@3.2.4_@types+node@22.19.15_jiti@1.21.7_tsx@4.21.0/node_modules/vitest/dist/chunks/config.d.d2roskhv.d.ts","../../node_modules/.pnpm/vitest@3.2.4_@types+node@22.19.15_jiti@1.21.7_tsx@4.21.0/node_modules/vitest/dist/chunks/worker.d.1gmbbd7g.d.ts","../../node_modules/.pnpm/@types+deep-eql@4.0.2/node_modules/@types/deep-eql/index.d.ts","../../node_modules/.pnpm/assertion-error@2.0.1/node_modules/assertion-error/index.d.ts","../../node_modules/.pnpm/@types+chai@5.2.3/node_modules/@types/chai/index.d.ts","../../node_modules/.pnpm/@vitest+runner@3.2.4/node_modules/@vitest/runner/dist/utils.d.ts","../../node_modules/.pnpm/tinybench@2.9.0/node_modules/tinybench/dist/index.d.ts","../../node_modules/.pnpm/vitest@3.2.4_@types+node@22.19.15_jiti@1.21.7_tsx@4.21.0/node_modules/vitest/dist/chunks/benchmark.d.bwvbvtda.d.ts","../../node_modules/.pnpm/vite-node@3.2.4_@types+node@22.19.15_jiti@1.21.7_tsx@4.21.0/node_modules/vite-node/dist/client.d.ts","../../node_modules/.pnpm/vitest@3.2.4_@types+node@22.19.15_jiti@1.21.7_tsx@4.21.0/node_modules/vitest/dist/chunks/coverage.d.s9rmnxie.d.ts","../../node_modules/.pnpm/@vitest+snapshot@3.2.4/node_modules/@vitest/snapshot/dist/manager.d.ts","../../node_modules/.pnpm/vitest@3.2.4_@types+node@22.19.15_jiti@1.21.7_tsx@4.21.0/node_modules/vitest/dist/chunks/reporters.d.bflkqcl6.d.ts","../../node_modules/.pnpm/vitest@3.2.4_@types+node@22.19.15_jiti@1.21.7_tsx@4.21.0/node_modules/vitest/dist/chunks/vite.d.cmlllifp.d.ts","../../node_modules/.pnpm/vitest@3.2.4_@types+node@22.19.15_jiti@1.21.7_tsx@4.21.0/node_modules/vitest/dist/config.d.ts","../../node_modules/.pnpm/vitest@3.2.4_@types+node@22.19.15_jiti@1.21.7_tsx@4.21.0/node_modules/vitest/config.d.ts","./vitest.config.ts","./src/app/api/revalidate/route.ts","./src/lib/corrections.ts","./src/lib/snap-targets.ts","./src/lib/timeline-engine.tsx","./src/app/components/timestampprovider.tsx","./src/app/components/useeditorkeyboard.ts","./src/lib/api.ts","../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/helpers/typealiases.d.cts","../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/helpers/util.d.cts","../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/index.d.cts","../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/zoderror.d.cts","../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/locales/en.d.cts","../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/errors.d.cts","../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/helpers/parseutil.d.cts","../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/helpers/enumutil.d.cts","../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/helpers/errorutil.d.cts","../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/helpers/partialutil.d.cts","../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/standard-schema.d.cts","../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/types.d.cts","../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/external.d.cts","../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/index.d.cts","../../node_modules/.pnpm/@atproto+lexicon@0.4.14/node_modules/@atproto/lexicon/dist/types.d.ts","../../node_modules/.pnpm/@atproto+lexicon@0.4.14/node_modules/@atproto/lexicon/dist/lexicons.d.ts","../../node_modules/.pnpm/@atproto+lexicon@0.4.14/node_modules/@atproto/lexicon/dist/blob-refs.d.ts","../../node_modules/.pnpm/@atproto+common-web@0.4.19/node_modules/@atproto/common-web/dist/check.d.ts","../../node_modules/.pnpm/@atproto+common-web@0.4.19/node_modules/@atproto/common-web/dist/util.d.ts","../../node_modules/.pnpm/@atproto+common-web@0.4.19/node_modules/@atproto/common-web/dist/arrays.d.ts","../../node_modules/.pnpm/@atproto+common-web@0.4.19/node_modules/@atproto/common-web/dist/async.d.ts","../../node_modules/.pnpm/@atproto+common-web@0.4.19/node_modules/@atproto/common-web/dist/tid.d.ts","../../node_modules/.pnpm/@atproto+common-web@0.4.19/node_modules/@atproto/common-web/dist/ipld.d.ts","../../node_modules/.pnpm/@atproto+common-web@0.4.19/node_modules/@atproto/common-web/dist/retry.d.ts","../../node_modules/.pnpm/@atproto+lex-data@0.0.14/node_modules/@atproto/lex-data/dist/cid.d.ts","../../node_modules/.pnpm/@atproto+lex-data@0.0.14/node_modules/@atproto/lex-data/dist/lex.d.ts","../../node_modules/.pnpm/@atproto+lex-data@0.0.14/node_modules/@atproto/lex-data/dist/blob.d.ts","../../node_modules/.pnpm/@atproto+lex-data@0.0.14/node_modules/@atproto/lex-data/dist/lex-equals.d.ts","../../node_modules/.pnpm/@atproto+lex-data@0.0.14/node_modules/@atproto/lex-data/dist/lex-error.d.ts","../../node_modules/.pnpm/@atproto+lex-data@0.0.14/node_modules/@atproto/lex-data/dist/object.d.ts","../../node_modules/.pnpm/@atproto+lex-data@0.0.14/node_modules/@atproto/lex-data/dist/uint8array-base64.d.ts","../../node_modules/.pnpm/@atproto+lex-data@0.0.14/node_modules/@atproto/lex-data/dist/uint8array.d.ts","../../node_modules/.pnpm/@atproto+lex-data@0.0.14/node_modules/@atproto/lex-data/dist/utf8.d.ts","../../node_modules/.pnpm/@atproto+lex-data@0.0.14/node_modules/@atproto/lex-data/dist/index.d.ts","../../node_modules/.pnpm/@atproto+common-web@0.4.19/node_modules/@atproto/common-web/dist/types.d.ts","../../node_modules/.pnpm/@atproto+common-web@0.4.19/node_modules/@atproto/common-web/dist/times.d.ts","../../node_modules/.pnpm/@atproto+syntax@0.5.2/node_modules/@atproto/syntax/dist/did.d.ts","../../node_modules/.pnpm/@atproto+syntax@0.5.2/node_modules/@atproto/syntax/dist/handle.d.ts","../../node_modules/.pnpm/@atproto+syntax@0.5.2/node_modules/@atproto/syntax/dist/at-identifier.d.ts","../../node_modules/.pnpm/@atproto+syntax@0.5.2/node_modules/@atproto/syntax/dist/nsid.d.ts","../../node_modules/.pnpm/@atproto+syntax@0.5.2/node_modules/@atproto/syntax/dist/aturi_validation.d.ts","../../node_modules/.pnpm/@atproto+syntax@0.5.2/node_modules/@atproto/syntax/dist/recordkey.d.ts","../../node_modules/.pnpm/@atproto+syntax@0.5.2/node_modules/@atproto/syntax/dist/aturi.d.ts","../../node_modules/.pnpm/@atproto+syntax@0.5.2/node_modules/@atproto/syntax/dist/datetime.d.ts","../../node_modules/.pnpm/@atproto+syntax@0.5.2/node_modules/@atproto/syntax/dist/language.d.ts","../../node_modules/.pnpm/@atproto+syntax@0.5.2/node_modules/@atproto/syntax/dist/tid.d.ts","../../node_modules/.pnpm/@atproto+syntax@0.5.2/node_modules/@atproto/syntax/dist/uri.d.ts","../../node_modules/.pnpm/@atproto+syntax@0.5.2/node_modules/@atproto/syntax/dist/index.d.ts","../../node_modules/.pnpm/@atproto+common-web@0.4.19/node_modules/@atproto/common-web/dist/strings.d.ts","../../node_modules/.pnpm/@atproto+common-web@0.4.19/node_modules/@atproto/common-web/dist/did-doc.d.ts","../../node_modules/.pnpm/@atproto+common-web@0.4.19/node_modules/@atproto/common-web/dist/index.d.ts","../../node_modules/.pnpm/@atproto+lexicon@0.4.14/node_modules/@atproto/lexicon/dist/serialize.d.ts","../../node_modules/.pnpm/@atproto+lexicon@0.4.14/node_modules/@atproto/lexicon/dist/index.d.ts","../../node_modules/.pnpm/@atproto+syntax@0.4.3/node_modules/@atproto/syntax/dist/did.d.ts","../../node_modules/.pnpm/@atproto+syntax@0.4.3/node_modules/@atproto/syntax/dist/handle.d.ts","../../node_modules/.pnpm/@atproto+syntax@0.4.3/node_modules/@atproto/syntax/dist/at-identifier.d.ts","../../node_modules/.pnpm/@atproto+syntax@0.4.3/node_modules/@atproto/syntax/dist/nsid.d.ts","../../node_modules/.pnpm/@atproto+syntax@0.4.3/node_modules/@atproto/syntax/dist/aturi_validation.d.ts","../../node_modules/.pnpm/@atproto+syntax@0.4.3/node_modules/@atproto/syntax/dist/aturi.d.ts","../../node_modules/.pnpm/@atproto+syntax@0.4.3/node_modules/@atproto/syntax/dist/datetime.d.ts","../../node_modules/.pnpm/@atproto+syntax@0.4.3/node_modules/@atproto/syntax/dist/language.d.ts","../../node_modules/.pnpm/@atproto+syntax@0.4.3/node_modules/@atproto/syntax/dist/recordkey.d.ts","../../node_modules/.pnpm/@atproto+syntax@0.4.3/node_modules/@atproto/syntax/dist/tid.d.ts","../../node_modules/.pnpm/@atproto+syntax@0.4.3/node_modules/@atproto/syntax/dist/uri.d.ts","../../node_modules/.pnpm/@atproto+syntax@0.4.3/node_modules/@atproto/syntax/dist/index.d.ts","../../node_modules/.pnpm/@atproto+lexicon@0.6.2/node_modules/@atproto/lexicon/dist/types.d.ts","../../node_modules/.pnpm/@atproto+lexicon@0.6.2/node_modules/@atproto/lexicon/dist/lexicons.d.ts","../../node_modules/.pnpm/@atproto+lexicon@0.6.2/node_modules/@atproto/lexicon/dist/blob-refs.d.ts","../../node_modules/.pnpm/@atproto+lexicon@0.6.2/node_modules/@atproto/lexicon/dist/serialize.d.ts","../../node_modules/.pnpm/@atproto+lexicon@0.6.2/node_modules/@atproto/lexicon/dist/index.d.ts","../../node_modules/.pnpm/@atproto+xrpc@0.7.7/node_modules/@atproto/xrpc/dist/types.d.ts","../../node_modules/.pnpm/@atproto+xrpc@0.7.7/node_modules/@atproto/xrpc/dist/fetch-handler.d.ts","../../node_modules/.pnpm/@atproto+xrpc@0.7.7/node_modules/@atproto/xrpc/dist/xrpc-client.d.ts","../../node_modules/.pnpm/@atproto+xrpc@0.7.7/node_modules/@atproto/xrpc/dist/client.d.ts","../../node_modules/.pnpm/@atproto+xrpc@0.7.7/node_modules/@atproto/xrpc/dist/util.d.ts","../../node_modules/.pnpm/@atproto+xrpc@0.7.7/node_modules/@atproto/xrpc/dist/index.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/util.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/admin/deleteaccount.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/admin/disableaccountinvites.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/admin/disableinvitecodes.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/admin/enableaccountinvites.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/server/defs.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/admin/defs.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/admin/getaccountinfo.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/admin/getaccountinfos.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/admin/getinvitecodes.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/repo/strongref.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/admin/getsubjectstatus.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/admin/searchaccounts.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/admin/sendemail.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/admin/updateaccountemail.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/admin/updateaccounthandle.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/admin/updateaccountpassword.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/admin/updateaccountsigningkey.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/admin/updatesubjectstatus.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/identity/getrecommendeddidcredentials.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/identity/defs.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/identity/refreshidentity.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/identity/requestplcoperationsignature.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/identity/resolvedid.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/identity/resolvehandle.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/identity/resolveidentity.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/identity/signplcoperation.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/identity/submitplcoperation.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/identity/updatehandle.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/label/defs.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/label/querylabels.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/lexicon/schema.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/moderation/defs.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/moderation/createreport.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/repo/defs.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/repo/applywrites.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/repo/createrecord.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/repo/deleterecord.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/repo/describerepo.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/repo/getrecord.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/repo/importrepo.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/repo/listmissingblobs.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/repo/listrecords.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/repo/putrecord.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/repo/uploadblob.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/server/activateaccount.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/server/checkaccountstatus.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/server/confirmemail.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/server/createaccount.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/server/createapppassword.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/server/createinvitecode.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/server/createinvitecodes.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/server/createsession.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/server/deactivateaccount.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/server/deleteaccount.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/server/deletesession.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/server/describeserver.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/server/getaccountinvitecodes.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/server/getserviceauth.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/server/getsession.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/server/listapppasswords.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/server/refreshsession.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/server/requestaccountdelete.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/server/requestemailconfirmation.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/server/requestemailupdate.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/server/requestpasswordreset.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/server/reservesigningkey.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/server/resetpassword.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/server/revokeapppassword.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/server/updateemail.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/sync/getblob.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/sync/getblocks.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/sync/getcheckout.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/sync/gethead.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/sync/defs.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/sync/gethoststatus.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/sync/getlatestcommit.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/sync/getrecord.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/sync/getrepo.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/sync/getrepostatus.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/sync/listblobs.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/sync/listhosts.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/sync/listrepos.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/sync/listreposbycollection.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/sync/notifyofupdate.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/sync/requestcrawl.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/temp/addreservedhandle.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/temp/checksignupqueue.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/temp/fetchlabels.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/temp/requestphoneverification.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/richtext/facet.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/embed/defs.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/embed/images.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/embed/video.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/embed/external.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/labeler/defs.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/embed/recordwithmedia.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/embed/record.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/feed/defs.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/graph/defs.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/notification/defs.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/feed/threadgate.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/feed/postgate.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/actor/defs.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/actor/getpreferences.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/actor/getprofile.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/actor/getprofiles.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/actor/getsuggestions.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/actor/profile.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/actor/putpreferences.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/actor/searchactors.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/actor/searchactorstypeahead.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/actor/status.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/feed/describefeedgenerator.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/feed/generator.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/feed/getactorfeeds.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/feed/getactorlikes.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/feed/getauthorfeed.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/feed/getfeed.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/feed/getfeedgenerator.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/feed/getfeedgenerators.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/feed/getfeedskeleton.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/feed/getlikes.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/feed/getlistfeed.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/feed/getposts.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/feed/getpostthread.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/feed/getquotes.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/feed/getrepostedby.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/feed/getsuggestedfeeds.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/feed/gettimeline.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/feed/like.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/feed/post.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/feed/repost.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/feed/searchposts.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/feed/sendinteractions.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/graph/block.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/graph/follow.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/graph/getactorstarterpacks.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/graph/getblocks.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/graph/getfollowers.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/graph/getfollows.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/graph/getknownfollowers.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/graph/getlist.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/graph/getlistblocks.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/graph/getlistmutes.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/graph/getlists.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/graph/getmutes.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/graph/getrelationships.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/graph/getstarterpack.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/graph/getstarterpacks.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/graph/getsuggestedfollowsbyactor.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/graph/list.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/graph/listblock.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/graph/listitem.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/graph/muteactor.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/graph/muteactorlist.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/graph/mutethread.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/graph/searchstarterpacks.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/graph/starterpack.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/graph/unmuteactor.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/graph/unmuteactorlist.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/graph/unmutethread.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/graph/verification.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/labeler/getservices.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/labeler/service.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/notification/declaration.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/notification/getpreferences.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/notification/getunreadcount.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/notification/listactivitysubscriptions.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/notification/listnotifications.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/notification/putactivitysubscription.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/notification/putpreferences.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/notification/putpreferencesv2.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/notification/registerpush.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/notification/unregisterpush.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/notification/updateseen.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/unspecced/checkhandleavailability.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/unspecced/defs.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/unspecced/getageassurancestate.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/unspecced/getconfig.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/unspecced/getpopularfeedgenerators.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/unspecced/getpostthreadotherv2.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/unspecced/getpostthreadv2.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/unspecced/getsuggestedfeeds.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/unspecced/getsuggestedfeedsskeleton.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/unspecced/getsuggestedstarterpacks.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/unspecced/getsuggestedstarterpacksskeleton.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/unspecced/getsuggestedusers.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/unspecced/getsuggestedusersskeleton.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/unspecced/getsuggestionsskeleton.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/unspecced/gettaggedsuggestions.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/unspecced/gettrendingtopics.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/unspecced/gettrends.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/unspecced/gettrendsskeleton.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/unspecced/initageassurance.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/unspecced/searchactorsskeleton.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/unspecced/searchpostsskeleton.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/unspecced/searchstarterpacksskeleton.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/video/defs.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/video/getjobstatus.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/video/getuploadlimits.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/app/bsky/video/uploadvideo.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/chat/bsky/actor/declaration.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/chat/bsky/actor/deleteaccount.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/chat/bsky/actor/exportaccountdata.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/chat/bsky/convo/acceptconvo.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/chat/bsky/actor/defs.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/chat/bsky/convo/defs.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/chat/bsky/convo/addreaction.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/chat/bsky/convo/deletemessageforself.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/chat/bsky/convo/getconvo.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/chat/bsky/convo/getconvoavailability.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/chat/bsky/convo/getconvoformembers.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/chat/bsky/convo/getlog.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/chat/bsky/convo/getmessages.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/chat/bsky/convo/leaveconvo.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/chat/bsky/convo/listconvos.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/chat/bsky/convo/muteconvo.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/chat/bsky/convo/removereaction.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/chat/bsky/convo/sendmessage.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/chat/bsky/convo/sendmessagebatch.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/chat/bsky/convo/unmuteconvo.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/chat/bsky/convo/updateallread.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/chat/bsky/convo/updateread.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/chat/bsky/moderation/getactormetadata.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/chat/bsky/moderation/getmessagecontext.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/chat/bsky/moderation/updateactoraccess.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/tools/ozone/communication/defs.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/tools/ozone/communication/createtemplate.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/tools/ozone/communication/deletetemplate.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/tools/ozone/communication/listtemplates.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/tools/ozone/communication/updatetemplate.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/tools/ozone/hosting/getaccounthistory.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/tools/ozone/moderation/defs.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/tools/ozone/moderation/emitevent.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/tools/ozone/moderation/getevent.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/tools/ozone/moderation/getrecord.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/tools/ozone/moderation/getrecords.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/tools/ozone/moderation/getrepo.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/tools/ozone/moderation/getreporterstats.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/tools/ozone/moderation/getrepos.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/tools/ozone/moderation/getsubjects.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/tools/ozone/moderation/queryevents.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/tools/ozone/moderation/querystatuses.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/tools/ozone/moderation/searchrepos.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/tools/ozone/safelink/defs.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/tools/ozone/safelink/addrule.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/tools/ozone/safelink/queryevents.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/tools/ozone/safelink/queryrules.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/tools/ozone/safelink/removerule.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/tools/ozone/safelink/updaterule.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/tools/ozone/server/getconfig.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/tools/ozone/set/addvalues.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/tools/ozone/set/deleteset.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/tools/ozone/set/deletevalues.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/tools/ozone/set/defs.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/tools/ozone/set/getvalues.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/tools/ozone/set/querysets.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/tools/ozone/set/upsertset.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/tools/ozone/setting/defs.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/tools/ozone/setting/listoptions.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/tools/ozone/setting/removeoptions.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/tools/ozone/setting/upsertoption.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/tools/ozone/signature/defs.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/tools/ozone/signature/findcorrelation.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/tools/ozone/signature/findrelatedaccounts.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/tools/ozone/signature/searchaccounts.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/tools/ozone/team/defs.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/tools/ozone/team/addmember.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/tools/ozone/team/deletemember.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/tools/ozone/team/listmembers.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/tools/ozone/team/updatemember.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/tools/ozone/verification/defs.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/tools/ozone/verification/grantverifications.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/tools/ozone/verification/listverifications.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/tools/ozone/verification/revokeverifications.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/label/subscribelabels.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/types/com/atproto/sync/subscriberepos.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/index.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/moderation/const/labels.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/moderation/mutewords.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/moderation/types.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/types.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/const.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/util.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/client/lexicons.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/rich-text/unicode.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/rich-text/rich-text.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/rich-text/sanitization.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/rich-text/util.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/moderation/ui.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/moderation/decision.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/moderation/util.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/moderation/index.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/mocker.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/session-manager.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/agent.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/atp-agent.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/bsky-agent.d.ts","../../node_modules/.pnpm/@atproto+api@0.15.27/node_modules/@atproto/api/dist/index.d.ts","./src/lib/comments.ts","../../node_modules/.pnpm/vitest@3.2.4_@types+node@22.19.15_jiti@1.21.7_tsx@4.21.0/node_modules/vitest/dist/chunks/worker.d.ckwwzbsj.d.ts","../../node_modules/.pnpm/vitest@3.2.4_@types+node@22.19.15_jiti@1.21.7_tsx@4.21.0/node_modules/vitest/dist/chunks/global.d.mamajcmj.d.ts","../../node_modules/.pnpm/vitest@3.2.4_@types+node@22.19.15_jiti@1.21.7_tsx@4.21.0/node_modules/vitest/dist/chunks/mocker.d.be_2ls6u.d.ts","../../node_modules/.pnpm/vitest@3.2.4_@types+node@22.19.15_jiti@1.21.7_tsx@4.21.0/node_modules/vitest/dist/chunks/suite.d.fvehnv49.d.ts","../../node_modules/.pnpm/expect-type@1.3.0/node_modules/expect-type/dist/utils.d.ts","../../node_modules/.pnpm/expect-type@1.3.0/node_modules/expect-type/dist/overloads.d.ts","../../node_modules/.pnpm/expect-type@1.3.0/node_modules/expect-type/dist/branding.d.ts","../../node_modules/.pnpm/expect-type@1.3.0/node_modules/expect-type/dist/messages.d.ts","../../node_modules/.pnpm/expect-type@1.3.0/node_modules/expect-type/dist/index.d.ts","../../node_modules/.pnpm/vitest@3.2.4_@types+node@22.19.15_jiti@1.21.7_tsx@4.21.0/node_modules/vitest/dist/index.d.ts","./src/lib/corrections.test.ts","./src/lib/ground-truth-export.ts","./src/lib/ground-truth-export.test.ts","./src/lib/snap-targets.test.ts","./src/lib/track-colors.ts","./src/lib/transcript.ts","./src/lib/transcript.test.ts","../../node_modules/.pnpm/@atproto+jwk@0.6.0/node_modules/@atproto/jwk/dist/jwk.d.ts","../../node_modules/.pnpm/@atproto+jwk@0.6.0/node_modules/@atproto/jwk/dist/alg.d.ts","../../node_modules/.pnpm/@atproto+jwk@0.6.0/node_modules/@atproto/jwk/dist/errors.d.ts","../../node_modules/.pnpm/@atproto+jwk@0.6.0/node_modules/@atproto/jwk/dist/jwks.d.ts","../../node_modules/.pnpm/@atproto+jwk@0.6.0/node_modules/@atproto/jwk/dist/jwt.d.ts","../../node_modules/.pnpm/@atproto+jwk@0.6.0/node_modules/@atproto/jwk/dist/jwt-decode.d.ts","../../node_modules/.pnpm/@atproto+jwk@0.6.0/node_modules/@atproto/jwk/dist/util.d.ts","../../node_modules/.pnpm/@atproto+jwk@0.6.0/node_modules/@atproto/jwk/dist/jwt-verify.d.ts","../../node_modules/.pnpm/@atproto+jwk@0.6.0/node_modules/@atproto/jwk/dist/key.d.ts","../../node_modules/.pnpm/@atproto+jwk@0.6.0/node_modules/@atproto/jwk/dist/keyset.d.ts","../../node_modules/.pnpm/@atproto+jwk@0.6.0/node_modules/@atproto/jwk/dist/index.d.ts","../../node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/types/types.d.ts","../../node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/types/jwe/compact/decrypt.d.ts","../../node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/types/jwe/flattened/decrypt.d.ts","../../node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/types/jwe/general/decrypt.d.ts","../../node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/types/jwe/general/encrypt.d.ts","../../node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/types/jws/compact/verify.d.ts","../../node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/types/jws/flattened/verify.d.ts","../../node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/types/jws/general/verify.d.ts","../../node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/types/jwt/verify.d.ts","../../node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/types/jwt/decrypt.d.ts","../../node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/types/jwt/produce.d.ts","../../node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/types/jwe/compact/encrypt.d.ts","../../node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/types/jwe/flattened/encrypt.d.ts","../../node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/types/jws/compact/sign.d.ts","../../node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/types/jws/flattened/sign.d.ts","../../node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/types/jws/general/sign.d.ts","../../node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/types/jwt/sign.d.ts","../../node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/types/jwt/encrypt.d.ts","../../node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/types/jwk/thumbprint.d.ts","../../node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/types/jwk/embedded.d.ts","../../node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/types/jwks/local.d.ts","../../node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/types/jwks/remote.d.ts","../../node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/types/jwt/unsecured.d.ts","../../node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/types/key/export.d.ts","../../node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/types/key/import.d.ts","../../node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/types/util/decode_protected_header.d.ts","../../node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/types/util/decode_jwt.d.ts","../../node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/types/util/errors.d.ts","../../node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/types/key/generate_key_pair.d.ts","../../node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/types/key/generate_secret.d.ts","../../node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/types/util/base64url.d.ts","../../node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/types/util/runtime.d.ts","../../node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/types/index.d.ts","../../node_modules/.pnpm/@atproto+jwk-jose@0.1.11/node_modules/@atproto/jwk-jose/dist/jose-key.d.ts","../../node_modules/.pnpm/@atproto+jwk-jose@0.1.11/node_modules/@atproto/jwk-jose/dist/index.d.ts","../../node_modules/.pnpm/@atproto+jwk-webcrypto@0.2.0/node_modules/@atproto/jwk-webcrypto/dist/webcrypto-key.d.ts","../../node_modules/.pnpm/@atproto+jwk-webcrypto@0.2.0/node_modules/@atproto/jwk-webcrypto/dist/index.d.ts","../../node_modules/.pnpm/@atproto+did@0.3.0/node_modules/@atproto/did/dist/did.d.ts","../../node_modules/.pnpm/@atproto+did@0.3.0/node_modules/@atproto/did/dist/did-document.d.ts","../../node_modules/.pnpm/@atproto+did@0.3.0/node_modules/@atproto/did/dist/utils.d.ts","../../node_modules/.pnpm/@atproto+did@0.3.0/node_modules/@atproto/did/dist/atproto.d.ts","../../node_modules/.pnpm/@atproto+did@0.3.0/node_modules/@atproto/did/dist/did-error.d.ts","../../node_modules/.pnpm/@atproto+did@0.3.0/node_modules/@atproto/did/dist/methods/plc.d.ts","../../node_modules/.pnpm/@atproto+did@0.3.0/node_modules/@atproto/did/dist/methods/web.d.ts","../../node_modules/.pnpm/@atproto+did@0.3.0/node_modules/@atproto/did/dist/methods.d.ts","../../node_modules/.pnpm/@atproto+did@0.3.0/node_modules/@atproto/did/dist/index.d.ts","../../node_modules/.pnpm/@atproto-labs+simple-store@0.3.0/node_modules/@atproto-labs/simple-store/dist/util.d.ts","../../node_modules/.pnpm/@atproto-labs+simple-store@0.3.0/node_modules/@atproto-labs/simple-store/dist/simple-store.d.ts","../../node_modules/.pnpm/@atproto-labs+simple-store@0.3.0/node_modules/@atproto-labs/simple-store/dist/cached-getter.d.ts","../../node_modules/.pnpm/@atproto-labs+simple-store@0.3.0/node_modules/@atproto-labs/simple-store/dist/index.d.ts","../../node_modules/.pnpm/@atproto-labs+did-resolver@0.2.6/node_modules/@atproto-labs/did-resolver/dist/did-method.d.ts","../../node_modules/.pnpm/@atproto-labs+did-resolver@0.2.6/node_modules/@atproto-labs/did-resolver/dist/did-resolver.d.ts","../../node_modules/.pnpm/@atproto-labs+did-resolver@0.2.6/node_modules/@atproto-labs/did-resolver/dist/did-cache.d.ts","../../node_modules/.pnpm/@atproto-labs+did-resolver@0.2.6/node_modules/@atproto-labs/did-resolver/dist/did-resolver-base.d.ts","../../node_modules/.pnpm/@atproto-labs+fetch@0.2.3/node_modules/@atproto-labs/fetch/dist/fetch-error.d.ts","../../node_modules/.pnpm/@atproto-labs+fetch@0.2.3/node_modules/@atproto-labs/fetch/dist/util.d.ts","../../node_modules/.pnpm/@atproto-labs+fetch@0.2.3/node_modules/@atproto-labs/fetch/dist/fetch.d.ts","../../node_modules/.pnpm/@atproto-labs+fetch@0.2.3/node_modules/@atproto-labs/fetch/dist/fetch-request.d.ts","../../node_modules/.pnpm/@atproto-labs+pipe@0.1.1/node_modules/@atproto-labs/pipe/dist/type.d.ts","../../node_modules/.pnpm/@atproto-labs+pipe@0.1.1/node_modules/@atproto-labs/pipe/dist/pipe.d.ts","../../node_modules/.pnpm/@atproto-labs+pipe@0.1.1/node_modules/@atproto-labs/pipe/dist/index.d.ts","../../node_modules/.pnpm/@atproto-labs+fetch@0.2.3/node_modules/@atproto-labs/fetch/dist/fetch-response.d.ts","../../node_modules/.pnpm/@atproto-labs+fetch@0.2.3/node_modules/@atproto-labs/fetch/dist/fetch-wrap.d.ts","../../node_modules/.pnpm/@atproto-labs+fetch@0.2.3/node_modules/@atproto-labs/fetch/dist/index.d.ts","../../node_modules/.pnpm/@atproto-labs+did-resolver@0.2.6/node_modules/@atproto-labs/did-resolver/dist/methods/plc.d.ts","../../node_modules/.pnpm/@atproto-labs+did-resolver@0.2.6/node_modules/@atproto-labs/did-resolver/dist/methods/web.d.ts","../../node_modules/.pnpm/@atproto-labs+did-resolver@0.2.6/node_modules/@atproto-labs/did-resolver/dist/util.d.ts","../../node_modules/.pnpm/@atproto-labs+did-resolver@0.2.6/node_modules/@atproto-labs/did-resolver/dist/did-resolver-common.d.ts","../../node_modules/.pnpm/@atproto-labs+did-resolver@0.2.6/node_modules/@atproto-labs/did-resolver/dist/create-did-resolver.d.ts","../../node_modules/.pnpm/@atproto-labs+simple-store-memory@0.1.4/node_modules/@atproto-labs/simple-store-memory/dist/index.d.ts","../../node_modules/.pnpm/@atproto-labs+did-resolver@0.2.6/node_modules/@atproto-labs/did-resolver/dist/did-cache-memory.d.ts","../../node_modules/.pnpm/@atproto-labs+did-resolver@0.2.6/node_modules/@atproto-labs/did-resolver/dist/methods.d.ts","../../node_modules/.pnpm/@atproto-labs+did-resolver@0.2.6/node_modules/@atproto-labs/did-resolver/dist/index.d.ts","../../node_modules/.pnpm/@atproto-labs+handle-resolver@0.3.6/node_modules/@atproto-labs/handle-resolver/dist/handle-resolver-error.d.ts","../../node_modules/.pnpm/@atproto-labs+handle-resolver@0.3.6/node_modules/@atproto-labs/handle-resolver/dist/types.d.ts","../../node_modules/.pnpm/@atproto-labs+handle-resolver@0.3.6/node_modules/@atproto-labs/handle-resolver/dist/xrpc-handle-resolver.d.ts","../../node_modules/.pnpm/@atproto-labs+handle-resolver@0.3.6/node_modules/@atproto-labs/handle-resolver/dist/internal-resolvers/dns-handle-resolver.d.ts","../../node_modules/.pnpm/@atproto-labs+handle-resolver@0.3.6/node_modules/@atproto-labs/handle-resolver/dist/internal-resolvers/well-known-handler-resolver.d.ts","../../node_modules/.pnpm/@atproto-labs+handle-resolver@0.3.6/node_modules/@atproto-labs/handle-resolver/dist/atproto-handle-resolver.d.ts","../../node_modules/.pnpm/@atproto-labs+handle-resolver@0.3.6/node_modules/@atproto-labs/handle-resolver/dist/atproto-doh-handle-resolver.d.ts","../../node_modules/.pnpm/@atproto-labs+handle-resolver@0.3.6/node_modules/@atproto-labs/handle-resolver/dist/cached-handle-resolver.d.ts","../../node_modules/.pnpm/@atproto-labs+handle-resolver@0.3.6/node_modules/@atproto-labs/handle-resolver/dist/create-handle-resolver.d.ts","../../node_modules/.pnpm/@atproto-labs+handle-resolver@0.3.6/node_modules/@atproto-labs/handle-resolver/dist/index.d.ts","../../node_modules/.pnpm/@atproto+oauth-types@0.6.3/node_modules/@atproto/oauth-types/dist/constants.d.ts","../../node_modules/.pnpm/@atproto+oauth-types@0.6.3/node_modules/@atproto/oauth-types/dist/uri.d.ts","../../node_modules/.pnpm/@atproto+oauth-types@0.6.3/node_modules/@atproto/oauth-types/dist/util.d.ts","../../node_modules/.pnpm/@atproto+oauth-types@0.6.3/node_modules/@atproto/oauth-types/dist/oauth-scope.d.ts","../../node_modules/.pnpm/@atproto+oauth-types@0.6.3/node_modules/@atproto/oauth-types/dist/atproto-oauth-scope.d.ts","../../node_modules/.pnpm/@atproto+oauth-types@0.6.3/node_modules/@atproto/oauth-types/dist/oauth-redirect-uri.d.ts","../../node_modules/.pnpm/@atproto+oauth-types@0.6.3/node_modules/@atproto/oauth-types/dist/oauth-client-id-loopback.d.ts","../../node_modules/.pnpm/@atproto+oauth-types@0.6.3/node_modules/@atproto/oauth-types/dist/atproto-loopback-client-id.d.ts","../../node_modules/.pnpm/@atproto+oauth-types@0.6.3/node_modules/@atproto/oauth-types/dist/oauth-client-metadata.d.ts","../../node_modules/.pnpm/@atproto+oauth-types@0.6.3/node_modules/@atproto/oauth-types/dist/atproto-loopback-client-metadata.d.ts","../../node_modules/.pnpm/@atproto+oauth-types@0.6.3/node_modules/@atproto/oauth-types/dist/atproto-loopback-client-redirect-uris.d.ts","../../node_modules/.pnpm/@atproto+oauth-types@0.6.3/node_modules/@atproto/oauth-types/dist/atproto-oauth-token-response.d.ts","../../node_modules/.pnpm/@atproto+oauth-types@0.6.3/node_modules/@atproto/oauth-types/dist/oauth-access-token.d.ts","../../node_modules/.pnpm/@atproto+oauth-types@0.6.3/node_modules/@atproto/oauth-types/dist/oauth-authorization-code-grant-token-request.d.ts","../../node_modules/.pnpm/@atproto+oauth-types@0.6.3/node_modules/@atproto/oauth-types/dist/oauth-authorization-details.d.ts","../../node_modules/.pnpm/@atproto+oauth-types@0.6.3/node_modules/@atproto/oauth-types/dist/oauth-authorization-request-jar.d.ts","../../node_modules/.pnpm/@atproto+oauth-types@0.6.3/node_modules/@atproto/oauth-types/dist/oauth-authorization-request-par.d.ts","../../node_modules/.pnpm/@atproto+oauth-types@0.6.3/node_modules/@atproto/oauth-types/dist/oauth-authorization-request-parameters.d.ts","../../node_modules/.pnpm/@atproto+oauth-types@0.6.3/node_modules/@atproto/oauth-types/dist/oauth-authorization-request-query.d.ts","../../node_modules/.pnpm/@atproto+oauth-types@0.6.3/node_modules/@atproto/oauth-types/dist/oauth-authorization-request-uri.d.ts","../../node_modules/.pnpm/@atproto+oauth-types@0.6.3/node_modules/@atproto/oauth-types/dist/oauth-authorization-response-error.d.ts","../../node_modules/.pnpm/@atproto+oauth-types@0.6.3/node_modules/@atproto/oauth-types/dist/oauth-authorization-server-metadata.d.ts","../../node_modules/.pnpm/@atproto+oauth-types@0.6.3/node_modules/@atproto/oauth-types/dist/oauth-client-credentials-grant-token-request.d.ts","../../node_modules/.pnpm/@atproto+oauth-types@0.6.3/node_modules/@atproto/oauth-types/dist/oauth-client-credentials.d.ts","../../node_modules/.pnpm/@atproto+oauth-types@0.6.3/node_modules/@atproto/oauth-types/dist/oauth-client-id-discoverable.d.ts","../../node_modules/.pnpm/@atproto+oauth-types@0.6.3/node_modules/@atproto/oauth-types/dist/oauth-client-id.d.ts","../../node_modules/.pnpm/@atproto+oauth-types@0.6.3/node_modules/@atproto/oauth-types/dist/oauth-endpoint-auth-method.d.ts","../../node_modules/.pnpm/@atproto+oauth-types@0.6.3/node_modules/@atproto/oauth-types/dist/oauth-endpoint-name.d.ts","../../node_modules/.pnpm/@atproto+oauth-types@0.6.3/node_modules/@atproto/oauth-types/dist/oauth-grant-type.d.ts","../../node_modules/.pnpm/@atproto+oauth-types@0.6.3/node_modules/@atproto/oauth-types/dist/oauth-token-type.d.ts","../../node_modules/.pnpm/@atproto+oauth-types@0.6.3/node_modules/@atproto/oauth-types/dist/oauth-introspection-response.d.ts","../../node_modules/.pnpm/@atproto+oauth-types@0.6.3/node_modules/@atproto/oauth-types/dist/oauth-issuer-identifier.d.ts","../../node_modules/.pnpm/@atproto+oauth-types@0.6.3/node_modules/@atproto/oauth-types/dist/oauth-par-response.d.ts","../../node_modules/.pnpm/@atproto+oauth-types@0.6.3/node_modules/@atproto/oauth-types/dist/oauth-password-grant-token-request.d.ts","../../node_modules/.pnpm/@atproto+oauth-types@0.6.3/node_modules/@atproto/oauth-types/dist/oauth-prompt-mode.d.ts","../../node_modules/.pnpm/@atproto+oauth-types@0.6.3/node_modules/@atproto/oauth-types/dist/oauth-protected-resource-metadata.d.ts","../../node_modules/.pnpm/@atproto+oauth-types@0.6.3/node_modules/@atproto/oauth-types/dist/oauth-refresh-token-grant-token-request.d.ts","../../node_modules/.pnpm/@atproto+oauth-types@0.6.3/node_modules/@atproto/oauth-types/dist/oauth-refresh-token.d.ts","../../node_modules/.pnpm/@atproto+oauth-types@0.6.3/node_modules/@atproto/oauth-types/dist/oauth-request-uri.d.ts","../../node_modules/.pnpm/@atproto+oauth-types@0.6.3/node_modules/@atproto/oauth-types/dist/oauth-response-mode.d.ts","../../node_modules/.pnpm/@atproto+oauth-types@0.6.3/node_modules/@atproto/oauth-types/dist/oauth-response-type.d.ts","../../node_modules/.pnpm/@atproto+oauth-types@0.6.3/node_modules/@atproto/oauth-types/dist/oauth-token-identification.d.ts","../../node_modules/.pnpm/@atproto+oauth-types@0.6.3/node_modules/@atproto/oauth-types/dist/oauth-token-request.d.ts","../../node_modules/.pnpm/@atproto+oauth-types@0.6.3/node_modules/@atproto/oauth-types/dist/oauth-token-response.d.ts","../../node_modules/.pnpm/@atproto+oauth-types@0.6.3/node_modules/@atproto/oauth-types/dist/oidc-authorization-error-response.d.ts","../../node_modules/.pnpm/@atproto+oauth-types@0.6.3/node_modules/@atproto/oauth-types/dist/oidc-claims-parameter.d.ts","../../node_modules/.pnpm/@atproto+oauth-types@0.6.3/node_modules/@atproto/oauth-types/dist/oidc-claims-properties.d.ts","../../node_modules/.pnpm/@atproto+oauth-types@0.6.3/node_modules/@atproto/oauth-types/dist/oidc-entity-type.d.ts","../../node_modules/.pnpm/@atproto+oauth-types@0.6.3/node_modules/@atproto/oauth-types/dist/oidc-userinfo.d.ts","../../node_modules/.pnpm/@atproto+oauth-types@0.6.3/node_modules/@atproto/oauth-types/dist/index.d.ts","../../node_modules/.pnpm/@atproto+oauth-client@0.6.0/node_modules/@atproto/oauth-client/dist/util.d.ts","../../node_modules/.pnpm/@atproto+oauth-client@0.6.0/node_modules/@atproto/oauth-client/dist/runtime-implementation.d.ts","../../node_modules/.pnpm/@atproto+oauth-client@0.6.0/node_modules/@atproto/oauth-client/dist/lock.d.ts","../../node_modules/.pnpm/@atproto+oauth-client@0.6.0/node_modules/@atproto/oauth-client/dist/oauth-authorization-server-metadata-resolver.d.ts","../../node_modules/.pnpm/@atproto+oauth-client@0.6.0/node_modules/@atproto/oauth-client/dist/oauth-callback-error.d.ts","../../node_modules/.pnpm/@atproto-labs+identity-resolver@0.3.6/node_modules/@atproto-labs/identity-resolver/dist/constants.d.ts","../../node_modules/.pnpm/@atproto-labs+identity-resolver@0.3.6/node_modules/@atproto-labs/identity-resolver/dist/identity-resolver.d.ts","../../node_modules/.pnpm/@atproto-labs+identity-resolver@0.3.6/node_modules/@atproto-labs/identity-resolver/dist/atproto-identity-resolver.d.ts","../../node_modules/.pnpm/@atproto-labs+identity-resolver@0.3.6/node_modules/@atproto-labs/identity-resolver/dist/create-identity-resolver.d.ts","../../node_modules/.pnpm/@atproto-labs+identity-resolver@0.3.6/node_modules/@atproto-labs/identity-resolver/dist/identity-resolver-error.d.ts","../../node_modules/.pnpm/@atproto-labs+identity-resolver@0.3.6/node_modules/@atproto-labs/identity-resolver/dist/util.d.ts","../../node_modules/.pnpm/@atproto-labs+identity-resolver@0.3.6/node_modules/@atproto-labs/identity-resolver/dist/index.d.ts","../../node_modules/.pnpm/@atproto+oauth-client@0.6.0/node_modules/@atproto/oauth-client/dist/identity-resolver.d.ts","../../node_modules/.pnpm/@atproto+oauth-client@0.6.0/node_modules/@atproto/oauth-client/dist/oauth-protected-resource-metadata-resolver.d.ts","../../node_modules/.pnpm/@atproto+oauth-client@0.6.0/node_modules/@atproto/oauth-client/dist/oauth-resolver.d.ts","../../node_modules/.pnpm/@atproto+oauth-client@0.6.0/node_modules/@atproto/oauth-client/dist/runtime.d.ts","../../node_modules/.pnpm/@atproto+oauth-client@0.6.0/node_modules/@atproto/oauth-client/dist/types.d.ts","../../node_modules/.pnpm/@atproto+oauth-client@0.6.0/node_modules/@atproto/oauth-client/dist/oauth-client-auth.d.ts","../../node_modules/.pnpm/@atproto+oauth-client@0.6.0/node_modules/@atproto/oauth-client/dist/oauth-server-agent.d.ts","../../node_modules/.pnpm/@atproto+oauth-client@0.6.0/node_modules/@atproto/oauth-client/dist/oauth-server-factory.d.ts","../../node_modules/.pnpm/@atproto+oauth-client@0.6.0/node_modules/@atproto/oauth-client/dist/errors/auth-method-unsatisfiable-error.d.ts","../../node_modules/.pnpm/@atproto+oauth-client@0.6.0/node_modules/@atproto/oauth-client/dist/errors/token-invalid-error.d.ts","../../node_modules/.pnpm/@atproto+oauth-client@0.6.0/node_modules/@atproto/oauth-client/dist/errors/token-refresh-error.d.ts","../../node_modules/.pnpm/@atproto+oauth-client@0.6.0/node_modules/@atproto/oauth-client/dist/errors/token-revoked-error.d.ts","../../node_modules/.pnpm/@atproto+oauth-client@0.6.0/node_modules/@atproto/oauth-client/dist/session-getter.d.ts","../../node_modules/.pnpm/@atproto+oauth-client@0.6.0/node_modules/@atproto/oauth-client/dist/oauth-session.d.ts","../../node_modules/.pnpm/@atproto+oauth-client@0.6.0/node_modules/@atproto/oauth-client/dist/state-store.d.ts","../../node_modules/.pnpm/@atproto+oauth-client@0.6.0/node_modules/@atproto/oauth-client/dist/oauth-client.d.ts","../../node_modules/.pnpm/@atproto+oauth-client@0.6.0/node_modules/@atproto/oauth-client/dist/oauth-resolver-error.d.ts","../../node_modules/.pnpm/@atproto+oauth-client@0.6.0/node_modules/@atproto/oauth-client/dist/oauth-response-error.d.ts","../../node_modules/.pnpm/@atproto+oauth-client@0.6.0/node_modules/@atproto/oauth-client/dist/index.d.ts","../../node_modules/.pnpm/@atproto+oauth-client-browser@0.3.41/node_modules/@atproto/oauth-client-browser/dist/util.d.ts","../../node_modules/.pnpm/@atproto+oauth-client-browser@0.3.41/node_modules/@atproto/oauth-client-browser/dist/browser-oauth-client.d.ts","../../node_modules/.pnpm/@atproto+oauth-client-browser@0.3.41/node_modules/@atproto/oauth-client-browser/dist/errors.d.ts","../../node_modules/.pnpm/@atproto+oauth-client-browser@0.3.41/node_modules/@atproto/oauth-client-browser/dist/index.d.ts","./src/lib/auth.tsx","./src/app/components/authbutton.tsx","./src/app/components/navheader.tsx","./src/app/layout.tsx","./src/app/page.tsx","./src/app/auth/callback/page.tsx","./src/app/components/commentpanel.tsx","./src/app/components/diarizationband.tsx","./src/app/components/interactionoverlay.tsx","./src/app/components/reactionbar.tsx","./src/app/components/speakerpopover.tsx","./src/app/components/streamtimeline.tsx","./src/app/components/textselector.tsx","./src/app/components/timelinetoolbar.tsx","./src/app/components/transcriptview.tsx","../../node_modules/.pnpm/hls.js@1.6.15/node_modules/hls.js/dist/hls.d.mts","./src/app/components/videoplayer.tsx","./src/app/components/waveformband.tsx","./src/app/components/windowedtranscriptview.tsx","./src/app/concepts/conceptslistcontent.tsx","./src/app/concepts/page.tsx","./src/app/talks/talkslistcontent.tsx","./src/app/concepts/[rkey]/page.tsx","../../node_modules/.pnpm/@chenglou+pretext@0.0.3/node_modules/@chenglou/pretext/dist/analysis.d.ts","../../node_modules/.pnpm/@chenglou+pretext@0.0.3/node_modules/@chenglou/pretext/dist/layout.d.ts","./src/app/concordance/indexcontent.tsx","./src/app/concordance/page.tsx","./src/app/speakers/speakerslistcontent.tsx","./src/app/speakers/page.tsx","./src/app/speakers/[rkey]/page.tsx","./src/app/talks/page.tsx","./src/app/talks/[rkey]/talkcontent.tsx","./src/app/talks/[rkey]/page.tsx","./src/app/tracks/page.tsx","./src/app/tracks/[stream]/trackviewcontent.tsx","./src/app/tracks/[stream]/page.tsx","./.next/types/cache-life.d.ts","./.next/types/validator.ts","./.next/types/app/layout.ts","./.next/types/app/page.ts","./.next/types/app/talks/page.ts","./.next/types/app/talks/[rkey]/page.ts","./.next/types/app/tracks/page.ts"],"fileIdsList":[[101,150,167,168,343,1170],[101,150,167,168,343,1171],[101,150,167,168,343,1199],[101,150,167,168,343,1197],[101,150,167,168,343,1200],[101,150,167,168,448,449,450,451],[101,150,167,168],[83,101,150,167,168,495,498,587,1170,1171,1172,1187,1189,1193,1195,1196,1197,1199,1200,1202],[83,101,150,167,168,499,500],[101,150,167,168,499],[101,150,167,168,495,1203],[87,101,150,167,168,482],[87,101,150,167,168,1167],[87,101,150,167,168,970,1167],[87,101,150,167,168,985],[87,101,150,167,168,590],[87,101,150,167,168,482,1168],[87,101,150,167,168,590,591,985],[101,150,167,168,590],[87,101,150,167,168],[87,101,150,167,168,591,970,986,1167,1179],[87,101,150,167,168,590,591],[87,101,150,167,168,591,1182],[87,101,150,167,168,590,985],[87,101,150,167,168,591,986],[101,150,167,168,499,593,1188],[87,101,150,167,168,591,970,1181,1183],[101,150,167,168,593,1186],[87,101,150,167,168,591,970,1181,1183,1191],[101,150,167,168,1192],[101,150,167,168,499,1167,1169],[101,150,167,168,482],[101,150,167,168,593,1194],[101,150,167,168,499,593,1198],[87,101,150,167,168,591,970,1176,1181,1183],[101,150,167,168,593,1188],[101,150,167,168,499,593,1201],[87,101,150,167,168,588,590,591,592,593,1175,1177,1178,1180,1183,1184,1185],[101,150,167,168,472,593],[87,101,150,167,168,969,1166],[101,150,167,168,969],[101,150,167,168,588,980],[101,150,167,168,588,980,982],[101,150,167,168,588],[101,150,167,168,589,980],[87,101,150,167,168,588,589],[101,150,167,168,980,986],[101,150,167,168,526,527],[101,150,167,168,172,585],[101,150,167,168,669,670,773,824,825,829,830,845,948,951,952,954,965],[101,150,167,168,669,948,952,965,966],[101,150,167,168,967],[101,150,167,168,669,670,671,672,673,674,675,676,677,678,679,680,681,682,683,684,685,686,687,688,689,690,691,692,693,694,695,696,697,698,699,700,701,702,703,704,705,706,707,708,709,710,711,712,713,714,715,716,717,718,719,720,721,722,723,724,725,726,727,728,729,730,731,732,733,734,735,736,737,738,739,740,741,742,743,744,745,746,747,748,749,750,751,752,753,754,755,756,757,758,759,760,761,762,763,764,765,766,767,768,769,770,771,772,773,774,775,776,777,778,779,780,781,782,783,784,785,786,787,788,789,790,791,792,793,794,795,796,797,798,799,800,801,802,803,804,805,806,807,808,809,810,811,812,813,814,815,816,817,818,819,820,821,822,823,824,825,826,827,828,829,830,831,832,833,834,835,836,837,838,839,840,841,842,843,844,845,846,847,848,849,850,851,852,853,854,855,856,857,858,859,860,861,862,863,864,865,866,867,868,869,870,871,872,873,874,875,876,877,878,879,880,881,882,883,884,885,886,887,888,889,890,891,892,893,894,895,896,897,898,899,900,901,902,903,904,905,906,907,908,909,910,911,912,913,914,915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,930,931,932,933,934,935,936,937,938,939,940,941,942,943,944,945,946,947],[101,150,167,168,646],[101,150,167,168,646,670,680,699,764,769,770,771,772],[101,150,167,168,669,773],[101,150,167,168,646,670,680,699],[101,150,167,168,646,670,764],[101,150,167,168,646,670],[101,150,167,168,646,670,761],[101,150,167,168,646,670,680,699,762,763,764,765,766,768,769,773],[101,150,167,168,646,670,762,763,764,767],[101,150,167,168,646,670,699,760,762,763,764,766,767,769,773],[101,150,167,168,646,669,670],[101,150,167,168,646,670,699,760],[101,150,167,168,669,768],[101,150,167,168,646,669,670,773],[101,150,167,168,669,670,768],[101,150,167,168,646,670,680],[101,150,167,168,646,670,680,699,760,762,763,764,766,767],[101,150,167,168,646,670,699,760,768,773],[101,150,167,168,669,769],[101,150,167,168,669,670,769],[101,150,167,168,646,670,699,760,769],[101,150,167,168,669],[101,150,167,168,646,670,760],[101,150,167,168,646,670,699,702,773],[101,150,167,168,669,670,765],[101,150,167,168,646,670,699,702,765],[101,150,167,168,669,770],[101,150,167,168,646,669,670,699,773],[101,150,167,168,646,670,768,773],[101,150,167,168,669,847],[101,150,167,168,646,669,670,847],[101,150,167,168,646,669,670,768,847],[101,150,167,168,669,868],[101,150,167,168,646,670,699,773],[101,150,167,168,669,877],[101,150,167,168,646,670,760,767,876],[101,150,167,168,669,670,877],[101,150,167,168,646,669,670,877],[101,150,167,168,646,670,675],[101,150,167,168,669,676],[101,150,167,168,669,675],[101,150,167,168,669,670,676,680],[101,150,167,168,669,690],[101,150,167,168,669,699],[101,150,167,168,646,670,699],[101,150,167,168,646,669,670,676,680,702],[101,150,167,168,646,669,670,704],[101,150,167,168,669,704],[101,150,167,168,646,669],[101,150,167,168,669,744],[101,150,167,168,646,669,670,744],[101,150,167,168,669,897],[101,150,167,168,646,670,675,676,680,699,702,877],[101,150,167,168,669,670,676,680,903],[101,150,167,168,669,903],[101,150,167,168,669,670,903],[101,150,167,168,669,915],[101,150,167,168,669,925],[101,150,167,168,669,929],[101,150,167,168,669,933],[101,150,167,168,646,669,670,676,933],[101,150,167,168,669,937],[101,150,167,168,646,670,773],[101,150,167,168,646,670,903],[101,150,167,168,646,669,670,942],[101,150,167,168,669,942],[101,150,167,168,644,646,658,670,948,949,951,952,953,954,955,956,957,958,959,963,964,966,967,968],[101,150,167,168,670,948],[101,150,167,168,951],[101,150,167,168,948,950,951,960],[101,150,167,168,950,951,960,961,962],[101,150,167,168,948],[101,150,167,168,948,949,950],[101,150,167,168,948,951],[101,150,167,168,948,956],[101,150,167,168,957],[101,150,167,168,607,773,948],[101,150,167,168,607],[101,150,167,168,611,612,613,614,615,616,617,628,629,642,643],[101,150,167,168,641],[101,150,167,168,607,611,627],[101,150,167,168,607,1036,1037,1038],[101,150,167,168,607,1036],[101,150,167,168,1036,1037,1038,1039,1040,1043],[101,150,167,168,1041,1042],[101,150,167,168,1036],[101,150,167,168,1032],[101,150,167,168,998,1031],[101,150,167,168,1034],[101,150,167,168,998,1033],[101,150,167,168,988],[101,150,167,168,607,988,989,990,991,992,993,995,996,997],[101,150,167,168,992],[101,150,167,168,992,994],[101,150,167,168,988,992,995],[101,150,167,168,988,991,992,994,995,996],[101,150,167,168,618,619],[101,150,167,168,618,619,620,621,622,623,625,626],[101,150,167,168,619],[101,150,167,168,618],[101,150,167,168,624],[101,150,167,168,625],[101,150,167,168,608,609,610,645],[101,150,167,168,608],[101,150,167,168,610,644],[101,150,167,168,659,660,661,662],[101,150,167,168,659],[101,150,167,168,644],[101,150,167,168,1131,1162,1163],[101,150,167,168,1035,1162,1163,1164,1165],[101,150,167,168,1143],[101,150,167,168,998,1044,1062,1071,1081,1131,1133,1134,1135,1136,1145,1148,1150,1151,1153,1154,1155,1156,1157,1158,1159,1160,1161],[101,150,167,168,1133],[101,150,167,168,1048,1062,1131],[101,150,167,168,998,1131,1132,1147,1148],[101,150,167,168,998,1062,1071,1081,1131,1133,1135,1143,1144,1145,1146,1147,1148,1150,1151,1156,1157,1158],[101,150,167,168,1131,1135,1143,1145],[101,150,167,168,1062],[101,150,167,168,998,1044,1048,1062,1131,1146,1147,1148,1149],[101,150,167,168,998,1062,1131,1135,1146,1147,1148,1149,1150],[101,150,167,168,1044,1062,1131,1150,1156],[101,150,167,168,998,1132],[101,150,167,168,998,1133],[101,150,167,168,998,1044,1048,1147,1149,1150,1151,1152,1153,1154,1155],[101,150,167,168,998,1048,1149],[101,150,167,168,607,1131,1132],[101,150,167,168,1086,1087,1088],[101,150,167,168,1086,1087,1088,1089,1090],[101,150,167,168,607,1084,1085],[101,150,167,168,607,1086],[101,150,167,168,1082,1083,1084,1085,1086,1087,1088,1089,1090,1091,1092,1093,1094,1095,1096,1097,1098,1099,1100,1101,1102,1103,1104,1105,1106,1107,1108,1109,1110,1111,1112,1113,1114,1115,1116,1117,1118,1119,1120,1121,1122,1123,1124,1125,1126,1127,1128,1129,1130],[101,150,167,168,607,1085,1087],[101,150,167,168,1096,1111],[101,150,167,168,647,648],[101,150,167,168,649,651],[101,150,167,168,649,650],[101,150,167,168,647,648,649,650,652,653,654,655,656,657],[101,150,167,168,630,631],[101,150,167,168,630,632,633,634,635],[101,150,167,168,632,633],[101,150,167,168,630,631,632,633,635,636,637,638,639,640],[101,150,167,168,663,664,666],[101,150,167,168,664],[101,150,167,168,664,665,666,667,668],[101,150,167,168,607,663],[101,150,167,168,663,664],[101,150,167,168,663,664,665],[101,150,167,168,1044,1050,1051,1066],[101,150,167,168,1044,1051,1068],[101,150,167,168,1044,1048,1049,1050],[101,150,167,168,1044],[101,150,167,168,1044,1049,1050],[101,150,167,168,1052,1063,1064,1065],[101,150,167,168,1044,1049],[101,150,167,168,1044,1049,1050,1051,1066,1067,1069,1070],[101,150,167,168,1063,1064],[101,150,167,168,1044,1049,1062],[101,150,167,168,1053,1055],[101,150,167,168,1053,1054,1059],[101,150,167,168,1055],[101,150,167,168,1054],[101,150,167,168,1053,1054,1055,1056,1060,1061],[101,150,167,168,1073,1077],[101,150,167,168,1073,1075,1076],[101,150,167,168,1048,1073],[101,150,167,168,1073,1074,1079],[101,150,167,168,1072,1073,1074,1077,1078,1079,1080],[101,150,167,168,1073],[101,150,167,168,607,1073],[101,150,167,168,1071,1081,1138],[101,150,167,168,1071,1137],[101,150,167,168,1137,1138,1139,1140,1141,1142],[101,150,167,168,1071],[101,150,167,168,1057,1058],[101,150,167,168,1057],[101,150,167,168,1048],[101,150,167,168,1045,1046],[101,150,167,168,1045,1046,1047],[101,150,167,168,1045],[101,150,167,168,1190],[101,150,167,168,573,574],[101,147,148,150,167,168],[101,149,150,167,168],[150,167,168],[101,150,155,167,168,185],[101,150,151,156,161,167,168,170,182,193],[101,150,151,152,161,167,168,170],[96,97,98,101,150,167,168],[101,150,153,167,168,194],[101,150,154,155,162,167,168,171],[101,150,155,167,168,182,190],[101,150,156,158,161,167,168,170],[101,149,150,157,167,168],[101,150,158,159,167,168],[101,150,160,161,167,168],[101,149,150,161,167,168],[101,150,161,162,163,167,168,182,193],[101,150,161,162,163,167,168,177,182,185],[101,143,150,158,161,164,167,168,170,182,193],[101,150,161,162,164,165,167,168,170,182,190,193],[101,150,164,166,167,168,182,190,193],[99,100,101,102,103,104,105,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199],[101,150,161,167,168],[101,150,167,168,169,193],[101,150,158,161,167,168,170,182],[101,150,167,168,171],[101,150,167,168,172],[101,149,150,167,168,173],[101,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199],[101,150,167,168,175],[101,150,167,168,176],[101,150,161,167,168,177,178],[101,150,167,168,177,179,194,196],[101,150,162,167,168],[101,150,161,167,168,182,183,185],[101,150,167,168,184,185],[101,150,167,168,182,183],[101,150,167,168,185],[101,150,167,168,186],[101,147,150,167,168,182,187,193],[101,150,161,167,168,188,189],[101,150,167,168,188,189],[101,150,155,167,168,170,182,190],[101,150,167,168,191],[101,150,167,168,170,192],[101,150,164,167,168,176,193],[101,150,155,167,168,194],[101,150,167,168,182,195],[101,150,167,168,169,196],[101,150,167,168,197],[101,143,150,167,168],[101,143,150,161,163,167,168,173,182,185,193,195,196,198],[101,150,167,168,182,199],[87,101,150,167,168,203,204,205,359],[87,101,150,167,168,203,204],[87,101,150,167,168,204,359],[87,91,101,150,167,168,202,443,491],[87,91,101,150,167,168,201,443,491],[84,85,86,101,150,167,168],[101,150,167,168,529,534,535,537],[101,150,167,168,560,561],[101,150,167,168,535,537,554,555,556],[101,150,167,168,535],[101,150,167,168,535,537,554],[101,150,167,168,535,554],[101,150,167,168,567],[101,150,167,168,530,567,568],[101,150,167,168,530,567],[101,150,167,168,530,536],[101,150,167,168,531],[101,150,167,168,530,531,532,534],[101,150,167,168,530],[101,150,167,168,975,976],[101,150,167,168,975,976,977,978],[101,150,167,168,975,977],[101,150,167,168,975],[101,150,167,168,999,1000,1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1011,1012,1013,1014,1015,1016,1017,1018,1019,1020,1021,1022,1023,1024,1025,1026,1027,1028,1029,1030],[101,150,167,168,999],[101,150,167,168,999,1009],[93,101,150,167,168],[101,150,167,168,446],[101,150,167,168,453],[101,150,167,168,209,223,224,225,227,440],[101,150,167,168,209,248,250,252,253,256,440,442],[101,150,167,168,209,213,215,216,217,218,219,429,440,442],[101,150,167,168,440],[101,150,167,168,224,326,410,419,436],[101,150,167,168,209],[101,150,167,168,206,436],[101,150,167,168,260],[101,150,167,168,259,440,442],[101,150,164,167,168,308,326,355,497],[101,150,164,167,168,319,335,419,435],[101,150,164,167,168,371],[101,150,167,168,423],[101,150,167,168,422,423,424],[101,150,167,168,422],[95,101,150,164,167,168,206,209,213,216,220,221,222,224,228,236,237,364,389,420,440,443],[101,150,167,168,209,226,244,248,249,254,255,440,497],[101,150,167,168,226,497],[101,150,167,168,237,244,306,440,497],[101,150,167,168,497],[101,150,167,168,209,226,227,497],[101,150,167,168,251,497],[101,150,167,168,220,421,428],[101,150,167,168,176,268,436],[101,150,167,168,268,436],[87,101,150,167,168,268],[87,101,150,167,168,327],[101,150,167,168,323,369,436,479,480],[101,150,167,168,416,473,474,475,476,478],[101,150,167,168,415],[101,150,167,168,415,416],[101,150,167,168,217,365,366,367],[101,150,167,168,365,368,369],[101,150,167,168,477],[101,150,167,168,365,369],[87,101,150,167,168,210,467],[87,101,150,167,168,193],[87,101,150,167,168,226,296],[87,101,150,167,168,226],[101,150,167,168,294,298],[87,101,150,167,168,295,445],[87,91,101,150,164,167,168,200,201,202,443,489,490],[101,150,164,167,168],[101,150,164,167,168,213,275,365,375,390,410,425,426,440,441,497],[101,150,167,168,236,427],[101,150,167,168,443],[101,150,167,168,208],[87,101,150,167,168,308,322,334,344,346,435],[101,150,167,168,176,308,322,343,344,345,435,496],[101,150,167,168,337,338,339,340,341,342],[101,150,167,168,339],[101,150,167,168,343],[101,150,167,168,266,267,268,270],[87,101,150,167,168,261,262,263,269],[101,150,167,168,266,269],[101,150,167,168,264],[101,150,167,168,265],[87,101,150,167,168,268,295,445],[87,101,150,167,168,268,444,445],[87,101,150,167,168,268,445],[101,150,167,168,390,432],[101,150,167,168,432],[101,150,164,167,168,441,445],[101,150,167,168,331],[101,149,150,167,168,330],[101,150,167,168,238,276,314,316,318,319,320,321,362,365,435,438,441],[101,150,167,168,238,352,365,369],[101,150,167,168,319,435],[87,101,150,167,168,319,328,329,331,332,333,334,335,336,347,348,349,350,351,353,354,435,436,497],[101,150,167,168,313],[101,150,164,167,168,176,238,239,275,290,320,362,363,364,369,390,410,431,440,441,442,443,497],[101,150,167,168,435],[101,149,150,167,168,224,317,320,364,431,433,434,441],[101,150,167,168,319],[101,149,150,167,168,275,280,309,310,311,312,313,314,315,316,318,435,436],[101,150,164,167,168,280,281,309,441,442],[101,150,167,168,224,364,365,390,431,435,441],[101,150,164,167,168,440,442],[101,150,164,167,168,182,438,441,442],[101,150,164,167,168,176,193,206,213,226,238,239,241,276,277,282,287,290,316,320,365,375,377,380,382,385,386,387,388,389,410,430,431,436,438,440,441,442],[101,150,164,167,168,182],[101,150,167,168,209,210,211,213,218,221,226,244,430,438,439,443,445,497],[101,150,164,167,168,182,193,256,258,260,261,262,263,270,497],[101,150,167,168,176,193,206,248,258,286,287,288,289,316,365,380,389,390,396,399,400,410,431,436,438],[101,150,167,168,220,221,236,364,389,431,440],[101,150,164,167,168,193,210,213,316,394,438,440],[101,150,167,168,307],[101,150,164,167,168,397,398,407],[101,150,167,168,438,440],[101,150,167,168,314,317],[101,150,167,168,316,320,430,445],[101,150,164,167,168,176,242,248,289,380,390,396,399,402,438],[101,150,164,167,168,220,236,248,403],[101,150,167,168,209,241,405,430,440],[101,150,164,167,168,193,440],[101,150,164,167,168,226,240,241,242,253,271,404,406,430,440],[95,101,150,167,168,238,320,409,443,445],[101,150,164,167,168,176,193,213,220,228,236,239,276,282,286,287,288,289,290,316,365,377,390,391,393,395,410,430,431,436,437,438,445],[101,150,164,167,168,182,220,396,401,407,438],[101,150,167,168,231,232,233,234,235],[101,150,167,168,277,381],[101,150,167,168,383],[101,150,167,168,381],[101,150,167,168,383,384],[101,150,164,167,168,213,216,217,275,441],[101,150,164,167,168,176,208,210,238,276,290,320,373,374,410,438,442,443,445],[101,150,164,167,168,176,193,212,217,316,374,437,441],[101,150,167,168,309],[101,150,167,168,310],[101,150,167,168,311],[101,150,167,168,436],[101,150,167,168,257,273],[101,150,164,167,168,213,257,276],[101,150,167,168,272,273],[101,150,167,168,274],[101,150,167,168,257,258],[101,150,167,168,257,291],[101,150,167,168,257],[101,150,167,168,277,379,437],[101,150,167,168,378],[101,150,167,168,258,436,437],[101,150,167,168,376,437],[101,150,167,168,258,436],[101,150,167,168,362],[101,150,167,168,213,218,276,305,308,314,316,320,322,325,356,358,361,365,409,430,438,441],[101,150,167,168,299,302,303,304,323,324,369],[87,101,150,167,168,203,204,205,268,357],[87,101,150,167,168,203,204,205,268,357,360],[101,150,167,168,418],[101,150,167,168,224,281,319,320,331,335,365,409,411,412,413,414,416,417,420,430,435,440],[101,150,167,168,369],[101,150,167,168,373],[101,150,164,167,168,276,292,370,372,375,409,438,443,445],[101,150,167,168,299,300,301,302,303,304,323,324,369,444],[95,101,150,164,167,168,176,193,239,257,258,290,316,320,407,408,410,430,431,440,441,443],[101,150,167,168,281,283,286,431],[101,150,164,167,168,277,440],[101,150,167,168,280,319],[101,150,167,168,279],[101,150,167,168,281,282],[101,150,167,168,278,280,440],[101,150,164,167,168,212,281,283,284,285,440,441],[87,101,150,167,168,365,366,368],[101,150,167,168,243],[87,101,150,167,168,210],[87,101,150,167,168,436],[87,95,101,150,167,168,290,320,443,445],[101,150,167,168,210,467,468],[87,101,150,167,168,298],[87,101,150,167,168,176,193,208,255,293,295,297,445],[101,150,167,168,226,436,441],[101,150,167,168,392,436],[101,150,167,168,365],[87,101,150,162,164,167,168,176,208,244,250,298,443,444],[87,101,150,167,168,201,202,443,491],[87,88,89,90,91,101,150,167,168],[101,150,155,167,168],[101,150,167,168,245,246,247],[101,150,167,168,245],[87,91,101,150,164,166,167,168,176,200,201,202,203,205,206,208,239,343,402,440,442,445,491],[101,150,167,168,455],[101,150,167,168,457],[101,150,167,168,459],[101,150,167,168,461],[101,150,167,168,463,464,465],[101,150,167,168,469],[92,94,101,150,167,168,447,452,454,456,458,460,462,466,470,472,482,483,485,495,496,497,498],[101,150,167,168,471],[101,150,167,168,481],[101,150,167,168,295],[101,150,167,168,484],[101,149,150,167,168,281,283,284,286,334,436,486,487,488,491,492,493,494],[101,150,167,168,200],[101,150,167,168,518],[101,150,167,168,516,518],[101,150,167,168,507,515,516,517,519,521],[101,150,167,168,505],[101,150,167,168,508,513,518,521],[101,150,167,168,504,521],[101,150,167,168,508,509,512,513,514,521],[101,150,167,168,508,509,510,512,513,521],[101,150,167,168,505,506,507,508,509,513,514,515,517,518,519,521],[101,150,167,168,521],[101,150,167,168,503,505,506,507,508,509,510,512,513,514,515,516,517,518,519,520],[101,150,167,168,503,521],[101,150,167,168,508,510,511,513,514,521],[101,150,167,168,512,521],[101,150,167,168,513,514,518,521],[101,150,167,168,506,516],[101,150,167,168,543,552,553],[101,150,167,168,542,543],[101,150,167,168,182,200],[101,150,167,168,523,524],[101,150,167,168,522,525],[101,150,167,168,533],[101,115,119,150,167,168,193],[101,115,150,167,168,182,193],[101,110,150,167,168],[101,112,115,150,167,168,190,193],[101,150,167,168,170,190],[101,110,150,167,168,200],[101,112,115,150,167,168,170,193],[101,107,108,111,114,150,161,167,168,182,193],[101,115,122,150,167,168],[101,107,113,150,167,168],[101,115,136,137,150,167,168],[101,111,115,150,167,168,185,193,200],[101,136,150,167,168,200],[101,109,110,150,167,168,200],[101,115,150,167,168],[101,109,110,111,112,113,114,115,116,117,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,137,138,139,140,141,142,150,167,168],[101,115,130,150,167,168],[101,115,122,123,150,167,168],[101,113,115,123,124,150,167,168],[101,114,150,167,168],[101,107,110,115,150,167,168],[101,115,119,123,124,150,167,168],[101,119,150,167,168],[101,113,115,118,150,167,168,193],[101,107,112,115,122,150,167,168],[101,150,167,168,182],[101,110,115,136,150,167,168,198,200],[101,150,167,168,564,565],[101,150,167,168,564],[101,150,167,168,539],[101,150,161,162,164,165,166,167,168,170,182,190,193,199,200,522,539,540,541,543,544,546,547,548,549,550,551,552,553],[101,150,167,168,539,540,541,545],[101,150,167,168,541],[101,150,167,168,543,553],[101,150,167,168,538,584,972],[101,150,167,168,557,576,577,972],[101,150,167,168,530,537,557,569,570,972],[101,150,167,168,579],[101,150,167,168,558],[101,150,167,168,530,538,557,559,569,578,972],[101,150,167,168,562],[101,150,153,162,167,168,182,530,535,537,553,557,559,562,563,566,569,571,572,575,578,580,581,583,972],[101,150,167,168,557,576,577,578,972],[101,150,167,168,553,582,583],[101,150,167,168,557,559,566,569,571,972],[101,150,167,168,198,572],[101,150,153,162,167,168,182,530,535,537,553,557,558,559,562,563,566,569,570,571,572,575,576,577,578,579,580,581,582,583,972],[101,150,153,162,167,168,182,198,529,530,535,537,538,553,557,558,559,562,563,566,569,570,571,572,575,576,577,578,579,580,581,582,583,971,972,973,974,979],[101,150,167,168,606],[101,150,167,168,597,598],[101,150,167,168,594,595,597,599,600,605],[101,150,167,168,595,597],[101,150,167,168,605],[101,150,167,168,597],[101,150,167,168,594,595,597,600,601,602,603,604],[101,150,167,168,594,595,596]],"fileInfos":[{"version":"c430d44666289dae81f30fa7b2edebf186ecc91a2d4c71266ea6ae76388792e1","affectsGlobalScope":true,"impliedFormat":1},{"version":"45b7ab580deca34ae9729e97c13cfd999df04416a79116c3bfb483804f85ded4","impliedFormat":1},{"version":"3facaf05f0c5fc569c5649dd359892c98a85557e3e0c847964caeb67076f4d75","impliedFormat":1},{"version":"e44bb8bbac7f10ecc786703fe0a6a4b952189f908707980ba8f3c8975a760962","impliedFormat":1},{"version":"5e1c4c362065a6b95ff952c0eab010f04dcd2c3494e813b493ecfd4fcb9fc0d8","impliedFormat":1},{"version":"68d73b4a11549f9c0b7d352d10e91e5dca8faa3322bfb77b661839c42b1ddec7","impliedFormat":1},{"version":"5efce4fc3c29ea84e8928f97adec086e3dc876365e0982cc8479a07954a3efd4","impliedFormat":1},{"version":"feecb1be483ed332fad555aff858affd90a48ab19ba7272ee084704eb7167569","impliedFormat":1},{"version":"ee7bad0c15b58988daa84371e0b89d313b762ab83cb5b31b8a2d1162e8eb41c2","impliedFormat":1},{"version":"27bdc30a0e32783366a5abeda841bc22757c1797de8681bbe81fbc735eeb1c10","impliedFormat":1},{"version":"8fd575e12870e9944c7e1d62e1f5a73fcf23dd8d3a321f2a2c74c20d022283fe","impliedFormat":1},{"version":"2ab096661c711e4a81cc464fa1e6feb929a54f5340b46b0a07ac6bbf857471f0","impliedFormat":1},{"version":"080941d9f9ff9307f7e27a83bcd888b7c8270716c39af943532438932ec1d0b9","affectsGlobalScope":true,"impliedFormat":1},{"version":"2e80ee7a49e8ac312cc11b77f1475804bee36b3b2bc896bead8b6e1266befb43","affectsGlobalScope":true,"impliedFormat":1},{"version":"c57796738e7f83dbc4b8e65132f11a377649c00dd3eee333f672b8f0a6bea671","affectsGlobalScope":true,"impliedFormat":1},{"version":"dc2df20b1bcdc8c2d34af4926e2c3ab15ffe1160a63e58b7e09833f616efff44","affectsGlobalScope":true,"impliedFormat":1},{"version":"515d0b7b9bea2e31ea4ec968e9edd2c39d3eebf4a2d5cbd04e88639819ae3b71","affectsGlobalScope":true,"impliedFormat":1},{"version":"0559b1f683ac7505ae451f9a96ce4c3c92bdc71411651ca6ddb0e88baaaad6a3","affectsGlobalScope":true,"impliedFormat":1},{"version":"0dc1e7ceda9b8b9b455c3a2d67b0412feab00bd2f66656cd8850e8831b08b537","affectsGlobalScope":true,"impliedFormat":1},{"version":"ce691fb9e5c64efb9547083e4a34091bcbe5bdb41027e310ebba8f7d96a98671","affectsGlobalScope":true,"impliedFormat":1},{"version":"8d697a2a929a5fcb38b7a65594020fcef05ec1630804a33748829c5ff53640d0","affectsGlobalScope":true,"impliedFormat":1},{"version":"4ff2a353abf8a80ee399af572debb8faab2d33ad38c4b4474cff7f26e7653b8d","affectsGlobalScope":true,"impliedFormat":1},{"version":"fb0f136d372979348d59b3f5020b4cdb81b5504192b1cacff5d1fbba29378aa1","affectsGlobalScope":true,"impliedFormat":1},{"version":"d15bea3d62cbbdb9797079416b8ac375ae99162a7fba5de2c6c505446486ac0a","affectsGlobalScope":true,"impliedFormat":1},{"version":"68d18b664c9d32a7336a70235958b8997ebc1c3b8505f4f1ae2b7e7753b87618","affectsGlobalScope":true,"impliedFormat":1},{"version":"eb3d66c8327153d8fa7dd03f9c58d351107fe824c79e9b56b462935176cdf12a","affectsGlobalScope":true,"impliedFormat":1},{"version":"38f0219c9e23c915ef9790ab1d680440d95419ad264816fa15009a8851e79119","affectsGlobalScope":true,"impliedFormat":1},{"version":"69ab18c3b76cd9b1be3d188eaf8bba06112ebbe2f47f6c322b5105a6fbc45a2e","affectsGlobalScope":true,"impliedFormat":1},{"version":"a680117f487a4d2f30ea46f1b4b7f58bef1480456e18ba53ee85c2746eeca012","affectsGlobalScope":true,"impliedFormat":1},{"version":"2f11ff796926e0832f9ae148008138ad583bd181899ab7dd768a2666700b1893","affectsGlobalScope":true,"impliedFormat":1},{"version":"4de680d5bb41c17f7f68e0419412ca23c98d5749dcaaea1896172f06435891fc","affectsGlobalScope":true,"impliedFormat":1},{"version":"954296b30da6d508a104a3a0b5d96b76495c709785c1d11610908e63481ee667","affectsGlobalScope":true,"impliedFormat":1},{"version":"ac9538681b19688c8eae65811b329d3744af679e0bdfa5d842d0e32524c73e1c","affectsGlobalScope":true,"impliedFormat":1},{"version":"0a969edff4bd52585473d24995c5ef223f6652d6ef46193309b3921d65dd4376","affectsGlobalScope":true,"impliedFormat":1},{"version":"9e9fbd7030c440b33d021da145d3232984c8bb7916f277e8ffd3dc2e3eae2bdb","affectsGlobalScope":true,"impliedFormat":1},{"version":"811ec78f7fefcabbda4bfa93b3eb67d9ae166ef95f9bff989d964061cbf81a0c","affectsGlobalScope":true,"impliedFormat":1},{"version":"717937616a17072082152a2ef351cb51f98802fb4b2fdabd32399843875974ca","affectsGlobalScope":true,"impliedFormat":1},{"version":"d7e7d9b7b50e5f22c915b525acc5a49a7a6584cf8f62d0569e557c5cfc4b2ac2","affectsGlobalScope":true,"impliedFormat":1},{"version":"71c37f4c9543f31dfced6c7840e068c5a5aacb7b89111a4364b1d5276b852557","affectsGlobalScope":true,"impliedFormat":1},{"version":"576711e016cf4f1804676043e6a0a5414252560eb57de9faceee34d79798c850","affectsGlobalScope":true,"impliedFormat":1},{"version":"89c1b1281ba7b8a96efc676b11b264de7a8374c5ea1e6617f11880a13fc56dc6","affectsGlobalScope":true,"impliedFormat":1},{"version":"74f7fa2d027d5b33eb0471c8e82a6c87216223181ec31247c357a3e8e2fddc5b","affectsGlobalScope":true,"impliedFormat":1},{"version":"d6d7ae4d1f1f3772e2a3cde568ed08991a8ae34a080ff1151af28b7f798e22ca","affectsGlobalScope":true,"impliedFormat":1},{"version":"063600664504610fe3e99b717a1223f8b1900087fab0b4cad1496a114744f8df","affectsGlobalScope":true,"impliedFormat":1},{"version":"934019d7e3c81950f9a8426d093458b65d5aff2c7c1511233c0fd5b941e608ab","affectsGlobalScope":true,"impliedFormat":1},{"version":"52ada8e0b6e0482b728070b7639ee42e83a9b1c22d205992756fe020fd9f4a47","affectsGlobalScope":true,"impliedFormat":1},{"version":"3bdefe1bfd4d6dee0e26f928f93ccc128f1b64d5d501ff4a8cf3c6371200e5e6","affectsGlobalScope":true,"impliedFormat":1},{"version":"59fb2c069260b4ba00b5643b907ef5d5341b167e7d1dbf58dfd895658bda2867","affectsGlobalScope":true,"impliedFormat":1},{"version":"639e512c0dfc3fad96a84caad71b8834d66329a1f28dc95e3946c9b58176c73a","affectsGlobalScope":true,"impliedFormat":1},{"version":"368af93f74c9c932edd84c58883e736c9e3d53cec1fe24c0b0ff451f529ceab1","affectsGlobalScope":true,"impliedFormat":1},{"version":"af3dd424cf267428f30ccfc376f47a2c0114546b55c44d8c0f1d57d841e28d74","affectsGlobalScope":true,"impliedFormat":1},{"version":"995c005ab91a498455ea8dfb63aa9f83fa2ea793c3d8aa344be4a1678d06d399","affectsGlobalScope":true,"impliedFormat":1},{"version":"959d36cddf5e7d572a65045b876f2956c973a586da58e5d26cde519184fd9b8a","affectsGlobalScope":true,"impliedFormat":1},{"version":"965f36eae237dd74e6cca203a43e9ca801ce38824ead814728a2807b1910117d","affectsGlobalScope":true,"impliedFormat":1},{"version":"3925a6c820dcb1a06506c90b1577db1fdbf7705d65b62b99dce4be75c637e26b","affectsGlobalScope":true,"impliedFormat":1},{"version":"0a3d63ef2b853447ec4f749d3f368ce642264246e02911fcb1590d8c161b8005","affectsGlobalScope":true,"impliedFormat":1},{"version":"8cdf8847677ac7d20486e54dd3fcf09eda95812ac8ace44b4418da1bbbab6eb8","affectsGlobalScope":true,"impliedFormat":1},{"version":"8444af78980e3b20b49324f4a16ba35024fef3ee069a0eb67616ea6ca821c47a","affectsGlobalScope":true,"impliedFormat":1},{"version":"3287d9d085fbd618c3971944b65b4be57859f5415f495b33a6adc994edd2f004","affectsGlobalScope":true,"impliedFormat":1},{"version":"b4b67b1a91182421f5df999988c690f14d813b9850b40acd06ed44691f6727ad","affectsGlobalScope":true,"impliedFormat":1},{"version":"df83c2a6c73228b625b0beb6669c7ee2a09c914637e2d35170723ad49c0f5cd4","affectsGlobalScope":true,"impliedFormat":1},{"version":"436aaf437562f276ec2ddbee2f2cdedac7664c1e4c1d2c36839ddd582eeb3d0a","affectsGlobalScope":true,"impliedFormat":1},{"version":"8e3c06ea092138bf9fa5e874a1fdbc9d54805d074bee1de31b99a11e2fec239d","affectsGlobalScope":true,"impliedFormat":1},{"version":"87dc0f382502f5bbce5129bdc0aea21e19a3abbc19259e0b43ae038a9fc4e326","affectsGlobalScope":true,"impliedFormat":1},{"version":"b1cb28af0c891c8c96b2d6b7be76bd394fddcfdb4709a20ba05a7c1605eea0f9","affectsGlobalScope":true,"impliedFormat":1},{"version":"2fef54945a13095fdb9b84f705f2b5994597640c46afeb2ce78352fab4cb3279","affectsGlobalScope":true,"impliedFormat":1},{"version":"ac77cb3e8c6d3565793eb90a8373ee8033146315a3dbead3bde8db5eaf5e5ec6","affectsGlobalScope":true,"impliedFormat":1},{"version":"56e4ed5aab5f5920980066a9409bfaf53e6d21d3f8d020c17e4de584d29600ad","affectsGlobalScope":true,"impliedFormat":1},{"version":"4ece9f17b3866cc077099c73f4983bddbcb1dc7ddb943227f1ec070f529dedd1","affectsGlobalScope":true,"impliedFormat":1},{"version":"0a6282c8827e4b9a95f4bf4f5c205673ada31b982f50572d27103df8ceb8013c","affectsGlobalScope":true,"impliedFormat":1},{"version":"1c9319a09485199c1f7b0498f2988d6d2249793ef67edda49d1e584746be9032","affectsGlobalScope":true,"impliedFormat":1},{"version":"e3a2a0cee0f03ffdde24d89660eba2685bfbdeae955a6c67e8c4c9fd28928eeb","affectsGlobalScope":true,"impliedFormat":1},{"version":"811c71eee4aa0ac5f7adf713323a5c41b0cf6c4e17367a34fbce379e12bbf0a4","affectsGlobalScope":true,"impliedFormat":1},{"version":"51ad4c928303041605b4d7ae32e0c1ee387d43a24cd6f1ebf4a2699e1076d4fa","affectsGlobalScope":true,"impliedFormat":1},{"version":"60037901da1a425516449b9a20073aa03386cce92f7a1fd902d7602be3a7c2e9","affectsGlobalScope":true,"impliedFormat":1},{"version":"d4b1d2c51d058fc21ec2629fff7a76249dec2e36e12960ea056e3ef89174080f","affectsGlobalScope":true,"impliedFormat":1},{"version":"22adec94ef7047a6c9d1af3cb96be87a335908bf9ef386ae9fd50eeb37f44c47","affectsGlobalScope":true,"impliedFormat":1},{"version":"196cb558a13d4533a5163286f30b0509ce0210e4b316c56c38d4c0fd2fb38405","affectsGlobalScope":true,"impliedFormat":1},{"version":"73f78680d4c08509933daf80947902f6ff41b6230f94dd002ae372620adb0f60","affectsGlobalScope":true,"impliedFormat":1},{"version":"c5239f5c01bcfa9cd32f37c496cf19c61d69d37e48be9de612b541aac915805b","affectsGlobalScope":true,"impliedFormat":1},{"version":"8e7f8264d0fb4c5339605a15daadb037bf238c10b654bb3eee14208f860a32ea","affectsGlobalScope":true,"impliedFormat":1},{"version":"782dec38049b92d4e85c1585fbea5474a219c6984a35b004963b00beb1aab538","affectsGlobalScope":true,"impliedFormat":1},{"version":"d6b520432c6ffb434a25b184060fc141f8870d2656894bdb1b0f7352b107e8fc","affectsGlobalScope":true},{"version":"eb5b19b86227ace1d29ea4cf81387279d04bb34051e944bc53df69f58914b788","affectsGlobalScope":true,"impliedFormat":1},{"version":"ac51dd7d31333793807a6abaa5ae168512b6131bd41d9c5b98477fc3b7800f9f","impliedFormat":1},{"version":"87d9d29dbc745f182683f63187bf3d53fd8673e5fca38ad5eaab69798ed29fbc","impliedFormat":1},{"version":"035312d4945d13efa134ae482f6dc56a1a9346f7ac3be7ccbad5741058ce87f3","affectsGlobalScope":true,"impliedFormat":1},{"version":"acd8fd5090ac73902278889c38336ff3f48af6ba03aa665eb34a75e7ba1dccc4","impliedFormat":1},{"version":"d6258883868fb2680d2ca96bc8b1352cab69874581493e6d52680c5ffecdb6cc","impliedFormat":1},{"version":"1b61d259de5350f8b1e5db06290d31eaebebc6baafd5f79d314b5af9256d7153","impliedFormat":1},{"version":"f258e3960f324a956fc76a3d3d9e964fff2244ff5859dcc6ce5951e5413ca826","impliedFormat":1},{"version":"643f7232d07bf75e15bd8f658f664d6183a0efaca5eb84b48201c7671a266979","impliedFormat":1},{"version":"0f6666b58e9276ac3a38fdc80993d19208442d6027ab885580d93aec76b4ef00","impliedFormat":1},{"version":"05fd364b8ef02fb1e174fbac8b825bdb1e5a36a016997c8e421f5fab0a6da0a0","impliedFormat":1},{"version":"631eff75b0e35d1b1b31081d55209abc43e16b49426546ab5a9b40bdd40b1f60","impliedFormat":1},{"version":"6c7176368037af28cb72f2392010fa1cef295d6d6744bca8cfb54985f3a18c3e","affectsGlobalScope":true,"impliedFormat":1},{"version":"ab41ef1f2cdafb8df48be20cd969d875602483859dc194e9c97c8a576892c052","affectsGlobalScope":true,"impliedFormat":1},{"version":"437e20f2ba32abaeb7985e0afe0002de1917bc74e949ba585e49feba65da6ca1","affectsGlobalScope":true,"impliedFormat":1},{"version":"21d819c173c0cf7cc3ce57c3276e77fd9a8a01d35a06ad87158781515c9a438a","impliedFormat":1},{"version":"98cffbf06d6bab333473c70a893770dbe990783904002c4f1a960447b4b53dca","affectsGlobalScope":true,"impliedFormat":1},{"version":"3af97acf03cc97de58a3a4bc91f8f616408099bc4233f6d0852e72a8ffb91ac9","affectsGlobalScope":true,"impliedFormat":1},{"version":"808069bba06b6768b62fd22429b53362e7af342da4a236ed2d2e1c89fcca3b4a","affectsGlobalScope":true,"impliedFormat":1},{"version":"1db0b7dca579049ca4193d034d835f6bfe73096c73663e5ef9a0b5779939f3d0","affectsGlobalScope":true,"impliedFormat":1},{"version":"9798340ffb0d067d69b1ae5b32faa17ab31b82466a3fc00d8f2f2df0c8554aaa","affectsGlobalScope":true,"impliedFormat":1},{"version":"f26b11d8d8e4b8028f1c7d618b22274c892e4b0ef5b3678a8ccbad85419aef43","affectsGlobalScope":true,"impliedFormat":1},{"version":"8e9c23ba78aabc2e0a27033f18737a6df754067731e69dc5f52823957d60a4b6","impliedFormat":1},{"version":"5929864ce17fba74232584d90cb721a89b7ad277220627cc97054ba15a98ea8f","impliedFormat":1},{"version":"763fe0f42b3d79b440a9b6e51e9ba3f3f91352469c1e4b3b67bfa4ff6352f3f4","impliedFormat":1},{"version":"25c8056edf4314820382a5fdb4bb7816999acdcb929c8f75e3f39473b87e85bc","impliedFormat":1},{"version":"c464d66b20788266e5353b48dc4aa6bc0dc4a707276df1e7152ab0c9ae21fad8","impliedFormat":1},{"version":"78d0d27c130d35c60b5e5566c9f1e5be77caf39804636bc1a40133919a949f21","impliedFormat":1},{"version":"c6fd2c5a395f2432786c9cb8deb870b9b0e8ff7e22c029954fabdd692bff6195","impliedFormat":1},{"version":"1d6e127068ea8e104a912e42fc0a110e2aa5a66a356a917a163e8cf9a65e4a75","impliedFormat":1},{"version":"5ded6427296cdf3b9542de4471d2aa8d3983671d4cac0f4bf9c637208d1ced43","impliedFormat":1},{"version":"7f182617db458e98fc18dfb272d40aa2fff3a353c44a89b2c0ccb3937709bfb5","impliedFormat":1},{"version":"cadc8aced301244057c4e7e73fbcae534b0f5b12a37b150d80e5a45aa4bebcbd","impliedFormat":1},{"version":"385aab901643aa54e1c36f5ef3107913b10d1b5bb8cbcd933d4263b80a0d7f20","impliedFormat":1},{"version":"9670d44354bab9d9982eca21945686b5c24a3f893db73c0dae0fd74217a4c219","impliedFormat":1},{"version":"0b8a9268adaf4da35e7fa830c8981cfa22adbbe5b3f6f5ab91f6658899e657a7","impliedFormat":1},{"version":"11396ed8a44c02ab9798b7dca436009f866e8dae3c9c25e8c1fbc396880bf1bb","impliedFormat":1},{"version":"ba7bc87d01492633cb5a0e5da8a4a42a1c86270e7b3d2dea5d156828a84e4882","impliedFormat":1},{"version":"4893a895ea92c85345017a04ed427cbd6a1710453338df26881a6019432febdd","impliedFormat":1},{"version":"c21dc52e277bcfc75fac0436ccb75c204f9e1b3fa5e12729670910639f27343e","impliedFormat":1},{"version":"13f6f39e12b1518c6650bbb220c8985999020fe0f21d818e28f512b7771d00f9","impliedFormat":1},{"version":"9b5369969f6e7175740bf51223112ff209f94ba43ecd3bb09eefff9fd675624a","impliedFormat":1},{"version":"4fe9e626e7164748e8769bbf74b538e09607f07ed17c2f20af8d680ee49fc1da","impliedFormat":1},{"version":"24515859bc0b836719105bb6cc3d68255042a9f02a6022b3187948b204946bd2","impliedFormat":1},{"version":"ea0148f897b45a76544ae179784c95af1bd6721b8610af9ffa467a518a086a43","impliedFormat":1},{"version":"24c6a117721e606c9984335f71711877293a9651e44f59f3d21c1ea0856f9cc9","impliedFormat":1},{"version":"dd3273ead9fbde62a72949c97dbec2247ea08e0c6952e701a483d74ef92d6a17","impliedFormat":1},{"version":"405822be75ad3e4d162e07439bac80c6bcc6dbae1929e179cf467ec0b9ee4e2e","impliedFormat":1},{"version":"0db18c6e78ea846316c012478888f33c11ffadab9efd1cc8bcc12daded7a60b6","impliedFormat":1},{"version":"e61be3f894b41b7baa1fbd6a66893f2579bfad01d208b4ff61daef21493ef0a8","impliedFormat":1},{"version":"bd0532fd6556073727d28da0edfd1736417a3f9f394877b6d5ef6ad88fba1d1a","impliedFormat":1},{"version":"89167d696a849fce5ca508032aabfe901c0868f833a8625d5a9c6e861ef935d2","impliedFormat":1},{"version":"615ba88d0128ed16bf83ef8ccbb6aff05c3ee2db1cc0f89ab50a4939bfc1943f","impliedFormat":1},{"version":"a4d551dbf8746780194d550c88f26cf937caf8d56f102969a110cfaed4b06656","impliedFormat":1},{"version":"8bd86b8e8f6a6aa6c49b71e14c4ffe1211a0e97c80f08d2c8cc98838006e4b88","impliedFormat":1},{"version":"317e63deeb21ac07f3992f5b50cdca8338f10acd4fbb7257ebf56735bf52ab00","impliedFormat":1},{"version":"4732aec92b20fb28c5fe9ad99521fb59974289ed1e45aecb282616202184064f","impliedFormat":1},{"version":"2e85db9e6fd73cfa3d7f28e0ab6b55417ea18931423bd47b409a96e4a169e8e6","impliedFormat":1},{"version":"c46e079fe54c76f95c67fb89081b3e399da2c7d109e7dca8e4b58d83e332e605","impliedFormat":1},{"version":"bf67d53d168abc1298888693338cb82854bdb2e69ef83f8a0092093c2d562107","impliedFormat":1},{"version":"b52476feb4a0cbcb25e5931b930fc73cb6643fb1a5060bf8a3dda0eeae5b4b68","affectsGlobalScope":true,"impliedFormat":1},{"version":"f9501cc13ce624c72b61f12b3963e84fad210fbdf0ffbc4590e08460a3f04eba","affectsGlobalScope":true,"impliedFormat":1},{"version":"e7721c4f69f93c91360c26a0a84ee885997d748237ef78ef665b153e622b36c1","affectsGlobalScope":true,"impliedFormat":1},{"version":"0fa06ada475b910e2106c98c68b10483dc8811d0c14a8a8dd36efb2672485b29","impliedFormat":1},{"version":"33e5e9aba62c3193d10d1d33ae1fa75c46a1171cf76fef750777377d53b0303f","impliedFormat":1},{"version":"2b06b93fd01bcd49d1a6bd1f9b65ddcae6480b9a86e9061634d6f8e354c1468f","impliedFormat":1},{"version":"6a0cd27e5dc2cfbe039e731cf879d12b0e2dded06d1b1dedad07f7712de0d7f4","affectsGlobalScope":true,"impliedFormat":1},{"version":"13f5c844119c43e51ce777c509267f14d6aaf31eafb2c2b002ca35584cd13b29","impliedFormat":1},{"version":"e60477649d6ad21542bd2dc7e3d9ff6853d0797ba9f689ba2f6653818999c264","impliedFormat":1},{"version":"c2510f124c0293ab80b1777c44d80f812b75612f297b9857406468c0f4dafe29","affectsGlobalScope":true,"impliedFormat":1},{"version":"5524481e56c48ff486f42926778c0a3cce1cc85dc46683b92b1271865bcf015a","impliedFormat":1},{"version":"4c829ab315f57c5442c6667b53769975acbf92003a66aef19bce151987675bd1","affectsGlobalScope":true,"impliedFormat":1},{"version":"b2ade7657e2db96d18315694789eff2ddd3d8aea7215b181f8a0b303277cc579","impliedFormat":1},{"version":"9855e02d837744303391e5623a531734443a5f8e6e8755e018c41d63ad797db2","impliedFormat":1},{"version":"4d631b81fa2f07a0e63a9a143d6a82c25c5f051298651a9b69176ba28930756d","impliedFormat":1},{"version":"836a356aae992ff3c28a0212e3eabcb76dd4b0cc06bcb9607aeef560661b860d","impliedFormat":1},{"version":"1e0d1f8b0adfa0b0330e028c7941b5a98c08b600efe7f14d2d2a00854fb2f393","impliedFormat":1},{"version":"41670ee38943d9cbb4924e436f56fc19ee94232bc96108562de1a734af20dc2c","affectsGlobalScope":true,"impliedFormat":1},{"version":"c906fb15bd2aabc9ed1e3f44eb6a8661199d6c320b3aa196b826121552cb3695","impliedFormat":1},{"version":"22295e8103f1d6d8ea4b5d6211e43421fe4564e34d0dd8e09e520e452d89e659","impliedFormat":1},{"version":"58647d85d0f722a1ce9de50955df60a7489f0593bf1a7015521efe901c06d770","impliedFormat":1},{"version":"6b4e081d55ac24fc8a4631d5dd77fe249fa25900abd7d046abb87d90e3b45645","impliedFormat":1},{"version":"a10f0e1854f3316d7ee437b79649e5a6ae3ae14ffe6322b02d4987071a95362e","impliedFormat":1},{"version":"e208f73ef6a980104304b0d2ca5f6bf1b85de6009d2c7e404028b875020fa8f2","impliedFormat":1},{"version":"d163b6bc2372b4f07260747cbc6c0a6405ab3fbcea3852305e98ac43ca59f5bc","impliedFormat":1},{"version":"e6fa9ad47c5f71ff733744a029d1dc472c618de53804eae08ffc243b936f87ff","affectsGlobalScope":true,"impliedFormat":1},{"version":"83e63d6ccf8ec004a3bb6d58b9bb0104f60e002754b1e968024b320730cc5311","impliedFormat":1},{"version":"24826ed94a78d5c64bd857570fdbd96229ad41b5cb654c08d75a9845e3ab7dde","impliedFormat":1},{"version":"8b479a130ccb62e98f11f136d3ac80f2984fdc07616516d29881f3061f2dd472","impliedFormat":1},{"version":"928af3d90454bf656a52a48679f199f64c1435247d6189d1caf4c68f2eaf921f","affectsGlobalScope":true,"impliedFormat":1},{"version":"bceb58df66ab8fb00170df20cd813978c5ab84be1d285710c4eb005d8e9d8efb","affectsGlobalScope":true,"impliedFormat":1},{"version":"3f16a7e4deafa527ed9995a772bb380eb7d3c2c0fd4ae178c5263ed18394db2c","impliedFormat":1},{"version":"933921f0bb0ec12ef45d1062a1fc0f27635318f4d294e4d99de9a5493e618ca2","impliedFormat":1},{"version":"71a0f3ad612c123b57239a7749770017ecfe6b66411488000aba83e4546fde25","impliedFormat":1},{"version":"77fbe5eecb6fac4b6242bbf6eebfc43e98ce5ccba8fa44e0ef6a95c945ff4d98","impliedFormat":1},{"version":"4f9d8ca0c417b67b69eeb54c7ca1bedd7b56034bb9bfd27c5d4f3bc4692daca7","impliedFormat":1},{"version":"814118df420c4e38fe5ae1b9a3bafb6e9c2aa40838e528cde908381867be6466","impliedFormat":1},{"version":"a3fc63c0d7b031693f665f5494412ba4b551fe644ededccc0ab5922401079c95","impliedFormat":1},{"version":"f27524f4bef4b6519c604bdb23bf4465bddcccbf3f003abb901acbd0d7404d99","impliedFormat":1},{"version":"37ba7b45141a45ce6e80e66f2a96c8a5ab1bcef0fc2d0f56bb58df96ec67e972","impliedFormat":1},{"version":"45650f47bfb376c8a8ed39d4bcda5902ab899a3150029684ee4c10676d9fbaee","impliedFormat":1},{"version":"6b039f55681caaf111d5eb84d292b9bee9e0131d0db1ad0871eef0964f533c73","affectsGlobalScope":true,"impliedFormat":1},{"version":"18fd40412d102c5564136f29735e5d1c3b455b8a37f920da79561f1fde068208","impliedFormat":1},{"version":"c8d3e5a18ba35629954e48c4cc8f11dc88224650067a172685c736b27a34a4dc","impliedFormat":1},{"version":"f0be1b8078cd549d91f37c30c222c2a187ac1cf981d994fb476a1adc61387b14","affectsGlobalScope":true,"impliedFormat":1},{"version":"0aaed1d72199b01234152f7a60046bc947f1f37d78d182e9ae09c4289e06a592","impliedFormat":1},{"version":"2b55d426ff2b9087485e52ac4bc7cfafe1dc420fc76dad926cd46526567c501a","impliedFormat":1},{"version":"66ba1b2c3e3a3644a1011cd530fb444a96b1b2dfe2f5e837a002d41a1a799e60","impliedFormat":1},{"version":"7e514f5b852fdbc166b539fdd1f4e9114f29911592a5eb10a94bb3a13ccac3c4","impliedFormat":1},{"version":"5b7aa3c4c1a5d81b411e8cb302b45507fea9358d3569196b27eb1a27ae3a90ef","affectsGlobalScope":true,"impliedFormat":1},{"version":"5987a903da92c7462e0b35704ce7da94d7fdc4b89a984871c0e2b87a8aae9e69","affectsGlobalScope":true,"impliedFormat":1},{"version":"ea08a0345023ade2b47fbff5a76d0d0ed8bff10bc9d22b83f40858a8e941501c","impliedFormat":1},{"version":"47613031a5a31510831304405af561b0ffaedb734437c595256bb61a90f9311b","impliedFormat":1},{"version":"ae062ce7d9510060c5d7e7952ae379224fb3f8f2dd74e88959878af2057c143b","impliedFormat":1},{"version":"8a1a0d0a4a06a8d278947fcb66bf684f117bf147f89b06e50662d79a53be3e9f","affectsGlobalScope":true,"impliedFormat":1},{"version":"358765d5ea8afd285d4fd1532e78b88273f18cb3f87403a9b16fef61ac9fdcfe","impliedFormat":1},{"version":"9f55299850d4f0921e79b6bf344b47c420ce0f507b9dcf593e532b09ea7eeea1","impliedFormat":1},{"version":"f9fd93190acb1ffe0bc0fb395df979452f8d625071e9ffc8636e4dfb86ab2508","impliedFormat":1},{"version":"5f41fd8732a89e940c58ce22206e3df85745feb8983e2b4c6257fb8cbb118493","impliedFormat":1},{"version":"17ed71200119e86ccef2d96b73b02ce8854b76ad6bd21b5021d4269bec527b5f","impliedFormat":1},{"version":"1cfa8647d7d71cb03847d616bd79320abfc01ddea082a49569fda71ac5ece66b","impliedFormat":1},{"version":"bb7a61dd55dc4b9422d13da3a6bb9cc5e89be888ef23bbcf6558aa9726b89a1c","impliedFormat":1},{"version":"413df52d4ea14472c2fa5bee62f7a40abd1eb49be0b9722ee01ee4e52e63beb2","impliedFormat":1},{"version":"db6d2d9daad8a6d83f281af12ce4355a20b9a3e71b82b9f57cddcca0a8964a96","impliedFormat":1},{"version":"829b9e6028b29e6a8b1c01ddb713efe59da04d857089298fa79acbdb3cfcfdef","impliedFormat":1},{"version":"24f8562308dd8ba6013120557fa7b44950b619610b2c6cb8784c79f11e3c4f90","impliedFormat":1},{"version":"5f90b8c733a1bda63e42160b15a2301051e83a6f9d5332a59d16eb12f463270d","impliedFormat":1},{"version":"a86f82d646a739041d6702101afa82dcb935c416dd93cbca7fd754fd0282ce1f","impliedFormat":1},{"version":"ad0d1d75d129b1c80f911be438d6b61bfa8703930a8ff2be2f0e1f8a91841c64","impliedFormat":1},{"version":"ce75b1aebb33d510ff28af960a9221410a3eaf7f18fc5f21f9404075fba77256","impliedFormat":1},{"version":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","impliedFormat":1},{"version":"496bbf339f3838c41f164238543e9fe5f1f10659cb30b68903851618464b98ba","impliedFormat":1},{"version":"5178eb4415a172c287c711dc60a619e110c3fd0b7de01ed0627e51a5336aa09c","impliedFormat":1},{"version":"ca6e5264278b53345bc1ce95f42fb0a8b733a09e3d6479c6ccfca55cdc45038c","impliedFormat":1},{"version":"9e2739b32f741859263fdba0244c194ca8e96da49b430377930b8f721d77c000","impliedFormat":1},{"version":"fb1d8e814a3eeb5101ca13515e0548e112bd1ff3fb358ece535b93e94adf5a3a","impliedFormat":1},{"version":"ffa495b17a5ef1d0399586b590bd281056cee6ce3583e34f39926f8dcc6ecdb5","impliedFormat":1},{"version":"98b18458acb46072947aabeeeab1e410f047e0cacc972943059ca5500b0a5e95","impliedFormat":1},{"version":"361e2b13c6765d7f85bb7600b48fde782b90c7c41105b7dab1f6e7871071ba20","impliedFormat":1},{"version":"c86fe861cf1b4c46a0fb7d74dffe596cf679a2e5e8b1456881313170f092e3fa","impliedFormat":1},{"version":"b6db56e4903e9c32e533b78ac85522de734b3d3a8541bf24d256058d464bf04b","impliedFormat":1},{"version":"24daa0366f837d22c94a5c0bad5bf1fd0f6b29e1fae92dc47c3072c3fdb2fbd5","impliedFormat":1},{"version":"570bb5a00836ffad3e4127f6adf581bfc4535737d8ff763a4d6f4cc877e60d98","impliedFormat":1},{"version":"889c00f3d32091841268f0b994beba4dceaa5df7573be12c2c829d7c5fbc232c","impliedFormat":1},{"version":"65f43099ded6073336e697512d9b80f2d4fec3182b7b2316abf712e84104db00","impliedFormat":1},{"version":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","impliedFormat":1},{"version":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","impliedFormat":1},{"version":"8e609bb71c20b858c77f0e9f90bb1319db8477b13f9f965f1a1e18524bf50881","impliedFormat":1},{"version":"acf5a2ac47b59ca07afa9abbd2b31d001bf7448b041927befae2ea5b1951d9f9","impliedFormat":1},{"version":"8e609bb71c20b858c77f0e9f90bb1319db8477b13f9f965f1a1e18524bf50881","impliedFormat":1},{"version":"d71291eff1e19d8762a908ba947e891af44749f3a2cbc5bd2ec4b72f72ea795f","impliedFormat":1},{"version":"c0480e03db4b816dff2682b347c95f2177699525c54e7e6f6aa8ded890b76be7","impliedFormat":1},{"version":"27ab780875bcbb65e09da7496f2ca36288b0c541abaa75c311450a077d54ec15","impliedFormat":1},{"version":"b620391fe8060cf9bedc176a4d01366e6574d7a71e0ac0ab344a4e76576fcbb8","impliedFormat":1},{"version":"380647d8f3b7f852cca6d154a376dbf8ac620a2f12b936594504a8a852e71d2f","impliedFormat":1},{"version":"208c9af9429dd3c76f5927b971263174aaa4bc7621ddec63f163640cbd3c473c","impliedFormat":1},{"version":"6459054aabb306821a043e02b89d54da508e3a6966601a41e71c166e4ea1474f","impliedFormat":1},{"version":"a23185bc5ef590c287c28a91baf280367b50ae4ea40327366ad01f6f4a8edbc5","impliedFormat":1},{"version":"bb37588926aba35c9283fe8d46ebf4e79ffe976343105f5c6d45f282793352b2","impliedFormat":1},{"version":"002eae065e6960458bda3cf695e578b0d1e2785523476f8a9170b103c709cd4f","impliedFormat":1},{"version":"c83bb0c9c5645a46c68356c2f73fdc9de339ce77f7f45a954f560c7e0b8d5ebb","impliedFormat":1},{"version":"05c97cddbaf99978f83d96de2d8af86aded9332592f08ce4a284d72d0952c391","impliedFormat":1},{"version":"72179f9dd22a86deaad4cc3490eb0fe69ee084d503b686985965654013f1391b","impliedFormat":1},{"version":"2e6114a7dd6feeef85b2c80120fdbfb59a5529c0dcc5bfa8447b6996c97a69f5","impliedFormat":1},{"version":"7b6ff760c8a240b40dab6e4419b989f06a5b782f4710d2967e67c695ef3e93c4","impliedFormat":1},{"version":"c8f004e6036aa1c764ad4ec543cf89a5c1893a9535c80ef3f2b653e370de45e6","impliedFormat":1},{"version":"dd80b1e600d00f5c6a6ba23f455b84a7db121219e68f89f10552c54ba46e4dc9","impliedFormat":1},{"version":"b064c36f35de7387d71c599bfcf28875849a1dbc733e82bd26cae3d1cd060521","impliedFormat":1},{"version":"6a148329edecbda07c21098639ef4254ef7869fb25a69f58e5d6a8b7b69d4236","impliedFormat":1},{"version":"8de9fe97fa9e00ec00666fa77ab6e91b35d25af8ca75dabcb01e14ad3299b150","impliedFormat":1},{"version":"f63ab283a1c8f5c79fabe7ca4ef85f9633339c4f0e822fce6a767f9d59282af2","impliedFormat":1},{"version":"dba114fb6a32b355a9cfc26ca2276834d72fe0e94cd2c3494005547025015369","impliedFormat":1},{"version":"a54c996c8870ef1728a2c1fa9b8eaec0bf4a8001cd2583c02dd5869289465b10","impliedFormat":1},{"version":"3e7efde639c6a6c3edb9847b3f61e308bf7a69685b92f665048c45132f51c218","impliedFormat":1},{"version":"df45ca1176e6ac211eae7ddf51336dc075c5314bc5c253651bae639defd5eec5","impliedFormat":1},{"version":"3754982006a3b32c502cff0867ca83584f7a43b1035989ca73603f400de13c96","impliedFormat":1},{"version":"a30ae9bb8a8fa7b90f24b8a0496702063ae4fe75deb27da731ed4a03b2eb6631","impliedFormat":1},{"version":"f974e4a06953682a2c15d5bd5114c0284d5abf8bc0fe4da25cb9159427b70072","impliedFormat":1},{"version":"50256e9c31318487f3752b7ac12ff365c8949953e04568009c8705db802776fb","impliedFormat":1},{"version":"7d73b24e7bf31dfb8a931ca6c4245f6bb0814dfae17e4b60c9e194a631fe5f7b","impliedFormat":1},{"version":"413586add0cfe7369b64979d4ec2ed56c3f771c0667fbde1bf1f10063ede0b08","impliedFormat":1},{"version":"06472528e998d152375ad3bd8ebcb69ff4694fd8d2effaf60a9d9f25a37a097a","impliedFormat":1},{"version":"50b5bc34ce6b12eccb76214b51aadfa56572aa6cc79c2b9455cdbb3d6c76af1d","impliedFormat":1},{"version":"b7e16ef7f646a50991119b205794ebfd3a4d8f8e0f314981ebbe991639023d0e","impliedFormat":1},{"version":"42c169fb8c2d42f4f668c624a9a11e719d5d07dacbebb63cbcf7ef365b0a75b3","impliedFormat":1},{"version":"a401617604fa1f6ce437b81689563dfdc377069e4c58465dbd8d16069aede0a5","impliedFormat":1},{"version":"e9dd71cf12123419c60dab867d44fbee5c358169f99529121eaef277f5c83531","impliedFormat":1},{"version":"5b6a189ba3a0befa1f5d9cb028eb9eec2af2089c32f04ff50e2411f63d70f25d","impliedFormat":1},{"version":"d6e73f8010935b7b4c7487b6fb13ea197cc610f0965b759bec03a561ccf8423a","impliedFormat":1},{"version":"174f3864e398f3f33f9a446a4f403d55a892aa55328cf6686135dfaf9e171657","impliedFormat":1},{"version":"824c76aec8d8c7e65769688cbee102238c0ef421ed6686f41b2a7d8e7e78a931","impliedFormat":1},{"version":"75b868be3463d5a8cfc0d9396f0a3d973b8c297401d00bfb008a42ab16643f13","impliedFormat":1},{"version":"15a234e5031b19c48a69ccc1607522d6e4b50f57d308ecb7fe863d44cd9f9eb3","impliedFormat":1},{"version":"d682336018141807fb602709e2d95a192828fcb8d5ba06dda3833a8ea98f69e3","impliedFormat":1},{"version":"6124e973eab8c52cabf3c07575204efc1784aca6b0a30c79eb85fe240a857efa","impliedFormat":1},{"version":"0d891735a21edc75df51f3eb995e18149e119d1ce22fd40db2b260c5960b914e","impliedFormat":1},{"version":"3b414b99a73171e1c4b7b7714e26b87d6c5cb03d200352da5342ab4088a54c85","impliedFormat":1},{"version":"4fbd3116e00ed3a6410499924b6403cc9367fdca303e34838129b328058ede40","impliedFormat":1},{"version":"b01bd582a6e41457bc56e6f0f9de4cb17f33f5f3843a7cf8210ac9c18472fb0f","impliedFormat":1},{"version":"0a437ae178f999b46b6153d79095b60c42c996bc0458c04955f1c996dc68b971","impliedFormat":1},{"version":"74b2a5e5197bd0f2e0077a1ea7c07455bbea67b87b0869d9786d55104006784f","impliedFormat":1},{"version":"4a7baeb6325920044f66c0f8e5e6f1f52e06e6d87588d837bdf44feb6f35c664","impliedFormat":1},{"version":"6dcf60530c25194a9ee0962230e874ff29d34c59605d8e069a49928759a17e0a","impliedFormat":1},{"version":"7274fbffbd7c9589d8d0ffba68157237afd5cecff1e99881ea3399127e60572f","impliedFormat":1},{"version":"1a42d2ec31a1fe62fdc51591768695ed4a2dc64c01be113e7ff22890bebb5e3f","impliedFormat":1},{"version":"1a82deef4c1d39f6882f28d275cad4c01f907b9b39be9cbc472fcf2cf051e05b","impliedFormat":1},{"version":"c5426dbfc1cf90532f66965a7aa8c1136a78d4d0f96d8180ecbfc11d7722f1a5","impliedFormat":1},{"version":"65a15fc47900787c0bd18b603afb98d33ede930bed1798fc984d5ebb78b26cf9","impliedFormat":1},{"version":"9d202701f6e0744adb6314d03d2eb8fc994798fc83d91b691b75b07626a69801","impliedFormat":1},{"version":"de9d2df7663e64e3a91bf495f315a7577e23ba088f2949d5ce9ec96f44fba37d","impliedFormat":1},{"version":"c7af78a2ea7cb1cd009cfb5bdb48cd0b03dad3b54f6da7aab615c2e9e9d570c5","impliedFormat":1},{"version":"1ee45496b5f8bdee6f7abc233355898e5bf9bd51255db65f5ff7ede617ca0027","impliedFormat":1},{"version":"0c7c947ff881c4274c0800deaa0086971e0bfe51f89a33bd3048eaa3792d4876","affectsGlobalScope":true,"impliedFormat":1},{"version":"db01d18853469bcb5601b9fc9826931cc84cc1a1944b33cad76fd6f1e3d8c544","affectsGlobalScope":true,"impliedFormat":1},{"version":"a8f8e6ab2fa07b45251f403548b78eaf2022f3c2254df3dc186cb2671fe4996d","affectsGlobalScope":true,"impliedFormat":1},{"version":"fa6c12a7c0f6b84d512f200690bfc74819e99efae69e4c95c4cd30f6884c526e","impliedFormat":1},{"version":"f1c32f9ce9c497da4dc215c3bc84b722ea02497d35f9134db3bb40a8d918b92b","impliedFormat":1},{"version":"b73c319af2cc3ef8f6421308a250f328836531ea3761823b4cabbd133047aefa","affectsGlobalScope":true,"impliedFormat":1},{"version":"e433b0337b8106909e7953015e8fa3f2d30797cea27141d1c5b135365bb975a6","impliedFormat":1},{"version":"15b36126e0089bfef173ab61329e8286ce74af5e809d8a72edcafd0cc049057f","impliedFormat":1},{"version":"ddff7fc6edbdc5163a09e22bf8df7bef75f75369ebd7ecea95ba55c4386e2441","impliedFormat":1},{"version":"106c6025f1d99fd468fd8bf6e5bda724e11e5905a4076c5d29790b6c3745e50c","impliedFormat":1},{"version":"a57b1802794433adec9ff3fed12aa79d671faed86c49b09e02e1ac41b4f1d33a","impliedFormat":1},{"version":"ad10d4f0517599cdeca7755b930f148804e3e0e5b5a3847adce0f1f71bbccd74","impliedFormat":1},{"version":"1042064ece5bb47d6aba91648fbe0635c17c600ebdf567588b4ca715602f0a9d","impliedFormat":1},{"version":"c49469a5349b3cc1965710b5b0f98ed6c028686aa8450bcb3796728873eb923e","impliedFormat":1},{"version":"4a889f2c763edb4d55cb624257272ac10d04a1cad2ed2948b10ed4a7fda2a428","impliedFormat":1},{"version":"7bb79aa2fead87d9d56294ef71e056487e848d7b550c9a367523ee5416c44cfa","impliedFormat":1},{"version":"72d63643a657c02d3e51cd99a08b47c9b020a565c55f246907050d3c8a5e77fb","impliedFormat":1},{"version":"1d415445ea58f8033ba199703e55ff7483c52ac6742075b803bd3e7bbe9f5d61","impliedFormat":1},{"version":"d6406c629bb3efc31aedb2de809bef471e475c86c7e67f3ef9b676b5d7e0d6b2","impliedFormat":1},{"version":"27ff4196654e6373c9af16b6165120e2dd2169f9ad6abb5c935af5abd8c7938c","impliedFormat":1},{"version":"71d8ba39a9e024d9e4bb922464d18542ed8d2c25ee78efa7890c27213cc6e5d3","impliedFormat":1},{"version":"8c030e515014c10a2b98f9f48408e3ba18023dfd3f56e3312c6c2f3ae1f55a16","impliedFormat":1},{"version":"dafc31e9e8751f437122eb8582b93d477e002839864410ff782504a12f2a550c","impliedFormat":1},{"version":"754498c5208ce3c5134f6eabd49b25cf5e1a042373515718953581636491f3c3","impliedFormat":1},{"version":"9c82171d836c47486074e4ca8e059735bf97b205e70b196535b5efd40cbe1bc5","impliedFormat":1},{"version":"f56bdc6884648806d34bc66d31cdb787c4718d04105ce2cd88535db214631f82","impliedFormat":1},{"version":"633d58a237f4bb25ec7d565e4ffa32cecdcee8660ac12189c4351c52557cee9e","impliedFormat":1},{"version":"2e4f37ffe8862b14d8e24ae8763daaa8340c0df0b859d9a9733def0eee7562d9","impliedFormat":1},{"version":"13283350547389802aa35d9f2188effaeac805499169a06ef5cd77ce2a0bd63f","impliedFormat":1},{"version":"ce791f6ea807560f08065d1af6014581eeb54a05abd73294777a281b6dfd73c2","impliedFormat":1},{"version":"6ac6715916fa75a1f7ebdfeacac09513b4d904b667d827b7535e84ff59679aff","impliedFormat":1},{"version":"49f95e989b4632c6c2a578cc0078ee19a5831832d79cc59abecf5160ea71abad","impliedFormat":1},{"version":"9666533332f26e8995e4d6fe472bdeec9f15d405693723e6497bf94120c566c8","impliedFormat":1},{"version":"ce0df82a9ae6f914ba08409d4d883983cc08e6d59eb2df02d8e4d68309e7848b","impliedFormat":1},{"version":"796273b2edc72e78a04e86d7c58ae94d370ab93a0ddf40b1aa85a37a1c29ecd7","impliedFormat":1},{"version":"5df15a69187d737d6d8d066e189ae4f97e41f4d53712a46b2710ff9f8563ec9f","impliedFormat":1},{"version":"e17cd049a1448de4944800399daa4a64c5db8657cc9be7ef46be66e2a2cd0e7c","impliedFormat":1},{"version":"43fa6ea8714e18adc312b30450b13562949ba2f205a1972a459180fa54471018","impliedFormat":1},{"version":"6e89c2c177347d90916bad67714d0fb473f7e37fb3ce912f4ed521fe2892cd0d","impliedFormat":1},{"version":"43ba4f2fa8c698f5c304d21a3ef596741e8e85a810b7c1f9b692653791d8d97a","impliedFormat":1},{"version":"4d4927cbee21750904af7acf940c5e3c491b4d5ebc676530211e389dd375607a","impliedFormat":1},{"version":"72105519d0390262cf0abe84cf41c926ade0ff475d35eb21307b2f94de985778","impliedFormat":1},{"version":"8a97e578a9bc40eb4f1b0ca78f476f2e9154ecbbfd5567ee72943bab37fc156a","impliedFormat":1},{"version":"c857e0aae3f5f444abd791ec81206020fbcc1223e187316677e026d1c1d6fe08","impliedFormat":1},{"version":"ccf6dd45b708fb74ba9ed0f2478d4eb9195c9dfef0ff83a6092fa3cf2ff53b4f","impliedFormat":1},{"version":"2d7db1d73456e8c5075387d4240c29a2a900847f9c1bff106a2e490da8fbd457","impliedFormat":1},{"version":"2b15c805f48e4e970f8ec0b1915f22d13ca6212375e8987663e2ef5f0205e832","impliedFormat":1},{"version":"f22d05663d873ee7a600faf78abb67f3f719d32266803440cf11d5db7ac0cab2","impliedFormat":1},{"version":"d93c544ad20197b3976b0716c6d5cd5994e71165985d31dcab6e1f77feb4b8f2","impliedFormat":1},{"version":"35069c2c417bd7443ae7c7cafd1de02f665bf015479fec998985ffbbf500628c","impliedFormat":1},{"version":"a8b1c79a833ee148251e88a2553d02ce1641d71d2921cce28e79678f3d8b96aa","impliedFormat":1},{"version":"126d4f950d2bba0bd45b3a86c76554d4126c16339e257e6d2fabf8b6bf1ce00c","impliedFormat":1},{"version":"7e0b7f91c5ab6e33f511efc640d36e6f933510b11be24f98836a20a2dc914c2d","impliedFormat":1},{"version":"045b752f44bf9bbdcaffd882424ab0e15cb8d11fa94e1448942e338c8ef19fba","impliedFormat":1},{"version":"2894c56cad581928bb37607810af011764a2f511f575d28c9f4af0f2ef02d1ab","impliedFormat":1},{"version":"0a72186f94215d020cb386f7dca81d7495ab6c17066eb07d0f44a5bf33c1b21a","impliedFormat":1},{"version":"2d3cc2211f352f46ea6b7cf2c751c141ffcdf514d6e7ae7ee20b7b6742da313f","impliedFormat":1},{"version":"c75445151ff8b77d9923191efed7203985b1a9e09eccf4b054e7be864e27923d","impliedFormat":1},{"version":"0aedb02516baf3e66b2c1db9fef50666d6ed257edac0f866ea32f1aa05aa474f","impliedFormat":1},{"version":"fa8a8fbf91ee2a4779496225f0312aac6635b0f21aa09cdafa4283fe32d519c5","affectsGlobalScope":true,"impliedFormat":1},{"version":"0e8aef93d79b000deb6ec336b5645c87de167168e184e84521886f9ecc69a4b5","impliedFormat":1},{"version":"56ccb49443bfb72e5952f7012f0de1a8679f9f75fc93a5c1ac0bafb28725fc5f","impliedFormat":1},{"version":"d90b9f1520366d713a73bd30c5a9eb0040d0fb6076aff370796bc776fd705943","impliedFormat":1},{"version":"05321b823dd3781d0b6aac8700bfdc0c9181d56479fe52ba6a40c9196fd661a8","impliedFormat":1},{"version":"736a8712572e21ee73337055ce15edb08142fc0f59cd5410af4466d04beff0f9","affectsGlobalScope":true,"impliedFormat":1},{"version":"bef86adb77316505c6b471da1d9b8c9e428867c2566270e8894d4d773a1c4dc2","impliedFormat":1},{"version":"de7052bfee2981443498239a90c04ea5cc07065d5b9bb61b12cb6c84313ad4ef","impliedFormat":1},{"version":"a3e7d932dc9c09daa99141a8e4800fc6c58c625af0d4bbb017773dc36da75426","impliedFormat":1},{"version":"43e96a3d5d1411ab40ba2f61d6a3192e58177bcf3b133a80ad2a16591611726d","impliedFormat":1},{"version":"4a2edd238d9104eac35b60d727f1123de5062f452b70ed8e0366cb36387dfdfd","impliedFormat":1},{"version":"ca921bf56756cb6fe957f6af693a35251b134fb932dc13f3dfff0bb7106f80b4","impliedFormat":1},{"version":"fee92c97f1aa59eb7098a0cc34ff4df7e6b11bae71526aca84359a2575f313d8","impliedFormat":1},{"version":"0bd0297484aacea217d0b76e55452862da3c5d9e33b24430e0719d1161657225","impliedFormat":1},{"version":"2ab6d334bcbf2aff3acfc4fd8c73ecd82b981d3c3aa47b3f3b89281772286904","impliedFormat":1},{"version":"d07cbc787a997d83f7bde3877fec5fb5b12ce8c1b7047eb792996ed9726b4dde","impliedFormat":1},{"version":"6ac6715916fa75a1f7ebdfeacac09513b4d904b667d827b7535e84ff59679aff","impliedFormat":1},{"version":"4805f6161c2c8cefb8d3b8bd96a080c0fe8dbc9315f6ad2e53238f9a79e528a6","impliedFormat":1},{"version":"b83cb14474fa60c5f3ec660146b97d122f0735627f80d82dd03e8caa39b4388c","impliedFormat":1},{"version":"f374cb24e93e7798c4d9e83ff872fa52d2cdb36306392b840a6ddf46cb925cb6","impliedFormat":1},{"version":"49179c6a23701c642bd99abe30d996919748014848b738d8e85181fc159685ff","impliedFormat":1},{"version":"b73cbf0a72c8800cf8f96a9acfe94f3ad32ca71342a8908b8ae484d61113f647","impliedFormat":1},{"version":"bae6dd176832f6423966647382c0d7ba9e63f8c167522f09a982f086cd4e8b23","impliedFormat":1},{"version":"20865ac316b8893c1a0cc383ccfc1801443fbcc2a7255be166cf90d03fac88c9","impliedFormat":1},{"version":"c9958eb32126a3843deedda8c22fb97024aa5d6dd588b90af2d7f2bfac540f23","impliedFormat":1},{"version":"461d0ad8ae5f2ff981778af912ba71b37a8426a33301daa00f21c6ccb27f8156","impliedFormat":1},{"version":"e927c2c13c4eaf0a7f17e6022eee8519eb29ef42c4c13a31e81a611ab8c95577","impliedFormat":1},{"version":"fcafff163ca5e66d3b87126e756e1b6dfa8c526aa9cd2a2b0a9da837d81bbd72","impliedFormat":1},{"version":"70246ad95ad8a22bdfe806cb5d383a26c0c6e58e7207ab9c431f1cb175aca657","impliedFormat":1},{"version":"f00f3aa5d64ff46e600648b55a79dcd1333458f7a10da2ed594d9f0a44b76d0b","impliedFormat":1},{"version":"772d8d5eb158b6c92412c03228bd9902ccb1457d7a705b8129814a5d1a6308fc","impliedFormat":1},{"version":"45490817629431853543adcb91c0673c25af52a456479588b6486daba34f68bb","impliedFormat":1},{"version":"802e797bcab5663b2c9f63f51bdf67eff7c41bc64c0fd65e6da3e7941359e2f7","impliedFormat":1},{"version":"8b4327413e5af38cd8cb97c59f48c3c866015d5d642f28518e3a891c469f240e","impliedFormat":1},{"version":"8514c62ce38e58457d967e9e73f128eedc1378115f712b9eef7127f7c88f82ae","impliedFormat":1},{"version":"f1289e05358c546a5b664fbb35a27738954ec2cc6eb4137350353099d154fc62","impliedFormat":1},{"version":"4b20fcf10a5413680e39f5666464859fc56b1003e7dfe2405ced82371ebd49b6","impliedFormat":1},{"version":"1d17ba45cfbe77a9c7e0df92f7d95f3eefd49ee23d1104d0548b215be56945ad","impliedFormat":1},{"version":"f7d628893c9fa52ba3ab01bcb5e79191636c4331ee5667ecc6373cbccff8ae12","impliedFormat":1},{"version":"1d879125d1ec570bf04bc1f362fdbe0cb538315c7ac4bcfcdf0c1e9670846aa6","impliedFormat":1},{"version":"a1ee88010a64e8647d07dba58ec43e6e05851b9ec7a62e4ca2b9c33be5abb2c8","impliedFormat":1},{"version":"46273e8c29816125d0d0b56ce9a849cc77f60f9a5ba627447501d214466f0ff3","impliedFormat":1},{"version":"d663134457d8d669ae0df34eabd57028bddc04fc444c4bc04bc5215afc91e1f4","impliedFormat":1},{"version":"e91f7b1344577a02f051b9b471f33044fef8334a76dc9e1de003d17595a5219b","impliedFormat":1},{"version":"3af3584f79c57853028ef9421ec172539e1fe01853296dc05a9d615ade4ffaf6","impliedFormat":1},{"version":"f82579d87701d639ff4e3930a9b24f4ee13ca74221a9a3a792feb47f01881a9c","impliedFormat":1},{"version":"d7e5d5245a8ba34a274717d085174b2c9827722778129b0081fefd341cca8f55","impliedFormat":1},{"version":"d9d32f94056181c31f553b32ce41d0ef75004912e27450738d57efcd2409c324","impliedFormat":1},{"version":"752513f35f6cff294ffe02d6027c41373adf7bfa35e593dbfd53d95c203635ee","impliedFormat":1},{"version":"6c800b281b9e89e69165fd11536195488de3ff53004e55905e6c0059a2d8591e","impliedFormat":1},{"version":"7d4254b4c6c67a29d5e7f65e67d72540480ac2cfb041ca484847f5ae70480b62","impliedFormat":1},{"version":"1a7e2ea171726446850ec72f4d1525d547ff7e86724cc9e7eec509725752a758","impliedFormat":1},{"version":"8c901126d73f09ecdea4785e9a187d1ac4e793e07da308009db04a7283ec2f37","impliedFormat":1},{"version":"db97922b767bd2675fdfa71e08b49c38b7d2c847a1cc4a7274cb77be23b026f1","impliedFormat":1},{"version":"aab290b8e4b7c399f2c09b957666fc95335eb4522b2dd9ead1bf0cb64da6d6ee","impliedFormat":1},{"version":"94fe3281392e1015b22f39535878610b4fa6f1388dc8d78746be3bc4e4bb8950","impliedFormat":1},{"version":"2652448ac55a2010a1f71dd141f828b682298d39728f9871e1cdf8696ef443fd","impliedFormat":1},{"version":"06c25ddfc2242bd06c19f66c9eae4c46d937349a267810f89783680a1d7b5259","impliedFormat":1},{"version":"120599fd965257b1f4d0ff794bc696162832d9d8467224f4665f713a3119078b","impliedFormat":1},{"version":"5433f33b0a20300cca35d2f229a7fc20b0e8477c44be2affeb21cb464af60c76","impliedFormat":1},{"version":"db036c56f79186da50af66511d37d9fe77fa6793381927292d17f81f787bb195","impliedFormat":1},{"version":"bd4131091b773973ca5d2326c60b789ab1f5e02d8843b3587effe6e1ea7c9d86","impliedFormat":1},{"version":"c7f6485931085bf010fbaf46880a9b9ec1a285ad9dc8c695a9e936f5a48f34b4","impliedFormat":1},{"version":"14f6b927888a1112d662877a5966b05ac1bf7ed25d6c84386db4c23c95a5363b","impliedFormat":1},{"version":"6ac6715916fa75a1f7ebdfeacac09513b4d904b667d827b7535e84ff59679aff","impliedFormat":1},{"version":"0427df5c06fafc5fe126d14b9becd24160a288deff40e838bfbd92a35f8d0d00","impliedFormat":1},{"version":"90c54a02432d04e4246c87736e53a6a83084357acfeeba7a489c5422b22f5c7a","impliedFormat":1},{"version":"49c346823ba6d4b12278c12c977fb3a31c06b9ca719015978cb145eb86da1c61","impliedFormat":1},{"version":"bfac6e50eaa7e73bb66b7e052c38fdc8ccfc8dbde2777648642af33cf349f7f1","impliedFormat":1},{"version":"92f7c1a4da7fbfd67a2228d1687d5c2e1faa0ba865a94d3550a3941d7527a45d","impliedFormat":1},{"version":"f53b120213a9289d9a26f5af90c4c686dd71d91487a0aa5451a38366c70dc64b","impliedFormat":1},{"version":"83fe880c090afe485a5c02262c0b7cdd76a299a50c48d9bde02be8e908fb4ae6","impliedFormat":1},{"version":"0a372c2d12a259da78e21b25974d2878502f14d89c6d16b97bd9c5017ab1bc12","impliedFormat":1},{"version":"57d67b72e06059adc5e9454de26bbfe567d412b962a501d263c75c2db430f40e","impliedFormat":1},{"version":"6511e4503cf74c469c60aafd6589e4d14d5eb0a25f9bf043dcbecdf65f261972","impliedFormat":1},{"version":"ec1ca97598eda26b7a5e6c8053623acbd88e43be7c4d29c77ccd57abc4c43999","impliedFormat":1},{"version":"6e2261cd9836b2c25eecb13940d92c024ebed7f8efe23c4b084145cd3a13b8a6","impliedFormat":1},{"version":"a67b87d0281c97dfc1197ef28dfe397fc2c865ccd41f7e32b53f647184cc7307","impliedFormat":1},{"version":"771ffb773f1ddd562492a6b9aaca648192ac3f056f0e1d997678ff97dbb6bf9b","impliedFormat":1},{"version":"232f70c0cf2b432f3a6e56a8dc3417103eb162292a9fd376d51a3a9ea5fbbf6f","impliedFormat":1},{"version":"a47e6d954d22dd9ebb802e7e431b560ed7c581e79fb885e44dc92ed4f60d4c07","impliedFormat":1},{"version":"f019e57d2491c159d47a107fd90219a1734bdd2e25cd8d1db3c8fae5c6b414c4","impliedFormat":1},{"version":"8a0e762ceb20c7e72504feef83d709468a70af4abccb304f32d6b9bac1129b2c","impliedFormat":1},{"version":"d1c9bf292a54312888a77bb19dba5e2503ad803f5393beafd45d78d2f4fe9b48","impliedFormat":1},{"version":"9252d498a77517aab5d8d4b5eb9d71e4b225bbc7123df9713e08181de63180f6","impliedFormat":1},{"version":"cb8d8ef7b9ce8ed3e6f1c814fcbf3f90dab0cb8863079236784fc350746e27c4","impliedFormat":1},{"version":"35e6379c3f7cb27b111ad4c1aa69538fd8e788ab737b8ff7596a1b40e96f4f90","impliedFormat":1},{"version":"1fffe726740f9787f15b532e1dc870af3cd964dbe29e191e76121aa3dd8693f2","impliedFormat":1},{"version":"3be035da7bee86b4c3abf392e0edaa44fc6e45092995eefe36b39118c8a84068","affectsGlobalScope":true,"impliedFormat":1},{"version":"8f828825d077c2fa0ea606649faeb122749273a353daab23924fe674e98ba44c","impliedFormat":1},{"version":"2896c2e673a5d3bd9b4246811f79486a073cbb03950c3d252fba10003c57411a","impliedFormat":1},{"version":"616775f16134fa9d01fc677ad3f76e68c051a056c22ab552c64cc281a9686790","impliedFormat":1},{"version":"65c24a8baa2cca1de069a0ba9fba82a173690f52d7e2d0f1f7542d59d5eb4db0","impliedFormat":1},{"version":"f9fe6af238339a0e5f7563acee3178f51db37f32a2e7c09f85273098cee7ec49","impliedFormat":1},{"version":"407a06ba04eede4074eec470ecba2784cbb3bf4e7de56833b097dd90a2aa0651","impliedFormat":1},{"version":"77e71242e71ebf8528c5802993697878f0533db8f2299b4d36aa015bae08a79c","impliedFormat":1},{"version":"98a787be42bd92f8c2a37d7df5f13e5992da0d967fab794adbb7ee18370f9849","impliedFormat":1},{"version":"5c96bad5f78466785cdad664c056e9e2802d5482ca5f862ed19ba34ffbb7b3a4","impliedFormat":1},{"version":"81d8603ac527e75cfec72bb9391228b58f161c2b33514a9d814c7f3ebd3ef466","impliedFormat":1},{"version":"5f3dc10ae646f375776b4e028d2bed039a93eebbba105694d8b910feebbe8b9c","impliedFormat":1},{"version":"bb0cd7862b72f5eba39909c9889d566e198fcaddf7207c16737d0c2246112678","impliedFormat":1},{"version":"4545c1a1ceca170d5d83452dd7c4994644c35cf676a671412601689d9a62da35","impliedFormat":1},{"version":"320f4091e33548b554d2214ce5fc31c96631b513dffa806e2e3a60766c8c49d9","impliedFormat":1},{"version":"a2d648d333cf67b9aeac5d81a1a379d563a8ffa91ddd61c6179f68de724260ff","impliedFormat":1},{"version":"d90d5f524de38889d1e1dbc2aeef00060d779f8688c02766ddb9ca195e4a713d","impliedFormat":1},{"version":"a3f41ed1b4f2fc3049394b945a68ae4fdefd49fa1739c32f149d32c0545d67f5","impliedFormat":1},{"version":"bad68fd0401eb90fe7da408565c8aee9c7a7021c2577aec92fa1382e8876071a","impliedFormat":1},{"version":"47699512e6d8bebf7be488182427189f999affe3addc1c87c882d36b7f2d0b0e","impliedFormat":1},{"version":"fec01479923e169fb52bd4f668dbeef1d7a7ea6e6d491e15617b46f2cacfa37d","impliedFormat":1},{"version":"8a8fb3097ba52f0ae6530ec6ab34e43e316506eb1d9aa29420a4b1e92a81442d","impliedFormat":1},{"version":"44e09c831fefb6fe59b8e65ad8f68a7ecc0e708d152cfcbe7ba6d6080c31c61e","impliedFormat":1},{"version":"1c0a98de1323051010ce5b958ad47bc1c007f7921973123c999300e2b7b0ecc0","impliedFormat":1},{"version":"4655709c9cb3fd6db2b866cab7c418c40ed9533ce8ea4b66b5f17ec2feea46a9","impliedFormat":1},{"version":"87affad8e2243635d3a191fa72ef896842748d812e973b7510a55c6200b3c2a4","impliedFormat":1},{"version":"ad036a85efcd9e5b4f7dd5c1a7362c8478f9a3b6c3554654ca24a29aa850a9c5","impliedFormat":1},{"version":"fedebeae32c5cdd1a85b4e0504a01996e4a8adf3dfa72876920d3dd6e42978e7","impliedFormat":1},{"version":"3eecb25bb467a948c04874d70452b14ae7edb707660aac17dc053e42f2088b00","impliedFormat":1},{"version":"cdf21eee8007e339b1b9945abf4a7b44930b1d695cc528459e68a3adc39a622e","impliedFormat":1},{"version":"330896c1a2b9693edd617be24fbf9e5895d6e18c7955d6c08f028f272b37314d","impliedFormat":1},{"version":"1d9c0a9a6df4e8f29dc84c25c5aa0bb1da5456ebede7a03e03df08bb8b27bae6","impliedFormat":1},{"version":"84380af21da938a567c65ef95aefb5354f676368ee1a1cbb4cae81604a4c7d17","impliedFormat":1},{"version":"1af3e1f2a5d1332e136f8b0b95c0e6c0a02aaabd5092b36b64f3042a03debf28","impliedFormat":1},{"version":"30d8da250766efa99490fc02801047c2c6d72dd0da1bba6581c7e80d1d8842a4","impliedFormat":1},{"version":"03566202f5553bd2d9de22dfab0c61aa163cabb64f0223c08431fb3fc8f70280","impliedFormat":1},{"version":"5f0292a40df210ab94b9fb44c8b775c51e96777e14e073900e392b295ca1061b","impliedFormat":1},{"version":"bc9ee0192f056b3d5527bcd78dc3f9e527a9ba2bdc0a2c296fbc9027147df4b2","impliedFormat":1},{"version":"8627ad129bcf56e82adff0ab5951627c993937aa99f5949c33240d690088b803","impliedFormat":1},{"version":"1de80059b8078ea5749941c9f863aa970b4735bdbb003be4925c853a8b6b4450","impliedFormat":1},{"version":"1d079c37fa53e3c21ed3fa214a27507bda9991f2a41458705b19ed8c2b61173d","impliedFormat":1},{"version":"5bf5c7a44e779790d1eb54c234b668b15e34affa95e78eada73e5757f61ed76a","impliedFormat":1},{"version":"5835a6e0d7cd2738e56b671af0e561e7c1b4fb77751383672f4b009f4e161d70","impliedFormat":1},{"version":"5c634644d45a1b6bc7b05e71e05e52ec04f3d73d9ac85d5927f647a5f965181a","impliedFormat":1},{"version":"4b7f74b772140395e7af67c4841be1ab867c11b3b82a51b1aeb692822b76c872","impliedFormat":1},{"version":"27be6622e2922a1b412eb057faa854831b95db9db5035c3f6d4b677b902ab3b7","impliedFormat":1},{"version":"a68d4b3182e8d776cdede7ac9630c209a7bfbb59191f99a52479151816ef9f9e","impliedFormat":99},{"version":"39644b343e4e3d748344af8182111e3bbc594930fff0170256567e13bbdbebb0","impliedFormat":99},{"version":"ed7fd5160b47b0de3b1571c5c5578e8e7e3314e33ae0b8ea85a895774ee64749","impliedFormat":99},{"version":"63a7595a5015e65262557f883463f934904959da563b4f788306f699411e9bac","impliedFormat":1},{"version":"ecbaf0da125974be39c0aac869e403f72f033a4e7fd0d8cd821a8349b4159628","impliedFormat":1},{"version":"4ba137d6553965703b6b55fd2000b4e07ba365f8caeb0359162ad7247f9707a6","impliedFormat":1},{"version":"ceec3c81b2d81f5e3b855d9367c1d4c664ab5046dff8fd56552df015b7ccbe8f","affectsGlobalScope":true,"impliedFormat":1},{"version":"8fac4a15690b27612d8474fb2fc7cc00388df52d169791b78d1a3645d60b4c8b","affectsGlobalScope":true,"impliedFormat":1},{"version":"064ac1c2ac4b2867c2ceaa74bbdce0cb6a4c16e7c31a6497097159c18f74aa7c","impliedFormat":1},{"version":"3dc14e1ab45e497e5d5e4295271d54ff689aeae00b4277979fdd10fa563540ae","impliedFormat":1},{"version":"1d63055b690a582006435ddd3aa9c03aac16a696fac77ce2ed808f3e5a06efab","impliedFormat":1},{"version":"b789bf89eb19c777ed1e956dbad0925ca795701552d22e68fd130a032008b9f9","impliedFormat":1},"85ae5aee75f011967cf2d25cbc342f62d69314e9d925f7f4aa3456fc2cffcca6",{"version":"496898063c834c666510bdb5bb472bcf08e01ca8eef297da101ad12680c8fc93","signature":"435a1e418e8338be3f39614b96b81a9aa2700bc8c27bc6b98f064ff9ce17c363"},{"version":"402e5c534fb2b85fa771170595db3ac0dd532112c8fa44fc23f233bc6967488b","impliedFormat":1},{"version":"7965dc3c7648e2a7a586d11781cabb43d4859920716bc2fdc523da912b06570d","impliedFormat":1},{"version":"90c2bd9a3e72fe08b8fa5982e78cb8dc855a1157b26e11e37a793283c52bf64b","impliedFormat":1},{"version":"a8122fe390a2a987079e06c573b1471296114677923c1c094c24a53ddd7344a2","impliedFormat":1},{"version":"70c2cb19c0c42061a39351156653aa0cf5ba1ecdc8a07424dd38e3a1f1e3c7f4","impliedFormat":1},{"version":"a8fb10fd8c7bc7d9b8f546d4d186d1027f8a9002a639bec689b5000dab68e35c","impliedFormat":1},{"version":"c9b467ea59b86bd27714a879b9ad43c16f186012a26d0f7110b1322025ceaa83","impliedFormat":1},{"version":"57ea19c2e6ba094d8087c721bac30ff1c681081dbd8b167ac068590ef633e7a5","impliedFormat":1},{"version":"cba81ec9ae7bc31a4dc56f33c054131e037649d6b9a2cfa245124c67e23e4721","impliedFormat":1},{"version":"ad193f61ba708e01218496f093c23626aa3808c296844a99189be7108a9c8343","impliedFormat":1},{"version":"a0544b3c8b70b2f319a99ea380b55ab5394ede9188cdee452a5d0ce264f258b2","impliedFormat":1},{"version":"8c654c17c334c7c168c1c36e5336896dc2c892de940886c1639bebd9fc7b9be4","impliedFormat":1},{"version":"6a4da742485d5c2eb6bcb322ae96993999ffecbd5660b0219a5f5678d8225bb0","impliedFormat":1},{"version":"c65ca21d7002bdb431f9ab3c7a6e765a489aa5196e7e0ef00aed55b1294df599","impliedFormat":1},{"version":"c8fc655c2c4bafc155ceee01c84ab3d6c03192ced5d3f2de82e20f3d1bd7f9fa","impliedFormat":1},{"version":"be5a7ff3b47f7e553565e9483bdcadb0ca2040ac9e5ec7b81c7e115a81059882","impliedFormat":1},{"version":"1a93f36ecdb60a95e3a3621b561763e2952da81962fae217ab5441ac1d77ffc5","impliedFormat":1},{"version":"2a771d907aebf9391ac1f50e4ad37952943515eeea0dcc7e78aa08f508294668","impliedFormat":1},{"version":"0146fd6262c3fd3da51cb0254bb6b9a4e42931eb2f56329edd4c199cb9aaf804","impliedFormat":1},{"version":"183f480885db5caa5a8acb833c2be04f98056bdcc5fb29e969ff86e07efe57ab","impliedFormat":99},{"version":"b558c9a18ea4e6e4157124465c3ef1063e64640da139e67be5edb22f534f2f08","impliedFormat":1},{"version":"01374379f82be05d25c08d2f30779fa4a4c41895a18b93b33f14aeef51768692","impliedFormat":1},{"version":"b0dee183d4e65cf938242efaf3d833c6b645afb35039d058496965014f158141","impliedFormat":1},{"version":"c0bbbf84d3fbd85dd60d040c81e8964cc00e38124a52e9c5dcdedf45fea3f213","impliedFormat":1},{"version":"1dacb6ae2c0d095c0c085032f1f918cbb29f27f1f433c0374935347a0d99bb5b","impliedFormat":1},{"version":"dabb467c756ac5fa436cdbc46878550c83127d05a6faa22e739f28e48c14519d","signature":"f65ce75c9085571e6321abf2bf9833709f4897e381f89e9925521833dbb7ab16"},{"version":"04471dc55f802c29791cc75edda8c4dd2a121f71c2401059da61eff83099e8ab","impliedFormat":99},{"version":"5c54a34e3d91727f7ae840bfe4d5d1c9a2f93c54cb7b6063d06ee4a6c3322656","impliedFormat":99},{"version":"db4da53b03596668cf6cc9484834e5de3833b9e7e64620cf08399fe069cd398d","impliedFormat":99},{"version":"ac7c28f153820c10850457994db1462d8c8e462f253b828ad942a979f726f2f9","impliedFormat":99},{"version":"f9b028d3c3891dd817e24d53102132b8f696269309605e6ed4f0db2c113bbd82","impliedFormat":99},{"version":"fb7c8d90e52e2884509166f96f3d591020c7b7977ab473b746954b0c8d100960","impliedFormat":99},{"version":"0bff51d6ed0c9093f6955b9d8258ce152ddb273359d50a897d8baabcb34de2c4","impliedFormat":99},{"version":"ef13c73d6157a32933c612d476c1524dd674cf5b9a88571d7d6a0d147544d529","impliedFormat":99},{"version":"13918e2b81c4288695f9b1f3dcc2468caf0f848d5c1f3dc00071c619d34ff63a","impliedFormat":99},{"version":"120a80aa556732f684db3ed61aeff1d6671e1655bd6cba0aa88b22b88ac9a6b1","affectsGlobalScope":true,"impliedFormat":99},{"version":"a7ca8df4f2931bef2aa4118078584d84a0b16539598eaadf7dce9104dfaa381c","impliedFormat":1},{"version":"10073cdcf56982064c5337787cc59b79586131e1b28c106ede5bff362f912b70","impliedFormat":99},{"version":"72950913f4900b680f44d8cab6dd1ea0311698fc1eefb014eb9cdfc37ac4a734","impliedFormat":1},{"version":"151ff381ef9ff8da2da9b9663ebf657eac35c4c9a19183420c05728f31a6761d","impliedFormat":1},{"version":"ee70b8037ecdf0de6c04f35277f253663a536d7e38f1539d270e4e916d225a3f","affectsGlobalScope":true,"impliedFormat":1},{"version":"a660aa95476042d3fdcc1343cf6bb8fdf24772d31712b1db321c5a4dcc325434","impliedFormat":1},{"version":"36977c14a7f7bfc8c0426ae4343875689949fb699f3f84ecbe5b300ebf9a2c55","impliedFormat":1},{"version":"ff0a83c9a0489a627e264ffcb63f2264b935b20a502afa3a018848139e3d8575","impliedFormat":99},{"version":"161c8e0690c46021506e32fda85956d785b70f309ae97011fd27374c065cac9b","affectsGlobalScope":true,"impliedFormat":1},{"version":"f582b0fcbf1eea9b318ab92fb89ea9ab2ebb84f9b60af89328a91155e1afce72","impliedFormat":1},{"version":"960bd764c62ac43edc24eaa2af958a4b4f1fa5d27df5237e176d0143b36a39c6","affectsGlobalScope":true,"impliedFormat":1},{"version":"4ec16d7a4e366c06a4573d299e15fe6207fc080f41beac5da06f4af33ea9761e","impliedFormat":1},{"version":"59f8dc89b9e724a6a667f52cdf4b90b6816ae6c9842ce176d38fcc973669009e","affectsGlobalScope":true,"impliedFormat":1},{"version":"e4af494f7a14b226bbe732e9c130d8811f8c7025911d7c58dd97121a85519715","impliedFormat":1},{"version":"47416e41b1af81e53e8c3cc5bf909d47ff632a7b6eddfe7ff43d187b4dcca047","impliedFormat":99},{"version":"45cec9a1ba6549060552eead8959d47226048e0b71c7d0702ae58b7e16a28912","impliedFormat":99},{"version":"6907b09850f86610e7a528348c15484c1e1c09a18a9c1e98861399dfe4b18b46","impliedFormat":99},{"version":"12deea8eaa7a4fc1a2908e67da99831e5c5a6b46ad4f4f948fd4759314ea2b80","impliedFormat":99},{"version":"f0a8b376568a18f9a4976ecb0855187672b16b96c4df1c183a7e52dc1b5d98e8","impliedFormat":99},{"version":"8124828a11be7db984fcdab052fd4ff756b18edcfa8d71118b55388176210923","impliedFormat":99},{"version":"092944a8c05f9b96579161e88c6f211d5304a76bd2c47f8d4c30053269146bc8","impliedFormat":99},{"version":"b34b5f6b506abb206b1ea73c6a332b9ee9c8c98be0f6d17cdbda9430ecc1efab","impliedFormat":99},{"version":"75d4c746c3d16af0df61e7b0afe9606475a23335d9f34fcc525d388c21e9058b","impliedFormat":99},{"version":"fa959bf357232201c32566f45d97e70538c75a093c940af594865d12f31d4912","impliedFormat":99},{"version":"d2c52abd76259fc39a30dfae70a2e5ce77fd23144457a7ff1b64b03de6e3aec7","impliedFormat":99},{"version":"e6233e1c976265e85aa8ad76c3881febe6264cb06ae3136f0257e1eab4a6cc5a","impliedFormat":99},{"version":"f73e2335e568014e279927321770da6fe26facd4ac96cdc22a56687f1ecbb58e","impliedFormat":99},{"version":"317878f156f976d487e21fd1d58ad0461ee0a09185d5b0a43eedf2a56eb7e4ea","impliedFormat":99},{"version":"324ac98294dab54fbd580c7d0e707d94506d7b2c3d5efe981a8495f02cf9ad96","impliedFormat":99},{"version":"9ec72eb493ff209b470467e24264116b6a8616484bca438091433a545dfba17e","impliedFormat":99},{"version":"d6ee22aba183d5fc0c7b8617f77ee82ecadc2c14359cc51271c135e23f6ed51f","impliedFormat":99},{"version":"49747416f08b3ba50500a215e7a55d75268b84e31e896a40313c8053e8dec908","impliedFormat":99},{"version":"81e634f1c5e1ca309e7e3dc69e2732eea932ef07b8b34517d452e5a3e9a36fa3","impliedFormat":99},{"version":"34f39f75f2b5aa9c84a9f8157abbf8322e6831430e402badeaf58dd284f9b9a6","impliedFormat":99},{"version":"427fe2004642504828c1476d0af4270e6ad4db6de78c0b5da3e4c5ca95052a99","impliedFormat":1},{"version":"2eeffcee5c1661ddca53353929558037b8cf305ffb86a803512982f99bcab50d","impliedFormat":99},{"version":"9afb4cb864d297e4092a79ee2871b5d3143ea14153f62ef0bb04ede25f432030","affectsGlobalScope":true,"impliedFormat":99},{"version":"891694d3694abd66f0b8872997b85fd8e52bc51632ce0f8128c96962b443189f","impliedFormat":99},{"version":"69bf2422313487956e4dacf049f30cb91b34968912058d244cb19e4baa24da97","impliedFormat":99},{"version":"971a2c327ff166c770c5fb35699575ba2d13bba1f6d2757309c9be4b30036c8e","impliedFormat":99},{"version":"4f45e8effab83434a78d17123b01124259fbd1e335732135c213955d85222234","impliedFormat":99},{"version":"7bd51996fb7717941cbe094b05adc0d80b9503b350a77b789bbb0fc786f28053","impliedFormat":99},{"version":"b62006bbc815fe8190c7aee262aad6bff993e3f9ade70d7057dfceab6de79d2f","impliedFormat":99},{"version":"13497c0d73306e27f70634c424cd2f3b472187164f36140b504b3756b0ff476d","impliedFormat":99},{"version":"a23a08b626aa4d4a1924957bd8c4d38a7ffc032e21407bbd2c97413e1d8c3dbd","impliedFormat":99},{"version":"c320fe76361c53cad266b46986aac4e68d644acda1629f64be29c95534463d28","impliedFormat":99},{"version":"7bbff6783e96c691a41a7cf12dd5486b8166a01b0c57d071dbcfca55c9525ec4","impliedFormat":99},{"version":"3aca5b7f6e76a762ed7ee9596a6dd9e0678a9908b055b4c44a0555096fc1ed9e","signature":"4b96dd19fd2949d28ce80e913412b0026dc421e5bf6c31d87c7b5eb11b5753b4"},{"version":"7bb9b7b5c580ebde3f2839818dc5f49053a4bc693088af3a30c6ca1b69042bfb","signature":"0a996bc5648f30c52e845d7da69010a87f8fb57987d8e9c943b58d8013286049"},{"version":"3e0600317b706f47f709979812e601b97c7b12d64079c36f3575772ffe4fe2f8","signature":"a43d90a5c8e7a34db9b75dfe22cb4bd54ca43c51b2f24dbe6c67f28501cf1c58"},{"version":"3cbe6707a9e935f5b798d42bfb5dfa8af06707ad9a145691f66f48448cfcb383","signature":"645c81e86b6da1969b258ea73b11aeaf1d1cb9ec3faff28014de22a4357690cf"},{"version":"0570edf836f8882cc0262e6256bc71b88a5ce812d54500d03c5ff710f3388e3b","signature":"e298db69b3fd67ae1a27eeae16706cd8364490934635d21f840c9eaf28e63148"},{"version":"7749949e4261420989f255c30de9454b9c8f944a3dadff68d7eca91c233d2c9b","signature":"13b1a2180942a338fa3899781c2861493613b5b374803e17fa935c784b49a4a9"},{"version":"f3f0696393d4bb80e22fba11c1a7d447b18baa1f7d0f4d2e2af5a902faf3f9d8","signature":"73d048af9f177612fb2e7f59a6623a14e9608311059928af1d5c10139d4576bc"},{"version":"74946ef6928945934a528cec504cc4ee73665c9c18707a877122a5256fc896f5","signature":"e35db0faf36c8c332f6429ed35934faea6a0a25249c2b86e1e0217ce346cbd12"},{"version":"d3cfde44f8089768ebb08098c96d01ca260b88bccf238d55eee93f1c620ff5a5","impliedFormat":1},{"version":"293eadad9dead44c6fd1db6de552663c33f215c55a1bfa2802a1bceed88ff0ec","impliedFormat":1},{"version":"833e92c058d033cde3f29a6c7603f517001d1ddd8020bc94d2067a3bc69b2a8e","impliedFormat":1},{"version":"08b2fae7b0f553ad9f79faec864b179fc58bc172e295a70943e8585dd85f600c","impliedFormat":1},{"version":"f12edf1672a94c578eca32216839604f1e1c16b40a1896198deabf99c882b340","impliedFormat":1},{"version":"e3498cf5e428e6c6b9e97bd88736f26d6cf147dedbfa5a8ad3ed8e05e059af8a","impliedFormat":1},{"version":"dba3f34531fd9b1b6e072928b6f885aa4d28dd6789cbd0e93563d43f4b62da53","impliedFormat":1},{"version":"f672c876c1a04a223cf2023b3d91e8a52bb1544c576b81bf64a8fec82be9969c","impliedFormat":1},{"version":"e4b03ddcf8563b1c0aee782a185286ed85a255ce8a30df8453aade2188bbc904","impliedFormat":1},{"version":"2329d90062487e1eaca87b5e06abcbbeeecf80a82f65f949fd332cfcf824b87b","impliedFormat":1},{"version":"25b3f581e12ede11e5739f57a86e8668fbc0124f6649506def306cad2c59d262","impliedFormat":1},{"version":"4fdb529707247a1a917a4626bfb6a293d52cd8ee57ccf03830ec91d39d606d6d","impliedFormat":1},{"version":"a9ebb67d6bbead6044b43714b50dcb77b8f7541ffe803046fdec1714c1eba206","impliedFormat":1},{"version":"5780b706cece027f0d4444fbb4e1af62dc51e19da7c3d3719f67b22b033859b9","impliedFormat":1},{"version":"cb1f8036f8f9c69cd27d53813b9adaa23b57cdc536c4089a8a0854c575cdd0b1","impliedFormat":1},{"version":"dfe290c5346b0014184b26f6a2150929727138c7da0f41922418f22a6f05c020","impliedFormat":1},{"version":"85c7009d9d3253ab5f36f4d62309136fa74d87f9097cbcf7885db7d286364b16","impliedFormat":1},{"version":"3db4bf7c73ec7f427c255b25dc2482c61943e2c29e1fb9e77d61b4ef1528ba52","impliedFormat":1},{"version":"304c574c4c392ec7cc96c4d800a853e705daa2062a4b24f7fc0795c1371eba39","impliedFormat":1},{"version":"0711cd64e19e00917238c4996c97ba0f69380135cdebdec69d27fbe71419826d","impliedFormat":1},{"version":"e165bf9cb5815b38a14cb5dbbff3f83b48b207b46cc7f448896bfc69b2dbe6a1","impliedFormat":1},{"version":"85bada258ba9e8ab7a28fb31c1387b5d6f36aacede9197a9224c7ac4d0c7afc4","impliedFormat":1},{"version":"4eb0ed5e5864eb77abb73452e6e2c8b584825afa75d72dda4a9996f3f8d160cb","impliedFormat":1},{"version":"5f35327c612000cef210e8066e8a081258adcf5b5ea5a20395b2a575c081104b","impliedFormat":1},{"version":"8f25dc8cea6689735bfb730f446fb62592150a32f3a75fce4b2c23237e057fc9","impliedFormat":1},{"version":"26cec5bfef392a4c36c1995bc96abbe0ca3e02577bf7c23638326e1deb694d83","impliedFormat":1},{"version":"73043405ac8b8a85412e24223525cf8542b72e1b7201bbcb7a9bb87e4699c109","impliedFormat":1},{"version":"76a9454e36c6dcbe0cb45fa47df11294474e4f56ae57fc5b1ea66031392e5021","impliedFormat":1},{"version":"ed4959e66a9254e26976fc8ae88e458b0b05ae16841f2c57adf3e19e686a0d6a","impliedFormat":1},{"version":"a789d89d816ef995ed356886b1388a09543e4a801adb311e75c755b5338dc3e6","impliedFormat":1},{"version":"7ed4d5512e1a7c276aa547ebaccba714d9984ec1669b5130a039753058275881","impliedFormat":1},{"version":"fcef4bd9130dc41bcc30da1779f3ebd62cd6f90b31318b73c7e3d25a8c33b9c4","impliedFormat":1},{"version":"b593f3100ecf48e39d8f1a2fc49373c56c8e6ac312af4594020c96f650769836","impliedFormat":1},{"version":"9527492b74946dac2d980a584bf7061dad2d48a0e8ac21c62444ffc94388d984","impliedFormat":1},{"version":"d7eb49400d3852943d03d34caaed4c670ba35aaa309c9c20b8a0db48dd77d3c4","impliedFormat":1},{"version":"3ccffc1aa34b00b09df345cbb494ba545aec52aab5741fc863e174cb8b2285cc","impliedFormat":1},{"version":"ec4acd6c65b2f3466cdaeacd5d630e1bfb558066499720dd0828fe0e73799683","impliedFormat":1},{"version":"eee31fee7d4112a523b6ed43967b1d458a1d3c3ad22607eb6bbb3f6e6a4bebf5","impliedFormat":1},{"version":"958266dfbad20d8a14a9c12a53d8d4640de211f3b287fb543839a50d95b0e9e3","impliedFormat":1},{"version":"72b62e78c48f06790526fb910199291450f355031d12b5a91233eaf0295e418e","impliedFormat":1},{"version":"33a3038cb23270db88281ff2ada83b26acc68f6e5984d66934bef19554347f1f","impliedFormat":1},{"version":"74720f66db4cc64aa195dd49d0439b9d5a339e558ae02d24bd0d39db0bbccfaf","impliedFormat":1},{"version":"2d5004701e2a8fc6d827dab5223481f68da96ec4732fe32e7e918c01a8a7a61a","impliedFormat":1},{"version":"0934b6143a95cd1c43feda2fa2c8c17379ec6f4dc3e3e9e5fd561d76cec17739","impliedFormat":1},{"version":"cfdafb61973717bee7c31a4c8eed91af04c476b4167be1340103a79dd0532de1","impliedFormat":1},{"version":"cfd663d0b2006e5795fa3b1952653dc5f5d323fc0149a9c38cda3201e1a61b73","impliedFormat":1},{"version":"9e622274dae946c2702eea53bf9018eccd2a51cb11947cfd9e81ef3bda017eb3","impliedFormat":1},{"version":"002108b90ff7e9e87a9aacec121b058cd9abb892ee54a799b6c8317ef8bfd72b","impliedFormat":1},{"version":"b8f48caba09cfffaeab5e762b0e731c47e529d9f19ab64eb3dd46fa389e16406","impliedFormat":1},{"version":"32a82ad869e2b34ed784f6f7e6f630eb6bfcbcf202e6afd7db92748001907411","impliedFormat":1},{"version":"0a48ca6a980592f75892a113d541052da384c39038a0896565f2ee3dd38e0ceb","impliedFormat":1},{"version":"85b36a92544cc714725c43fe08e7da5e39dba751a9f80aa2d8ce6d8b667615e0","impliedFormat":1},{"version":"5754a019a1c1d6675966dc9f3736f3a1e646676ea262579fcc9dc676b4c269e0","impliedFormat":1},{"version":"ec4acd6c65b2f3466cdaeacd5d630e1bfb558066499720dd0828fe0e73799683","impliedFormat":1},{"version":"f227ccf65cd58641e192d41861ba64b310a981e9bfaeea22c08eff201300f6f3","impliedFormat":1},{"version":"b46f91ec07ec2882258d985037d4b45cede03326de6e1a57935cfef9e58a0c1e","impliedFormat":1},{"version":"4d828dd54c61e3436a3f0733f1c4d119828bf420740de7deacfe605519c3fe59","impliedFormat":1},{"version":"33a3038cb23270db88281ff2ada83b26acc68f6e5984d66934bef19554347f1f","impliedFormat":1},{"version":"9571c4af5c4e96120b86db94167847d583def98675ce1134faaf2a65de98ae94","impliedFormat":1},{"version":"427e9515091a96a82217de1dcb2b5fa0ff09cacf7c1359fae28050903fcfe1f8","affectsGlobalScope":true,"impliedFormat":1},{"version":"cfdafb61973717bee7c31a4c8eed91af04c476b4167be1340103a79dd0532de1","impliedFormat":1},{"version":"74720f66db4cc64aa195dd49d0439b9d5a339e558ae02d24bd0d39db0bbccfaf","impliedFormat":1},{"version":"cfd663d0b2006e5795fa3b1952653dc5f5d323fc0149a9c38cda3201e1a61b73","impliedFormat":1},{"version":"9e622274dae946c2702eea53bf9018eccd2a51cb11947cfd9e81ef3bda017eb3","impliedFormat":1},{"version":"002108b90ff7e9e87a9aacec121b058cd9abb892ee54a799b6c8317ef8bfd72b","impliedFormat":1},{"version":"0b6e86f4022fd9587b9987d5753aa2acdb05dd96b40576cc1db0734b2683a33d","impliedFormat":1},{"version":"dfe290c5346b0014184b26f6a2150929727138c7da0f41922418f22a6f05c020","impliedFormat":1},{"version":"2ecf1fb584b8762acab872e26630c3588587ee8cb3761638d4e8f96726a1b9be","impliedFormat":1},{"version":"84695653be49f0ee6685ad56fd3025f6f2935f834cc736b6ebe18f4ba35c2036","impliedFormat":1},{"version":"5754a019a1c1d6675966dc9f3736f3a1e646676ea262579fcc9dc676b4c269e0","impliedFormat":1},{"version":"13e8a533b3f6fa9a49bb77daef2cdfd4e8ab78887b68210ed0d4357c5cb7260e","impliedFormat":1},{"version":"436a4e249d1e2e7b5b599de2f13088c5b2a181e2e7a69b3fb83bbb3fe4c58c0f","impliedFormat":1},{"version":"6733f45a5cf9c190bf55c36a71eb7226258c32c422fdbd9bdcf712d60f29f914","impliedFormat":1},{"version":"f384f32f37497419f864977504318a703ff9974d7484e1e00f15a7c27ded4beb","impliedFormat":1},{"version":"3b79dcddcd327a1adf18eedbd1e71975e5526482207640afdcecb82631713df1","impliedFormat":1},{"version":"cbd591f32d67e0168030d8ac63fe9f5305e3b12dc66eff11388b017799e3fdcc","impliedFormat":1},{"version":"e00793ecb619340557aacc35f3f2810434bf55a070a8ee2548bfe7e58cd691d8","impliedFormat":1},{"version":"c380eccd51906944bccb84d9339172351d7d3032cc6109e8f2cd7b49f6a4074f","impliedFormat":1},{"version":"e0f6a5c6df80ac903fcbf81d8e2031509d99f84da6a02cc0c3f07a2e2f0bb69d","impliedFormat":1},{"version":"7b67e92e550658a3400740cd2c6c0694f425d4b38670784f1dad742a58aad5fe","impliedFormat":1},{"version":"69922c21d6e04d08496a75cfe979d1b42e5c4dada2dc1fabe7d3d85dc5c9be9b","impliedFormat":1},{"version":"b297245ccf3ec72e4b413e21ec6720d03ded5f5d208883592161d584fda3b1bd","impliedFormat":1},{"version":"976245df09b78e9f693eeaadcc6f24ec9837ee1fe61dc2124bbfd3d61e988d1b","impliedFormat":1},{"version":"4d12a68269f94c046f5865ac57369536ed2ebde3ab27545e82b728463dad3bf4","impliedFormat":1},{"version":"5bfbec6f4a9e5c3dbbeceaee7e9ab62d792b86bbba4098b7617ac04ad922088c","impliedFormat":1},{"version":"1e09d3ba318b6b09b888d96a43c57fee2fbf886eeeff0aad41e8f4386741c4d8","impliedFormat":1},{"version":"3bc93d58fd6910e6efb7db1d77f98f6c99e85576c920b5de973cc034a9f76728","impliedFormat":1},{"version":"8a1ec29f23543d9ddaaa883ada4325a418ed92bf09efc5f02771c51cbae253ae","impliedFormat":1},{"version":"df0e194edb86a119b1f021f9d5ee07fa689b2ebe703f2f29aaf436d3d3546e21","impliedFormat":1},{"version":"15c445f430445ebf6bfbc107ddbd94c5a1f6a1f07a3e03804478311358c9a6bc","impliedFormat":1},{"version":"0e2b2d160948defe907e86c937c6cc72593e2860183efebfb468942acaf4489e","impliedFormat":1},{"version":"8fc1ddf85214631bd866863970b8461ce0a176082862195cc46719f690fe1e43","impliedFormat":1},{"version":"0f70fe3235108c8fe062e36f9926e7683e3f9e46072d0940ace9a18e63a39479","impliedFormat":1},{"version":"36a8c33d093e1bc26ef5e87574b2a42d663a784355e0b9e1e94097847982d59a","impliedFormat":1},{"version":"60de2aba74b5b3f4293675e513f2c718c4cd074d77682e3b34f5233280497ef8","impliedFormat":1},{"version":"4eb134c8bd84bdfca82f233e659890b7dc9d1c471dae2ede990ffd1811e7f402","impliedFormat":1},{"version":"ae3e6bdeb49784a5a4af737bd6192035d02daf9cb4d21346ec572c2e5e180ff4","impliedFormat":1},{"version":"2eb2c6e8c9530e6807316bc0b863b7228c5e9ed3f69d9257c99185146499f0e2","impliedFormat":1},{"version":"d9c326e2b89124e3444439c75d0ac329b775ba89eba2486000780537b38430fb","impliedFormat":1},{"version":"48abb94feb786107ae4e934c60f3953230033f8d0dd5879245f2f7834f08a648","impliedFormat":1},{"version":"9682f9ab43c4b22a42960d6fb30d83876678cfa2b6f989478531488b5fbf5e8f","impliedFormat":1},{"version":"b813061d28e68084d190f0fda9509a64d156473db3ab696e5b28de0f05af7205","impliedFormat":1},{"version":"c9eef8879eac553d9482a84d60f183aca06dda7450dd1a776f5bc26dff38d636","impliedFormat":1},{"version":"b975867b8f5e0dbb461e4d29340561df8238fe42aa3132403086c1066d97f09f","impliedFormat":1},{"version":"75b4ff3600baa5111e336bf63bf1ce5ed1f6a3261e880de04d99abbe2b0550d8","impliedFormat":1},{"version":"7d8d645a484a708b37ca2dc8b192bc5a687a2bb3da7fe300c7f31cd80be591b4","impliedFormat":1},{"version":"d68165735d6bfc43cdc59e2acc0a3b0873b34525d71b1c266c7c6fba237926af","impliedFormat":1},{"version":"d22fad3dbd720f40e76e466d2df066005e11aeff2d1afd31e6de7a4385905eaf","impliedFormat":1},{"version":"219a5ba6fce5cd56ded80cd38a9061a8284a22400f80cdb7e78128f44e1e82ae","impliedFormat":1},{"version":"4eb343113cace665dea18eb3902f10785d2b95b3fe27c4b17833733c8c5766a9","impliedFormat":1},{"version":"0459512bf4737c1c50d71ff66370a0613fe58c42888ebd70ea5cb0df2b55e16a","impliedFormat":1},{"version":"14f588f95f40f3bedeb7a40b47e0cbe8d2326e3a88647766872403ed9c9809de","impliedFormat":1},{"version":"1848ed70143118527b8d9f44c42ad3af6304cb6e1cfcb3b0f7e4b2f1abfeb66e","impliedFormat":1},{"version":"ffbd00f89064a9963f9c790b9828c74caffc37c817f27954e3f58ccdcbf6b4ee","impliedFormat":1},{"version":"f50495adbdad305534adc331c1616d60fae4862a491433b02f60688399387193","impliedFormat":1},{"version":"3b385547db42cce98dcabd9dc9c6fe23c580807ae8d250fcb5789e505a988dda","impliedFormat":1},{"version":"0618d4380d763a72a1dba237b163c6cf2e087e3b845b2ad83700affccbb80082","impliedFormat":1},{"version":"08d9d00a2a86597cab6dd27fe19ab0ceea6010a86c74f806b00857242ddd047c","impliedFormat":1},{"version":"1ed02e88ae4a0022b5b2abde292fc349bca71815248a607d00f3d1960500544f","impliedFormat":1},{"version":"3d0874bcc16917437655ecb436f3d44920baf428b914aa456617454294f9ffc3","impliedFormat":1},{"version":"b478a4e6bd2d39ded7cbe64dcacbf999734828267c67490c167271dd32af3b23","impliedFormat":1},{"version":"d9c326e2b89124e3444439c75d0ac329b775ba89eba2486000780537b38430fb","impliedFormat":1},{"version":"250c5905bf19aefd93d4172b2d0ca4f9dd5e00d1ce6b4b2e4ccefe21ff728c86","impliedFormat":1},{"version":"6ddf24f9ecaac66bff4cedcb7d03865f340e75598400d265b00e29f0c6406b80","impliedFormat":1},{"version":"5330f4f848654078d37780010652b49115d9f89896a3401703ea3cf0baa8cf04","impliedFormat":1},{"version":"ef1364efe7d2d72b53e021336a601beb05b4050181354d58be8fa023d4dd20a7","impliedFormat":1},{"version":"609d234ca974cd849d39b6e3f52e3eecb879142a6ef0f2bc9f4ce97e81452d11","impliedFormat":1},{"version":"5af232c60b98d7fcc0e1025cb18f7b8037fe3eae1c8a372269e0f1b99c9fef4a","impliedFormat":1},{"version":"2caee401eb12d2302cd30ca71484fd49179a570863f31ae95acc35b76ec6bfbd","impliedFormat":1},{"version":"e02922a03c6b317ffee8c7bacd9290e094371ff76a7728c53785a55c37b55f69","impliedFormat":1},{"version":"2a7043737e1d8d80ecd74d646fb4446d149ccad99b8625f01f1e32e81b594ad1","impliedFormat":1},{"version":"d9c326e2b89124e3444439c75d0ac329b775ba89eba2486000780537b38430fb","impliedFormat":1},{"version":"47d88349632322b02448baa8671242ef999652300a86e044b957d084e590b3ef","impliedFormat":1},{"version":"fb7729535e349f99937d227817f21bf587ed3ae716c5bce33edca0cf204914bf","impliedFormat":1},{"version":"d287a83521026c13e7f0c26fe93ec1f8d996ae9846b187af45493b4d3e75eaf5","impliedFormat":1},{"version":"bf73c3a606a90a0e0fdf16784a45b67cdf9818f2a38d06c84fb56288ed911041","impliedFormat":1},{"version":"af107421a701786800dc523275bb847823c97dea400dc96b12fa59df8a9e9436","impliedFormat":1},{"version":"3c3eb531c13b6ae3d0d038f07a28ad1260b0fa249df7fa1caa434a047b88fa0a","impliedFormat":1},{"version":"d9c326e2b89124e3444439c75d0ac329b775ba89eba2486000780537b38430fb","impliedFormat":1},{"version":"d9c326e2b89124e3444439c75d0ac329b775ba89eba2486000780537b38430fb","impliedFormat":1},{"version":"803def89d1c799f619a300cd57853b7956bce6e76305d0aad806ef89a022dbb9","impliedFormat":1},{"version":"c53164284974ac89d51386ac9a5bb18c34477ae1f39d410013ea44763c2b9206","impliedFormat":1},{"version":"89f0ba5074e15ef17ad5cd4199aaa6a8a047496a70ca1843d54c613e0603c865","impliedFormat":1},{"version":"428554d1b6bd039eff68ed3ee14942908ae8146f219b238da2f653ac2ac2f861","impliedFormat":1},{"version":"ee0dc9004728daa40b27f979568954414a38dfbe24606001e700b3bfe72c2db8","impliedFormat":1},{"version":"37c762ab5356af4ca3e6546c54150224ce5012325041a85b2e6f3710cbd7a1f9","impliedFormat":1},{"version":"73e01307cfd6334a483b80a2aec03c0d07caa9eadac8aabe5ef7e9665fe15c59","impliedFormat":1},{"version":"fd3c1ccea875d68afc590962ee38f0260998bcc8dd001e8da68fc96c3d1b0ef5","impliedFormat":1},{"version":"faaeaf97593e09f191316a820953400b98ff53c778ad9ce888b93389f41ae5e3","impliedFormat":1},{"version":"14bd37fc13e1cb4595d490ebc90d2a4752b9043a745079662232ee3492b12ec6","impliedFormat":1},{"version":"2592f6ae20b3c3953fdf29a5be55d59929ae54d43ac4b208254307904e97db01","impliedFormat":1},{"version":"2997e9f7087398a4e44d6a0aed6f45a7aa9a0df99e653eedd37e2bf434feab26","impliedFormat":1},{"version":"10182b6a50cc485aa657eb4db9f783a3781897a5c2a1a9fe83e0f55d9e34fd95","impliedFormat":1},{"version":"4b4ca97d1f43f99ac609c2b2d1a4629854fcfb411b9ae640b9a3e06a74a70a8e","impliedFormat":1},{"version":"b31bb5cfb4285544ea7c5f86948df4b0ae4b7457bce668bcadf6ae665196db0e","impliedFormat":1},{"version":"3ece3336776791bfa8209355870b04629b46a7e574c8b101ddd98bf1a66751d5","impliedFormat":1},{"version":"f14037babbdeeac50e775ed72ef141dcd6565e78445c577cb95254024834fbea","impliedFormat":1},{"version":"a93fd929cd40ba2a5940d3639837645f8b21bba2a41c192796b12adc959d7776","impliedFormat":1},{"version":"ccfc9213fa3abbf42ecd7a0a3864cca0b17e77e485837a819a5272a2101a9268","impliedFormat":1},{"version":"b19aac4a14edfad05beb451bae30492b76f00ee4ecf79c9bbdd3334c13f68d8e","impliedFormat":1},{"version":"9c9f3389cf8e2369db03ff255c178f0f0f952fec8b672a738ed681c850342a4b","impliedFormat":1},{"version":"67d029c07b26107415ef6fc6e5f9e839767dbf91fe252c847cfeb7f0292cd8c0","impliedFormat":1},{"version":"5b527764483b100cc496c78e1d6fdd398117ed33ca9afc33f4941a4ee484ad5a","impliedFormat":1},{"version":"b91db5b602d5a13bef17751f95ebacf0054164660378c78306fa41f9d871d2d1","impliedFormat":1},{"version":"d0ad7cbec66adb43a08ab426aa6f22590e2183fc8faadd556d2ccb3e930e9941","impliedFormat":1},{"version":"6d7d868af595e9ec3d7d1334d751e0ec7da622df213d676dd25ba000394c22c4","impliedFormat":1},{"version":"9b54e2b3ebc2bd20c5b2e7cc0ca5a1173720b7df0ea4f36be8a173ff4648b34e","impliedFormat":1},{"version":"72b3a0765eb1e90558baee690f559cc2588b9a127ac33eb254b3efe73ac3e1c9","impliedFormat":1},{"version":"98be5603c4f3dac1335ff3e527f41d4fafeed14e2f3d013239d977ed657e693b","impliedFormat":1},{"version":"cc701f24f92ec8e6f852b97d776b1ae0f25bd2b669fcc8694898c3f2d555c8c0","impliedFormat":1},{"version":"26d573d47d7a3a228f510bec272aaa275350cebd9d2ecbaed90a4effc6e557c0","impliedFormat":1},{"version":"4b4fe975f117be911361c11924c5f4837c264e72f500e328dd1bb9e830443767","impliedFormat":1},{"version":"a537c671ffdc208d6b9c57caa97c1913da4c7cc2d1115f013fb2f7a6f95d1471","impliedFormat":1},{"version":"bafbd6ddff858792855ae5e1bb51a0b2c5a6e0dedb45b2cd892c357722ac3508","impliedFormat":1},{"version":"ea41963e99d0311c2ae979e8f5cd5c8caa9139f93c61a80fead4652e61677e3c","impliedFormat":1},{"version":"5ae06496f79ffffed758ae9c827a9948f5305839b7ff84e1b920ba1f5fa24d5c","impliedFormat":1},{"version":"9a869954197de6d2f2ceb6971856396e082cf7d0f8b58335d1109b0aa84c8bde","impliedFormat":1},{"version":"3054b2d41619ab80be976f6422b4220c7125f30f19a7dfcd282ee1fcee4458c5","impliedFormat":1},{"version":"edec72c09ee9bdb97f1001d5ca3793a7df71e53a6122579c0de98726b8a69e7a","impliedFormat":1},{"version":"8db830f5cb44fbd450010601c02b5225d9b69fb4e0565ae6a69f5ed441d350ed","impliedFormat":1},{"version":"af1066f19969a40c06a064168ea271d466ef8911b70e38db0241147c0f9b1534","impliedFormat":1},{"version":"48f1679dc3ea2f380b04b2c2256092a9a31b30edd5b52a8fd1260341696a2e5c","impliedFormat":1},{"version":"8129c7fa5e0b91362d8484fcfc853ea2de354497ef0ef656707dc251b47d30d2","impliedFormat":1},{"version":"7d99bf795b8a2080c5acbaec7648dce0aa014f61654363cbb8da631e158813ca","impliedFormat":1},{"version":"38c2d29872995e0eba3cc77ec7714be7c8714024a56d0698c0ccdfebc8b34333","impliedFormat":1},{"version":"b17dfe247aa0111c3ca2eadf2165b50833f6b2b64ef7b66319b5f30b6ecb316a","impliedFormat":1},{"version":"e4714e134970d7a51f7ec1b4e91747058e7fb77daad7a18702a5383d499b633a","impliedFormat":1},{"version":"c9fd408bd5813a02a9e30f0a1f85221e0f13f9f46d1405c3b0717c749fbb6c89","impliedFormat":1},{"version":"e7f8905bc9f71122a3ea5eb210256b206893bfd80101c5f4bab9855117a0ac80","impliedFormat":1},{"version":"f087db095dab80bddce2d43ae95d603f7bba06201a16bdee5b028ceded4899c0","impliedFormat":1},{"version":"6f85468ab5d8d3e9c6653f1a55a43a03bde345a48d50918f53a334f738295ad4","impliedFormat":1},{"version":"4d5a81f83f85d33f21fe6bb37652841db2ba290b94f52f60e5352996e1cfdc1f","impliedFormat":1},{"version":"d698b3f9912dc7ac5a7039530413f6ccc44945b431c3370885bfae8370430c0b","impliedFormat":1},{"version":"f2d82744b9d0b4dc459588b995832c047bfbccaed5fdd2907cf69af10d3360ec","impliedFormat":1},{"version":"576bf26ab310f0d948285920746ff9ab299d8515f84368fdd94b867fa932570c","impliedFormat":1},{"version":"49c3d2fea73d85b4024a3b4cbfd4c086d85a5a1a4c8920f23c40e6c81b7446dc","impliedFormat":1},{"version":"2d0e15690b38b53346045a15e9e1359509aa2c24170039abc50faefbc6b002e7","impliedFormat":1},{"version":"cacf5c0c429c4beddd0858f77bf68a918ceb0896802793a9e62736c7313b198a","impliedFormat":1},{"version":"9e3e5c5a74925a0aea9c786095c04f1348e75988f1066660fb0d045de83cb486","impliedFormat":1},{"version":"1035c6b42fbacc428e6c6b10f5c11ca567a9150e6017e6e5829d72ea1aa70cad","impliedFormat":1},{"version":"590f44dd7425356e40db71a9063fb7605fa5817ca2090000491111e0f535c540","impliedFormat":1},{"version":"0e8b0e62026c9166bec95ead366d2cbd01e0086582cb59a01301054731cf9eb1","impliedFormat":1},{"version":"3f588900bc393edd5d39d66e55cf73d54e64616bb10e16aabb69308b527e63da","impliedFormat":1},{"version":"549049e4aa464cceb66f0bc4525e7466b26f9d6db45d1a89129b2fb042270284","impliedFormat":1},{"version":"66889f57294f06e1c0a891a2af5298d1aff23861e3290c697b5f3eb2e5f8da23","impliedFormat":1},{"version":"9e9b4741ad5e7228a62961357dc596dd12f94569c03b515d6aa80adf51b64778","impliedFormat":1},{"version":"8b0990d1eb332f973044a845912d182ebc6ab87fac6ea52fa984452feac91816","impliedFormat":1},{"version":"abdba7845ee011022e227abecd75cbe599b43f3d5ea57bad547c1ae2a564af2c","impliedFormat":1},{"version":"1d57d1aa30f5f99aa31bdfa469804afb8420390d3a77b94c4f0aa285d5dc2401","impliedFormat":1},{"version":"49a01bb34f6651d5f33143d8d90653de8369b3c354cf56d33130c7f7fbd7c4da","impliedFormat":1},{"version":"d433831ee2ac9c9291290323bde0ef405ccb999de68c97a5428488f424508cd6","impliedFormat":1},{"version":"e1f419783736d84f773c9a7a47d3c8ba9884b75d01a950061f2556170bb51ba8","impliedFormat":1},{"version":"24f0897ddb49d344daf653ccb10655c0f345f59c9265dfb42984ffbcaf35c189","impliedFormat":1},{"version":"01696b6221d4bf20aea3ebe7717e2698a65fe6c5d8c163bc005d0741f031275e","impliedFormat":1},{"version":"16091fc8e371ecfe5e676673930fa06ed3664c4949d47a55e749609066bd25ca","impliedFormat":1},{"version":"38bada6c35d518359a6a7720b1dd7eea522873c4cb70bef80585e6f184e3be8c","impliedFormat":1},{"version":"d079bebca6469ebb44340b0c5458f14be6aa8ed9be2347bb9374d89f9b2a48a1","impliedFormat":1},{"version":"38bada6c35d518359a6a7720b1dd7eea522873c4cb70bef80585e6f184e3be8c","impliedFormat":1},{"version":"27302c5f42cf901cdc4206f8243b8cbe2ab3326d043e201086a354cc0d36f066","impliedFormat":1},{"version":"6233d61f7d2db398c5a1aa699ce306c32ea9aed3a7351f07f15e2133be0f1a1e","impliedFormat":1},{"version":"6233d61f7d2db398c5a1aa699ce306c32ea9aed3a7351f07f15e2133be0f1a1e","impliedFormat":1},{"version":"b43c0bcd2b1c1772aa7f7e04276b6e4674edb44faae05ed04c03dc573439ad08","impliedFormat":1},{"version":"6799fe20fd9575bac4a4131a05ea5f6e8b96e9c8c5eacd65aa1e3a2e3ae4a6e3","impliedFormat":1},{"version":"c3202f06147190991108fb9f3c574d5c2dd2b7b21fcb2c3bb9692472161a46e1","impliedFormat":1},{"version":"523fa4399cdc798164636b07a8b8f5f31c3ed7fb73b96df0d4d84f7f7e59fd6c","impliedFormat":1},{"version":"ba62fdf8d36f79a237de7d6d3f9c60bf3104af8e29c4de86af66b069cf857cda","impliedFormat":1},{"version":"95ce2a6f4e50fbfc542a287f9697c196e962dd89e554b5b7e69e07a5bcdeec93","impliedFormat":1},{"version":"47927e7a2e0a90119cefd0dcb79fa33738470d4c044de62f9030208fad91ea6e","impliedFormat":1},{"version":"429445903ca521abb9ca988d76f04e42792e28764acf3f4f494f3ca66c584e13","impliedFormat":1},{"version":"8b57b9ee66d3ef2c6674ad59be788cec9e95f5e974a4c7b5576627bea555da79","impliedFormat":1},{"version":"97f7424a7d768cd76302507d2ca5169105d26f0c92fe6f47e90bba843e400672","impliedFormat":1},{"version":"6911553948a0327a55b1cfea76ab9a4da2b4b13b7040fce08758eb84ba09c5ce","impliedFormat":1},{"version":"d720bad723bd8d6dbb04f76118c0b90c44b8b5bc4e5ec3fd3408b076153f2ace","impliedFormat":1},{"version":"7fcd666aff2087ccbad00794d2c8b92341190bf603661bc53ce0c848a8898d26","impliedFormat":1},{"version":"64c39c750a8556d514709f6f72e3acec60b8dc8a39045aa4102d81f5797f1b6f","impliedFormat":1},{"version":"97f7424a7d768cd76302507d2ca5169105d26f0c92fe6f47e90bba843e400672","impliedFormat":1},{"version":"6911553948a0327a55b1cfea76ab9a4da2b4b13b7040fce08758eb84ba09c5ce","impliedFormat":1},{"version":"d720bad723bd8d6dbb04f76118c0b90c44b8b5bc4e5ec3fd3408b076153f2ace","impliedFormat":1},{"version":"3db86af32ed40cc024a705f5bdbd2f851ea68e68cf9f779f0b2e4b7a332a7c55","impliedFormat":1},{"version":"c249089e61536ac3fdea7344280f4e3ade979f510b8c79ea23dbedab33df5360","impliedFormat":1},{"version":"3efe8e2b11ed4c737c5f1716759329c2859e83409b7ddf1514c10a2a267c2f33","impliedFormat":1},{"version":"285c3fcb2cdc80a125297403f9248f00a8b705f7e3aa1ccdb11f73f6add72394","impliedFormat":1},{"version":"dc871fa2f1ff416dbb5948ba7c69e143a9062d45c0620f618bd3d6936b9429bd","impliedFormat":1},{"version":"f05ce5c3ab663ed93097b98229f7e3ac3f3c98b7f6076cf29232bd090702efe0","impliedFormat":1},{"version":"f30b367468119582fc0a19466de8615998e15bd2f2c0ec4c33e9826cbcef8ee7","impliedFormat":1},{"version":"026e2ceda497ebdb829d810e5d8c018838412d4b9b16c52d1ef521f27f4a7cef","impliedFormat":1},{"version":"eb20bcc78034839e75de88f72cbb31a51a099201c72bbc563910933c0dedbb35","impliedFormat":1},{"version":"bd7107d42df22463ee116e095ea51a10fa3cc6be719043cf24c41189d07b09e0","impliedFormat":1},{"version":"9bea8564c9d245b0043916cd3267e63fc8b63c3ee3ab45b91214da7d59296500","impliedFormat":1},{"version":"6f384d5fdd6d5b427cd30e22d2998a9ef0c9abfcc92d3e3221d6082e6ae49241","impliedFormat":1},{"version":"26b7da74bac1b95dbba09430b2a2d2a313dd2a4ae4eb0d21c37d0133560167db","impliedFormat":1},{"version":"c4fcda5921f7b3d759116533f53757244c33f673666980c34934c4746ec75276","impliedFormat":1},{"version":"d1b6c97f6c075043a84c0ff906a4bea9bd689dc4d4fb798908b5dd16b9fe84ab","impliedFormat":1},{"version":"6b27a4157ebe97ae97dd63c13b6861036b2c9a6973e83fb636724f556ad4f814","impliedFormat":1},{"version":"6d2406b7484df398062c6d0a88bd4e71b3d6339aa079b785676f25e677f8cf5a","impliedFormat":1},{"version":"5209d0af91f77915c6552c7eed807a416131c19734d0264a81bf6e782f667fec","impliedFormat":1},{"version":"5130b0078e3616e4e1fe375c044d0a2c0d8eb99b477cc6e2037e881b0eb4664a","impliedFormat":1},{"version":"2863d27262545b9fb5d30d88c26b26fd1a54cacb07d89ea048eaa068c9a12e0b","impliedFormat":1},{"version":"07fca2cd875b20e85679790c59059b28cccff059c0059d67b5890f508a3a2e60","impliedFormat":1},{"version":"01248b7e8d551298920ad0f9480727bab67451214a5967b13e57f3f339e0f483","impliedFormat":1},{"version":"9673acf0ad66b0f381c223d8315eaca2705dbc4a70ec66ee7e74f76b979967b7","impliedFormat":1},{"version":"21e4632cce155fd43d83f80b068ba6509327a2746266147bcc28d8d9356164dd","impliedFormat":1},{"version":"7c5bddae9b801a72006e3f9bc294e82b728ec7da9c4df84946fb09c20c79923b","impliedFormat":1},{"version":"502e95eac78518007547ce992e054027be6782b08ae6a894a4f34b8fd181edc7","impliedFormat":1},{"version":"6c9d79d814d1f2be36ddd8e0eaef8a0996caf3bd249f0f97e290c8cc5445e632","impliedFormat":1},{"version":"4464b4ce8828c885c068acaa2a6e3ee7726cdb470377999fcf4af2e5bbe91b41","impliedFormat":1},{"version":"1f7fc42238e1f3c6b03b96002005a2ffd057e16f334ae9c1499ce3db02047e1f","impliedFormat":1},{"version":"02253965788d57f8b948175eac6ac874c3c9ff36404e9eb2c3eee2f3fd6298b5","impliedFormat":1},{"version":"6178abc2f31f50d5b0fb8c1877ed4e3c1af2412619f5825588099b254bae7090","impliedFormat":1},{"version":"742126ff1ca779a40038998d3c92bf0edb69cb1af8f3da6d8090705392c92afb","impliedFormat":1},{"version":"16b2edd77efe81e51069427a5edf2f96115a05a7e1169852f39f0c3ddb285266","impliedFormat":1},{"version":"59c1d976a5cb3b8e47a79e00db4b28532da67f46f6044d0ff34718ce68843976","impliedFormat":1},{"version":"43af042220029f253356622d5a2977e263036861414f20ea2ed502746c891434","impliedFormat":1},{"version":"9176ff1ca320c9735003e9caec7a5f722976e943b2043c58106170406df8614b","impliedFormat":1},{"version":"df9342677f9aa42b3d879bbb9daf7584c0d6f63cdfa49e9d009d80adf8d490d6","impliedFormat":1},{"version":"b2a585472d160d95a13cf17fe373959fd892cc78c96436545754a5dc7defeed7","impliedFormat":1},{"version":"24de25465e109f08469b8c56791bc1d75aab7c87d27c026879c22cde97e3297a","impliedFormat":1},{"version":"87d50c6588751a6d4692f0dd0186ad8c0d591253f2e21fbf3c5f962f21b8c8b2","impliedFormat":1},{"version":"ec2779b18cf625e277642b2a09b4e6104bd90f2765b2fb36a97115b0a9a4871d","impliedFormat":1},{"version":"09b2592b11a0ed66c442c314d11290bc550e4358fadbf5f9647a404c11399cab","impliedFormat":1},{"version":"50b49b549fc393ffc61aac1171bf12cc46f6eda3d3082cd1876d14758edd606e","impliedFormat":1},{"version":"6657c0cf3308ac450633a08f7835765cce67a13c409d6a09d2fe19e66f5252fe","impliedFormat":1},{"version":"1abdbe2031378fb1f7883ba0d60a2cda3e0ce42a60402d356e115b00850e2d53","impliedFormat":1},{"version":"023554b09495d4e4594b8ed70fefb8329a562d364769ec62db8844c96e69dfc5","impliedFormat":1},{"version":"8b3fbc2adaf95c5b68d11eefff5965c7024f40d4b21a6d0263e5caefd637209b","impliedFormat":1},{"version":"cd32b6ba989eedad32612bd49643ba71bd83e3cc78c066d857d8db8273680ccc","impliedFormat":1},{"version":"b5a4495bb01dadf0d320ae0987d6ad9a7d9270f4e0fb31b35497f8e3ad02fe35","impliedFormat":1},{"version":"8306e2999f7af8d69e238629596c936362ddbfd27a0859d0102261c582952664","impliedFormat":1},{"version":"07f39e8c121c4ad995bc5b648d95e3029cf1de7948bb8f52242d1c9571bde8e3","impliedFormat":1},{"version":"9569532b4674ce1c66f59ed98a1139484ce10599ec31e7d1fe306e326d784ed3","impliedFormat":1},{"version":"eceb1d0beebbdaae0b41b0c80856764f4932660d45f875954f491e09a34c0d7a","impliedFormat":1},{"version":"ec4ec23de9c89c96e96e31c88975a98ecbe94638d0f7fa9b93d5b8fc6d02a79f","impliedFormat":1},{"version":"ed028d7023163d03c9547d64e642ed39e6dc544e1f4bc00715c997d9daa1e98b","impliedFormat":1},{"version":"51f5665aeb2774990b3b0eab4fc39ceb53e674e4b5fa88d1e6d64dfbca36c636","impliedFormat":1},{"version":"e6f2dbd92a37874ceb4a65a9cfa393f216a215a58a6baf0128e2fa5a3098603f","impliedFormat":1},{"version":"cef4fe0e1c6eb9b0e14a23201ff3b5edabe329aabca23a14e178108c49be8752","impliedFormat":1},{"version":"d544a24aef3010d12aeadcc7813c9b4ec02ca2447262cda7d561f31e8ab4ab4a","impliedFormat":1},{"version":"51f5665aeb2774990b3b0eab4fc39ceb53e674e4b5fa88d1e6d64dfbca36c636","impliedFormat":1},{"version":"4ba3b22edd355ae3316dabb362a7e41c8bfe2a22818cb9b4e0abfb26a9618a48","impliedFormat":1},{"version":"8015f3c46a39b4cb2ada00f4acd5c21b33b90aad98b7a44e311c53b74e444695","impliedFormat":1},{"version":"7019c88002c488be672c19ad13def90a2edbcd699d423240d601b79a76599866","impliedFormat":1},{"version":"4757254beac0f2a34c1625f950279c82185de944e1ff81c5ef9bb9279d6e492b","impliedFormat":1},{"version":"924d65cd98350be913955cae8c89ea19ecaf5cbcc10b6c6252d2fcb2ab7b3518","impliedFormat":1},{"version":"afb80020cf49bfbd5f08a60737e4f0c84dd819193f8adcbbe6f7d7a96b3852be","impliedFormat":1},{"version":"fc74a81d71ecfe1926214c4fc172f540e51a15bae98616278d165f33846f1fc1","impliedFormat":1},{"version":"bb697f2636d63cf2960bbf91a65744b705ae32c786d9d9934607e587fcffdb8b","impliedFormat":1},{"version":"0a8259e9ef9e33557e7fd4763bc871581b7ffbea5d6d6de7bee8cccb57c68db3","impliedFormat":1},{"version":"7c307c4ca0a07f8ef7b9bd8c5b7b0e48f894203b2d543b5848f471914633ac5a","impliedFormat":1},{"version":"786426518b5c3582c00528444c0562fd1b995464cd67be7095944bcda8ab7677","impliedFormat":1},{"version":"064070134a2e8ea83dd3f9d5b40c41431315cbb660333370aed8e77bf2da6b08","impliedFormat":1},{"version":"3453583e8f126b7d1d19d311ee10ffee609a2167b05bddb96c370fbea40e87ba","impliedFormat":1},{"version":"ae76aca56117673e501c7e5cab55e31eea3344aba6324407164bf2729770a598","impliedFormat":1},{"version":"6fac972fb851716995eef39678b2055bafc802b57bd94ccfae263c263213ec0c","impliedFormat":1},{"version":"7a7eeb228a832cd49484d1192db993dd120a2202fec9dead9411d5781b608660","impliedFormat":1},{"version":"486157b5283f5679b3c422dd4c9bd4e3f215ba41736019f5b61508852d2e4c8b","impliedFormat":1},{"version":"325379e60d8e0465149fb0ef9812a9eb1a12982b5cc16aeab90067360044f289","impliedFormat":1},{"version":"b418f0bdbf8c35aee9b89fda32b04f53decd9c7481b6f871692458f1be97b462","impliedFormat":1},{"version":"1d8f51a4eaea84b7908e26d87d3d0abcbc3eb78ff8ec86c1c0f311075d4d245c","impliedFormat":1},{"version":"2189bc92169eacac269706b342b75c0f0c089fb35b053ec30962b4dd483b5ec0","impliedFormat":1},{"version":"b97c3f409bdedf9ac0852f3a4f5ee1827f7d75d686efc2ee38c47cc175b2a1e9","impliedFormat":1},{"version":"05cd813328106c081a3f13fc3f9a4781bc0f756f5655279123306501d093aa44","impliedFormat":1},{"version":"4aa9a7d7480f1f844e42c189ae4e101e6e42dc488b0ccbf077a5c9a9f70d97a3","impliedFormat":1},{"version":"6a11946ceb52ef7e4885c245b0a6b2e7a5b3ef90e0cbf8e480639f2b82aba681","impliedFormat":1},{"version":"a49ca8bfdf9affced255ecdb77cc23e2b4cb6d52c8ff2f777026d300083c14f4","impliedFormat":1},{"version":"2a98d6fe953220a7a1ae8dba58aa5bc28d8d6cd9fa1f166199c2c1116ecd3c38","impliedFormat":1},{"version":"466aad8a0d48efb91dfae2570478ef8eae643657d4f6547e3013967bf3db4ffe","impliedFormat":1},{"version":"26054f90788c0e761b748411a6fb223bb61ec680041eb2eddd39cd970f4fcd39","impliedFormat":1},{"version":"e251b6550b56f8f8c838f8ddd4990bc60fec06d9c99527a080c619dcafdf02aa","impliedFormat":1},{"version":"36ca919dfeab1d304e60d703956d899087212701c175ab574eca3d54b0a9ff2f","impliedFormat":1},{"version":"ae98194239f1570466d7bfd8835cdae1343ffa8969bcaeca6f7237bbbbaea2a6","impliedFormat":1},{"version":"ee9b869e0409f0bf6857d4a2e02b64c2554071fb76f9cc3c3555d1dde25b5a18","impliedFormat":1},{"version":"2efd52338da3ff5711cc72e5b73a7b2be30ef4131301f3802eea0b9b98eeccc4","impliedFormat":1},{"version":"c9639824974e1515a9d4a0befc673eb3a396529362331ce3bbddd79cbb2716a5","impliedFormat":1},{"version":"20082c0404595cd12f067e44d592ccc88d818eb09cc1c4e4a129fc3f7636a643","impliedFormat":1},{"version":"f81f66f5bd361fc82717f591971666bca517a7a6f2e202963097cb5cfa507a64","impliedFormat":1},{"version":"53fbde0efcc4a821f2dba6d6ea27e1a80d7da02fbb367d9f73eb944516785f13","impliedFormat":1},{"version":"a90b15539d910b1560c4ab715fb7330e175e591d01e7e31b2c9bfda65de938f1","impliedFormat":1},{"version":"6a36da368780386326462d6f48f47222cbde9a00fbfaa0f855034ac6751c8f85","impliedFormat":1},{"version":"861f698c8bfd16f1acaff2ae370bed396b9dd4a0a8aa790be6d93be2f542d55a","impliedFormat":1},{"version":"60aec83c734c6445d2dfc2eb1ec3ce22d4addd3999c05046483ebf64f36566d6","impliedFormat":1},{"version":"cfbe384795dee8102f2fcfac7126e07f55e7d343fafc887cc08051f01165168a","impliedFormat":1},{"version":"09cb1355bcecf2cc77e2f01b439497afc40d11e614d1efed532dc706dcdef335","impliedFormat":1},{"version":"51afdbccecc8375ebe5d89095d15fd07b1111c2e42d092df3b1b3a78aadf9098","impliedFormat":1},{"version":"82b276fcb52e5a460b21290cefa1ec98268466215276a7b4fb9cb44cde5315b4","impliedFormat":1},{"version":"d2cb3dc749548c173c0c135b3c8abc02dfb088d3559eb9bac31c8a5f58125d29","impliedFormat":1},{"version":"c15e99f7d8fa0717ea26d36af76f371f066372c581312d8d28f3a47b553c67a4","impliedFormat":1},{"version":"2d844d3589f04bf3b3f53216b72271312acb459d4ed70f603e52da034fe594af","impliedFormat":1},{"version":"ce30a913ea003516f6dd959ca623550da569fc1af7660f17c4cf53d9f28b826a","impliedFormat":1},{"version":"44cec0d12d632b7bb943fd681c23ddc1b031078b28697358ec2cae7f99bf8a92","impliedFormat":1},{"version":"839abd29c3fef0c2777be53ebf099e545718779ff76ef31120f6436e2448fada","impliedFormat":1},{"version":"7ec31d0f2e40ef288d68b8afe023f38c033a32a4cfde5541e75a4ab4da1ad499","impliedFormat":1},{"version":"e413696188f357020e920078f8a04bdf8752bba0b21ba61ea4b7a0ca066da22d","impliedFormat":1},{"version":"868867a0ba768c46a5a72043814d18e89370d479fc34f3c0d9c22fe81c1ca23f","impliedFormat":1},{"version":"3003540eb4037023bc605b9560f65bb93ec37f4c28ffa65b38552b68d3bd8f32","impliedFormat":1},{"version":"fcd8e7548a5bd2715a1c47611af7b2d0fb870589917876e18305cf4d35fbbae3","impliedFormat":1},{"version":"a3c1743275c71b8bd46a2bd63c1d9a7a90be4ce373ead58654ce8653acf7dd70","impliedFormat":1},{"version":"d0e562fbc98b25a154ddfca69fdf86c18ae6c09545a1166a609224e399fe3474","impliedFormat":1},{"version":"59d95dde3c75f13bbdff4842f35993b96b54509e423421534881f62377a28102","impliedFormat":1},{"version":"518012d5a74b0973d64e5e59577c094dfcf71d14ef5ae07d9610fb83d36f6acf","impliedFormat":1},{"version":"8f6ac9f91fa905a021fa8702f621680d56849deffd3b1ba170ccf7dda3a8bafd","impliedFormat":1},{"version":"b23709afde997019d6b35ceafd5f68103ce55ac1cb6988d439e7624f3db69f99","impliedFormat":1},{"version":"1b173650e2ec1b05d89d6bb5d8eea3d9b4ff32c51d0368c4c8c235259b36522f","impliedFormat":1},{"version":"25f7bb52ffdb36ca9ad22a7bf134e9fe0fdf79fffe7d37ccd656c8bfeca394ef","impliedFormat":1},{"version":"5c99dd66b0a3fc5a0afef3c352e1c63e6f889964d51e0906ff25b04ea83d1a57","impliedFormat":1},{"version":"5bf185675b60707802daa0d6d2b495c24ccc6dc98fc2e388a0b5c7f6da1d999d","impliedFormat":1},{"version":"fd93d73895c75a7b2e5a83820955edcbd64934c72236598a68d12b20ffb7b25d","impliedFormat":1},{"version":"0d7cd779405f2cbdba626fa1353419bc5cc85c497782a5381d2b363f523e3701","impliedFormat":1},{"version":"b0ae7203c5b50f8b368e007532a19cf5a0a51ed6d2bb7549b56e7f41ed2ebd82","impliedFormat":1},{"version":"2fd2392d984c25633d5738fc80ac2449faadfc867ed89274884da1771752b091","impliedFormat":1},{"version":"415ead3b5b34239b5fafd4dff7d92e3a99b5887b4bda47d803782d5fa2366e7c","impliedFormat":1},{"version":"a1ad2126f33bd34ebc21b97c04e496773f564bf842b9a24ed0d9e41e19fcf600","impliedFormat":1},{"version":"98ce3d77d663139a7c20fd506354b13628157092995d76d60c55a73e35d505fb","impliedFormat":1},{"version":"6549a1e655ad2265e294e57622b077f16c8ad74c820697c88fafe454cf743770","impliedFormat":1},{"version":"4655832f525f00b8796f42b0e73807d62fe7c5863890478781a5a7520b093404","impliedFormat":1},{"version":"4b71432f437f48272e6879cca65f2510e01419527f658846c0c65f3cfb6bb5b7","impliedFormat":1},{"version":"64fb1bbd008a55ddb5737c80d246a60cc4863751f8079670a3c3caaba79699e1","impliedFormat":1},{"version":"a4696fa234d9c6342e5103362ba4aa9e5bbc8179e132c240bf9fc388f09d9236","signature":"0e6b78bcd048d61224795ce4458f5138cb0ae8f3832437e697036c65603d0538"},{"version":"bf7a2d0f6d9e72d59044079d61000c38da50328ccdff28c47528a1a139c610ec","impliedFormat":99},{"version":"e58c0b5226aff07b63be6ac6e1bec9d55bc3d2bda3b11b9b68cccea8c24ae839","affectsGlobalScope":true,"impliedFormat":99},{"version":"5a88655bf852c8cc007d6bc874ab61d1d63fba97063020458177173c454e9b4a","impliedFormat":99},{"version":"7e4dfae2da12ec71ffd9f55f4641a6e05610ce0d6784838659490e259e4eb13c","impliedFormat":99},{"version":"c30a41267fc04c6518b17e55dcb2b810f267af4314b0b6d7df1c33a76ce1b330","impliedFormat":1},{"version":"72422d0bac4076912385d0c10911b82e4694fc106e2d70added091f88f0824ba","impliedFormat":1},{"version":"da251b82c25bee1d93f9fd80c5a61d945da4f708ca21285541d7aff83ecb8200","impliedFormat":1},{"version":"64db14db2bf37ac089766fdb3c7e1160fabc10e9929bc2deeede7237e4419fc8","impliedFormat":1},{"version":"98b94085c9f78eba36d3d2314affe973e8994f99864b8708122750788825c771","impliedFormat":1},{"version":"13573a613314e40482386fe9c7934f9d86f3e06f19b840466c75391fb833b99b","impliedFormat":99},{"version":"64c18db93d238750fffddbefab86ba3475686afd50ae44748b73a8d280c1a9cb","signature":"8e609bb71c20b858c77f0e9f90bb1319db8477b13f9f965f1a1e18524bf50881"},{"version":"b47bff28e5e91082a4b08cd9bd83a788596bf28218bb75476260acac6844ff3b","signature":"a5f04e1e0258c0d0c50c2121b702f32d34e6ea0c0018798f58a810e24aa1a6a2"},{"version":"44e7cd3ada74ce6f1c3f462e07cca990691d1188cebf04c77de3028c6f3e2703","signature":"8e609bb71c20b858c77f0e9f90bb1319db8477b13f9f965f1a1e18524bf50881"},{"version":"6542e1e73662ce0b0efca7c3860ddd4c577a3fb6d4896066bf363d090488a606","signature":"8e609bb71c20b858c77f0e9f90bb1319db8477b13f9f965f1a1e18524bf50881"},{"version":"3c3174c0432ee84e2c715c2fd6a9d2eca247d767acab85543a92ff34a37f18e7","signature":"3450bd5107d2b9c131247a65d4407b59178e6a14417076cb44fe01d6d456ecf5"},{"version":"c5ac1af551965a7f273eae5ab64a663bdabdd0adbda15aa61e4a2c8fa90a6dc7","signature":"360671b472e5ef927fd00e85095bfa2d665c42e7f58efe24f7521d0373a6d218"},{"version":"31b1f342c3c5a85d113717320d8be1a08d250a2954ebcd5b99c3ec2ccb31cea3","signature":"8e609bb71c20b858c77f0e9f90bb1319db8477b13f9f965f1a1e18524bf50881"},{"version":"63ff6dc64ef576df79545bbaa963d23cf124e8ad0bab7b20d08152ee04b6342a","impliedFormat":1},{"version":"2f6cb703e70a0c84b7e1c4f04573144d9779e4812d295ee1336c33c8c619d598","impliedFormat":1},{"version":"1667c652b307c2827c64ce3bbb2e635345c55a92c3d4abd7253e56869f5a7e61","impliedFormat":1},{"version":"ec291aef6983ef8c26e982c82b110aa39aa30e952991f8965f25bac02b5c6d47","impliedFormat":1},{"version":"8008ef47146c0fae2f633ffc92fec12ce1c3d3cde21446fe9d2966cab9cbbfa5","impliedFormat":1},{"version":"0f6ccb7b3426efd6222202f72b7c651f62ef6c9f0a77f6cc87db1bc4e4b48805","impliedFormat":1},{"version":"d5b0e01b58aab75223f97953afba894bb2e73cf935d6aedc85d54aca0115cc36","impliedFormat":1},{"version":"19b744a6fe628b476011906b02b5fbf579aaa1fff5dd039de5e3637c5bdf2928","impliedFormat":1},{"version":"192c70866ca70b0edbb78e05bdcdd6052262aa8cc7dcd3df28607646775e5bc3","impliedFormat":1},{"version":"d8710b3620c0301e1d0c8477bfeaf6e074ae31c517bc7aac55c05db3ffd11832","impliedFormat":1},{"version":"487c1324f90d0a25cd10eef3225f966100c2f403c334090f1540fed30d118124","impliedFormat":1},{"version":"7bb53546e9bd6e3f22804497a41d4b885674e7b15b7d64c7d3f83722dfd2b456","impliedFormat":1},{"version":"4083e6d84bfe72b0835b600185c7b7ce321da3d6053f866859185eefc161e7a0","impliedFormat":1},{"version":"b883e245dc30c73b655ffe175712cac82981fc999d6284685f0ed7c1dac8aa6f","impliedFormat":1},{"version":"626e3504b81883fa94578c2a97eff345fadc5eae17a57c39f585655eef5b8272","impliedFormat":1},{"version":"e9a15eeba29ceb0ee109dd5e0282d2877d8165d87251f2ea9741a82685a25c61","impliedFormat":1},{"version":"c6cb06cc021d9149301f3c51762a387f9d7571feed74273b157d934c56857fac","impliedFormat":1},{"version":"cd7c133395a1c72e7c9e546f62292f839819f50a8aa46050f8588b63ef56df88","impliedFormat":1},{"version":"196f5f74208ce4accea017450ed2abc9ce4ab13c29a9ea543db4c2d715a19183","impliedFormat":1},{"version":"4687c961ab2e3107379f139d22932253afb7dd52e75a18890e70d4a376cdf5d9","impliedFormat":1},{"version":"ae8cfe2e3bdef3705fc294d07869a0ab8a52d9b623d1cc0482b6fc2be262b015","impliedFormat":1},{"version":"94c8e9c00244bbf1c868ca526b12b4db1fab144e3f5e18af3591b5b471854157","impliedFormat":1},{"version":"827d576995f67a6205c0f048ae32f6a1cf7bda9a7a76917ab286ef11d7987fd7","impliedFormat":1},{"version":"cb5dc83310a61d2bb351ddcdcaa6ec1cf60cc965d26ce6f156a28b4062e96ab2","impliedFormat":1},{"version":"0091cb2456a823e123fe76faa8b94dea81db421770d9a9c9ade1b111abe0fcd1","impliedFormat":1},{"version":"034d811fd7fb2262ad35b21df0ecab14fdd513e25dbf563572068e3f083957d9","impliedFormat":1},{"version":"298bcc906dd21d62b56731f9233795cd11d88e062329f5df7cdb4e499207cdd4","impliedFormat":1},{"version":"f7e64be58c24f2f0b7116bed8f8c17e6543ddcdc1f46861d5c54217b4a47d731","impliedFormat":1},{"version":"966394e0405e675ca1282edbfa5140df86cb6dc025e0f957985f059fe4b9d5d6","impliedFormat":1},{"version":"b0587deb3f251b7ad289240c54b7c41161bb6488807d1f713e0a14c540cbcaee","impliedFormat":1},{"version":"4254aab77d0092cab52b34c2e0ab235f24f82a5e557f11d5409ae02213386e29","impliedFormat":1},{"version":"19db45929fad543b26b12504ee4e3ff7d9a8bddc1fc3ed39723c2259e3a4590f","impliedFormat":1},{"version":"b21934bebe4cd01c02953ab8d17be4d33d69057afdb5469be3956e84a09a8d99","impliedFormat":1},{"version":"b2b734c414d440c92a17fd409fa8dac89f425031a6fc7843bac765c6c174d1ca","impliedFormat":1},{"version":"239f39e8ad95065f5188a7acd8dbefbbbf94d9e00c460ffdc331e24bc1f63a54","impliedFormat":1},{"version":"d44f78893cb79e00e16a028e3023a65c1f2968352378e8e323f8c8f88b8da495","impliedFormat":1},{"version":"32afc9daae92391cb4efeb0d2dac779dc0fb17c69be0eb171fd5ed7f7908eeb4","impliedFormat":1},{"version":"b835c6e093ad9cda87d376c248735f7e4081f64d304b7c54a688f1276875cbf0","impliedFormat":1},{"version":"a9eabe1d0b20e967a18758a77884fbd61b897d72a57ddd9bf7ea6ef1a3f4514b","impliedFormat":1},{"version":"64c5059e7d7a80fe99d7dad639f3ba765f8d5b42c5b265275d7cd68f8426be75","impliedFormat":1},{"version":"05dc1970dc02c54db14d23ff7a30af00efbd7735313aa8af45c4fd4f5c3d3a33","impliedFormat":1},{"version":"a0caf07fe750954ad4cf079c5cf036be2191a758c2700424085ffde6af60d185","impliedFormat":1},{"version":"1ea59d0d71022de8ea1c98a3f88d452ad5701c7f85e74ddaa0b3b9a34ed0e81c","impliedFormat":1},{"version":"eab89b3aa37e9e48b2679f4abe685d56ac371daa8fbe68526c6b0c914eb28474","impliedFormat":1},{"version":"8ec83fc8f345a4f5011dd9ea16a10aadc1fab5c5bab6215451f0027a05cd627b","impliedFormat":1},{"version":"64456bf67e3e27ee199ebf28b90105f293c479dcdbb1720c041f9f54b2447f67","impliedFormat":1},{"version":"08953b65d641e31c0cb7a5e9cf82657f0d06113cbbdf63c7bef19ddab3c5f38b","impliedFormat":1},{"version":"6b75f3cb3254ed2ebde6f7c9487711bd498406d86310033f5b705655016d3086","impliedFormat":1},{"version":"65edde03abcb84048a8782670a52e027d2864090827fb9f6a593df442b9a7552","impliedFormat":1},{"version":"83eaf9842aaec8f93fa3dfd2f5ff82af72aa07de1855c5e405d52cb5ddbd0561","impliedFormat":1},{"version":"58961616c80eb882f198633f36128267882f1e38ce5d1acf21893726218d6f4e","impliedFormat":1},{"version":"4e50de679406cabd9ef284e0b6fa8b2e190bb00b3a1beb70afb2f85dd21b09c8","impliedFormat":1},{"version":"2e812554c576fa240ffaa71d0ca5259181cfb00cab70c5c1f78eb7d8e3330e44","impliedFormat":1},{"version":"fe59811a5b7433b873afe7ea9024f0fdf8626b7523e8df26f53d17f652f66eae","impliedFormat":1},{"version":"6605e78846265f409ef1ff82eaa6b4c11ab50ef2e6eb634982506cafce5e2c5b","impliedFormat":1},{"version":"a09dee614aa1423e888a527e4bf11ada691427416a3af8911b5b5f9ecf21ebc7","impliedFormat":1},{"version":"ab9467ccc825bce823575de19bda4c744a7079455a9aee79e2d5b28a127df558","impliedFormat":1},{"version":"cdffa4d1d8670f17245f6ff2afcbe07947467c55b44387d43ed58e7b4744a139","impliedFormat":1},{"version":"6e35ffd1ead2afed3c2c6a46e878022ba579c202a38fe4d7a32a7bf33ae276f0","impliedFormat":1},{"version":"4026aa06fee0b478cec95e4dfdbef51aebb5e204ea4f1597c8439883a45b3cd8","impliedFormat":1},{"version":"d14bf272185fece955d0b9d8977cd34ad8ccdfedb7b7c40b5b3355111a07cfb7","impliedFormat":1},{"version":"0856233bdf7a3f9f2d8da63236e81b759a409b7e371e94b57619401e80703a0f","impliedFormat":1},{"version":"779007337a0ce855eaef8fae082043a48ea00ccbafc5fd182bae4d94a1ea8d46","impliedFormat":1},{"version":"dc18423f1519fb93f4fbba99cd139237736702fd8c6aebc5e4646dd7f0cfd1fa","impliedFormat":1},{"version":"fe0e84cad25365bd7cd69e6a022e2e0dc921bbbca793b1f72a9099ef129425b4","impliedFormat":1},{"version":"bb5ac364cae40e941865a0413a868a3d0feec1d5f1b80045d352d5df9f57bdbb","impliedFormat":1},{"version":"d270126e54ce74bc28448b9879e4e034cf1b6a412a0b3ee8cbf3c8ed13ef6550","impliedFormat":1},{"version":"8f01a3f96136b81ab57882f99b1153162f23601bb4fc4e698e742d46255757f1","impliedFormat":1},{"version":"e565c4c402e75e639dbbe62457e6630d265f13076be4557ebecc50c4a14bac39","impliedFormat":1},{"version":"5971d32a8fbc962d3b56f68c24b1cbb071be5a03a9febb4d6ee7787990249e60","impliedFormat":1},{"version":"bf7c5173ecbd23b2642a23eb37607b4a9e8c533c3beed32cb28fe777cdc913ad","impliedFormat":1},{"version":"1ddd5fa2d7f7857f05e263b108bd6713525a553b3b63fa36310f24356e7480bd","impliedFormat":1},{"version":"345dc25bfa274a8086b0cdfa65dec6ed9ce34dc53c19f36f10d0d3ce4270938f","impliedFormat":1},{"version":"33ba37fbce1b78c28e860fb312b6284587b0224640bf8233cca69ebbb78b1629","impliedFormat":1},{"version":"ab4ec5d270e1b668b58c02984e3b108f28521d6c0e3ef5226306d1548e88f19b","impliedFormat":1},{"version":"e3f92a43b3990ccee0f634b38021c7267dfbd2f831ceb82806cd86fd9b970aa2","impliedFormat":1},{"version":"ee6971c95c495d2e746251a3a4edebaa9f3d1f2e3f6d4b5cdd210b8e3a36e097","impliedFormat":1},{"version":"93cfb20661b6e888148813f15c85f7b0c88fac9f01ac8d42e28f2c9bfef44aa6","impliedFormat":1},{"version":"0b5d14c81c906ba9dd283d8fbb0d3c5cdf98339688fc4eed0b10ba2e07cef7b2","impliedFormat":1},{"version":"2a25deb835ad5c88aba7f0148e4fa58d0989f45570dddb5811e327e1eaeed4ad","impliedFormat":1},{"version":"8eaa99fa1669a382ec159ce60f9f1d81959a994debeb8ff6e167e87bd59b68a6","impliedFormat":1},{"version":"68abc9d3fdc5cd30079d5aa79aee3fe335e97fd2465a6e0d97a911ed5f126be7","impliedFormat":1},{"version":"a09dee614aa1423e888a527e4bf11ada691427416a3af8911b5b5f9ecf21ebc7","impliedFormat":1},{"version":"295048b3b1f5d88d6b4ed98f5db01205424f5c87053fd39f86dffceee7bdf1aa","impliedFormat":1},{"version":"a91b73ce817b20437417d24221dce06c13e94f868abeb926eb859649b96d4dd2","impliedFormat":1},{"version":"52937dcd1b720c242993e82d765a4493378dd92d1af840d1f1c2d505a8d8fb52","impliedFormat":1},{"version":"9e51f0a6a0e89504afafcb32d2723f09f8898f6a7dcf92dc6cb90fa173492b98","impliedFormat":1},{"version":"d7c447aaf48a7dc6f2c05de54b6f69fef43d470db301a578563b6743a8af6c5b","impliedFormat":1},{"version":"9072df8167c523cb92a0ade4494b84ba744ed3b0779b690d6671a8febb130d6d","impliedFormat":1},{"version":"9146d34a054ad4e3b4c3f53f64d4c106e643f41209bf05b94d95b593bd6c76c0","impliedFormat":1},{"version":"ac26beae2bf3f2c845b7ffad4f55328ed160dd0f463a58372704fa7a6c27f793","impliedFormat":1},{"version":"ac20be3a60ff3c03777c81b858e6c78784352ef7aaf798fd34b8cf2e29b38ed0","impliedFormat":1},{"version":"97fd4e7d6ae8ba1f2594f1caf41cbc1be95029783f973d87525b246c6e95f0a7","impliedFormat":1},{"version":"1d6791c65ea98d1541f74ad5e213b75982384b6ae5a4057bcb41466961709bb5","impliedFormat":1},{"version":"281cc4fead96675e77eb85d6f5208a514500188b2fbda2935134da18c77ff5c9","impliedFormat":1},{"version":"82c726b64759224520bb3c187cd3494f7731a9244573445d917122b22fa41f8b","impliedFormat":1},{"version":"e459ce3fb3308c97e106f748a151e6ce78ebd11a09551b2d02a3c088dfd1d7d5","impliedFormat":1},{"version":"6a50ed407459f72bde387960e0260a325644cd0ca3bf3e2bcadcc2bd970afa40","impliedFormat":1},{"version":"c99ebe0198a5e793ef35564e012aaca09d2cc13203ae3cd47516f2f15f0062cb","impliedFormat":1},{"version":"906fec947a3ff4f891c58406b56a23d839d374b2b3351e1591086493e3acd76c","impliedFormat":1},{"version":"5257b83697b5aa5fd2592133315a38682928bc663c874324541a22395d758ac4","impliedFormat":1},{"version":"ccb70257fea5c213e4ea55e37ded0acd02bcaf55743a96c46add9bbe29262abe","impliedFormat":1},{"version":"f8c3bd231d511bded4ad4b3ebfa29d26c45529e5dfee3c1a767004953889d206","impliedFormat":1},{"version":"6bcfd8bd7a995605a557c3d4578056038f16cc3d128a6e5ca25bd7d948563a70","impliedFormat":1},{"version":"e74145e707933003eeb6613b8eb7d0880ddaeb1fbc47642694da119279e26b98","impliedFormat":1},{"version":"72be37952168ab433b352d5ec8f51b73aa64c9ebf2dc5538cadb02c6d47e01cb","impliedFormat":1},{"version":"727950dfc1b8ea42553aa73d4070d302db0a72b6cba269e4ff330561f90e1ac1","impliedFormat":1},{"version":"387751c30bb534d0c2cdca023a75b77c4859ec4b16f874e498d69213ee40efc7","impliedFormat":1},{"version":"39c4884d89bf2b8ea56944dc1d4f68fd605b9731a542394d3f168149440daf3f","impliedFormat":1},{"version":"bb7e593672a1ba37acfeda32959bb875b0c1b99b42ac7d2d16ecd90112444ea3","impliedFormat":1},{"version":"5b2ac30cc8aaf9d0e6b97e0ac8e88c48b0132937743b7865fc605cec8257cd02","impliedFormat":1},{"version":"db63de117cdb3bf857512198f988577498e16b8069f27099ab8fb71f5e5f9faf","impliedFormat":1},{"version":"7ebba6429a982ba3ee14d2f0e6f65596171ec96a5bcdecc963a3521f19718374","impliedFormat":1},{"version":"d1d18efda8252075a82a6d3e6c373e144322b1bf1a018ec831aec2a34cfc6384","impliedFormat":1},{"version":"2e8415a4268001bfce5672f1fca8b5f45474b82b2cf082693502376d1de22f02","impliedFormat":1},{"version":"25c16b6d66a09258a2cedd5a68a3524b85f0abc362bf5cb92841f2a87d08f8b3","impliedFormat":1},{"version":"e3f4430a9aa0d8cbb580de46fdc9eae49137275a62e5129e916d3aa03f1f7c81","impliedFormat":1},{"version":"8fdf0d718f6a6cc522c6b9d187fb5ccbdbbc4f36d5c5f53cf868ddc8cb619fc0","impliedFormat":1},{"version":"ffd8da17fc910d12f14597471210e28e57ff745271c0c9448ecbc28b13fda608","impliedFormat":1},{"version":"d08347843fa76bb14ba0e003803278711515b04c2f0ab0bf0a14baa89acfe3b9","impliedFormat":1},{"version":"14a56bbcee52b698f1907c3d9428b2d9bef8ea611ddd6f5f76af3f601d9c6c6d","impliedFormat":1},{"version":"540e084b06df30a4e27b271bc2163c8f88b3d181c18497173f8ab3c6218107b5","impliedFormat":1},{"version":"75739fdfe4274aa1603b8c3e08ab21d2465ba4fa598912aa447590af2ebe35a7","impliedFormat":1},{"version":"60387bc1f3a8ac59f3cecd4e37ae632852982b9d0a37849b113502f96abad4dd","impliedFormat":1},{"version":"448088258817dcfac1af44820f02268d3a733fba3165a4df27eeadbec2416064","impliedFormat":1},{"version":"f838227553bed5ea4557c9eb3a3782ac2e9395c01918223f087f0b760eb726b8","impliedFormat":1},{"version":"1a44297617788065c56ecac49d14a27d61b3c8b6dd93044d40afc8283cfa3706","impliedFormat":1},{"version":"5dc248f7d6c401a87b4468922af2cedb4efa98f0ac10f7f0547cf13988f99e48","impliedFormat":1},{"version":"8c9947d347d356d81a062232ae1ff2afaf97b702d4bb9f5d1781d101aa52b1ae","impliedFormat":1},{"version":"30d4b608895479c30604878dd6a4d31dddc0cfb64189b71833fc2ecc2be4abc6","impliedFormat":1},{"version":"939bfbbc861cbe104793567d5505609012a0ce84901a9c044e282d180981982d","impliedFormat":1},{"version":"88069fbc0eaf70d82d1439504a0cada34250d761b65de8ff350a778e3fb3063d","impliedFormat":1},{"version":"da592d0fdb1a2897803ccb0f949320dfeb76dad033fec0f8d5d6933fddfa0f4b","impliedFormat":1},{"version":"7be3fe0dd8fd7e3a6296c2a0b9e017b8dec496e461d46d6ba66925d8b0d778cf","impliedFormat":1},{"version":"7b32a09d43a93680b366cc7a7637c884e1dd817e3939f413c5aa0cdad914afeb","impliedFormat":1},{"version":"1a5a65d70494b82429b5bd78ce6cdf73037b10e7342ecd825a660b11ff72d630","impliedFormat":1},{"version":"511bf2e95b882104430ced0c627834fa54df8070c50829201dfa012dc6058009","impliedFormat":1},{"version":"d8a711cb6e0725f842cbe33ba8aa2bc7bdda76431d86e471a7ff7aea7163f323","impliedFormat":1},{"version":"73473a5f6064e3d8bd29185a6a3b88b6ac5916b901a17fa66d7cea50f98ee856","impliedFormat":1},{"version":"f339feba19bec1ecf5861b9bf95290b5f97a33f996e7fc848975eb18b32c8f5f","impliedFormat":1},{"version":"fc5b3fbd60f681038a883b3b0a1d114684b36d8350e24d9fd2c7d5a6ffd2ac2b","impliedFormat":1},{"version":"f95cad3d309ede51f10e1aa0c2c7821a41193fa10de7712c8166663225aec4d0","impliedFormat":1},{"version":"7624531047fba888b685932752f3ef5c2738e034303c93579fd811349006ece7","impliedFormat":1},{"version":"d7f3939e0ff0c8aa52c8165c9385b481ffee240537464459822533c22f67815a","impliedFormat":1},{"version":"37fd6df68a4992adf9489418c96777874ef425ad884f9df004f92e29626bc53e","impliedFormat":1},{"version":"45182be842c1c6809296c46f24fd45a1fd6298f7b4b84a414436fd2ad5827d4e","impliedFormat":1},{"version":"ab9f456f60347c8ed06a7bf3ebbd54162184e9cbf6dc2f43127ff631ce74757d","impliedFormat":1},{"version":"b46bc135f59ad7cbda10236d127679fb92c9b4665e082b87f801125b86a79c2c","impliedFormat":1},{"version":"a8dd5ff55b15c2966589edf335832b73f09e1a4dd6c3d5e75a99384f3ff364f4","impliedFormat":1},{"version":"7693e2ee55c5df4b0940f1c66d86b5fb5e9224b8bbe849a43f0468ace0d16e8e","impliedFormat":1},{"version":"a8a1481056c587c8e257bf519a23c4f600ee764a627268a969791c6ab995144f","impliedFormat":1},{"version":"787b0bd0ef9dd83b7bc898b7f831ddf71862652017a336c22bdb23244f89bf36","impliedFormat":1},{"version":"81521858f1817c1ae701537adbd3dcf3254bf9857a83856a2f4ea573b6cab85f","impliedFormat":1},{"version":"db3eb26b69a3b3574d17b87c447c4f560828d9230a1c2fb1ca8eeed1f61b2957","impliedFormat":1},{"version":"e412ec3e685a55847d85bf04e9332e5af82e28dc92c778184038d0bfc695283e","impliedFormat":1},{"version":"60fd4af8ecad9bb99dd1b29ee1b69e9714263b11bc0b504b9d7beb164d7a1a35","impliedFormat":1},{"version":"f7ebd3c4e33524de1e4924028c22946b7fb95788d4e0c13d72545b76e5b464b6","impliedFormat":1},{"version":"486ca4fa9d5c0a5c01472a81a7ce51a76dc3ab86de70164bc0e5ad99859eb9eb","impliedFormat":1},{"version":"d1305eb5d7fa2ba5a60d6ad2de0e036d15588d49a88c0f92f3956bcd4700f104","impliedFormat":1},{"version":"e5dfe656913c2450a17c62988011b9d821edb4fea05dbd602675e3aa7c9d73f6","impliedFormat":1},{"version":"da88233ec70b4ac49df88c8345d0df8b1309c53d5df0017cf668876c0785680a","impliedFormat":1},{"version":"92407620ad81bb95c91a6cdac78a769fc155e12fef59468eb0882aed9b733a9e","impliedFormat":1},{"version":"b07349b94e69b9e9bb67499fea99bd1fa6e9d9df2a8b571b9941287455c76ed3","impliedFormat":1},{"version":"19bdc305c904559ed5d4c367ac50dbe9fede36557abc2d023e6228690e6fb207","impliedFormat":1},{"version":"2ad274d45e2a9dc66915b1806c3c02b065889e32a487dee5af20ed9bd53c9d6a","impliedFormat":1},{"version":"d4ae12fd53be33b90aeda73d73f644337b7623fb0e60b69ad32c526dbf785a5a","impliedFormat":1},{"version":"da7476aaf1035c16565fb8402a2704cc8c8e3d7cb39180120bb3711525d0ab8b","impliedFormat":1},{"version":"99030f98187f417f3b9ef1e4110e7c9ca1ab6ed98b6e12e6130d168f943be079","impliedFormat":1},{"version":"6489a56dd93d8cecfe86e21c25aada578281973cbd41910e9cfc975a51963904","impliedFormat":1},{"version":"8967ae64c201c0c563070d526b1d9a9f46b417523a62433699f2e2048b4d82ed","impliedFormat":1},{"version":"521bb8058e97d1dbc36c06f94b95cd87f4b7f39b9a443f64cc483492048375da","impliedFormat":1},{"version":"f74437df66cbcae00ed3b71ae771fe998edd4f30f28cf8b917070cdbb060e7bb","impliedFormat":1},{"version":"fa8b0784e57a825ac298e89a5c43ac4ec88b8dbde74f9bef87c38f891fc2e162","impliedFormat":1},{"version":"738634e0df0b2c4a4ba1b2969e3de2a7661b1f19d0001eda6fa53e4ca6e0b788","impliedFormat":1},{"version":"8fac9df67977bcd5a0036bff1ce0d7eacf190ebe2fe93c073d0ecfb93934799d","impliedFormat":1},{"version":"33113406bbee152d17b1f11f75e220af79a971c229e2dddf7239bcde6eedb591","impliedFormat":1},{"version":"4e3eb4be1bc777e2c2babde44132c9b36e3f85ecc50de28321a75cc936f03508","impliedFormat":1},{"version":"25fa594d7e17d731fd20195af7569bf71e087ec5b724c7cbd406777f37b601b1","impliedFormat":1},{"version":"84dbb23aa064c4ee274e831ccaaf0162346a93cff5c95aedebf71b883543c9d7","impliedFormat":1},{"version":"592ef2afa2e3332d7e982d134b0149356ebf7ed61b43d56ca6dd4c063cb71a62","signature":"36aa37b82a71d1451256ab107a5714dcd7b0e73775db33a779dcdd703047b47e"},{"version":"7457091c71c795629e6608f0d2b7132d5a82b514fca5dd19200590646ebfdd0d","signature":"4be0cf8d79dd3d065e03d5d0b3544fe7ef55a07d0f337b0e0d75399d6e8edeec"},{"version":"033183f3e07c8123da9036b2230e7a0d982655ae5f9f3fedd32431140b5ab6c5","signature":"03b14e671dda7f9d14bce7589a9fd9df1955232fc2f9a386e8f348dce096e5aa"},{"version":"bad9cb35ff53dc90f58f570223ced376f650eac46df68e0c663f8838eddf7b9d","signature":"d50234446709c93924529c0508fb514f3a19916424febb911dd43644b268c3ce"},{"version":"0b88bf253914e4480466ccdfbc9bae5d8891c9e2a20ace102059ee01d3ae4582","signature":"f5b5d4d2565e15fa4ea35249f6dfac49afe8d18383b09d6f2732010ea11ff387"},{"version":"abcb770e2d0739e7e135836d444bb51e40409727319104aaa7c2237c469c4c83","signature":"8b9f4974d96b0ed131f8d6fc666e5c48990c24ad021734f546d6acab6d743828"},{"version":"5b34f838294309cf3e868c2277fafb006da9395020b1e609bd80d799e2f685f5","signature":"02cc2e63ce9e2b48aa02c06d8de191fb2f2497bd814ecc3058cc817dbbed7e12"},{"version":"c31dc8d99fbff90dc21e03688efc95e3bc7633531f7c1429de53d9810039394d","signature":"1642157a7dc01181a6ec5fae4a1235322df48321e48dfe753b95436a283e1927"},{"version":"d42fcd5036105aa8d0fb8155bcaac21a2445a050cd414f5cc16e34475d5ed2a9","signature":"ac8cb98638a06209e221d0dd33e7cae666cf5b98406d4b48ab8c72edd6a6f62f"},{"version":"ba877158db20e6494d6306b52e58cc9fec61bca0f168e0613724d4d208382871","signature":"0997461569544422e239d876edc79a9d7d13056f2f8e38b1db886fd508f1d6ee"},{"version":"9b766ef6750ed26ef5f53599e619fd04c29105d81cc28716279d1691bc48fa55","signature":"5e4948745a003a646ca8a48697c51e8c2149f6a5faa99b10417adc62dd53470b"},{"version":"6a879d49aed9827ff3c66501b96da532850951eba61f2a8b6b5fc92424aa29ae","signature":"b3929979c35152e2c0d667d240d8cd0f88443e94aa8c457aa6f0455b0fbfd607"},{"version":"d142090eda68447039a260082d250740ccd84e9ddcfe8327f6087f8ab1469f34","signature":"7bb2c604bc7416a7e0dea2042821bdfa0016763660d480dde967602b8dcedeb0"},{"version":"96ec71bbb3f94ee8d8f5e97a7b720bee69e6ab17e5afd23cd3ddc680de03b5a9","signature":"3168d333ebf0629d346dd4a4ba94270dfc111be0e9ffec6808bf94362db2a274"},{"version":"c16dc630fe331571849aa39aee62c5df6a276667191c5d39180f4e04addd1755","signature":"d3466e4394bf4d8124e8231e07b8faffaf5243dd885724df03449fa3fc6d9cf7"},{"version":"853bece6815b265980b443f83d4ed245ffcccce293aa60dc1bce18aeaec827c8","impliedFormat":99},{"version":"aa6b9f986505ec8aa368b29a127fbb9631ef97569508163abec2b873b2807081","signature":"c7c0d5aac178defd5257116d30fcbafc866c7d30b539ae34d67f2af4a60a8d5a"},{"version":"71467450570e5dbff1c30766967804ec100d254e471ae7d737c6ac17dd28eab5","signature":"db4a5843e5eeee8d1e7f2705a0e775fe8c745c18120c3d4a49f57a2e49dcd36b"},{"version":"e5505d0c3ce74c8ed85b8c0ba80fa5c05859a6dd663a20da4f02c269c7d8a441","signature":"332d65424ab41b4f1621efc6f707c855a0371154ef027da48c3f0b3fa8280d69"},{"version":"21bccfc7ed64517768bbb5867fee35ef26e23af2ba0227081c49685ee5bcbf99","signature":"eac8fa25389b9e19a88d3240a2a2a9018f6b6b5a3117007041eb246c4cf0243a"},{"version":"25d287ce4f272889cb18d1a4a1bbbce4510f61a54e3161c36af6e8861974892c","signature":"3163779e52856fd99d3ca639d6e67f993cc57627d5ea929ab6481a98bd5cad24"},{"version":"b50f7438df1d20b5fd5f86aef67c361b7cc541d3efbb233025b069bc02e465c6","signature":"80016cbb5870f8f650a509ef53a186a36089766d3426d3f884276e8502b9aa4d"},{"version":"7cb98bd432df5f315874f66285c8d9ab37ba1fd15fe3892c74135c8284fd066b","signature":"a3b22789c3ad2309c354d06fd13a3ae1b69cc32a57b39ced004e3a9c0435ddcf"},{"version":"68941aafaa2db7181b9ef62e21afc8648596fc4c30eec8e6e2e9af0c8af96739","impliedFormat":99},{"version":"a2f54ab67759f89cc2101fb1d0008e9ea88b2398e2f5808befbc7406ebfe7d45","impliedFormat":99},{"version":"21cf3fc93e67812e34cc6459f378ee169fec5c72d9b73fc75a4fd994ac97d619","signature":"d1b225ce055322c95052c7b45e5f593af90ec1e109b02f7d86a5021f06629803"},{"version":"1ecdc2c8e2b97cd89ebfdc0944c6070bb6af493839c85c8f7d072c6a341ca71f","signature":"20a4889dcdfbfb38e094af503d9764d3dbb68992c42ac620abbe46849766417f"},{"version":"c03f8af8b1acedcd04e899dc11d6f2ce3697aa415e287f217489ba19f5487275","signature":"d8a4f999cc0695d21b3c05450f769c8eb116dabcc84f862437ca63a55675156f"},{"version":"1816a3ab1770ca4e6de9b495267f0b21da3c24d26fd9e20b6833e600acbec1ba","signature":"2342f0f37d8ab3d926a01afa21fc82f0ce50dd243ea018c109f04290dc3955dd"},{"version":"c4d6c4265d1f73ef06c8a5573800425fcfe2f9a669c12d83140327443c9d74a1","signature":"bd9babe770cb24f4ab34f7f3636cf5bbf11308122fab291027d61d2ee1eac2b1"},{"version":"9d47cb4a30bf1d6c2b11624bd258e2be4684585f8b3d876bf758556adf79cf91","signature":"2af59c137264af8b0a67836fd2d4bc54d08274ca98d349b3b2dc6c342e10ce71"},{"version":"922e1676960cf5d7d175bb5084105b255ac2855fb1444ce0453a0a5754c4a419","signature":"dadfe66204b0f5dbd8a551a5c613bf3833981afea20be8bd92303a9a96d261b8"},{"version":"457ee66ec0b4409c36fba9e8d21df74cb14d416831fea90cac5165ec3c5018d0","signature":"eb0793356ed53d5a677eb5c91488c9b1f3b313f9372f8285485377576cbc0cff"},{"version":"a2aa194504e0752db1946e04b3e53a713c30c5bc1ab2db5228ec206d86010658","signature":"065d0a7e46cb901b054794e3bbaec7261fe2586ef960b1a490e5e5a8c510c98e"},{"version":"1ef8d397d04d9b44eead0f7417b6e4c0ec5e0e3d51a293d8fa35b52a9d741927","signature":"6798a0326ee9602d16bf562060d760561b5d58c394d1cbc782b03cb7ada0786b"},{"version":"f1b5c5d726adcc9f0a11067e066d45a7448e965406bc25d3735772f2342fb650","signature":"594e32c13a91d5a04f02260316c5ff228e476deeda40282fa947373a45ca4575"},"2552a31fad45a9ed1bde87e51b038dc0e786cd364b597162263abbf57018949b",{"version":"71b9f0ab8a0c41cfe30aadc2b730b4e632ba491de9956cc01a64b24cec734073","signature":"8e609bb71c20b858c77f0e9f90bb1319db8477b13f9f965f1a1e18524bf50881"},{"version":"0aa889b47b57bd54e355a1ac35b8bcf21bb21e674c02b96bba28b3b8f7af9fa1","signature":"89b0f68f8f0b901f9dfff2b9e7255520283a783d6af7f2bc2953d771232317a2"},{"version":"698a2674dac0c2505831ee674adce5d943cff69f2b3a827961a7e2f12cdcfbdf","signature":"89b0f68f8f0b901f9dfff2b9e7255520283a783d6af7f2bc2953d771232317a2"},{"version":"e7718e5d403d13c06e6496f38f64d18482c08e35437c32218264b928732f5fb4","signature":"89b0f68f8f0b901f9dfff2b9e7255520283a783d6af7f2bc2953d771232317a2"},{"version":"302491633ac63a333c53b8382a49efeb47a2d9bad006028049dd3e4de8c09dde","signature":"89b0f68f8f0b901f9dfff2b9e7255520283a783d6af7f2bc2953d771232317a2"},{"version":"4a7209ef2d7c8cd448761f0089de8c035f3f5b33ea78cfe7db478e947ae649f8","signature":"89b0f68f8f0b901f9dfff2b9e7255520283a783d6af7f2bc2953d771232317a2"}],"root":[83,501,502,528,[586,593],970,[981,987],[1167,1181],[1183,1189],[1192,1209]],"options":{"allowJs":true,"esModuleInterop":true,"jsx":1,"module":99,"skipLibCheck":true,"strict":true,"target":4},"referencedMap":[[1205,1],[1206,2],[1208,3],[1207,4],[1209,5],[1203,6],[83,7],[1204,8],[501,9],[502,10],[587,11],[1172,12],[1168,13],[1173,14],[1174,15],[1175,16],[1169,17],[1176,14],[1177,16],[1178,18],[1179,13],[1180,19],[591,20],[1181,21],[592,22],[1183,23],[1184,24],[1185,25],[1189,26],[1186,27],[1187,28],[1192,29],[1193,30],[1170,31],[1171,32],[1196,26],[1195,33],[1194,27],[1199,34],[1198,35],[1197,36],[1188,35],[1202,37],[1201,38],[1200,39],[593,7],[1167,40],[970,41],[981,42],[588,7],[983,43],[982,44],[984,45],[589,7],[590,46],[985,7],[987,47],[986,7],[528,48],[586,49],[966,50],[967,51],[968,52],[948,53],[955,54],[773,55],[774,56],[775,56],[776,56],[777,56],[778,57],[779,56],[780,56],[781,56],[782,58],[761,59],[764,59],[762,60],[767,61],[766,62],[763,60],[768,63],[783,64],[784,65],[785,66],[786,66],[787,66],[788,66],[789,66],[790,66],[791,66],[792,67],[793,66],[794,66],[795,68],[796,66],[797,56],[798,66],[799,66],[800,69],[801,70],[772,59],[802,69],[803,66],[804,66],[771,59],[805,59],[769,71],[806,59],[807,72],[808,56],[809,56],[810,56],[811,56],[812,72],[813,72],[814,72],[815,72],[816,56],[817,73],[818,72],[819,72],[820,56],[821,74],[822,59],[823,59],[824,75],[825,75],[826,75],[827,72],[828,76],[829,75],[830,75],[831,75],[832,59],[765,77],[833,78],[834,79],[835,59],[770,59],[836,80],[837,75],[838,56],[839,81],[840,80],[841,75],[842,80],[843,75],[844,75],[845,75],[760,59],[846,64],[847,82],[848,83],[849,64],[850,66],[851,84],[852,85],[853,66],[854,75],[855,72],[856,75],[857,56],[858,75],[859,83],[860,64],[861,83],[862,83],[863,83],[864,83],[865,83],[866,83],[867,83],[868,59],[869,86],[870,75],[871,86],[872,59],[876,87],[873,75],[874,75],[875,75],[878,88],[877,89],[879,88],[880,88],[881,88],[882,88],[883,90],[884,90],[885,75],[886,88],[887,88],[888,88],[889,88],[890,91],[891,88],[892,75],[893,88],[894,64],[895,90],[896,75],[676,92],[671,75],[672,75],[673,75],[674,75],[677,93],[678,93],[679,94],[681,95],[682,93],[683,75],[684,75],[685,75],[686,75],[687,75],[688,95],[690,59],[689,75],[691,96],[692,75],[693,75],[694,75],[695,96],[696,75],[697,75],[698,75],[699,59],[700,97],[946,98],[701,59],[703,99],[702,7],[705,100],[706,101],[704,59],[707,101],[708,75],[709,75],[710,75],[711,64],[712,64],[713,101],[680,59],[714,102],[715,75],[716,75],[717,75],[718,75],[719,64],[720,75],[721,64],[722,75],[723,75],[675,59],[724,75],[725,75],[726,64],[727,94],[728,75],[729,75],[730,64],[731,75],[732,75],[733,75],[734,75],[735,75],[736,75],[737,75],[738,75],[739,75],[744,7],[740,75],[741,75],[742,75],[743,75],[745,103],[746,75],[747,75],[748,75],[749,75],[750,75],[751,104],[752,64],[753,64],[754,75],[755,75],[947,59],[756,75],[757,75],[758,97],[759,75],[898,105],[897,59],[899,75],[900,105],[901,105],[902,64],[903,106],[904,107],[905,108],[906,108],[907,109],[908,108],[909,108],[910,109],[911,108],[912,108],[913,108],[914,108],[916,110],[915,59],[917,110],[918,110],[919,110],[920,110],[921,64],[922,75],[925,59],[923,75],[924,75],[926,111],[927,111],[928,111],[929,59],[930,112],[931,75],[932,112],[933,59],[934,113],[935,114],[936,93],[938,115],[937,116],[939,75],[940,115],[941,115],[942,117],[943,118],[944,119],[945,64],[670,54],[953,7],[969,120],[964,121],[949,122],[961,123],[963,124],[950,125],[951,126],[960,122],[962,127],[957,128],[958,129],[956,7],[959,7],[965,75],[952,127],[954,130],[613,7],[614,7],[611,7],[643,131],[644,132],[616,7],[617,7],[642,133],[615,7],[629,7],[628,134],[612,7],[1039,135],[1037,136],[1040,7],[1036,131],[1044,137],[1043,138],[1041,139],[1042,139],[1038,7],[1033,140],[1032,141],[1035,142],[1034,143],[989,144],[990,7],[998,145],[988,131],[991,131],[993,146],[995,147],[992,131],[996,148],[997,149],[994,131],[620,150],[618,7],[627,151],[621,152],[622,7],[619,153],[623,7],[624,7],[625,154],[626,155],[610,131],[646,156],[609,157],[645,158],[608,131],[661,131],[663,159],[660,160],[662,161],[659,131],[1164,162],[1165,7],[1166,163],[1163,7],[1152,7],[1153,7],[1154,7],[1155,7],[1144,164],[1162,165],[1134,166],[1135,167],[1136,7],[1149,168],[1159,169],[1145,167],[1160,7],[1146,170],[1161,171],[1150,172],[1151,173],[1157,174],[1133,175],[1147,176],[1156,177],[1158,178],[1148,179],[1132,7],[1089,180],[1091,181],[1092,7],[1086,182],[1093,183],[1082,7],[1131,184],[1094,131],[1095,131],[1096,131],[1097,131],[1098,131],[1099,131],[1100,131],[1101,131],[1102,131],[1103,131],[1104,131],[1105,131],[1106,131],[1088,185],[1107,131],[1090,131],[1108,131],[1109,7],[1110,131],[1112,186],[1113,131],[1114,131],[1115,131],[1116,131],[1117,131],[1087,131],[1118,131],[1119,131],[1120,131],[1121,131],[1122,131],[1085,131],[1123,131],[1124,131],[1125,131],[1111,131],[1126,131],[1127,131],[1128,131],[1129,131],[1130,131],[1083,131],[1084,7],[649,187],[652,188],[651,189],[653,7],[647,7],[648,7],[658,190],[654,7],[650,7],[655,7],[656,7],[657,7],[632,191],[636,192],[634,193],[637,7],[630,7],[631,7],[641,194],[638,7],[633,7],[635,7],[639,7],[640,7],[667,195],[665,196],[669,197],[664,198],[668,199],[666,200],[1067,201],[1069,202],[1051,203],[1049,204],[1052,205],[1066,206],[1050,207],[1071,208],[1070,209],[1063,210],[1064,210],[1065,7],[1053,7],[1056,211],[1060,212],[1061,213],[1055,214],[1062,215],[1054,7],[1078,216],[1077,217],[1079,218],[1080,219],[1072,7],[1081,220],[1075,221],[1076,221],[1073,204],[1074,222],[1139,223],[1137,7],[1140,223],[1141,7],[1138,224],[1143,225],[1142,226],[1059,227],[1058,228],[1057,7],[1068,229],[1047,230],[1048,231],[1046,232],[1045,7],[1190,7],[1191,233],[250,7],[527,7],[575,234],[573,7],[542,7],[147,235],[148,235],[149,236],[101,237],[150,238],[151,239],[152,240],[96,7],[99,241],[97,7],[98,7],[153,242],[154,243],[155,244],[156,245],[157,246],[158,247],[159,247],[160,248],[161,249],[162,250],[163,251],[102,7],[100,7],[164,252],[165,253],[166,254],[200,255],[167,256],[168,7],[169,257],[170,258],[171,259],[172,260],[173,261],[174,262],[175,263],[176,264],[177,265],[178,265],[179,266],[180,7],[181,267],[182,268],[184,269],[183,270],[185,271],[186,272],[187,273],[188,274],[189,275],[190,276],[191,277],[192,278],[193,279],[194,280],[195,281],[196,282],[197,283],[103,7],[104,7],[105,7],[144,284],[145,7],[146,7],[198,285],[199,286],[86,7],[204,287],[359,20],[205,288],[203,20],[360,289],[201,290],[202,291],[84,7],[87,292],[357,20],[268,20],[538,293],[562,294],[560,7],[561,7],[530,7],[557,295],[554,296],[555,297],[576,298],[567,7],[570,299],[569,300],[581,300],[568,301],[529,7],[537,302],[556,302],[532,303],[535,304],[563,303],[536,305],[531,7],[574,7],[106,7],[85,7],[547,7],[977,306],[979,307],[978,308],[976,309],[975,7],[1182,7],[1031,310],[1000,311],[1010,311],[1001,311],[1011,311],[1002,311],[1003,311],[1018,311],[1017,311],[1019,311],[1020,311],[1012,311],[1004,311],[1013,311],[1005,311],[1014,311],[1006,311],[1008,311],[1016,312],[1009,311],[1015,312],[1021,312],[1007,311],[1022,311],[1027,311],[1028,311],[1023,311],[999,7],[1029,7],[1025,311],[1024,311],[1026,311],[1030,311],[94,313],[447,314],[452,6],[454,315],[226,316],[254,317],[430,318],[249,319],[237,7],[218,7],[224,7],[420,320],[285,321],[225,7],[389,322],[259,323],[260,324],[356,325],[417,326],[372,327],[424,328],[425,329],[423,330],[422,7],[421,331],[256,332],[227,333],[306,7],[307,334],[222,7],[238,335],[228,336],[290,335],[287,335],[211,335],[252,337],[251,7],[429,338],[439,7],[217,7],[332,339],[333,340],[327,20],[475,7],[335,7],[336,341],[328,342],[481,343],[479,344],[474,7],[416,345],[415,7],[473,346],[329,20],[368,347],[366,348],[476,7],[480,7],[478,349],[477,7],[367,350],[468,351],[471,352],[297,353],[296,354],[295,355],[484,20],[294,356],[279,7],[487,7],[490,7],[489,20],[491,357],[207,7],[426,358],[427,359],[428,360],[240,7],[216,361],[206,7],[348,20],[209,362],[347,363],[346,364],[337,7],[338,7],[345,7],[340,7],[343,365],[339,7],[341,366],[344,367],[342,366],[223,7],[214,7],[215,335],[269,368],[270,369],[267,370],[265,371],[266,372],[262,7],[354,341],[374,341],[446,373],[455,374],[459,375],[433,376],[432,7],[282,7],[492,377],[442,378],[330,379],[331,380],[322,381],[312,7],[353,382],[313,383],[355,384],[350,385],[349,7],[351,7],[365,386],[434,387],[435,388],[315,389],[319,390],[310,391],[412,392],[441,393],[289,394],[390,395],[212,396],[440,397],[208,319],[263,7],[271,398],[401,399],[261,7],[400,400],[95,7],[395,401],[239,7],[308,402],[391,7],[213,7],[272,7],[399,403],[221,7],[277,404],[318,405],[431,406],[317,7],[398,7],[264,7],[403,407],[404,408],[219,7],[406,409],[408,410],[407,411],[242,7],[397,396],[410,412],[396,413],[402,414],[230,7],[233,7],[231,7],[235,7],[232,7],[234,7],[236,415],[229,7],[382,416],[381,7],[387,417],[383,418],[386,419],[385,419],[388,417],[384,418],[276,420],[375,421],[438,422],[494,7],[463,423],[465,424],[314,7],[464,425],[436,387],[493,426],[334,387],[220,7],[316,427],[273,428],[274,429],[275,430],[305,431],[411,431],[291,431],[376,432],[292,432],[258,433],[257,7],[380,434],[379,435],[378,436],[377,437],[437,438],[326,439],[362,440],[325,441],[358,442],[361,443],[419,444],[418,445],[414,446],[371,447],[373,448],[370,449],[409,450],[364,7],[451,7],[363,451],[413,7],[278,452],[311,358],[309,453],[280,454],[283,455],[488,7],[281,456],[284,456],[449,7],[448,7],[450,7],[486,7],[286,457],[324,20],[93,7],[369,458],[255,7],[244,459],[320,7],[457,20],[467,460],[304,20],[461,341],[303,461],[444,462],[302,460],[210,7],[469,463],[300,20],[301,20],[293,7],[243,7],[299,464],[298,465],[241,466],[321,264],[288,264],[405,7],[393,467],[392,7],[453,7],[352,468],[323,20],[445,469],[88,20],[91,470],[92,471],[89,20],[90,7],[253,472],[248,473],[247,7],[246,474],[245,7],[443,475],[456,476],[458,477],[460,478],[462,479],[466,480],[500,481],[470,481],[499,482],[472,483],[482,484],[483,485],[485,486],[495,487],[498,361],[497,7],[496,488],[519,489],[517,490],[518,491],[506,492],[507,490],[514,493],[505,494],[510,495],[520,7],[511,496],[516,497],[522,498],[521,499],[504,500],[512,501],[513,502],[508,503],[515,489],[509,504],[544,505],[543,506],[394,507],[503,7],[525,508],[524,7],[523,7],[526,509],[577,7],[533,7],[534,510],[81,7],[82,7],[13,7],[14,7],[16,7],[15,7],[2,7],[17,7],[18,7],[19,7],[20,7],[21,7],[22,7],[23,7],[24,7],[3,7],[25,7],[26,7],[4,7],[27,7],[31,7],[28,7],[29,7],[30,7],[32,7],[33,7],[34,7],[5,7],[35,7],[36,7],[37,7],[38,7],[6,7],[42,7],[39,7],[40,7],[41,7],[43,7],[7,7],[44,7],[49,7],[50,7],[45,7],[46,7],[47,7],[48,7],[8,7],[54,7],[51,7],[52,7],[53,7],[55,7],[9,7],[56,7],[57,7],[58,7],[60,7],[59,7],[61,7],[62,7],[10,7],[63,7],[64,7],[65,7],[11,7],[66,7],[67,7],[68,7],[69,7],[70,7],[1,7],[71,7],[72,7],[12,7],[76,7],[74,7],[79,7],[78,7],[73,7],[77,7],[75,7],[80,7],[122,511],[132,512],[121,511],[142,513],[113,514],[112,515],[141,488],[135,516],[140,517],[115,518],[129,519],[114,520],[138,521],[110,522],[109,488],[139,523],[111,524],[116,525],[117,7],[120,525],[107,7],[143,526],[133,527],[124,528],[125,529],[127,530],[123,531],[126,532],[136,488],[118,533],[119,534],[128,535],[108,536],[131,527],[130,525],[134,7],[137,537],[579,538],[565,539],[566,538],[564,7],[540,540],[553,541],[546,542],[541,540],[539,7],[545,543],[551,7],[549,7],[550,7],[548,7],[552,544],[585,545],[578,546],[571,547],[580,548],[559,549],[972,550],[973,551],[582,552],[974,553],[583,554],[572,555],[971,556],[584,557],[980,558],[558,7],[607,559],[599,560],[606,561],[601,7],[602,7],[600,562],[603,563],[594,7],[595,7],[596,559],[598,564],[604,7],[605,565],[597,566]],"affectedFilesPendingEmit":[1205,1206,1208,1207,1209,1204,502,587,1172,1168,1173,1174,1175,1169,1176,1177,1178,1179,1180,591,1181,592,1183,1184,1185,1189,1186,1187,1192,1193,1170,1171,1196,1195,1194,1199,1198,1197,1188,1202,1201,1200,593,1167,970,981,588,983,982,984,589,590,985,987,986,528,586],"version":"5.9.3"}
+1097
docs/superpowers/plans/2026-04-12-enrichment-phases-2-3.md
··· 1 + # Enrichment Phases 2-3 Implementation Plan 2 + 3 + > **For agentic workers:** REQUIRED: Use superpowers:subagent-driven-development (if subagents available) or superpowers:executing-plans to implement this plan. Steps use checkbox (`- [ ]`) syntax for tracking. 4 + 5 + **Goal:** Add named entity recognition with AT Protocol record linking and topic segmentation to the transcript enrichment pipeline, achieving feature parity before deployment. 6 + 7 + **Architecture:** Two new Python NLP passes (entity detection + topic segmentation) extend the existing pipeline. Entity resolution matches against speaker/concept records from the SQLite database, with diarization context for disambiguation. Topic boundaries use sentence embeddings with cosine similarity. The TypeScript document assembly and React renderer extend to handle entity links and topic dividers. 8 + 9 + **Tech Stack:** Python 3.12+, spaCy NER (`en_core_web_sm`), sentence-transformers (`all-MiniLM-L6-v2`), sqlite3 (stdlib), vitest, React/Next.js 10 + 11 + **Spec:** `docs/superpowers/specs/2026-04-12-enrichment-phases-2-3-design.md` 12 + 13 + --- 14 + 15 + ## Chunk 1: New facet types + NlpAnnotations extension 16 + 17 + ### Task 1: Add topic-break and entity facet types to format lexicon 18 + 19 + **Files:** 20 + - Modify: `formats/tv.ionosphere/ionosphere.lexicon.json` 21 + 22 + - [ ] **Step 1: Add `#topic-break` (block) and `#entity` (inline) to the features array** 23 + 24 + ```json 25 + { 26 + "typeId": "tv.ionosphere.facet#topic-break", 27 + "featureClass": "block", 28 + "expandStart": false, 29 + "expandEnd": false 30 + }, 31 + { 32 + "typeId": "tv.ionosphere.facet#entity", 33 + "featureClass": "inline", 34 + "expandStart": false, 35 + "expandEnd": false 36 + } 37 + ``` 38 + 39 + - [ ] **Step 2: Commit** 40 + 41 + ```bash 42 + git add formats/tv.ionosphere/ionosphere.lexicon.json 43 + git commit -m "feat: add topic-break (block) and entity (inline) facet types" 44 + ``` 45 + 46 + ### Task 2: Extend NlpAnnotations and decodeToDocumentWithStructure 47 + 48 + **Files:** 49 + - Modify: `formats/tv.ionosphere/ts/transcript-encoding.ts` 50 + - Modify: `formats/tv.ionosphere/ts/transcript-encoding.test.ts` 51 + 52 + - [ ] **Step 1: Write the failing test** 53 + 54 + Add to `formats/tv.ionosphere/ts/transcript-encoding.test.ts`, in the `decodeToDocumentWithStructure` describe block: 55 + 56 + ```typescript 57 + it("adds entity, speaker-segment, and topic-break facets", () => { 58 + const compact = encode(contiguous); 59 + const annotations = { 60 + sentences: [{ byteStart: 0, byteEnd: 26 }], 61 + paragraphs: [{ byteStart: 0, byteEnd: 26 }], 62 + entities: [ 63 + { 64 + byteStart: 0, byteEnd: 5, label: "hello", nerType: "PERSON", 65 + speakerDid: "did:plc:abc123", 66 + }, 67 + { 68 + byteStart: 6, byteEnd: 11, label: "world", nerType: "ORG", 69 + conceptUri: "at://did:plc:xyz/tv.ionosphere.concept/test", 70 + }, 71 + { 72 + byteStart: 12, byteEnd: 16, label: "this", nerType: "PRODUCT", 73 + }, 74 + ], 75 + speakerSegments: [ 76 + { 77 + byteStart: 0, byteEnd: 26, speakerDid: "did:plc:abc123", 78 + speakerName: "Test Speaker", 79 + }, 80 + ], 81 + topicBreaks: [{ byteStart: 12 }], 82 + }; 83 + const doc = decodeToDocumentWithStructure(compact, annotations); 84 + 85 + const speakerRefs = doc.facets.filter(f => 86 + f.features.some(feat => feat.$type === "tv.ionosphere.facet#speaker-ref") 87 + ); 88 + const conceptRefs = doc.facets.filter(f => 89 + f.features.some(feat => feat.$type === "tv.ionosphere.facet#concept-ref") 90 + ); 91 + const entities = doc.facets.filter(f => 92 + f.features.some(feat => feat.$type === "tv.ionosphere.facet#entity") 93 + ); 94 + const speakerSegs = doc.facets.filter(f => 95 + f.features.some(feat => feat.$type === "tv.ionosphere.facet#speaker-segment") 96 + ); 97 + const topicBreaks = doc.facets.filter(f => 98 + f.features.some(feat => feat.$type === "tv.ionosphere.facet#topic-break") 99 + ); 100 + 101 + expect(speakerRefs).toHaveLength(1); 102 + expect(speakerRefs[0].features[0].speakerDid).toBe("did:plc:abc123"); 103 + expect(conceptRefs).toHaveLength(1); 104 + expect(conceptRefs[0].features[0].conceptUri).toBe("at://did:plc:xyz/tv.ionosphere.concept/test"); 105 + expect(entities).toHaveLength(1); // unresolved entity 106 + expect(entities[0].features[0].label).toBe("this"); 107 + expect(speakerSegs).toHaveLength(1); 108 + expect(topicBreaks).toHaveLength(1); 109 + }); 110 + 111 + it("handles missing optional annotation fields gracefully", () => { 112 + const compact = encode(contiguous); 113 + const annotations = { 114 + sentences: [{ byteStart: 0, byteEnd: 26 }], 115 + paragraphs: [{ byteStart: 0, byteEnd: 26 }], 116 + // No entities, speakerSegments, or topicBreaks 117 + }; 118 + const doc = decodeToDocumentWithStructure(compact, annotations); 119 + // Should have sentences + paragraphs + timestamps, nothing else 120 + const tsFacets = doc.facets.filter(f => 121 + f.features.some(feat => feat.$type === "tv.ionosphere.facet#timestamp") 122 + ); 123 + expect(tsFacets).toHaveLength(6); 124 + }); 125 + ``` 126 + 127 + - [ ] **Step 2: Run test to verify it fails** 128 + 129 + ```bash 130 + cd formats/tv.ionosphere && npx vitest run ts/transcript-encoding.test.ts 131 + ``` 132 + 133 + - [ ] **Step 3: Extend NlpAnnotations interface and decodeToDocumentWithStructure** 134 + 135 + Update `formats/tv.ionosphere/ts/transcript-encoding.ts`: 136 + 137 + ```typescript 138 + export interface NlpAnnotations { 139 + sentences: Array<{ byteStart: number; byteEnd: number }>; 140 + paragraphs: Array<{ byteStart: number; byteEnd: number }>; 141 + entities?: Array<{ 142 + byteStart: number; byteEnd: number; 143 + label: string; nerType: string; 144 + speakerDid?: string; conceptUri?: string; 145 + }>; 146 + speakerSegments?: Array<{ 147 + byteStart: number; byteEnd: number; 148 + speakerDid: string; speakerName: string; 149 + }>; 150 + topicBreaks?: Array<{ byteStart: number }>; 151 + } 152 + ``` 153 + 154 + Add to `decodeToDocumentWithStructure`, after the paragraph facet loop: 155 + 156 + ```typescript 157 + // Entity facets — route to speaker-ref, concept-ref, or generic entity 158 + for (const e of annotations.entities ?? []) { 159 + if (e.speakerDid) { 160 + doc.facets.push({ 161 + index: { byteStart: e.byteStart, byteEnd: e.byteEnd }, 162 + features: [{ 163 + $type: "tv.ionosphere.facet#speaker-ref", 164 + speakerDid: e.speakerDid, 165 + label: e.label, 166 + }], 167 + }); 168 + } else if (e.conceptUri) { 169 + doc.facets.push({ 170 + index: { byteStart: e.byteStart, byteEnd: e.byteEnd }, 171 + features: [{ 172 + $type: "tv.ionosphere.facet#concept-ref", 173 + conceptUri: e.conceptUri, 174 + conceptName: e.label, 175 + }], 176 + }); 177 + } else { 178 + doc.facets.push({ 179 + index: { byteStart: e.byteStart, byteEnd: e.byteEnd }, 180 + features: [{ 181 + $type: "tv.ionosphere.facet#entity", 182 + label: e.label, 183 + nerType: e.nerType, 184 + }], 185 + }); 186 + } 187 + } 188 + 189 + // Speaker segment facets 190 + for (const seg of annotations.speakerSegments ?? []) { 191 + doc.facets.push({ 192 + index: { byteStart: seg.byteStart, byteEnd: seg.byteEnd }, 193 + features: [{ 194 + $type: "tv.ionosphere.facet#speaker-segment", 195 + speakerDid: seg.speakerDid, 196 + speakerName: seg.speakerName, 197 + }], 198 + }); 199 + } 200 + 201 + // Topic break facets 202 + for (const tb of annotations.topicBreaks ?? []) { 203 + doc.facets.push({ 204 + index: { byteStart: tb.byteStart, byteEnd: tb.byteStart }, 205 + features: [{ $type: "tv.ionosphere.facet#topic-break" }], 206 + }); 207 + } 208 + ``` 209 + 210 + - [ ] **Step 4: Run tests to verify all pass** 211 + 212 + ```bash 213 + cd formats/tv.ionosphere && npx vitest run ts/transcript-encoding.test.ts 214 + ``` 215 + 216 + - [ ] **Step 5: Commit** 217 + 218 + ```bash 219 + git add formats/tv.ionosphere/ts/transcript-encoding.ts formats/tv.ionosphere/ts/transcript-encoding.test.ts 220 + git commit -m "feat: extend NlpAnnotations with entities, speakers, topic breaks" 221 + ``` 222 + 223 + --- 224 + 225 + ## Chunk 2: Python NER + entity linking 226 + 227 + ### Task 3: Install sentence-transformers dependency 228 + 229 + **Files:** 230 + - Modify: `pipeline/pyproject.toml` 231 + 232 + - [ ] **Step 1: Add sentence-transformers to dependencies** 233 + 234 + ```toml 235 + dependencies = [ 236 + "spacy>=3.7", 237 + "sentence-transformers>=2.0", 238 + ] 239 + ``` 240 + 241 + - [ ] **Step 2: Install** 242 + 243 + ```bash 244 + cd pipeline && source .venv/bin/activate && pip install -e ".[dev]" 245 + ``` 246 + 247 + - [ ] **Step 3: Verify sentence-transformers loads** 248 + 249 + ```bash 250 + python -c "from sentence_transformers import SentenceTransformer; print('OK')" 251 + ``` 252 + 253 + - [ ] **Step 4: Commit** 254 + 255 + ```bash 256 + git add pipeline/pyproject.toml 257 + git commit -m "feat: add sentence-transformers dependency for topic segmentation" 258 + ``` 259 + 260 + ### Task 4: Implement speaker lookup builder 261 + 262 + **Files:** 263 + - Create: `pipeline/nlp/speaker_lookup.py` 264 + - Create: `pipeline/tests/test_speaker_lookup.py` 265 + 266 + - [ ] **Step 1: Write the failing test** 267 + 268 + Create `pipeline/tests/test_speaker_lookup.py`: 269 + 270 + ```python 271 + from nlp.speaker_lookup import build_speaker_lookup 272 + 273 + 274 + def test_build_lookup_from_rows(): 275 + """Build lookup from speaker database rows.""" 276 + rows = [ 277 + ("Matt Akamatsu", "matsulab.com", "did:plc:matt123"), 278 + ("Rowan Cockett", "row1.ca", "did:plc:rowan456"), 279 + ("Jay Graber", "jay.bsky.team", "did:plc:jay789"), 280 + ] 281 + lookup = build_speaker_lookup(rows) 282 + 283 + # Full name match (case-insensitive) 284 + assert lookup.resolve("Matt Akamatsu") is not None 285 + assert lookup.resolve("Matt Akamatsu")["did"] == "did:plc:matt123" 286 + assert lookup.resolve("matt akamatsu")["did"] == "did:plc:matt123" 287 + 288 + # First name match 289 + assert lookup.resolve("Matt") is not None 290 + assert lookup.resolve("Matt")["did"] == "did:plc:matt123" 291 + 292 + # Handle match 293 + assert lookup.resolve("row1.ca") is not None 294 + assert lookup.resolve("row1.ca")["did"] == "did:plc:rowan456" 295 + 296 + # No match 297 + assert lookup.resolve("Unknown Person") is None 298 + 299 + 300 + def test_first_name_collision_returns_none(): 301 + """When multiple speakers share a first name, first-name lookup returns None (ambiguous).""" 302 + rows = [ 303 + ("Matt Akamatsu", "matsulab.com", "did:plc:matt1"), 304 + ("Matt Jones", "mattj.com", "did:plc:matt2"), 305 + ] 306 + lookup = build_speaker_lookup(rows) 307 + 308 + # Full name still works 309 + assert lookup.resolve("Matt Akamatsu")["did"] == "did:plc:matt1" 310 + # First name alone is ambiguous 311 + assert lookup.resolve("Matt") is None 312 + 313 + 314 + def test_empty_speakers(): 315 + lookup = build_speaker_lookup([]) 316 + assert lookup.resolve("Anyone") is None 317 + ``` 318 + 319 + - [ ] **Step 2: Run test to verify it fails** 320 + 321 + ```bash 322 + cd pipeline && source .venv/bin/activate && pytest tests/test_speaker_lookup.py -v 323 + ``` 324 + 325 + - [ ] **Step 3: Implement speaker_lookup.py** 326 + 327 + Create `pipeline/nlp/speaker_lookup.py`: 328 + 329 + ```python 330 + """Build a speaker lookup table from database records for entity resolution.""" 331 + 332 + 333 + class SpeakerLookup: 334 + def __init__(self): 335 + self._by_full_name: dict[str, dict] = {} 336 + self._by_first_name: dict[str, dict | None] = {} 337 + self._by_handle: dict[str, dict] = {} 338 + 339 + def add(self, name: str, handle: str | None, did: str | None): 340 + entry = {"name": name, "handle": handle, "did": did} 341 + self._by_full_name[name.lower()] = entry 342 + 343 + if handle: 344 + self._by_handle[handle.lower()] = entry 345 + 346 + first = name.split()[0].lower() 347 + if first in self._by_first_name: 348 + # Collision — mark as ambiguous 349 + self._by_first_name[first] = None 350 + else: 351 + self._by_first_name[first] = entry 352 + 353 + def resolve(self, name: str) -> dict | None: 354 + key = name.lower().strip() 355 + # Try full name first 356 + if key in self._by_full_name: 357 + return self._by_full_name[key] 358 + # Try handle 359 + if key in self._by_handle: 360 + return self._by_handle[key] 361 + # Try first name (returns None if ambiguous) 362 + if key in self._by_first_name: 363 + return self._by_first_name[key] 364 + return None 365 + 366 + 367 + def build_speaker_lookup(rows: list[tuple]) -> SpeakerLookup: 368 + """Build lookup from database rows of (name, handle, speaker_did).""" 369 + lookup = SpeakerLookup() 370 + for name, handle, did in rows: 371 + lookup.add(name, handle, did) 372 + return lookup 373 + ``` 374 + 375 + - [ ] **Step 4: Run tests to verify they pass** 376 + 377 + ```bash 378 + cd pipeline && source .venv/bin/activate && pytest tests/test_speaker_lookup.py -v 379 + ``` 380 + 381 + - [ ] **Step 5: Commit** 382 + 383 + ```bash 384 + git add pipeline/nlp/speaker_lookup.py pipeline/tests/test_speaker_lookup.py 385 + git commit -m "feat: speaker lookup builder for entity resolution" 386 + ``` 387 + 388 + ### Task 5: Implement NER + entity linking pass 389 + 390 + **Files:** 391 + - Create: `pipeline/nlp/entities.py` 392 + - Create: `pipeline/tests/test_entities.py` 393 + 394 + - [ ] **Step 1: Write the failing test** 395 + 396 + Create `pipeline/tests/test_entities.py`: 397 + 398 + ```python 399 + from nlp.entities import detect_entities 400 + from nlp.speaker_lookup import build_speaker_lookup 401 + 402 + 403 + def test_detects_person_entities(): 404 + text = "Matt Akamatsu is presenting today." 405 + rows = [("Matt Akamatsu", "matsulab.com", "did:plc:matt123")] 406 + lookup = build_speaker_lookup(rows) 407 + 408 + entities = detect_entities(text, speaker_lookup=lookup) 409 + 410 + persons = [e for e in entities if e["nerType"] == "PERSON"] 411 + assert len(persons) >= 1 412 + # Should resolve to the speaker 413 + resolved = [e for e in persons if e.get("speakerDid")] 414 + assert len(resolved) >= 1 415 + assert resolved[0]["speakerDid"] == "did:plc:matt123" 416 + 417 + 418 + def test_detects_org_entities(): 419 + text = "The work at Bluesky is impressive." 420 + concepts = [{"name": "Bluesky", "uri": "at://did/concept/bluesky", "aliases": "[]"}] 421 + 422 + entities = detect_entities(text, concept_rows=concepts) 423 + 424 + orgs = [e for e in entities if e.get("conceptUri")] 425 + assert len(orgs) >= 1 426 + 427 + 428 + def test_unresolved_entities_have_label(): 429 + text = "Barack Obama spoke at the conference." 430 + entities = detect_entities(text) 431 + 432 + persons = [e for e in entities if e["nerType"] == "PERSON"] 433 + assert len(persons) >= 1 434 + assert persons[0].get("speakerDid") is None 435 + assert persons[0]["label"] == "Barack Obama" 436 + 437 + 438 + def test_byte_offsets_correct(): 439 + text = "Matt Akamatsu presented." 440 + entities = detect_entities(text) 441 + if entities: 442 + e = entities[0] 443 + # Verify byte range matches the label 444 + text_at_range = text.encode("utf-8")[e["byteStart"]:e["byteEnd"]].decode("utf-8") 445 + assert e["label"] in text_at_range or text_at_range in e["label"] 446 + 447 + 448 + def test_empty_text(): 449 + entities = detect_entities("") 450 + assert entities == [] 451 + ``` 452 + 453 + - [ ] **Step 2: Run test to verify it fails** 454 + 455 + ```bash 456 + cd pipeline && source .venv/bin/activate && pytest tests/test_entities.py -v 457 + ``` 458 + 459 + - [ ] **Step 3: Implement entities.py** 460 + 461 + Create `pipeline/nlp/entities.py`: 462 + 463 + ```python 464 + """Pass 3: Named entity recognition + entity linking.""" 465 + 466 + import json 467 + import spacy 468 + 469 + _nlp = None 470 + 471 + 472 + def _get_nlp(): 473 + global _nlp 474 + if _nlp is None: 475 + _nlp = spacy.load("en_core_web_sm") 476 + return _nlp 477 + 478 + 479 + def detect_entities( 480 + text: str, 481 + speaker_lookup=None, 482 + concept_rows: list[dict] | None = None, 483 + ) -> list[dict]: 484 + """Detect named entities and resolve against speaker/concept records. 485 + 486 + Returns a list of entity dicts with: 487 + byteStart, byteEnd: UTF-8 byte offsets 488 + label: entity text 489 + nerType: spaCy entity type (PERSON, ORG, PRODUCT, etc.) 490 + speakerDid: (optional) resolved speaker DID 491 + conceptUri: (optional) resolved concept URI 492 + """ 493 + if not text.strip(): 494 + return [] 495 + 496 + nlp = _get_nlp() 497 + doc = nlp(text) 498 + 499 + # Build concept lookup 500 + concept_lookup: dict[str, str] = {} 501 + if concept_rows: 502 + for c in concept_rows: 503 + concept_lookup[c["name"].lower()] = c["uri"] 504 + aliases = c.get("aliases", "[]") 505 + if isinstance(aliases, str): 506 + try: 507 + aliases = json.loads(aliases) 508 + except (json.JSONDecodeError, TypeError): 509 + aliases = [] 510 + for alias in aliases: 511 + concept_lookup[alias.lower()] = c["uri"] 512 + 513 + entities = [] 514 + for ent in doc.ents: 515 + if ent.label_ not in ("PERSON", "ORG", "PRODUCT", "WORK_OF_ART", "GPE", "EVENT"): 516 + continue 517 + 518 + byte_start = len(text[:ent.start_char].encode("utf-8")) 519 + byte_end = len(text[:ent.end_char].encode("utf-8")) 520 + 521 + entity = { 522 + "byteStart": byte_start, 523 + "byteEnd": byte_end, 524 + "label": ent.text, 525 + "nerType": ent.label_, 526 + } 527 + 528 + # Try to resolve 529 + if ent.label_ == "PERSON" and speaker_lookup: 530 + match = speaker_lookup.resolve(ent.text) 531 + if match and match.get("did"): 532 + entity["speakerDid"] = match["did"] 533 + elif ent.label_ in ("ORG", "PRODUCT", "WORK_OF_ART"): 534 + uri = concept_lookup.get(ent.text.lower()) 535 + if uri: 536 + entity["conceptUri"] = uri 537 + 538 + entities.append(entity) 539 + 540 + return entities 541 + ``` 542 + 543 + - [ ] **Step 4: Run tests to verify they pass** 544 + 545 + ```bash 546 + cd pipeline && source .venv/bin/activate && pytest tests/test_entities.py -v 547 + ``` 548 + 549 + - [ ] **Step 5: Commit** 550 + 551 + ```bash 552 + git add pipeline/nlp/entities.py pipeline/tests/test_entities.py 553 + git commit -m "feat: NER + entity linking against speakers and concepts" 554 + ``` 555 + 556 + --- 557 + 558 + ## Chunk 3: Topic segmentation 559 + 560 + ### Task 6: Implement topic segmentation pass 561 + 562 + **Files:** 563 + - Create: `pipeline/nlp/topics.py` 564 + - Create: `pipeline/tests/test_topics.py` 565 + 566 + - [ ] **Step 1: Write the failing test** 567 + 568 + Create `pipeline/tests/test_topics.py`: 569 + 570 + ```python 571 + from nlp.topics import detect_topic_breaks 572 + 573 + 574 + def test_detects_topic_change(): 575 + """Distinct topics should produce at least one break.""" 576 + sentences = [ 577 + # Topic 1: cooking 578 + {"byteStart": 0, "byteEnd": 30, "text": "Today we will make a cake."}, 579 + {"byteStart": 31, "byteEnd": 65, "text": "First mix the flour and sugar."}, 580 + {"byteStart": 66, "byteEnd": 100, "text": "Then add the eggs and butter."}, 581 + {"byteStart": 101, "byteEnd": 135, "text": "Bake at 350 degrees for 30 minutes."}, 582 + {"byteStart": 136, "byteEnd": 170, "text": "Let it cool before adding frosting."}, 583 + # Topic 2: space exploration (very different) 584 + {"byteStart": 171, "byteEnd": 210, "text": "NASA launched a new rocket to Mars."}, 585 + {"byteStart": 211, "byteEnd": 250, "text": "The spacecraft will orbit the red planet."}, 586 + {"byteStart": 251, "byteEnd": 295, "text": "Astronauts may visit Mars within ten years."}, 587 + {"byteStart": 296, "byteEnd": 340, "text": "The mission costs billions of dollars."}, 588 + {"byteStart": 341, "byteEnd": 380, "text": "Space exploration advances human knowledge."}, 589 + ] 590 + breaks = detect_topic_breaks(sentences) 591 + assert len(breaks) >= 1 592 + # Break should be near the topic transition (around sentence 5) 593 + assert any(4 <= b["sentenceIndex"] <= 6 for b in breaks) 594 + 595 + 596 + def test_no_breaks_for_single_topic(): 597 + sentences = [ 598 + {"byteStart": 0, "byteEnd": 30, "text": "The cat sat on the mat."}, 599 + {"byteStart": 31, "byteEnd": 60, "text": "The cat was very happy."}, 600 + {"byteStart": 61, "byteEnd": 90, "text": "It purred loudly all day."}, 601 + ] 602 + breaks = detect_topic_breaks(sentences, min_segment_sentences=2) 603 + # Might have 0 breaks or very few — should not over-segment 604 + assert len(breaks) <= 1 605 + 606 + 607 + def test_empty_input(): 608 + assert detect_topic_breaks([]) == [] 609 + 610 + 611 + def test_too_few_sentences(): 612 + sentences = [{"byteStart": 0, "byteEnd": 10, "text": "Hello."}] 613 + assert detect_topic_breaks(sentences) == [] 614 + ``` 615 + 616 + - [ ] **Step 2: Run test to verify it fails** 617 + 618 + ```bash 619 + cd pipeline && source .venv/bin/activate && pytest tests/test_topics.py -v 620 + ``` 621 + 622 + - [ ] **Step 3: Implement topics.py** 623 + 624 + Create `pipeline/nlp/topics.py`: 625 + 626 + ```python 627 + """Pass 4: Topic segmentation using sentence embeddings.""" 628 + 629 + import numpy as np 630 + 631 + _model = None 632 + 633 + 634 + def _get_model(): 635 + global _model 636 + if _model is None: 637 + from sentence_transformers import SentenceTransformer 638 + _model = SentenceTransformer("all-MiniLM-L6-v2") 639 + return _model 640 + 641 + 642 + def detect_topic_breaks( 643 + sentences: list[dict], 644 + window_size: int = 3, 645 + similarity_threshold: float = 0.3, 646 + min_segment_sentences: int = 5, 647 + ) -> list[dict]: 648 + """Detect topic boundaries using sentence embedding similarity. 649 + 650 + Args: 651 + sentences: list of dicts with byteStart, byteEnd, text 652 + window_size: number of sentences per comparison window 653 + similarity_threshold: cosine similarity below this = topic break 654 + min_segment_sentences: minimum sentences between breaks 655 + 656 + Returns: 657 + list of dicts with byteStart and sentenceIndex 658 + """ 659 + if len(sentences) < window_size * 2: 660 + return [] 661 + 662 + model = _get_model() 663 + texts = [s["text"] for s in sentences] 664 + embeddings = model.encode(texts, show_progress_bar=False) 665 + 666 + # Compute cosine similarity between adjacent windows 667 + similarities = [] 668 + for i in range(window_size, len(sentences) - window_size + 1): 669 + left = np.mean(embeddings[i - window_size:i], axis=0) 670 + right = np.mean(embeddings[i:i + window_size], axis=0) 671 + cos_sim = np.dot(left, right) / (np.linalg.norm(left) * np.linalg.norm(right)) 672 + similarities.append((i, float(cos_sim))) 673 + 674 + # Find drops below threshold, respecting minimum segment length 675 + breaks = [] 676 + last_break = 0 677 + for sent_idx, sim in similarities: 678 + if sim < similarity_threshold and (sent_idx - last_break) >= min_segment_sentences: 679 + breaks.append({ 680 + "byteStart": sentences[sent_idx]["byteStart"], 681 + "sentenceIndex": sent_idx, 682 + }) 683 + last_break = sent_idx 684 + 685 + return breaks 686 + ``` 687 + 688 + - [ ] **Step 4: Run tests to verify they pass** 689 + 690 + ```bash 691 + cd pipeline && source .venv/bin/activate && pytest tests/test_topics.py -v 692 + ``` 693 + 694 + Note: the first run will download the `all-MiniLM-L6-v2` model (~80MB). 695 + 696 + - [ ] **Step 5: Commit** 697 + 698 + ```bash 699 + git add pipeline/nlp/topics.py pipeline/tests/test_topics.py 700 + git commit -m "feat: topic segmentation via sentence-transformer embeddings" 701 + ``` 702 + 703 + --- 704 + 705 + ## Chunk 4: Update pipeline orchestrator 706 + 707 + ### Task 7: Extend run.py with NER and topic passes 708 + 709 + **Files:** 710 + - Modify: `pipeline/nlp/run.py` 711 + - Modify: `pipeline/tests/test_run.py` 712 + 713 + - [ ] **Step 1: Update the integration test** 714 + 715 + Add to `pipeline/tests/test_run.py`: 716 + 717 + ```python 718 + def test_process_transcript_with_enrichment(): 719 + """Full pipeline with entity and topic passes.""" 720 + transcript = { 721 + "text": "Matt Akamatsu is presenting. The AT Protocol is decentralized. Now we discuss a completely different topic about cooking recipes and baking.", 722 + "startMs": 0, 723 + "timings": [100, 100, 100, 100, 100, 100, 100, 100, 100, -3000, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100], 724 + } 725 + speaker_rows = [("Matt Akamatsu", "matsulab.com", "did:plc:matt123")] 726 + concept_rows = [{"name": "AT Protocol", "uri": "at://did/concept/atp", "aliases": "[]"}] 727 + 728 + result = process_transcript( 729 + transcript, talk_rkey="test", 730 + speaker_rows=speaker_rows, 731 + concept_rows=concept_rows, 732 + ) 733 + 734 + assert "entities" in result 735 + assert "topicBreaks" in result 736 + assert len(result["entities"]) >= 1 737 + # At least one resolved entity 738 + resolved = [e for e in result["entities"] if e.get("speakerDid") or e.get("conceptUri")] 739 + assert len(resolved) >= 1 740 + ``` 741 + 742 + - [ ] **Step 2: Run test to verify it fails** 743 + 744 + ```bash 745 + cd pipeline && source .venv/bin/activate && pytest tests/test_run.py -v 746 + ``` 747 + 748 + - [ ] **Step 3: Update process_transcript in run.py** 749 + 750 + Add imports at top: 751 + ```python 752 + from nlp.entities import detect_entities 753 + from nlp.speaker_lookup import build_speaker_lookup 754 + from nlp.topics import detect_topic_breaks 755 + ``` 756 + 757 + Update `process_transcript` signature to accept optional speaker/concept data: 758 + ```python 759 + def process_transcript( 760 + transcript: dict, 761 + talk_rkey: str, 762 + pause_threshold_ms: int = 2000, 763 + proximity_words: int = 5, 764 + speaker_rows: list[tuple] | None = None, 765 + concept_rows: list[dict] | None = None, 766 + ) -> dict: 767 + ``` 768 + 769 + Add after the paragraph detection: 770 + ```python 771 + # Pass 3: NER + entity linking 772 + speaker_lookup = build_speaker_lookup(speaker_rows) if speaker_rows else None 773 + entities = detect_entities(text, speaker_lookup=speaker_lookup, concept_rows=concept_rows) 774 + 775 + # Pass 4: Topic segmentation 776 + # Enrich sentences with text for embedding 777 + sentences_with_text = [] 778 + for s in sentences: 779 + sent_text = text.encode("utf-8")[s["byteStart"]:s["byteEnd"]].decode("utf-8") 780 + sentences_with_text.append({**s, "text": sent_text}) 781 + topic_breaks = detect_topic_breaks(sentences_with_text) 782 + ``` 783 + 784 + Update the return dict to include: 785 + ```python 786 + return { 787 + "talkRkey": talk_rkey, 788 + "sentences": sentences, 789 + "paragraphs": paragraphs, 790 + "entities": entities, 791 + "topicBreaks": [{"byteStart": tb["byteStart"]} for tb in topic_breaks], 792 + "metadata": { ... }, 793 + } 794 + ``` 795 + 796 + - [ ] **Step 4: Update main() to load speaker/concept data from SQLite** 797 + 798 + Add to the `main()` function, before the transcript loop: 799 + 800 + ```python 801 + import sqlite3 802 + db_path = Path(__file__).resolve().parent.parent.parent / "apps" / "data" / "ionosphere.sqlite" 803 + speaker_rows = [] 804 + concept_rows = [] 805 + if db_path.exists(): 806 + conn = sqlite3.connect(str(db_path)) 807 + speaker_rows = conn.execute( 808 + "SELECT name, handle, speaker_did FROM speakers" 809 + ).fetchall() 810 + concept_rows = [ 811 + {"name": r[0], "uri": r[1], "aliases": r[2] or "[]"} 812 + for r in conn.execute("SELECT name, uri, aliases FROM concepts").fetchall() 813 + ] 814 + conn.close() 815 + print(f"Loaded {len(speaker_rows)} speakers, {len(concept_rows)} concepts from DB") 816 + else: 817 + print(f"Warning: database not found at {db_path}, entity linking disabled") 818 + ``` 819 + 820 + Pass these to `process_transcript`: 821 + ```python 822 + result = process_transcript( 823 + compact, talk_rkey=talk_rkey, 824 + speaker_rows=speaker_rows, 825 + concept_rows=concept_rows, 826 + ) 827 + ``` 828 + 829 + Update the log line: 830 + ```python 831 + entity_count = len(result.get("entities", [])) 832 + topic_count = len(result.get("topicBreaks", [])) 833 + print(f" {talk_rkey}: {len(result['sentences'])} sentences, {len(result['paragraphs'])} paragraphs, {entity_count} entities, {topic_count} topics") 834 + ``` 835 + 836 + - [ ] **Step 5: Run ALL tests** 837 + 838 + ```bash 839 + cd pipeline && source .venv/bin/activate && pytest tests/ -v 840 + ``` 841 + 842 + - [ ] **Step 6: Commit** 843 + 844 + ```bash 845 + git add pipeline/nlp/run.py pipeline/tests/test_run.py 846 + git commit -m "feat: extend pipeline with NER, entity linking, and topic segmentation" 847 + ``` 848 + 849 + --- 850 + 851 + ## Chunk 5: Renderer — entities and topic dividers 852 + 853 + ### Task 8: Extend extractData for entities and topic breaks 854 + 855 + **Files:** 856 + - Modify: `apps/ionosphere/src/lib/transcript.ts` 857 + - Modify: `apps/ionosphere/src/lib/transcript.test.ts` 858 + 859 + - [ ] **Step 1: Write failing tests** 860 + 861 + Add to `apps/ionosphere/src/lib/transcript.test.ts`: 862 + 863 + ```typescript 864 + describe("extractData — entities and topic breaks", () => { 865 + it("extracts entity spans from facets", () => { 866 + const doc = makeDoc([ 867 + { text: "Matt", startNs: 1000, endNs: 2000 }, 868 + { text: "presented.", startNs: 2000, endNs: 3000 }, 869 + ]); 870 + const encoder = new TextEncoder(); 871 + // Add a speaker-ref entity facet 872 + doc.facets.push({ 873 + index: { byteStart: 0, byteEnd: encoder.encode("Matt").length }, 874 + features: [{ 875 + $type: "tv.ionosphere.facet#speaker-ref", 876 + speakerDid: "did:plc:matt123", 877 + label: "Matt", 878 + }], 879 + }); 880 + 881 + const result = extractData(doc); 882 + expect(result.entities).toHaveLength(1); 883 + expect(result.entities[0].speakerDid).toBe("did:plc:matt123"); 884 + expect(result.entities[0].byteStart).toBe(0); 885 + }); 886 + 887 + it("extracts topic breaks as paragraph indices", () => { 888 + const doc = makeDoc([ 889 + { text: "A.", startNs: 1000, endNs: 2000 }, 890 + { text: "B.", startNs: 3000, endNs: 4000 }, 891 + ]); 892 + const encoder = new TextEncoder(); 893 + const text = "A. B."; 894 + const s1End = encoder.encode("A.").length; 895 + const s2Start = encoder.encode("A. ").length; 896 + const s2End = encoder.encode(text).length; 897 + 898 + // Two paragraphs 899 + doc.facets.push({ index: { byteStart: 0, byteEnd: s1End }, features: [{ $type: "tv.ionosphere.facet#paragraph" }] }); 900 + doc.facets.push({ index: { byteStart: s2Start, byteEnd: s2End }, features: [{ $type: "tv.ionosphere.facet#paragraph" }] }); 901 + // Topic break at second paragraph 902 + doc.facets.push({ index: { byteStart: s2Start, byteEnd: s2Start }, features: [{ $type: "tv.ionosphere.facet#topic-break" }] }); 903 + // Sentences 904 + doc.facets.push({ index: { byteStart: 0, byteEnd: s1End }, features: [{ $type: "tv.ionosphere.facet#sentence" }] }); 905 + doc.facets.push({ index: { byteStart: s2Start, byteEnd: s2End }, features: [{ $type: "tv.ionosphere.facet#sentence" }] }); 906 + 907 + const result = extractData(doc); 908 + expect(result.topicBreaks.has(1)).toBe(true); // second paragraph 909 + expect(result.topicBreaks.has(0)).toBe(false); // first paragraph 910 + }); 911 + 912 + it("returns empty entities and topicBreaks when no such facets exist", () => { 913 + const doc = makeDoc([ 914 + { text: "Hello", startNs: 1000, endNs: 2000 }, 915 + ]); 916 + const result = extractData(doc); 917 + expect(result.entities).toHaveLength(0); 918 + expect(result.topicBreaks.size).toBe(0); 919 + }); 920 + }); 921 + ``` 922 + 923 + - [ ] **Step 2: Run tests to verify they fail** 924 + 925 + ```bash 926 + cd apps/ionosphere && npx vitest run src/lib/transcript.test.ts 927 + ``` 928 + 929 + - [ ] **Step 3: Add EntitySpan type and update extractData** 930 + 931 + Add to `apps/ionosphere/src/lib/transcript.ts`: 932 + 933 + ```typescript 934 + export interface EntitySpan { 935 + byteStart: number; 936 + byteEnd: number; 937 + label: string; 938 + nerType?: string; 939 + speakerDid?: string; 940 + conceptUri?: string; 941 + conceptName?: string; 942 + } 943 + ``` 944 + 945 + In `extractData`, add extraction of entity facets (speaker-ref, concept-ref, entity) and topic-break facets. Map topic breaks to paragraph indices by finding which paragraph contains each break's byte position. 946 + 947 + Return `entities: EntitySpan[]` and `topicBreaks: Set<number>` alongside existing fields. 948 + 949 + - [ ] **Step 4: Run tests to verify all pass** 950 + 951 + ```bash 952 + cd apps/ionosphere && npx vitest run src/lib/transcript.test.ts 953 + ``` 954 + 955 + - [ ] **Step 5: Commit** 956 + 957 + ```bash 958 + git add apps/ionosphere/src/lib/transcript.ts apps/ionosphere/src/lib/transcript.test.ts 959 + git commit -m "feat: extract entities and topic breaks from facets" 960 + ``` 961 + 962 + ### Task 9: Update TranscriptView for entity rendering and topic dividers 963 + 964 + **Files:** 965 + - Modify: `apps/ionosphere/src/app/components/TranscriptView.tsx` 966 + 967 + - [ ] **Step 1: Extract entities and topicBreaks from extractData** 968 + 969 + In the `useMemo` that calls `extractData`, also destructure `entities` and `topicBreaks`. 970 + 971 + - [ ] **Step 2: Build word-to-entity lookup** 972 + 973 + ```typescript 974 + const wordEntities = useMemo(() => { 975 + const map = new Map<number, EntitySpan>(); 976 + for (const entity of entities) { 977 + for (let i = 0; i < words.length; i++) { 978 + const w = words[i]; 979 + if (w.byteStart >= entity.byteStart && w.byteEnd <= entity.byteEnd) { 980 + // First word of entity gets the entity data (for rendering the link) 981 + if (!map.has(i)) map.set(i, entity); 982 + } 983 + } 984 + } 985 + return map; 986 + }, [words, entities]); 987 + ``` 988 + 989 + - [ ] **Step 3: Add entity link styling to WordSpanComponent or a wrapper** 990 + 991 + For words that are part of an entity, add visual treatment: 992 + - `speaker-ref`: blue underline, link to `/speakers/{rkey}` or Bluesky profile 993 + - `concept-ref`: amber underline (matching existing concept style) 994 + - `entity` (unresolved): dotted underline, no link 995 + 996 + The simplest approach: check `wordEntities.get(globalIdx)` when rendering each word, and wrap entity-start words in an `<a>` or styled `<span>`. 997 + 998 + - [ ] **Step 4: Add topic dividers between paragraphs** 999 + 1000 + In the paragraph rendering loop, check `topicBreaks.has(paragraphIndex)` and insert an `<hr>` before that paragraph: 1001 + 1002 + ```tsx 1003 + {paragraphs.map((para, pi) => ( 1004 + <> 1005 + {topicBreaks.has(pi) && ( 1006 + <hr key={`topic-${pi}`} className="border-neutral-800 my-6" /> 1007 + )} 1008 + <div key={pi} className="mb-4"> 1009 + {/* sentences... */} 1010 + </div> 1011 + </> 1012 + ))} 1013 + ``` 1014 + 1015 + - [ ] **Step 5: Verify in browser** 1016 + 1017 + Load a talk page. Verify: 1018 + - Entity names have visible styling (underlines) 1019 + - Resolved entities are clickable 1020 + - Topic dividers appear as subtle horizontal rules 1021 + - Existing functionality (scroll, brightness, comments) unchanged 1022 + 1023 + - [ ] **Step 6: Commit** 1024 + 1025 + ```bash 1026 + git add apps/ionosphere/src/app/components/TranscriptView.tsx 1027 + git commit -m "feat: render entity links and topic dividers in transcript" 1028 + ``` 1029 + 1030 + --- 1031 + 1032 + ## Chunk 6: End-to-end integration 1033 + 1034 + ### Task 10: Run the full enriched pipeline 1035 + 1036 + - [ ] **Step 1: Run the pipeline on all transcripts** 1037 + 1038 + ```bash 1039 + cd pipeline && source .venv/bin/activate && python -m nlp.run 1040 + ``` 1041 + 1042 + Verify output includes entity and topic data. Spot-check 3-5 output files. 1043 + 1044 + - [ ] **Step 2: Inject documents into local database** 1045 + 1046 + Use the same inject pattern as Phase 1 — create a temporary script that reads NLP output + transcripts, calls `decodeToDocumentWithStructure`, and updates the talks table. 1047 + 1048 + - [ ] **Step 3: Verify in browser** 1049 + 1050 + Load several talk pages. Check: 1051 + - Entity links point to correct profiles/concepts 1052 + - Topic dividers land at natural transitions 1053 + - Talks without diarization still work (entities just don't have speaker context) 1054 + - All existing features (paragraphs, sentences, timing, comments) unchanged 1055 + 1056 + - [ ] **Step 4: Run all tests** 1057 + 1058 + ```bash 1059 + # Python 1060 + cd pipeline && source .venv/bin/activate && pytest -v 1061 + 1062 + # TypeScript 1063 + cd formats/tv.ionosphere && npx vitest run 1064 + cd ../../apps/ionosphere && npx vitest run src/lib/transcript.test.ts 1065 + ``` 1066 + 1067 + - [ ] **Step 5: Commit any integration fixes** 1068 + 1069 + ```bash 1070 + git add -A && git commit -m "fix: integration fixes from end-to-end verification" 1071 + ``` 1072 + 1073 + ### Task 11: Update publish.ts for enriched annotations 1074 + 1075 + **Files:** 1076 + - Modify: `apps/ionosphere-appview/src/publish.ts` 1077 + 1078 + - [ ] **Step 1: Update the NLP data reading to include new fields** 1079 + 1080 + The publish.ts code that reads NLP JSON and passes it to `decodeToDocumentWithStructure` needs to include the new fields (entities, speakerSegments, topicBreaks) from the NLP output. Since `NlpAnnotations` now has these as optional fields, this is just passing them through: 1081 + 1082 + ```typescript 1083 + const doc = decodeToDocumentWithStructure(compact, { 1084 + sentences: nlpData.sentences, 1085 + paragraphs: nlpData.paragraphs, 1086 + entities: nlpData.entities, 1087 + topicBreaks: nlpData.topicBreaks, 1088 + // speakerSegments will come when diarization is integrated 1089 + }); 1090 + ``` 1091 + 1092 + - [ ] **Step 2: Commit** 1093 + 1094 + ```bash 1095 + git add apps/ionosphere-appview/src/publish.ts 1096 + git commit -m "feat: pass entity and topic data through publish pipeline" 1097 + ```
+1138
docs/superpowers/plans/2026-04-12-transcript-formatting.md
··· 1 + # Transcript Formatting Implementation Plan 2 + 3 + > **For agentic workers:** REQUIRED: Use superpowers:subagent-driven-development (if subagents available) or superpowers:executing-plans to implement this plan. Steps use checkbox (`- [ ]`) syntax for tracking. 4 + 5 + **Goal:** Add NLP-based sentence and paragraph detection to transcripts so they render as structured prose instead of a wall of text. 6 + 7 + **Architecture:** A Python NLP pipeline (spaCy) produces sentence/paragraph annotation layers as JSON files. A TypeScript publish step validates and publishes these as layers.pub AT Protocol records. The document assembly step reads annotation layers and emits structural facets (`#sentence`, `#paragraph`) that the React renderer consumes as inline spans and block elements. The old `tv.ionosphere.annotation` system is removed entirely. 8 + 9 + **Tech Stack:** Python 3.12+, spaCy (`en_core_web_sm`), vitest, layers.pub lexicons, panproto, React/Next.js 10 + 11 + **Spec:** `docs/superpowers/specs/2026-04-12-transcript-formatting-design.md` 12 + 13 + **Scope note:** This plan implements the rendering pipeline (NLP → facets → renderer) end-to-end. Publishing layers.pub records to the PDS and creating panproto lenses are deferred to a follow-up — the vendored lexicons and spec are forward preparation. The immediate goal is formatted transcripts in the browser. 14 + 15 + **UX note:** Removing the old annotation system (Task 13) will temporarily remove concept highlighting from talk pages. Concepts return via NLP in Phase 2. If this is unacceptable, Task 13 can be deferred and the old overlay path kept alongside the new structural facets. 16 + 17 + --- 18 + 19 + ## Chunk 1: Vendor layers.pub lexicons and define new facet types 20 + 21 + ### Task 1: Vendor layers.pub lexicon definitions 22 + 23 + **Files:** 24 + - Create: `lexicons/pub/layers/defs.json` 25 + - Create: `lexicons/pub/layers/expression/expression.json` 26 + - Create: `lexicons/pub/layers/segmentation/segmentation.json` 27 + - Create: `lexicons/pub/layers/annotation/annotationLayer.json` 28 + 29 + - [ ] **Step 1: Create the `pub.layers.defs` shared definitions lexicon** 30 + 31 + Vendor the subset of `pub.layers.defs` that we use: `span`, `temporalSpan`, `uuid`, `tokenRef`, `anchor`, `annotationMetadata`, `featureMap`, `feature`. Pull the field definitions from https://docs.layers.pub/lexicons/defs. These are the shared types referenced by the other lexicons. 32 + 33 + - [ ] **Step 2: Create the `pub.layers.expression.expression` lexicon** 34 + 35 + Vendor the expression record schema from https://docs.layers.pub/lexicons/expression. Required fields: `id`, `kindUri`, `kind`, `text`, `language`, `createdAt`. Optional: `sourceRef`, `parentRef`, `anchor`, `metadata`, `features`. 36 + 37 + - [ ] **Step 3: Create the `pub.layers.segmentation.segmentation` lexicon** 38 + 39 + Vendor the segmentation record schema from https://docs.layers.pub/lexicons/segmentation. This includes the `segmentation` record and the `tokenization` and `token` object defs. 40 + 41 + - [ ] **Step 4: Create the `pub.layers.annotation.annotationLayer` lexicon** 42 + 43 + Vendor the annotation layer record schema from https://docs.layers.pub/lexicons/annotation. This includes `annotationLayer` record and the `annotation` object def. 44 + 45 + - [ ] **Step 5: Commit** 46 + 47 + ```bash 48 + git add lexicons/pub/ 49 + git commit -m "feat: vendor layers.pub lexicons for transcript enrichment" 50 + ``` 51 + 52 + ### Task 2: Add sentence and paragraph facet types to the format lexicon 53 + 54 + **Files:** 55 + - Modify: `formats/tv.ionosphere/ionosphere.lexicon.json` 56 + 57 + - [ ] **Step 1: Add `#sentence` (inline) and `#paragraph` (block) facet entries** 58 + 59 + Add to the `features` array in `formats/tv.ionosphere/ionosphere.lexicon.json`: 60 + 61 + ```json 62 + { 63 + "typeId": "tv.ionosphere.facet#sentence", 64 + "featureClass": "inline", 65 + "expandStart": false, 66 + "expandEnd": false 67 + }, 68 + { 69 + "typeId": "tv.ionosphere.facet#paragraph", 70 + "featureClass": "block", 71 + "expandStart": false, 72 + "expandEnd": false 73 + } 74 + ``` 75 + 76 + - [ ] **Step 2: Commit** 77 + 78 + ```bash 79 + git add formats/tv.ionosphere/ionosphere.lexicon.json 80 + git commit -m "feat: add sentence (inline) and paragraph (block) facet types" 81 + ``` 82 + 83 + --- 84 + 85 + ## Chunk 2: Python NLP pipeline 86 + 87 + ### Task 3: Set up the Python enrichment project 88 + 89 + **Files:** 90 + - Create: `pipeline/pyproject.toml` 91 + - Create: `pipeline/nlp/__init__.py` 92 + 93 + - [ ] **Step 1: Create `pipeline/pyproject.toml`** 94 + 95 + ```toml 96 + [project] 97 + name = "ionosphere-nlp" 98 + version = "0.1.0" 99 + description = "NLP enrichment pipeline for ionosphere transcripts" 100 + requires-python = ">=3.12" 101 + dependencies = [ 102 + "spacy>=3.7", 103 + ] 104 + 105 + [project.optional-dependencies] 106 + dev = ["pytest>=8.0"] 107 + 108 + [tool.pytest.ini_options] 109 + testpaths = ["tests"] 110 + ``` 111 + 112 + - [ ] **Step 2: Create the package init** 113 + 114 + Create `pipeline/nlp/__init__.py` (empty file). 115 + 116 + - [ ] **Step 3: Create `pipeline/tests/__init__.py`** 117 + 118 + Empty file (needed for pytest discovery). 119 + 120 + - [ ] **Step 4: Add `.gitignore` entries for Python artifacts** 121 + 122 + Add to the repo root `.gitignore`: 123 + ``` 124 + pipeline/.venv/ 125 + pipeline/data/ 126 + __pycache__/ 127 + *.pyc 128 + ``` 129 + 130 + - [ ] **Step 5: Install dependencies** 131 + 132 + ```bash 133 + cd pipeline 134 + python -m venv .venv 135 + source .venv/bin/activate 136 + pip install -e ".[dev]" 137 + python -m spacy download en_core_web_sm 138 + ``` 139 + 140 + - [ ] **Step 6: Commit** 141 + 142 + ```bash 143 + git add pipeline/pyproject.toml pipeline/nlp/__init__.py pipeline/tests/__init__.py .gitignore 144 + git commit -m "feat: scaffold Python NLP pipeline project" 145 + ``` 146 + 147 + ### Task 4: Implement sentence boundary detection (Pass 1) 148 + 149 + **Files:** 150 + - Create: `pipeline/tests/test_sentences.py` 151 + - Create: `pipeline/nlp/sentences.py` 152 + 153 + - [ ] **Step 1: Write the failing test** 154 + 155 + Create `pipeline/tests/test_sentences.py`: 156 + 157 + ```python 158 + from nlp.sentences import detect_sentences 159 + 160 + 161 + def test_basic_sentences(): 162 + text = "Hello world. This is a test. And another sentence." 163 + sentences = detect_sentences(text) 164 + assert len(sentences) == 3 165 + # Each sentence is a dict with byteStart and byteEnd 166 + assert sentences[0]["byteStart"] == 0 167 + assert sentences[0]["byteEnd"] == len("Hello world.".encode("utf-8")) 168 + assert sentences[1]["byteStart"] == len("Hello world. ".encode("utf-8")) 169 + 170 + 171 + def test_speech_without_punctuation(): 172 + """spaCy should detect sentence boundaries even with poor punctuation.""" 173 + text = "so the thing is we need to think about this carefully and then we can move on to the next topic which is about protocols" 174 + sentences = detect_sentences(text) 175 + # spaCy should find at least 1 sentence (the whole text if no clear boundary) 176 + assert len(sentences) >= 1 177 + # All sentences should cover the full text 178 + assert sentences[0]["byteStart"] == 0 179 + assert sentences[-1]["byteEnd"] == len(text.encode("utf-8")) 180 + 181 + 182 + def test_empty_text(): 183 + sentences = detect_sentences("") 184 + assert sentences == [] 185 + 186 + 187 + def test_byte_offsets_for_unicode(): 188 + text = "Caf\u00e9 is great. Let\u2019s go." 189 + sentences = detect_sentences(text) 190 + # Byte offsets must account for multi-byte characters 191 + full_bytes = text.encode("utf-8") 192 + assert sentences[-1]["byteEnd"] == len(full_bytes) 193 + ``` 194 + 195 + - [ ] **Step 2: Run test to verify it fails** 196 + 197 + ```bash 198 + cd pipeline && source .venv/bin/activate && pytest tests/test_sentences.py -v 199 + ``` 200 + Expected: FAIL with `ModuleNotFoundError` 201 + 202 + - [ ] **Step 3: Implement `detect_sentences`** 203 + 204 + Create `pipeline/nlp/sentences.py`: 205 + 206 + ```python 207 + """Pass 1: Sentence boundary detection using spaCy.""" 208 + 209 + import spacy 210 + 211 + _nlp = None 212 + 213 + 214 + def _get_nlp(): 215 + global _nlp 216 + if _nlp is None: 217 + _nlp = spacy.load("en_core_web_sm") 218 + return _nlp 219 + 220 + 221 + def detect_sentences(text: str) -> list[dict]: 222 + """Detect sentence boundaries and return byte-range spans. 223 + 224 + Returns a list of dicts, each with: 225 + byteStart: int — UTF-8 byte offset of sentence start 226 + byteEnd: int — UTF-8 byte offset of sentence end (exclusive) 227 + """ 228 + if not text.strip(): 229 + return [] 230 + 231 + nlp = _get_nlp() 232 + doc = nlp(text) 233 + text_bytes = text.encode("utf-8") 234 + sentences = [] 235 + 236 + for sent in doc.sents: 237 + # spaCy gives character offsets; convert to byte offsets 238 + byte_start = len(text[:sent.start_char].encode("utf-8")) 239 + byte_end = len(text[:sent.end_char].encode("utf-8")) 240 + sentences.append({ 241 + "byteStart": byte_start, 242 + "byteEnd": byte_end, 243 + }) 244 + 245 + return sentences 246 + ``` 247 + 248 + - [ ] **Step 4: Run tests to verify they pass** 249 + 250 + ```bash 251 + cd pipeline && source .venv/bin/activate && pytest tests/test_sentences.py -v 252 + ``` 253 + Expected: all PASS 254 + 255 + - [ ] **Step 5: Commit** 256 + 257 + ```bash 258 + git add pipeline/nlp/sentences.py pipeline/tests/test_sentences.py 259 + git commit -m "feat: sentence boundary detection via spaCy" 260 + ``` 261 + 262 + ### Task 5: Implement paragraph segmentation (Pass 2) 263 + 264 + **Files:** 265 + - Create: `pipeline/tests/test_paragraphs.py` 266 + - Create: `pipeline/nlp/paragraphs.py` 267 + 268 + - [ ] **Step 1: Write the failing test** 269 + 270 + Create `pipeline/tests/test_paragraphs.py`: 271 + 272 + ```python 273 + from nlp.paragraphs import detect_paragraphs 274 + 275 + 276 + def test_basic_paragraphs(): 277 + text = "Hello world. This is sentence two. After a long pause here. New topic starts." 278 + sentences = [ 279 + {"byteStart": 0, "byteEnd": 12}, 280 + {"byteStart": 13, "byteEnd": 34}, 281 + {"byteStart": 35, "byteEnd": 59}, 282 + {"byteStart": 60, "byteEnd": 77}, 283 + ] 284 + # Words: "Hello"=0, "world."=1, "This"=2, "is"=3, "sentence"=4, "two."=5, 285 + # "After"=6, "a"=7, "long"=8, "pause"=9, "here."=10, 286 + # "New"=11, "topic"=12, "starts."=13 287 + # Big pause gap (3000ms) between word index 5 and 6 (between sentence 2 and 3) 288 + timings = [100, 100, 100, 100, 100, 100, -3000, 100, 100, 100, 100, 100, 100, 100] 289 + start_ms = 0 290 + 291 + paragraphs = detect_paragraphs( 292 + text=text, 293 + timings=timings, 294 + start_ms=start_ms, 295 + sentences=sentences, 296 + pause_threshold_ms=2000, 297 + proximity_words=5, 298 + ) 299 + # Should detect a paragraph break at the sentence boundary near the 3s pause 300 + assert len(paragraphs) == 2 301 + assert paragraphs[0]["byteStart"] == 0 302 + assert paragraphs[1]["byteStart"] == 35 # "After a long pause..." 303 + 304 + 305 + def test_no_long_pauses_single_paragraph(): 306 + text = "One sentence. Two sentence." 307 + sentences = [ 308 + {"byteStart": 0, "byteEnd": 13}, 309 + {"byteStart": 14, "byteEnd": 27}, 310 + ] 311 + timings = [100, 100, 100, 100] 312 + paragraphs = detect_paragraphs( 313 + text=text, timings=timings, start_ms=0, 314 + sentences=sentences, 315 + ) 316 + assert len(paragraphs) == 1 317 + 318 + 319 + def test_empty_input(): 320 + paragraphs = detect_paragraphs( 321 + text="", timings=[], start_ms=0, sentences=[], 322 + ) 323 + assert paragraphs == [] 324 + ``` 325 + 326 + - [ ] **Step 2: Run test to verify it fails** 327 + 328 + ```bash 329 + cd pipeline && source .venv/bin/activate && pytest tests/test_paragraphs.py -v 330 + ``` 331 + Expected: FAIL with `ModuleNotFoundError` 332 + 333 + - [ ] **Step 3: Implement `detect_paragraphs`** 334 + 335 + Create `pipeline/nlp/paragraphs.py`: 336 + 337 + ```python 338 + """Pass 2: Paragraph segmentation using pause duration + sentence boundaries.""" 339 + 340 + 341 + def detect_paragraphs( 342 + text: str, 343 + timings: list[int], 344 + start_ms: int, 345 + sentences: list[dict], 346 + pause_threshold_ms: int = 2000, 347 + proximity_words: int = 5, 348 + ) -> list[dict]: 349 + """Detect paragraph boundaries from timing gaps and sentence boundaries. 350 + 351 + Returns a list of paragraph dicts with byteStart and byteEnd. 352 + """ 353 + if not text.strip() or not sentences: 354 + return [] 355 + 356 + text_bytes = text.encode("utf-8") 357 + 358 + # Find word indices where long pauses occur 359 + pause_word_indices: list[int] = [] 360 + word_index = 0 361 + for value in timings: 362 + if value < 0: 363 + if abs(value) >= pause_threshold_ms: 364 + pause_word_indices.append(word_index) 365 + else: 366 + word_index += 1 367 + 368 + if not pause_word_indices: 369 + # No long pauses — entire text is one paragraph 370 + return [{"byteStart": sentences[0]["byteStart"], 371 + "byteEnd": sentences[-1]["byteEnd"]}] 372 + 373 + # Build a char→byte offset map once, then compute word byte starts 374 + text_bytes = text.encode("utf-8") 375 + char_to_byte = [] 376 + byte_pos = 0 377 + for ch in text: 378 + char_to_byte.append(byte_pos) 379 + byte_pos += len(ch.encode("utf-8")) 380 + char_to_byte.append(byte_pos) # sentinel for end of text 381 + 382 + # Find word start char offsets using split positions 383 + words = text.split() 384 + word_byte_starts: list[int] = [] 385 + char_offset = 0 386 + for w in words: 387 + idx = text.index(w, char_offset) 388 + word_byte_starts.append(char_to_byte[idx]) 389 + char_offset = idx + len(w) 390 + 391 + def word_index_for_byte(byte_pos: int) -> int: 392 + """Find the word index closest to a byte position.""" 393 + best = 0 394 + for i, wb in enumerate(word_byte_starts): 395 + if wb <= byte_pos: 396 + best = i 397 + return best 398 + 399 + # Find sentence boundaries (byte positions where one sentence ends 400 + # and the next begins) 401 + sentence_break_byte_positions: list[int] = [] 402 + sentence_break_word_indices: list[int] = [] 403 + for i in range(1, len(sentences)): 404 + bp = sentences[i]["byteStart"] 405 + sentence_break_byte_positions.append(bp) 406 + sentence_break_word_indices.append(word_index_for_byte(bp)) 407 + 408 + # For each long pause, find the nearest sentence boundary 409 + paragraph_break_bytes: set[int] = set() 410 + for pause_wi in pause_word_indices: 411 + best_dist = float("inf") 412 + best_bp = None 413 + for sb_wi, sb_bp in zip( 414 + sentence_break_word_indices, sentence_break_byte_positions 415 + ): 416 + dist = abs(sb_wi - pause_wi) 417 + if dist <= proximity_words and dist < best_dist: 418 + best_dist = dist 419 + best_bp = sb_bp 420 + if best_bp is not None: 421 + paragraph_break_bytes.add(best_bp) 422 + 423 + # Build paragraph spans from the break points 424 + sorted_breaks = sorted(paragraph_break_bytes) 425 + paragraphs: list[dict] = [] 426 + current_start = sentences[0]["byteStart"] 427 + 428 + for brk in sorted_breaks: 429 + # Find the sentence that ends just before this break 430 + para_end = brk 431 + for s in sentences: 432 + if s["byteEnd"] <= brk: 433 + para_end = s["byteEnd"] 434 + paragraphs.append({"byteStart": current_start, "byteEnd": para_end}) 435 + current_start = brk 436 + 437 + # Final paragraph 438 + paragraphs.append({ 439 + "byteStart": current_start, 440 + "byteEnd": sentences[-1]["byteEnd"], 441 + }) 442 + 443 + return paragraphs 444 + ``` 445 + 446 + - [ ] **Step 4: Run tests to verify they pass** 447 + 448 + ```bash 449 + cd pipeline && source .venv/bin/activate && pytest tests/test_paragraphs.py -v 450 + ``` 451 + Expected: all PASS 452 + 453 + - [ ] **Step 5: Commit** 454 + 455 + ```bash 456 + git add pipeline/nlp/paragraphs.py pipeline/tests/test_paragraphs.py 457 + git commit -m "feat: paragraph segmentation from pause data + sentence boundaries" 458 + ``` 459 + 460 + ### Task 6: Pipeline orchestrator — process all transcripts 461 + 462 + **Files:** 463 + - Create: `pipeline/nlp/run.py` 464 + - Create: `pipeline/tests/test_run.py` 465 + 466 + - [ ] **Step 1: Write the failing test** 467 + 468 + Create `pipeline/tests/test_run.py`: 469 + 470 + ```python 471 + import json 472 + import os 473 + from pathlib import Path 474 + from nlp.run import process_transcript 475 + 476 + 477 + def test_process_transcript_produces_output(tmp_path): 478 + """Integration test: full pipeline on a simple transcript.""" 479 + transcript = { 480 + "text": "Hello world. This is a test. After a long pause. New topic here.", 481 + "startMs": 0, 482 + "timings": [100, 100, 100, 100, 100, 100, -3000, 100, 100, 100, 100, 100, 100, 100], 483 + } 484 + 485 + result = process_transcript(transcript, talk_rkey="test-talk") 486 + 487 + # Should have sentences and paragraphs 488 + assert "sentences" in result 489 + assert "paragraphs" in result 490 + assert len(result["sentences"]) >= 2 491 + assert len(result["paragraphs"]) >= 1 492 + # Each sentence has byte ranges 493 + for s in result["sentences"]: 494 + assert "byteStart" in s 495 + assert "byteEnd" in s 496 + # Metadata present 497 + assert "metadata" in result 498 + assert result["metadata"]["tool"] == "spacy/en_core_web_sm" 499 + ``` 500 + 501 + - [ ] **Step 2: Run test to verify it fails** 502 + 503 + ```bash 504 + cd pipeline && source .venv/bin/activate && pytest tests/test_run.py -v 505 + ``` 506 + 507 + - [ ] **Step 3: Implement the orchestrator** 508 + 509 + Create `pipeline/nlp/run.py`: 510 + 511 + ```python 512 + """Pipeline orchestrator: run all NLP passes on a transcript.""" 513 + 514 + import json 515 + import sys 516 + from pathlib import Path 517 + from nlp.sentences import detect_sentences 518 + from nlp.paragraphs import detect_paragraphs 519 + 520 + 521 + def process_transcript( 522 + transcript: dict, 523 + talk_rkey: str, 524 + pause_threshold_ms: int = 2000, 525 + proximity_words: int = 5, 526 + ) -> dict: 527 + """Run all NLP passes on a single transcript. 528 + 529 + Args: 530 + transcript: dict with text, startMs, timings 531 + talk_rkey: the talk's record key (for output naming) 532 + 533 + Returns: 534 + dict with sentences, paragraphs, and metadata 535 + """ 536 + text = transcript["text"] 537 + timings = transcript["timings"] 538 + start_ms = transcript["startMs"] 539 + 540 + # Pass 1: Sentence detection 541 + sentences = detect_sentences(text) 542 + 543 + # Pass 2: Paragraph segmentation 544 + paragraphs = detect_paragraphs( 545 + text=text, 546 + timings=timings, 547 + start_ms=start_ms, 548 + sentences=sentences, 549 + pause_threshold_ms=pause_threshold_ms, 550 + proximity_words=proximity_words, 551 + ) 552 + 553 + return { 554 + "talkRkey": talk_rkey, 555 + "sentences": sentences, 556 + "paragraphs": paragraphs, 557 + "metadata": { 558 + "tool": "spacy/en_core_web_sm", 559 + "pauseThresholdMs": pause_threshold_ms, 560 + "proximityWords": proximity_words, 561 + }, 562 + } 563 + 564 + 565 + def main(): 566 + """CLI: read transcripts from appview data/transcripts/, write results to pipeline/data/nlp/.""" 567 + # Match the path used by publish.ts: apps/ionosphere-appview/data/transcripts/ 568 + transcripts_dir = Path(__file__).resolve().parent.parent.parent / "apps" / "ionosphere-appview" / "data" / "transcripts" 569 + output_dir = Path(__file__).resolve().parent.parent / "data" / "nlp" 570 + output_dir.mkdir(parents=True, exist_ok=True) 571 + 572 + if not transcripts_dir.exists(): 573 + print(f"Transcripts directory not found: {transcripts_dir}") 574 + sys.exit(1) 575 + 576 + transcript_files = sorted(transcripts_dir.glob("*.json")) 577 + print(f"Processing {len(transcript_files)} transcripts...") 578 + 579 + for tf in transcript_files: 580 + talk_rkey = tf.stem 581 + transcript = json.loads(tf.read_text()) 582 + 583 + # The cached transcript files contain TranscriptResult format 584 + # (text + words array). We need to encode to compact format first. 585 + # But the pipeline needs text + timings. Let's derive timings from words. 586 + if "words" in transcript and "timings" not in transcript: 587 + from nlp.encoding import words_to_compact 588 + compact = words_to_compact(transcript) 589 + else: 590 + compact = transcript 591 + 592 + result = process_transcript(compact, talk_rkey=talk_rkey) 593 + 594 + out_path = output_dir / f"{talk_rkey}.json" 595 + out_path.write_text(json.dumps(result, indent=2)) 596 + print(f" {talk_rkey}: {len(result['sentences'])} sentences, {len(result['paragraphs'])} paragraphs") 597 + 598 + print("Done.") 599 + 600 + 601 + if __name__ == "__main__": 602 + main() 603 + ``` 604 + 605 + - [ ] **Step 4: Create `pipeline/nlp/encoding.py` — helper to convert word-level transcripts to compact format** 606 + 607 + ```python 608 + """Convert word-level transcript format to compact (text + timings) format.""" 609 + 610 + 611 + def words_to_compact(transcript: dict) -> dict: 612 + """Convert TranscriptResult {text, words[{word, start, end}]} to compact {text, startMs, timings}.""" 613 + words = transcript.get("words", []) 614 + if not words: 615 + return {"text": transcript.get("text", ""), "startMs": 0, "timings": []} 616 + 617 + start_ms = round(words[0]["start"] * 1000) 618 + timings = [] 619 + cursor = start_ms 620 + 621 + for w in words: 622 + word_start_ms = round(w["start"] * 1000) 623 + word_end_ms = round(w["end"] * 1000) 624 + duration = word_end_ms - word_start_ms 625 + 626 + gap = word_start_ms - cursor 627 + if gap > 0: 628 + timings.append(-gap) 629 + 630 + timings.append(max(duration, 1)) 631 + cursor = word_end_ms 632 + 633 + return { 634 + "text": transcript["text"], 635 + "startMs": start_ms, 636 + "timings": timings, 637 + } 638 + ``` 639 + 640 + - [ ] **Step 5: Run tests to verify they pass** 641 + 642 + ```bash 643 + cd pipeline && source .venv/bin/activate && pytest tests/ -v 644 + ``` 645 + Expected: all PASS 646 + 647 + - [ ] **Step 6: Commit** 648 + 649 + ```bash 650 + git add pipeline/nlp/run.py pipeline/nlp/encoding.py pipeline/tests/test_run.py 651 + git commit -m "feat: NLP pipeline orchestrator with CLI entry point" 652 + ``` 653 + 654 + --- 655 + 656 + ## Chunk 3: TypeScript — update `extractData` for hierarchical structure 657 + 658 + ### Task 7: Add `ParagraphSpan` and `SentenceSpan` types and update `extractData` 659 + 660 + **Files:** 661 + - Modify: `apps/ionosphere/src/lib/transcript.ts` 662 + - Modify: `apps/ionosphere/src/lib/transcript.test.ts` 663 + 664 + - [ ] **Step 1: Write failing tests for hierarchical extraction** 665 + 666 + Add to `apps/ionosphere/src/lib/transcript.test.ts`: 667 + 668 + ```typescript 669 + describe("extractData — hierarchical structure", () => { 670 + it("groups words into sentences and paragraphs when facets present", () => { 671 + const doc = makeDoc([ 672 + { text: "Hello", startNs: 1000, endNs: 2000 }, 673 + { text: "world.", startNs: 2000, endNs: 3000 }, 674 + { text: "New", startNs: 4000, endNs: 5000 }, 675 + { text: "sentence.", startNs: 5000, endNs: 6000 }, 676 + ]); 677 + const encoder = new TextEncoder(); 678 + const text = "Hello world. New sentence."; 679 + // Add sentence facets 680 + doc.facets.push({ 681 + index: { 682 + byteStart: 0, 683 + byteEnd: encoder.encode("Hello world.").length, 684 + }, 685 + features: [{ $type: "tv.ionosphere.facet#sentence" }], 686 + }); 687 + doc.facets.push({ 688 + index: { 689 + byteStart: encoder.encode("Hello world. ").length, 690 + byteEnd: encoder.encode(text).length, 691 + }, 692 + features: [{ $type: "tv.ionosphere.facet#sentence" }], 693 + }); 694 + // Add paragraph facet (one paragraph covering everything) 695 + doc.facets.push({ 696 + index: { byteStart: 0, byteEnd: encoder.encode(text).length }, 697 + features: [{ $type: "tv.ionosphere.facet#paragraph" }], 698 + }); 699 + 700 + const result = extractData(doc); 701 + expect(result.paragraphs).toHaveLength(1); 702 + expect(result.paragraphs[0].sentences).toHaveLength(2); 703 + expect(result.paragraphs[0].sentences[0].words).toHaveLength(2); 704 + expect(result.paragraphs[0].sentences[1].words).toHaveLength(2); 705 + }); 706 + 707 + it("gracefully degrades to singleton paragraph/sentence when no structural facets", () => { 708 + const doc = makeDoc([ 709 + { text: "Hello", startNs: 1000, endNs: 2000 }, 710 + { text: "world", startNs: 2000, endNs: 3000 }, 711 + ]); 712 + 713 + const result = extractData(doc); 714 + // Should still have paragraphs/sentences structure 715 + expect(result.paragraphs).toHaveLength(1); 716 + expect(result.paragraphs[0].sentences).toHaveLength(1); 717 + expect(result.paragraphs[0].sentences[0].words).toHaveLength(2); 718 + // Legacy flat access still works 719 + expect(result.words).toHaveLength(2); 720 + }); 721 + }); 722 + ``` 723 + 724 + - [ ] **Step 2: Run tests to verify they fail** 725 + 726 + ```bash 727 + cd apps/ionosphere && npx vitest run src/lib/transcript.test.ts 728 + ``` 729 + Expected: FAIL — `paragraphs` property does not exist 730 + 731 + - [ ] **Step 3: Add types and update `extractData`** 732 + 733 + Add these types to `apps/ionosphere/src/lib/transcript.ts`: 734 + 735 + ```typescript 736 + export interface SentenceSpan { 737 + byteStart: number; 738 + byteEnd: number; 739 + words: WordSpan[]; 740 + } 741 + 742 + export interface ParagraphSpan { 743 + byteStart: number; 744 + byteEnd: number; 745 + sentences: SentenceSpan[]; 746 + } 747 + ``` 748 + 749 + Update `extractData` to return `paragraphs: ParagraphSpan[]` alongside the existing flat `words` array. The function extracts `#sentence` and `#paragraph` facets, groups words into sentences by byte range overlap, groups sentences into paragraphs, and falls back to singleton wrappers when structural facets are absent. 750 + 751 + Key logic: 752 + 1. Extract words and concepts as before (existing code unchanged). 753 + 2. Extract sentence facets (byteStart/byteEnd from `#sentence` features). Sort by byteStart. 754 + 3. Extract paragraph facets (byteStart/byteEnd from `#paragraph` features). Sort by byteStart. 755 + 4. If no sentence facets: wrap all words in one sentence. If no paragraph facets: wrap all sentences in one paragraph. 756 + 5. Assign each word to its sentence (word.byteStart >= sentence.byteStart && word.byteEnd <= sentence.byteEnd). 757 + 6. Assign each sentence to its paragraph (sentence.byteStart >= paragraph.byteStart && sentence.byteEnd <= paragraph.byteEnd). 758 + 759 + - [ ] **Step 4: Run tests to verify they pass** 760 + 761 + ```bash 762 + cd apps/ionosphere && npx vitest run src/lib/transcript.test.ts 763 + ``` 764 + Expected: all PASS (both new and existing tests) 765 + 766 + - [ ] **Step 5: Commit** 767 + 768 + ```bash 769 + git add apps/ionosphere/src/lib/transcript.ts apps/ionosphere/src/lib/transcript.test.ts 770 + git commit -m "feat: hierarchical extractData with paragraph/sentence grouping" 771 + ``` 772 + 773 + --- 774 + 775 + ## Chunk 4: Update the renderer 776 + 777 + ### Task 8: Update `TranscriptView` to render paragraphs and sentences 778 + 779 + **Files:** 780 + - Modify: `apps/ionosphere/src/app/components/TranscriptView.tsx` 781 + 782 + - [ ] **Step 1: Update the render tree** 783 + 784 + Replace the flat `words.map(...)` rendering with a nested structure: 785 + 786 + ```tsx 787 + {paragraphs.map((para, pi) => ( 788 + <div key={pi} className="mb-4"> 789 + {para.sentences.map((sent, si) => ( 790 + <span key={si} className="sentence"> 791 + {sent.words.map((word, wi) => { 792 + const globalIdx = /* compute global word index */; 793 + return ( 794 + <WordSpanComponent 795 + key={globalIdx} 796 + ref={(el) => setWordRef(globalIdx, el)} 797 + word={word} 798 + concept={wordConcepts[globalIdx]?.[0] || null} 799 + currentTimeNs={currentTimeNs} 800 + onSeek={handleSeek} 801 + hasComment={wordHasComment.has(globalIdx)} 802 + /> 803 + ); 804 + })} 805 + </span> 806 + ))} 807 + </div> 808 + ))} 809 + ``` 810 + 811 + The `useMemo` call to `extractData` now destructures `paragraphs` alongside `words` and `wordConcepts`. The global word index is computed by maintaining a running counter across paragraphs and sentences. 812 + 813 + The comment system, reaction groups, text selection, and scroll/time mappings continue to use the flat `words` array (unchanged). Only the DOM structure changes to add the paragraph/sentence grouping. 814 + 815 + - [ ] **Step 2: Verify in browser** 816 + 817 + Start the dev server and load a talk page. Verify: 818 + - Transcripts without structural facets render identically to before (graceful degradation) 819 + - No console errors 820 + - Scroll-to-time and click-to-seek still work 821 + - Comments and reactions still work 822 + 823 + - [ ] **Step 3: Commit** 824 + 825 + ```bash 826 + git add apps/ionosphere/src/app/components/TranscriptView.tsx 827 + git commit -m "feat: render transcripts with paragraph/sentence DOM structure" 828 + ``` 829 + 830 + ### Task 9: Update `WindowedTranscriptView` for paragraph gaps 831 + 832 + **Files:** 833 + - Modify: `apps/ionosphere/src/app/components/WindowedTranscriptView.tsx` 834 + 835 + - [ ] **Step 1: Update `computeMonospaceLayout` to accept paragraph breaks** 836 + 837 + Add a `paragraphStartIndices: Set<number>` parameter. When a word is a paragraph start (its global index is in the set), insert a gap of `LINE_HEIGHT` pixels before that line entry. Add `isParagraphStart: boolean` to `LineEntry`. 838 + 839 + - [ ] **Step 2: Update the rendering to add paragraph gap spacers** 840 + 841 + For each visible line with `isParagraphStart: true`, render a gap spacer `div` above it. 842 + 843 + - [ ] **Step 3: Update `timeToScrollY` and `scrollYToTime`** 844 + 845 + Gap entries have no time range. Scrolling through a gap seeks to the end of the preceding line's time range (treating the gap as an extension of the previous paragraph's final time). 846 + 847 + - [ ] **Step 4: Verify in browser** 848 + 849 + Load the track view (which uses `WindowedTranscriptView`). Verify paragraph gaps appear and scroll behavior is smooth. 850 + 851 + - [ ] **Step 5: Commit** 852 + 853 + ```bash 854 + git add apps/ionosphere/src/app/components/WindowedTranscriptView.tsx 855 + git commit -m "feat: WindowedTranscriptView paragraph gap support" 856 + ``` 857 + 858 + --- 859 + 860 + ## Chunk 5: Document assembly and publish pipeline 861 + 862 + ### Task 10: Update document assembly to include structural facets 863 + 864 + **Files:** 865 + - Modify: `formats/tv.ionosphere/ts/transcript-encoding.ts` 866 + - Modify: `formats/tv.ionosphere/ts/transcript-encoding.test.ts` 867 + 868 + - [ ] **Step 1: Write the failing test** 869 + 870 + Add to `formats/tv.ionosphere/ts/transcript-encoding.test.ts`: 871 + 872 + ```typescript 873 + describe("decodeToDocumentWithStructure", () => { 874 + it("adds sentence and paragraph facets from NLP annotations", () => { 875 + const compact = encode(contiguous); 876 + const annotations = { 877 + sentences: [ 878 + { byteStart: 0, byteEnd: 11 }, // "hello world" 879 + { byteStart: 12, byteEnd: 26 }, // "this is a test" 880 + ], 881 + paragraphs: [ 882 + { byteStart: 0, byteEnd: 26 }, 883 + ], 884 + }; 885 + const doc = decodeToDocumentWithStructure(compact, annotations); 886 + 887 + const sentenceFacets = doc.facets.filter(f => 888 + f.features.some(feat => feat.$type === "tv.ionosphere.facet#sentence") 889 + ); 890 + const paragraphFacets = doc.facets.filter(f => 891 + f.features.some(feat => feat.$type === "tv.ionosphere.facet#paragraph") 892 + ); 893 + expect(sentenceFacets).toHaveLength(2); 894 + expect(paragraphFacets).toHaveLength(1); 895 + }); 896 + 897 + it("produces valid document without annotations (backward compatible)", () => { 898 + const compact = encode(contiguous); 899 + const doc = decodeToDocumentWithStructure(compact, null); 900 + // Same as decodeToDocument 901 + expect(doc.facets.length).toBe(6); // just timestamp facets 902 + }); 903 + }); 904 + ``` 905 + 906 + - [ ] **Step 2: Run test to verify it fails** 907 + 908 + ```bash 909 + cd formats/tv.ionosphere && npx vitest run ts/transcript-encoding.test.ts 910 + ``` 911 + 912 + - [ ] **Step 3: Implement `decodeToDocumentWithStructure`** 913 + 914 + Add to `formats/tv.ionosphere/ts/transcript-encoding.ts`: 915 + 916 + ```typescript 917 + export interface NlpAnnotations { 918 + sentences: Array<{ byteStart: number; byteEnd: number }>; 919 + paragraphs: Array<{ byteStart: number; byteEnd: number }>; 920 + } 921 + 922 + export function decodeToDocumentWithStructure( 923 + compact: CompactTranscript, 924 + annotations: NlpAnnotations | null, 925 + ): Document { 926 + // Start with the base document (timestamp facets) 927 + const doc = decodeToDocument(compact); 928 + 929 + if (!annotations) return doc; 930 + 931 + // Add sentence facets 932 + for (const s of annotations.sentences) { 933 + doc.facets.push({ 934 + index: { byteStart: s.byteStart, byteEnd: s.byteEnd }, 935 + features: [{ $type: "tv.ionosphere.facet#sentence" }], 936 + }); 937 + } 938 + 939 + // Add paragraph facets 940 + for (const p of annotations.paragraphs) { 941 + doc.facets.push({ 942 + index: { byteStart: p.byteStart, byteEnd: p.byteEnd }, 943 + features: [{ $type: "tv.ionosphere.facet#paragraph" }], 944 + }); 945 + } 946 + 947 + return doc; 948 + } 949 + ``` 950 + 951 + - [ ] **Step 4: Run tests to verify they pass** 952 + 953 + ```bash 954 + cd formats/tv.ionosphere && npx vitest run ts/transcript-encoding.test.ts 955 + ``` 956 + 957 + - [ ] **Step 5: Commit** 958 + 959 + ```bash 960 + git add formats/tv.ionosphere/ts/transcript-encoding.ts formats/tv.ionosphere/ts/transcript-encoding.test.ts 961 + git commit -m "feat: decodeToDocumentWithStructure for NLP annotations" 962 + ``` 963 + 964 + ### Task 11: Update publish.ts to include assembled documents on talk records 965 + 966 + **Files:** 967 + - Modify: `apps/ionosphere-appview/src/publish.ts` 968 + 969 + - [ ] **Step 1: Update the talk publishing step** 970 + 971 + After publishing transcripts (step 4 in publish.ts), add a step that: 972 + 1. For each talk, checks if NLP output exists at `pipeline/data/nlp/{rkey}.json` 973 + 2. If it does, reads the NLP annotations 974 + 3. Calls `decodeToDocumentWithStructure` with the compact transcript + annotations 975 + 4. Includes the assembled `document` field on the `tv.ionosphere.talk` record 976 + 977 + This moves document assembly from serve time to publish time, as specified in the design. 978 + 979 + - [ ] **Step 2: Verify by running publish in dry-run or against local PDS** 980 + 981 + Check that talk records now include the `document` field with sentence/paragraph facets. 982 + 983 + - [ ] **Step 3: Commit** 984 + 985 + ```bash 986 + git add apps/ionosphere-appview/src/publish.ts 987 + git commit -m "feat: publish assembled documents with structural facets on talk records" 988 + ``` 989 + 990 + ### Task 12: Update appview routes to serve pre-assembled documents 991 + 992 + **Files:** 993 + - Modify: `apps/ionosphere-appview/src/routes.ts` 994 + 995 + - [ ] **Step 1: Remove `overlayAnnotations` and serve pre-assembled document** 996 + 997 + In the `getTalk` route handler: 998 + 1. Remove the `overlayAnnotations` function entirely (lines 17-59). 999 + 2. Remove the annotation overlay logic in the route (lines 173-185). 1000 + 3. If the talk record has a `document` field in the DB, serve it directly. 1001 + 4. Fall back to `decodeToDocument` from the compact transcript if no pre-assembled document exists (backward compatibility during transition). 1002 + 1003 + - [ ] **Step 2: Update the indexer to store the document field** 1004 + 1005 + In `apps/ionosphere-appview/src/indexer.ts`, update the `indexTalk` function's INSERT statement (line 176-197). The `talks` table already has a `document TEXT` column (line 54 of db.ts), but the INSERT does not include it. Add `document` to the column list and bind `record.document ? JSON.stringify(record.document) : null` as the value. This is a SQL change — the column list and VALUES placeholders must both be updated. 1006 + 1007 + - [ ] **Step 3: Commit** 1008 + 1009 + ```bash 1010 + git add apps/ionosphere-appview/src/routes.ts apps/ionosphere-appview/src/indexer.ts 1011 + git commit -m "feat: serve pre-assembled documents, remove overlayAnnotations" 1012 + ``` 1013 + 1014 + --- 1015 + 1016 + ## Chunk 6: Remove old enrichment system 1017 + 1018 + ### Task 13: Remove old annotation/enrichment code 1019 + 1020 + **Files:** 1021 + - Delete: `apps/ionosphere-appview/src/enrich.ts` 1022 + - Delete: `apps/ionosphere-appview/src/enrich-all.ts` 1023 + - Delete: `apps/ionosphere-appview/src/publish-annotations.ts` 1024 + - Modify: `apps/ionosphere-appview/src/indexer.ts` — remove `tv.ionosphere.annotation` handling 1025 + - Modify: `apps/ionosphere-appview/src/routes.ts` — remove annotation-related queries from `getTalk` 1026 + 1027 + - [ ] **Step 1: Delete enrichment files** 1028 + 1029 + ```bash 1030 + rm apps/ionosphere-appview/src/enrich.ts 1031 + rm apps/ionosphere-appview/src/enrich-all.ts 1032 + rm apps/ionosphere-appview/src/publish-annotations.ts 1033 + ``` 1034 + 1035 + - [ ] **Step 2: Remove annotation indexing from `indexer.ts`** 1036 + 1037 + Remove `"tv.ionosphere.annotation"` from `IONOSPHERE_COLLECTIONS` array (line 28). Remove the annotation delete case (lines 72-75). Remove the annotation create/update case (lines 116-117). Remove the `indexAnnotation` function and `rebuildTalkConcepts` helper. 1038 + 1039 + - [ ] **Step 3: Remove annotation queries from `routes.ts`** 1040 + 1041 + In the `getTalk` route, remove the concepts query (lines 149-157) and the annotation overlay logic. The concepts data will return via layers.pub in Phase 2. 1042 + 1043 + - [ ] **Step 4: Remove annotation publishing from `publish.ts`** 1044 + 1045 + Remove step 6 (lines 158-177) that publishes `tv.ionosphere.annotation` records. 1046 + 1047 + - [ ] **Step 5: Verify the appview still starts and serves talks** 1048 + 1049 + ```bash 1050 + cd apps/ionosphere-appview && npx tsx src/appview.ts 1051 + ``` 1052 + Hit the `/xrpc/tv.ionosphere.getTalk?rkey=<some-rkey>` endpoint and verify it returns a talk with a document. 1053 + 1054 + - [ ] **Step 6: Commit** 1055 + 1056 + ```bash 1057 + git add -A apps/ionosphere-appview/src/ 1058 + git commit -m "chore: remove old enrichment system (enrich.ts, annotations, overlayAnnotations)" 1059 + ``` 1060 + 1061 + --- 1062 + 1063 + ## Chunk 7: End-to-end integration and verification 1064 + 1065 + **IMPORTANT:** Tasks 11-12 create the publish-time document assembly path, but existing talks in the appview DB will have NULL documents until a full re-publish is done. Task 14 performs this re-publish. Do NOT deploy Tasks 11-12 without running Task 14, or existing talks will lose concept overlays with no replacement. 1066 + 1067 + ### Task 14: Run the full pipeline end-to-end 1068 + 1069 + - [ ] **Step 1: Run the Python NLP pipeline on all transcripts** 1070 + 1071 + ```bash 1072 + cd pipeline && source .venv/bin/activate && python -m nlp.run 1073 + ``` 1074 + 1075 + Verify output files appear in `pipeline/data/nlp/` with sentence and paragraph data. 1076 + 1077 + - [ ] **Step 2: Spot-check 3-5 NLP output files** 1078 + 1079 + Open output JSON files for talks of different types (presentation, panel, lightning talk). Verify: 1080 + - Sentence count is reasonable (expect 50-300 for a 20-min talk) 1081 + - Paragraph count is reasonable (expect 5-30) 1082 + - Byte ranges are valid (byteStart < byteEnd, monotonically increasing) 1083 + - Paragraph boundaries fall at sentence boundaries 1084 + 1085 + - [ ] **Step 3: Run the TypeScript publish pipeline** 1086 + 1087 + ```bash 1088 + cd apps/ionosphere-appview && npx tsx src/publish.ts 1089 + ``` 1090 + 1091 + Verify talk records now include the `document` field with structural facets. 1092 + 1093 + - [ ] **Step 4: Start the appview and frontend, verify in browser** 1094 + 1095 + Start the dev environment and load several talk pages. Verify: 1096 + - Paragraphs have visible vertical spacing 1097 + - Sentences are grouped as inline spans 1098 + - Scroll-to-time and click-to-seek work correctly 1099 + - The playhead brightness gradient is smooth across paragraph breaks 1100 + - Comments and reactions still work 1101 + - Talks without NLP data still render correctly (graceful degradation) 1102 + 1103 + - [ ] **Step 5: Commit any fixes found during verification** 1104 + 1105 + ```bash 1106 + git add -A && git commit -m "fix: integration fixes from end-to-end verification" 1107 + ``` 1108 + 1109 + ### Task 15: Final cleanup 1110 + 1111 + - [ ] **Step 1: Run all tests** 1112 + 1113 + ```bash 1114 + # Python 1115 + cd pipeline && source .venv/bin/activate && pytest -v 1116 + 1117 + # TypeScript 1118 + cd ../.. && npx vitest run 1119 + ``` 1120 + 1121 + All tests should pass. 1122 + 1123 + - [ ] **Step 2: Update `.gitignore` for Python artifacts** 1124 + 1125 + Add to `.gitignore`: 1126 + ``` 1127 + pipeline/.venv/ 1128 + pipeline/data/ 1129 + __pycache__/ 1130 + *.pyc 1131 + ``` 1132 + 1133 + - [ ] **Step 3: Final commit** 1134 + 1135 + ```bash 1136 + git add -A 1137 + git commit -m "chore: final cleanup — tests passing, gitignore updated" 1138 + ```
+751
docs/superpowers/plans/2026-04-13-layers-pub-publishing.md
··· 1 + # layers.pub Record Publishing via Panproto Lenses — Implementation Plan 2 + 3 + > **For agentic workers:** REQUIRED: Use superpowers:subagent-driven-development (if subagents available) or superpowers:executing-plans to implement this plan. Steps use checkbox (`- [ ]`) syntax for tracking. 4 + 5 + **Goal:** Publish NLP enrichment data as layers.pub AT Protocol records, with panproto lenses as the authoritative transform pipeline, and index those records back into the appview's materialized document view. 6 + 7 + **Architecture:** Data flows through panproto lenses: compact transcript → expression + segmentation (Lens 1), NLP annotations → annotation layers (Lens 2). The appview indexes layers.pub records and rebuilds the materialized talk document using a reverse lens (Lens 3). No parallel TypeScript transform pipelines — lenses are the single source of truth. 8 + 9 + **Tech Stack:** @panproto/core v0.25.1 (WASM), AT Protocol lexicons, better-sqlite3, Hono, vitest 10 + 11 + **Spec:** `docs/superpowers/specs/2026-04-13-layers-pub-publishing-design.md` 12 + 13 + --- 14 + 15 + ## File Structure 16 + 17 + ### New files 18 + - `formats/tv.ionosphere/nlpAnnotations.lexicon.json` — NLP annotations schema (lens source, not published to PDS) 19 + - `formats/tv.ionosphere/lenses/transcript-to-expression.lens.json` — Lens 1 spec 20 + - `formats/tv.ionosphere/lenses/nlp-to-annotation-layers.lens.json` — Lens 2 spec 21 + - `formats/tv.ionosphere/lenses/layers-to-document.lens.json` — Lens 3 spec 22 + - `formats/tv.ionosphere/ts/layers-pub.ts` — layers.pub record builders (runs data through panproto lenses) 23 + - `apps/ionosphere-appview/src/layers-indexer.ts` — indexer for layers.pub records + document rebuild 24 + - `apps/ionosphere-appview/src/__tests__/layers-pub.test.ts` — round-trip test: publish → index → verify 25 + 26 + ### Modified files 27 + - `apps/ionosphere-appview/src/publish.ts` — add Stage 6 (layers.pub publishing) 28 + - `apps/ionosphere-appview/src/db.ts` — add 3 new tables (layers_expressions, layers_segmentations, layers_annotations) 29 + - `apps/ionosphere-appview/src/indexer.ts` — add layers.pub collections to IONOSPHERE_COLLECTIONS + wire to layers-indexer 30 + 31 + --- 32 + 33 + ## Chunk 1: NLP Annotations Lexicon + Lens 1 (Transcript → Expression + Segmentation) 34 + 35 + ### Task 1: Define the NLP annotations lexicon 36 + 37 + This lexicon formalizes the JSON shape produced by the NLP pipeline so panproto can use it as a lens source schema. It is never published to PDS. 38 + 39 + **Files:** 40 + - Create: `formats/tv.ionosphere/nlpAnnotations.lexicon.json` 41 + 42 + - [ ] **Step 1: Write the lexicon** 43 + 44 + The NLP JSON has this shape (from `pipeline/data/nlp/*.json`): 45 + ```json 46 + { 47 + "talkRkey": "string", 48 + "sentences": [{ "byteStart": 0, "byteEnd": 214 }], 49 + "paragraphs": [{ "byteStart": 0, "byteEnd": 1729 }], 50 + "entities": [{ "byteStart": 15, "byteEnd": 19, "label": "Matt", "nerType": "PERSON", "conceptUri": "at://..." }], 51 + "topicBreaks": [{ "byteStart": 1596 }], 52 + "metadata": { "tool": "spacy/en_core_web_sm", "pauseThresholdMs": 2000, "proximityWords": 5 } 53 + } 54 + ``` 55 + 56 + Write `formats/tv.ionosphere/nlpAnnotations.lexicon.json` as an ATProto lexicon that models this exactly. Key types: 57 + - `nlpSentence`: `{ byteStart: integer, byteEnd: integer }` 58 + - `nlpParagraph`: `{ byteStart: integer, byteEnd: integer }` 59 + - `nlpEntity`: `{ byteStart: integer, byteEnd: integer, label: string, nerType: string, conceptUri?: string (format: at-uri) }` 60 + - `nlpTopicBreak`: `{ byteStart: integer }` 61 + - `nlpMetadata`: `{ tool: string, pauseThresholdMs?: integer, proximityWords?: integer }` 62 + - Main record: `{ talkRkey: string, sentences: nlpSentence[], paragraphs: nlpParagraph[], entities: nlpEntity[], topicBreaks: nlpTopicBreak[], metadata: nlpMetadata }` 63 + 64 + - [ ] **Step 2: Validate the lexicon parses with panproto** 65 + 66 + ```bash 67 + cd apps/ionosphere-appview 68 + npx tsx -e " 69 + import { loadSchema } from '../../formats/tv.ionosphere/ts/panproto.js'; 70 + import nlp from '../../formats/tv.ionosphere/nlpAnnotations.lexicon.json' assert { type: 'json' }; 71 + const schema = await loadSchema(nlp); 72 + console.log('NLP annotations schema loaded:', !!schema); 73 + " 74 + ``` 75 + 76 + Expected: `NLP annotations schema loaded: true` 77 + 78 + - [ ] **Step 3: Commit** 79 + 80 + ```bash 81 + git add formats/tv.ionosphere/nlpAnnotations.lexicon.json 82 + git commit -m "feat: define tv.ionosphere.nlpAnnotations lexicon for lens source schema" 83 + ``` 84 + 85 + ### Task 2: Define Lens 1 — compact transcript → expression + segmentation 86 + 87 + This lens transforms `tv.ionosphere.transcript` records into `pub.layers.expression.expression` + `pub.layers.segmentation.segmentation` records. It is the authoritative transform for the text and temporal mapping. 88 + 89 + **Files:** 90 + - Create: `formats/tv.ionosphere/lenses/transcript-to-expression.lens.json` 91 + - Create: `formats/tv.ionosphere/ts/layers-pub.ts` 92 + - Create: `apps/ionosphere-appview/src/__tests__/layers-pub.test.ts` 93 + 94 + - [ ] **Step 1: Write the failing test** 95 + 96 + Create `apps/ionosphere-appview/src/__tests__/layers-pub.test.ts`: 97 + 98 + ```typescript 99 + import { describe, it, expect } from 'vitest'; 100 + import { transcriptToLayersPub } from '../../../formats/tv.ionosphere/ts/layers-pub.js'; 101 + 102 + describe('Lens 1: transcript → expression + segmentation', () => { 103 + const transcript = { 104 + $type: 'tv.ionosphere.transcript', 105 + talkUri: 'at://did:plc:test/tv.ionosphere.talk/test-talk', 106 + text: 'Hello world foo bar', 107 + startMs: 1000, 108 + // word durations: Hello=200ms, world=300ms, 100ms gap, foo=150ms, bar=250ms 109 + timings: [200, 300, -100, 150, 250], 110 + }; 111 + 112 + const did = 'did:plc:test'; 113 + const talkRkey = 'test-talk'; 114 + 115 + it('produces an expression record with correct fields', async () => { 116 + const { expression } = await transcriptToLayersPub(transcript, did, talkRkey); 117 + expect(expression.$type).toBe('pub.layers.expression.expression'); 118 + expect(expression.id).toBe('test-talk'); 119 + expect(expression.kind).toBe('transcript'); 120 + expect(expression.text).toBe('Hello world foo bar'); 121 + expect(expression.language).toBe('en'); 122 + expect(expression.sourceRef).toBe('at://did:plc:test/tv.ionosphere.transcript/test-talk-transcript'); 123 + expect(expression.metadata.tool).toBe('ionosphere-pipeline'); 124 + expect(expression.metadata.timestamp).toBeDefined(); 125 + expect(expression.createdAt).toBeDefined(); 126 + }); 127 + 128 + it('produces a segmentation record with word tokens', async () => { 129 + const { segmentation } = await transcriptToLayersPub(transcript, did, talkRkey); 130 + expect(segmentation.$type).toBe('pub.layers.segmentation.segmentation'); 131 + expect(segmentation.expression).toBe( 132 + 'at://did:plc:test/pub.layers.expression.expression/test-talk-expression' 133 + ); 134 + expect(segmentation.tokenizations).toHaveLength(1); 135 + 136 + const tok = segmentation.tokenizations[0]; 137 + expect(tok.kind).toBe('word'); 138 + expect(tok.tokens).toHaveLength(4); 139 + 140 + // Check first token 141 + expect(tok.tokens[0].tokenIndex).toBe(0); 142 + expect(tok.tokens[0].text).toBe('Hello'); 143 + expect(tok.tokens[0].textSpan.byteStart).toBe(0); 144 + expect(tok.tokens[0].textSpan.byteEnd).toBe(5); 145 + expect(tok.tokens[0].temporalSpan.start).toBe(1000); 146 + expect(tok.tokens[0].temporalSpan.ending).toBe(1200); 147 + 148 + // Check third token (after gap) 149 + expect(tok.tokens[2].text).toBe('foo'); 150 + expect(tok.tokens[2].temporalSpan.start).toBe(1600); // 1000+200+300+100gap 151 + expect(tok.tokens[2].temporalSpan.ending).toBe(1750); 152 + }); 153 + }); 154 + ``` 155 + 156 + - [ ] **Step 2: Run the test to verify it fails** 157 + 158 + ```bash 159 + cd apps/ionosphere-appview 160 + npx vitest run src/__tests__/layers-pub.test.ts 161 + ``` 162 + 163 + Expected: FAIL — `transcriptToLayersPub` does not exist yet. 164 + 165 + - [ ] **Step 3: Write the layers-pub module with Lens 1** 166 + 167 + Create `formats/tv.ionosphere/ts/layers-pub.ts`. This module initializes panproto, loads the transcript and layers.pub schemas, builds the lens, and exposes `transcriptToLayersPub()`. 168 + 169 + The function must: 170 + 1. Initialize panproto WASM (via existing `init()` from panproto.ts) 171 + 2. Load `tv.ionosphere.transcript` schema and `pub.layers.expression.expression` + `pub.layers.segmentation.segmentation` schemas 172 + 3. Use `autoGenerateWithHints()` to create a protolens chain with hints mapping transcript fields to layers.pub fields 173 + 4. Run the transcript record through the lens 174 + 5. Post-process: inject `$type`, `sourceRef`, `expression` URI (pre-computed from DID + rkey), `createdAt` 175 + 6. Return `{ expression, segmentation }` 176 + 177 + The timings replay algorithm is the same as `decodeToDocument()` in `transcript-encoding.ts`: 178 + - Split text by whitespace to get words 179 + - Use TextEncoder for UTF-8 byte offsets 180 + - Iterate timings: negative = silence gap (advance cursor), positive = word duration 181 + - Each word becomes a token with `textSpan: { byteStart, byteEnd }` and `temporalSpan: { start, ending }` in ms 182 + 183 + If panproto's auto-generated lens cannot handle the timings array → token list transform natively (likely — this is algorithmic, not structural), implement the timings replay in TypeScript and feed the pre-built token array into the lens as a morphism hint's computed field. The lens still owns the structural mapping; the timings replay is a computed input. 184 + 185 + - [ ] **Step 4: Run the test to verify it passes** 186 + 187 + ```bash 188 + cd apps/ionosphere-appview 189 + npx vitest run src/__tests__/layers-pub.test.ts 190 + ``` 191 + 192 + Expected: PASS 193 + 194 + - [ ] **Step 5: Commit** 195 + 196 + ```bash 197 + git add formats/tv.ionosphere/ts/layers-pub.ts formats/tv.ionosphere/lenses/transcript-to-expression.lens.json apps/ionosphere-appview/src/__tests__/layers-pub.test.ts 198 + git commit -m "feat: Lens 1 — compact transcript to layers.pub expression + segmentation" 199 + ``` 200 + 201 + --- 202 + 203 + ## Chunk 2: Lens 2 (NLP Annotations → Annotation Layers) 204 + 205 + ### Task 3: Define Lens 2 — NLP annotations → 4 annotation layers 206 + 207 + This lens transforms the NLP pipeline JSON into 4 `pub.layers.annotation.annotationLayer` records (sentences, paragraphs, entities, topics). 208 + 209 + **Files:** 210 + - Create: `formats/tv.ionosphere/lenses/nlp-to-annotation-layers.lens.json` 211 + - Modify: `formats/tv.ionosphere/ts/layers-pub.ts` — add `nlpToAnnotationLayers()` 212 + - Modify: `apps/ionosphere-appview/src/__tests__/layers-pub.test.ts` — add Lens 2 tests 213 + 214 + - [ ] **Step 1: Write the failing tests** 215 + 216 + Add to `apps/ionosphere-appview/src/__tests__/layers-pub.test.ts`: 217 + 218 + ```typescript 219 + import { nlpToAnnotationLayers } from '../../../formats/tv.ionosphere/ts/layers-pub.js'; 220 + 221 + describe('Lens 2: NLP annotations → annotation layers', () => { 222 + const nlpAnnotations = { 223 + talkRkey: 'test-talk', 224 + sentences: [ 225 + { byteStart: 0, byteEnd: 11 }, 226 + { byteStart: 12, byteEnd: 19 }, 227 + ], 228 + paragraphs: [ 229 + { byteStart: 0, byteEnd: 19 }, 230 + ], 231 + entities: [ 232 + { byteStart: 0, byteEnd: 5, label: 'Hello', nerType: 'MISC' }, 233 + { byteStart: 12, byteEnd: 15, label: 'foo', nerType: 'ORG', conceptUri: 'at://did:plc:test/tv.ionosphere.concept/foo' }, 234 + ], 235 + topicBreaks: [ 236 + { byteStart: 12 }, 237 + ], 238 + metadata: { tool: 'spacy/en_core_web_sm' }, 239 + }; 240 + 241 + const did = 'did:plc:test'; 242 + const talkRkey = 'test-talk'; 243 + const expressionUri = 'at://did:plc:test/pub.layers.expression.expression/test-talk-expression'; 244 + 245 + it('produces 4 annotation layer records', async () => { 246 + const layers = await nlpToAnnotationLayers(nlpAnnotations, did, talkRkey, expressionUri); 247 + expect(Object.keys(layers)).toEqual(['sentences', 'paragraphs', 'entities', 'topics']); 248 + }); 249 + 250 + it('sentences layer has correct structure', async () => { 251 + const { sentences } = await nlpToAnnotationLayers(nlpAnnotations, did, talkRkey, expressionUri); 252 + expect(sentences.$type).toBe('pub.layers.annotation.annotationLayer'); 253 + expect(sentences.expression).toBe(expressionUri); 254 + expect(sentences.kind).toBe('span'); 255 + expect(sentences.subkind).toBe('sentence-boundary'); 256 + expect(sentences.sourceMethod).toBe('automatic'); 257 + expect(sentences.metadata.tool).toBe('ionosphere-nlp-pipeline'); 258 + expect(sentences.annotations).toHaveLength(2); 259 + expect(sentences.annotations[0].anchor.textSpan).toEqual({ byteStart: 0, byteEnd: 11 }); 260 + }); 261 + 262 + it('entities layer wraps features in featureMap', async () => { 263 + const { entities } = await nlpToAnnotationLayers(nlpAnnotations, did, talkRkey, expressionUri); 264 + expect(entities.annotations).toHaveLength(2); 265 + 266 + // Plain entity — nerType is always present 267 + const plain = entities.annotations[0]; 268 + expect(plain.label).toBe('Hello'); 269 + expect(plain.features.entries).toContainEqual({ key: 'nerType', value: 'MISC' }); 270 + 271 + // Entity with conceptUri — all known keys forwarded to features 272 + const withConcept = entities.annotations[1]; 273 + expect(withConcept.features.entries).toContainEqual({ 274 + key: 'conceptUri', 275 + value: 'at://did:plc:test/tv.ionosphere.concept/foo', 276 + }); 277 + expect(withConcept.features.entries).toContainEqual({ key: 'nerType', value: 'ORG' }); 278 + }); 279 + 280 + it('topics layer has correct subkind and uses zero-width spans', async () => { 281 + const { topics } = await nlpToAnnotationLayers(nlpAnnotations, did, talkRkey, expressionUri); 282 + expect(topics.subkind).toBe('topic-segment'); 283 + expect(topics.annotations).toHaveLength(1); 284 + expect(topics.annotations[0].anchor.textSpan).toEqual({ byteStart: 12, byteEnd: 12 }); 285 + }); 286 + }); 287 + ``` 288 + 289 + - [ ] **Step 2: Run tests to verify they fail** 290 + 291 + ```bash 292 + cd apps/ionosphere-appview 293 + npx vitest run src/__tests__/layers-pub.test.ts 294 + ``` 295 + 296 + Expected: FAIL — `nlpToAnnotationLayers` does not exist. 297 + 298 + - [ ] **Step 3: Implement nlpToAnnotationLayers in layers-pub.ts** 299 + 300 + Add `nlpToAnnotationLayers()` to `formats/tv.ionosphere/ts/layers-pub.ts`. 301 + 302 + The function: 303 + 1. Loads the NLP annotations schema and annotation layer schema via panproto 304 + 2. Builds protolens with hints for each annotation type 305 + 3. For each of the 4 annotation types, maps the NLP data to a `pub.layers.annotation.annotationLayer` record: 306 + 307 + **Sentences layer** (`{talkRkey}-sentences`): 308 + - Each sentence `{ byteStart, byteEnd }` → annotation with `anchor: { textSpan: { byteStart, byteEnd } }`, `label`: truncated text (or "sentence") 309 + 310 + **Paragraphs layer** (`{talkRkey}-paragraphs`): 311 + - Each paragraph → annotation with `anchor: { textSpan }`, `label: "paragraph"` 312 + 313 + **Entities layer** (`{talkRkey}-entities`): 314 + - Each entity → annotation with `anchor: { textSpan }`, `label: entity.label` 315 + - `features: { entries: [] }` — forward all entity keys beyond byteStart/byteEnd/label into entries: `nerType` always, `conceptUri` if present, and any future keys (e.g., `speakerDid`) passthrough automatically 316 + 317 + **Topics layer** (`{talkRkey}-topics`): 318 + - Each topicBreak → annotation with `anchor: { textSpan: { byteStart, byteEnd: byteStart } }` (zero-width), `label: "topic-break"` 319 + 320 + All layers get: `$type`, `expression` URI, `kind: "span"`, `sourceMethod: "automatic"`, `metadata: { tool, timestamp }`, `createdAt`. 321 + 322 + Similar to Lens 1: if the structural fan-out (one source → four targets) is beyond what panproto's protolens can express natively, implement the fan-out in TypeScript and use the lens for each individual layer's structural mapping. The lens remains authoritative for the shape of each annotation layer record. 323 + 324 + - [ ] **Step 4: Run tests to verify they pass** 325 + 326 + ```bash 327 + cd apps/ionosphere-appview 328 + npx vitest run src/__tests__/layers-pub.test.ts 329 + ``` 330 + 331 + Expected: All PASS 332 + 333 + - [ ] **Step 5: Commit** 334 + 335 + ```bash 336 + git add formats/tv.ionosphere/ts/layers-pub.ts formats/tv.ionosphere/lenses/nlp-to-annotation-layers.lens.json apps/ionosphere-appview/src/__tests__/layers-pub.test.ts 337 + git commit -m "feat: Lens 2 — NLP annotations to 4 annotation layer records" 338 + ``` 339 + 340 + --- 341 + 342 + ## Chunk 3: Publish Pipeline Stage 6 343 + 344 + ### Task 4: Add layers.pub publishing to publish.ts 345 + 346 + Wire the lens functions into the existing publish pipeline as a new Stage 6. 347 + 348 + **Files:** 349 + - Modify: `apps/ionosphere-appview/src/publish.ts` — add Stage 6 350 + - Modify: `apps/ionosphere-appview/src/__tests__/layers-pub.test.ts` — add integration test 351 + 352 + - [ ] **Step 1: Write the failing integration test** 353 + 354 + Add to `apps/ionosphere-appview/src/__tests__/layers-pub.test.ts`: 355 + 356 + ```typescript 357 + describe('Stage 6: layers.pub publish pipeline', () => { 358 + it('produces 6 records for a talk with transcript + NLP data', async () => { 359 + // Use real fixture data from pipeline/data/ 360 + // Read a compact transcript and NLP annotations for the same talk 361 + // Run both lenses, verify 6 records produced with correct rkeys and $type values 362 + }); 363 + }); 364 + ``` 365 + 366 + The test should use fixture data from `pipeline/data/nlp/ats26-keynote.json` and a corresponding transcript to verify end-to-end record production. It does NOT publish to a PDS — it verifies the lens output shape. 367 + 368 + - [ ] **Step 2: Run test to verify it fails** 369 + 370 + ```bash 371 + cd apps/ionosphere-appview 372 + npx vitest run src/__tests__/layers-pub.test.ts 373 + ``` 374 + 375 + - [ ] **Step 3: Add Stage 6 to publish.ts** 376 + 377 + Add after the existing transcript publishing stage in `apps/ionosphere-appview/src/publish.ts`: 378 + 379 + ```typescript 380 + // ── Stage 6: layers.pub records ──────────────────────────────────────────── 381 + console.log("\n=== Stage 6: layers.pub records ==="); 382 + ``` 383 + 384 + For each talk that has both a transcript and NLP annotations: 385 + - Transcripts: `apps/data/transcripts/{rkey}.json` (same path as existing Stage 5, resolved via `../../data/transcripts` from `src/`) 386 + - NLP: `pipeline/data/nlp/{rkey}.json` (same path as existing Stage 4) 387 + 388 + 1. Load transcript JSON → `encode()` → CompactTranscript 389 + 2. Load NLP annotations JSON 390 + 3. Call `transcriptToLayersPub(transcriptRecord, did, rkey)` → expression + segmentation 391 + 4. Call `nlpToAnnotationLayers(nlpData, did, rkey, expressionUri)` → 4 annotation layers 392 + 5. Publish all 6 records via `pds.putRecord()` — parallel within each talk using `Promise.all()` 393 + 6. Log progress: `Published 6 layers.pub records for {rkey}` 394 + 395 + Record collections and rkeys: 396 + - `pub.layers.expression.expression` / `{rkey}-expression` 397 + - `pub.layers.segmentation.segmentation` / `{rkey}-segmentation` 398 + - `pub.layers.annotation.annotationLayer` / `{rkey}-sentences` 399 + - `pub.layers.annotation.annotationLayer` / `{rkey}-paragraphs` 400 + - `pub.layers.annotation.annotationLayer` / `{rkey}-entities` 401 + - `pub.layers.annotation.annotationLayer` / `{rkey}-topics` 402 + 403 + Also publish the 3 new lens files (transcript-to-expression, nlp-to-annotation-layers, layers-to-document) in Stage 1 alongside the existing 4 lenses. 404 + 405 + - [ ] **Step 4: Run test to verify it passes** 406 + 407 + ```bash 408 + cd apps/ionosphere-appview 409 + npx vitest run src/__tests__/layers-pub.test.ts 410 + ``` 411 + 412 + - [ ] **Step 5: Commit** 413 + 414 + ```bash 415 + git add apps/ionosphere-appview/src/publish.ts apps/ionosphere-appview/src/__tests__/layers-pub.test.ts 416 + git commit -m "feat: publish layers.pub records in Stage 6 of publish pipeline" 417 + ``` 418 + 419 + --- 420 + 421 + ## Chunk 4: Lens 3 (Reverse) + Appview Indexer 422 + 423 + ### Task 5: Define Lens 3 — layers.pub → ionosphere document facets 424 + 425 + This is the reverse lens: given layers.pub records, produce the materialized RelationalText document with ionosphere facets. Used by the appview indexer. 426 + 427 + **Files:** 428 + - Create: `formats/tv.ionosphere/lenses/layers-to-document.lens.json` 429 + - Modify: `formats/tv.ionosphere/ts/layers-pub.ts` — add `layersPubToDocument()` 430 + - Modify: `apps/ionosphere-appview/src/__tests__/layers-pub.test.ts` — add round-trip test 431 + 432 + - [ ] **Step 1: Write the failing round-trip test** 433 + 434 + This is the critical correctness test. Feed a real transcript + NLP annotations through Lens 1+2, then feed the output through Lens 3, and compare the result with what `decodeToDocumentWithStructure()` produces for the same input. 435 + 436 + ```typescript 437 + import { decodeToDocumentWithStructure, encode } from '../../../formats/tv.ionosphere/ts/transcript-encoding.js'; 438 + import { transcriptToLayersPub, nlpToAnnotationLayers, layersPubToDocument } from '../../../formats/tv.ionosphere/ts/layers-pub.js'; 439 + 440 + describe('Lens 3: round-trip correctness', () => { 441 + it('layers.pub → document matches decodeToDocumentWithStructure output', async () => { 442 + // Load real fixture data 443 + // Transcripts: apps/data/transcripts/{rkey}.json (resolved from publish.ts: ../../data/transcripts) 444 + // NLP: pipeline/data/nlp/{rkey}.json 445 + const transcriptData = /* read from apps/data/transcripts/ats26-keynote.json */; 446 + const nlpData = /* read from pipeline/data/nlp/ats26-keynote.json */; 447 + 448 + // Path A: existing direct path 449 + const compact = encode(transcriptData); 450 + const directDoc = decodeToDocumentWithStructure(compact, nlpData); 451 + 452 + // Path B: through lenses 453 + const transcriptRecord = { text: compact.text, startMs: compact.startMs, timings: compact.timings, talkUri: 'at://test/tv.ionosphere.talk/test' }; 454 + const { expression, segmentation } = await transcriptToLayersPub(transcriptRecord, 'did:plc:test', 'test'); 455 + const annotationLayers = await nlpToAnnotationLayers(nlpData, 'did:plc:test', 'test', 'at://...'); 456 + const lensDoc = await layersPubToDocument(expression, segmentation, annotationLayers); 457 + 458 + // Compare 459 + expect(lensDoc.text).toBe(directDoc.text); 460 + expect(lensDoc.facets.length).toBe(directDoc.facets.length); 461 + // Facets may be in different order — sort by byteStart then compare 462 + }); 463 + }); 464 + ``` 465 + 466 + - [ ] **Step 2: Run test to verify it fails** 467 + 468 + ```bash 469 + cd apps/ionosphere-appview 470 + npx vitest run src/__tests__/layers-pub.test.ts 471 + ``` 472 + 473 + - [ ] **Step 3: Implement layersPubToDocument** 474 + 475 + Add `layersPubToDocument()` to `formats/tv.ionosphere/ts/layers-pub.ts`. 476 + 477 + Inputs: expression record, segmentation record, annotation layers (object with sentences/paragraphs/entities/topics). 478 + 479 + Output: `{ text: string, facets: DocumentFacet[] }` — same shape as `decodeToDocumentWithStructure()`. 480 + 481 + Transform: 482 + 1. `text` comes from the expression record 483 + 2. Timestamp facets: iterate segmentation tokens, for each token create a facet with `$type: "tv.ionosphere.facet#timestamp"`, `startTime` and `endTime` in nanoseconds (ms × 1_000_000), `byteStart`/`byteEnd` from token's textSpan 484 + 3. Sentence facets: from sentences annotation layer, each annotation → facet with `$type: "tv.ionosphere.facet#sentence"` 485 + 4. Paragraph facets: similar, `$type: "tv.ionosphere.facet#paragraph"` 486 + 5. Entity facets: route by features — if has `conceptUri` → `#concept-ref`, else → `#entity` 487 + 6. Topic facets: `$type: "tv.ionosphere.facet#topic-break"`, zero-width span 488 + 489 + - [ ] **Step 4: Run test to verify it passes** 490 + 491 + ```bash 492 + cd apps/ionosphere-appview 493 + npx vitest run src/__tests__/layers-pub.test.ts 494 + ``` 495 + 496 + - [ ] **Step 5: Commit** 497 + 498 + ```bash 499 + git add formats/tv.ionosphere/ts/layers-pub.ts formats/tv.ionosphere/lenses/layers-to-document.lens.json apps/ionosphere-appview/src/__tests__/layers-pub.test.ts 500 + git commit -m "feat: Lens 3 — layers.pub records to ionosphere document facets (round-trip verified)" 501 + ``` 502 + 503 + ### Task 6: Add layers.pub DB tables 504 + 505 + **Files:** 506 + - Modify: `apps/ionosphere-appview/src/db.ts` 507 + 508 + - [ ] **Step 1: Add 3 new tables to migrate()** 509 + 510 + Add after the existing `_cursor` table creation in `apps/ionosphere-appview/src/db.ts`: 511 + 512 + ```sql 513 + CREATE TABLE IF NOT EXISTS layers_expressions ( 514 + uri TEXT PRIMARY KEY, 515 + rkey TEXT NOT NULL, 516 + did TEXT NOT NULL, 517 + transcript_uri TEXT NOT NULL, 518 + text TEXT NOT NULL, 519 + language TEXT NOT NULL DEFAULT 'en', 520 + created_at TEXT DEFAULT CURRENT_TIMESTAMP 521 + ); 522 + 523 + -- uri IS the expression URI for this table; other tables reference it via expression_uri 524 + CREATE INDEX IF NOT EXISTS idx_layers_expr_transcript ON layers_expressions(transcript_uri); 525 + 526 + CREATE TABLE IF NOT EXISTS layers_segmentations ( 527 + uri TEXT PRIMARY KEY, 528 + rkey TEXT NOT NULL, 529 + did TEXT NOT NULL, 530 + expression_uri TEXT NOT NULL, 531 + tokens_json TEXT NOT NULL, 532 + created_at TEXT DEFAULT CURRENT_TIMESTAMP 533 + ); 534 + 535 + CREATE INDEX IF NOT EXISTS idx_layers_seg_expression ON layers_segmentations(expression_uri); 536 + 537 + CREATE TABLE IF NOT EXISTS layers_annotations ( 538 + uri TEXT PRIMARY KEY, 539 + rkey TEXT NOT NULL, 540 + did TEXT NOT NULL, 541 + expression_uri TEXT NOT NULL, 542 + kind TEXT NOT NULL, 543 + subkind TEXT NOT NULL, 544 + annotations_json TEXT NOT NULL, 545 + created_at TEXT DEFAULT CURRENT_TIMESTAMP 546 + ); 547 + 548 + CREATE INDEX IF NOT EXISTS idx_layers_ann_expression ON layers_annotations(expression_uri); 549 + ``` 550 + 551 + - [ ] **Step 2: Verify DB migration runs clean** 552 + 553 + ```bash 554 + cd apps/ionosphere-appview 555 + npx tsx -e " 556 + import { openDb, migrate } from './src/db.js'; 557 + const db = openDb(); 558 + migrate(db); 559 + const tables = db.prepare(\"SELECT name FROM sqlite_master WHERE type='table' AND name LIKE 'layers_%'\").all(); 560 + console.log('New tables:', tables.map(t => t.name)); 561 + " 562 + ``` 563 + 564 + Expected: `New tables: ['layers_expressions', 'layers_segmentations', 'layers_annotations']` 565 + 566 + - [ ] **Step 3: Commit** 567 + 568 + ```bash 569 + git add apps/ionosphere-appview/src/db.ts 570 + git commit -m "feat: add layers.pub DB tables (expressions, segmentations, annotations)" 571 + ``` 572 + 573 + ### Task 7: Wire layers.pub indexer into appview 574 + 575 + **Files:** 576 + - Create: `apps/ionosphere-appview/src/layers-indexer.ts` 577 + - Modify: `apps/ionosphere-appview/src/indexer.ts` 578 + 579 + - [ ] **Step 1: Create the layers-indexer module** 580 + 581 + Create `apps/ionosphere-appview/src/layers-indexer.ts` with these functions: 582 + 583 + ```typescript 584 + export function indexExpression(db, did, rkey, uri, record): void 585 + export function indexSegmentation(db, did, rkey, uri, record): void 586 + export function indexAnnotationLayer(db, did, rkey, uri, record): void 587 + export function deleteExpression(db, uri): void 588 + export function deleteSegmentation(db, uri): void 589 + export function deleteAnnotationLayer(db, uri): void 590 + export async function rebuildDocument(db, expressionUri): Promise<void> 591 + ``` 592 + 593 + **indexExpression:** INSERT OR REPLACE into `layers_expressions`. The record's `uri` IS the expression URI (used by other tables' `expression_uri` FK). Extract `sourceRef` as `transcript_uri`. 594 + 595 + **indexSegmentation:** INSERT OR REPLACE into `layers_segmentations`. Store tokenizations as JSON. 596 + 597 + **indexAnnotationLayer:** INSERT OR REPLACE into `layers_annotations`. Store annotations array as JSON. 598 + 599 + **deleteExpression:** DELETE from `layers_expressions` WHERE uri. CASCADE: also delete from `layers_segmentations` and `layers_annotations` WHERE expression_uri matches. Clear the talk's document field in the talks table. 600 + 601 + **deleteSegmentation/deleteAnnotationLayer:** DELETE the specific row, then call `rebuildDocument`. 602 + 603 + **rebuildDocument:** 604 + 1. Look up expression by `uri` (= expression_uri) → get transcript_uri 605 + 2. Look up segmentation by expression_uri 606 + 3. Look up all annotation layers by expression_uri 607 + 4. If expression + segmentation exist, call `layersPubToDocument()` (Lens 3) 608 + 5. Find the talk_uri from the transcript table using transcript_uri 609 + 6. UPDATE the talk's `document` field with `JSON.stringify(document)` 610 + 611 + - [ ] **Step 2: Wire into indexer.ts** 612 + 613 + Add 3 new collections to `IONOSPHERE_COLLECTIONS`: 614 + 615 + ```typescript 616 + "pub.layers.expression.expression", 617 + "pub.layers.segmentation.segmentation", 618 + "pub.layers.annotation.annotationLayer", 619 + ``` 620 + 621 + Add DID filter in `processEvent()` — only process layers.pub records from the bot DID: 622 + 623 + ```typescript 624 + if (collection.startsWith("pub.layers.") && event.did !== BOT_DID) return; 625 + ``` 626 + 627 + The `BOT_DID` is already resolved in `appview.ts` — pass it to the indexer or make it available as a module-level constant. 628 + 629 + Add delete and create/update cases for the 3 new collections in the switch statements, calling the functions from `layers-indexer.ts`. 630 + 631 + After each create/update of a layers.pub record, call `rebuildDocument()` with the expression URI. 632 + 633 + - [ ] **Step 3: Test indexer locally** 634 + 635 + ```bash 636 + cd apps/ionosphere-appview 637 + # Start local environment 638 + docker compose up -d 639 + PORT=9401 npx tsx src/appview.ts & 640 + # Publish records 641 + PDS_URL=http://localhost:2690 BOT_HANDLE=ionosphere.test BOT_PASSWORD=ionosphere-dev-password npx tsx src/publish.ts 642 + # Verify layers.pub records were indexed 643 + curl -s http://localhost:9401/xrpc/tv.ionosphere.getTalk?rkey=ats26-keynote | python3 -c "import sys,json; d=json.load(sys.stdin); print('Has document:', bool(d.get('document'))); print('Facet count:', len(d['document']['facets']) if d.get('document') else 0)" 644 + ``` 645 + 646 + - [ ] **Step 4: Commit** 647 + 648 + ```bash 649 + git add apps/ionosphere-appview/src/layers-indexer.ts apps/ionosphere-appview/src/indexer.ts 650 + git commit -m "feat: index layers.pub records and rebuild materialized documents via Lens 3" 651 + ``` 652 + 653 + --- 654 + 655 + ## Chunk 5: Schema Versioning + Final Verification 656 + 657 + ### Task 8: Initialize panproto VCS 658 + 659 + **Files:** 660 + - Project root — panproto VCS state 661 + 662 + - [ ] **Step 1: Initialize and commit schemas** 663 + 664 + ```bash 665 + # From project root 666 + schema init 667 + schema add lexicons/pub/layers/ 668 + schema add formats/tv.ionosphere/ionosphere.lexicon.json 669 + schema add formats/tv.ionosphere/nlpAnnotations.lexicon.json 670 + schema add formats/tv.ionosphere/lenses/ 671 + schema commit -m "Initial schema commit: layers.pub v0.5.0, ionosphere facets, NLP annotations, 7 lenses" 672 + schema tag v0.5.0 673 + ``` 674 + 675 + - [ ] **Step 2: Verify VCS state** 676 + 677 + ```bash 678 + schema log 679 + schema status 680 + ``` 681 + 682 + Expected: clean state, one commit, tagged v0.5.0. 683 + 684 + - [ ] **Step 3: Commit VCS state to git** 685 + 686 + ```bash 687 + git add .panproto/ # or wherever schema VCS stores its state 688 + git commit -m "feat: initialize panproto VCS, tag layers.pub v0.5.0" 689 + ``` 690 + 691 + ### Task 9: End-to-end verification 692 + 693 + - [ ] **Step 1: Run full test suite** 694 + 695 + ```bash 696 + cd apps/ionosphere-appview 697 + npx vitest run 698 + ``` 699 + 700 + Expected: All tests pass. 701 + 702 + - [ ] **Step 2: Run publish against local PDS and verify round-trip** 703 + 704 + ```bash 705 + cd apps/ionosphere-appview 706 + docker compose up -d 707 + PORT=9401 npx tsx src/appview.ts & 708 + PDS_URL=http://localhost:2690 BOT_HANDLE=ionosphere.test BOT_PASSWORD=ionosphere-dev-password npx tsx src/publish.ts 709 + ``` 710 + 711 + Verify: 712 + 1. layers.pub records appear in PDS (check via `com.atproto.repo.listRecords`) 713 + 2. Appview indexes them and rebuilds documents 714 + 3. Documents served via API match previous output 715 + 4. Frontend renders correctly at http://127.0.0.1:9402/talks 716 + 717 + - [ ] **Step 3: Commit any fixes** 718 + 719 + ### Task 10: Deploy 720 + 721 + - [ ] **Step 1: Deploy appview** 722 + 723 + ```bash 724 + flyctl deploy --config fly.appview.toml --remote-only 725 + ``` 726 + 727 + - [ ] **Step 2: Publish to production PDS** 728 + 729 + ```bash 730 + cd apps/ionosphere-appview 731 + PDS_URL=https://jellybaby.us-east.host.bsky.network \ 732 + BOT_HANDLE=ionosphere.tv \ 733 + BOT_PASSWORD=<app-password> \ 734 + npx tsx src/publish.ts 735 + ``` 736 + 737 + - [ ] **Step 3: Invalidate caches** 738 + 739 + ```bash 740 + curl -X POST https://api.ionosphere.tv/xrpc/tv.ionosphere.invalidate 741 + ``` 742 + 743 + - [ ] **Step 4: Deploy frontend** 744 + 745 + ```bash 746 + flyctl deploy --config fly.web.toml --remote-only 747 + ``` 748 + 749 + - [ ] **Step 5: Verify production** 750 + 751 + Check https://ionosphere.tv/talks — documents should render with all enrichment annotations intact.
+173
docs/superpowers/specs/2026-04-12-enrichment-phases-2-3-design.md
··· 1 + # Enrichment Phases 2-3: NER + Entity Linking, Topic Segmentation 2 + 3 + **Date:** 2026-04-12 4 + **Status:** Approved 5 + **Depends on:** Phase 1 transcript formatting (complete) 6 + 7 + ## Goal 8 + 9 + Add named entity recognition with AT Protocol record linking (Phase 2) and topic segmentation with visual dividers (Phase 3) to the existing NLP enrichment pipeline. Achieve feature parity with the old concept system while adding speaker attribution and topic navigation, before deploying. 10 + 11 + ## Constraints 12 + 13 + - **Text is immutable.** Same as Phase 1 — annotations only, no word changes. 14 + - **Build-time processing.** New passes extend the existing Python pipeline. 15 + - **Leverage existing data.** Speaker records, diarization records, and concept records are already in the database. Use them for entity resolution. 16 + - **layers.pub annotation model.** Each pass produces a separate annotation layer, consistent with Phase 1's approach. 17 + 18 + ## Pipeline Passes 19 + 20 + ### Pass 3: Named Entity Recognition + Entity Linking 21 + 22 + **Input:** transcript text + speaker records (from SQLite) + diarization records (from SQLite) + concept records (from SQLite) 23 + 24 + **Steps:** 25 + 26 + 1. **Build speaker lookup.** Query `speakers` table, build a map of `{name, aliases, handle, did}` for all speakers. Include normalized variants (lowercase, first-name-only for disambiguation with diarization context). 27 + 28 + 2. **Load diarization.** Query `stream_diarizations` table for the talk's stream. Map diarization time ranges to speaker identities. Each segment tells us who is speaking when — this provides context for resolving ambiguous names. 29 + 30 + 3. **Run spaCy NER.** The existing `en_core_web_sm` model (already loaded for sentence detection) provides NER via `doc.ents`. Extract entities with types: PERSON, ORG, PRODUCT, WORK_OF_ART, GPE, EVENT. Compute byte ranges using the same char→byte conversion as sentence detection. 31 + 32 + 4. **Resolve entities:** 33 + - **PERSON entities:** Match against speaker lookup by name similarity. Use diarization context for disambiguation — if a first name is mentioned while a known speaker with that first name is presenting or was just speaking, prefer that match. Resolved entities get a `speakerDid` linking to the Bluesky profile. 34 + - **ORG/PRODUCT entities:** Match against concept records by name and aliases. Resolved entities get a `conceptUri`. 35 + - **Unresolved entities:** Keep as labeled spans with NER type but no link target. Available for manual curation in Phase 4. 36 + 37 + 5. **Emit speaker attribution.** For each diarization segment, emit a speaker-segment annotation spanning the corresponding byte range in the transcript. Cross-reference diarization time ranges with word timestamps to find byte boundaries. 38 + 39 + **Output:** NLP JSON with `entities` array and `speakerSegments` array. 40 + 41 + ### Pass 4: Topic Segmentation 42 + 43 + **Input:** transcript text + sentence boundaries (from Pass 1) 44 + 45 + **Steps:** 46 + 47 + 1. **Embed sentences.** Run each sentence through `all-MiniLM-L6-v2` (384-dim sentence embeddings). The model is ~80MB, downloaded on first run. Embedding 300 sentences takes ~2 seconds on CPU. 48 + 49 + 2. **Compute similarity.** For each pair of adjacent sentence windows (window size N, default 3 sentences), compute cosine similarity between the mean embedding of the left window and the right window. 50 + 51 + 3. **Detect boundaries.** Similarity drops below a threshold (tunable, default 0.3) indicate topic shifts. Apply a minimum segment length (default 5 sentences) to avoid over-segmentation. 52 + 53 + 4. **Snap to structure.** Topic breaks are snapped to the nearest paragraph boundary where possible (since paragraphs already represent pause-based thought transitions). If no paragraph boundary is within 2 sentences of the detected break, snap to the nearest sentence boundary. 54 + 55 + **Output:** NLP JSON with `topicBreaks` array (byte positions of topic boundaries). 56 + 57 + **Parameters stored in metadata:** `embeddingModel`, `windowSize`, `similarityThreshold`, `minSegmentSentences`. 58 + 59 + ## Facet Schema 60 + 61 + **Existing facets now populated:** 62 + 63 + | Facet type | Class | Use | 64 + |---|---|---| 65 + | `tv.ionosphere.facet#speaker-segment` | `block` | Wraps diarization segment — attributes text to speaker | 66 + | `tv.ionosphere.facet#speaker-ref` | `inline` | Links person mention to speaker DID/profile | 67 + | `tv.ionosphere.facet#concept-ref` | `inline` | Links ORG/PRODUCT mention to concept record | 68 + 69 + **New facets to add to format lexicon:** 70 + 71 + | Facet type | Class | Use | 72 + |---|---|---| 73 + | `tv.ionosphere.facet#topic-break` | `block` | Topic boundary — renderer inserts divider | 74 + | `tv.ionosphere.facet#entity` | `inline` | Unresolved entity — has label + NER type, no linked record | 75 + 76 + ## Document Assembly 77 + 78 + The `NlpAnnotations` interface in `transcript-encoding.ts` extends to: 79 + 80 + ```typescript 81 + interface NlpAnnotations { 82 + sentences: Array<{ byteStart: number; byteEnd: number }>; 83 + paragraphs: Array<{ byteStart: number; byteEnd: number }>; 84 + entities: Array<{ 85 + byteStart: number; byteEnd: number; 86 + label: string; nerType: string; 87 + speakerDid?: string; conceptUri?: string; 88 + }>; 89 + speakerSegments: Array<{ 90 + byteStart: number; byteEnd: number; 91 + speakerDid: string; speakerName: string; 92 + }>; 93 + topicBreaks: Array<{ byteStart: number }>; 94 + } 95 + ``` 96 + 97 + `decodeToDocumentWithStructure` maps these to facets: 98 + - `entities` with `speakerDid` → `#speaker-ref` facets 99 + - `entities` with `conceptUri` → `#concept-ref` facets 100 + - `entities` with neither → `#entity` facets (unresolved) 101 + - `speakerSegments` → `#speaker-segment` facets 102 + - `topicBreaks` → `#topic-break` facets 103 + 104 + ## Renderer Changes 105 + 106 + ### Entity spans 107 + 108 + `extractData` returns `entities: EntitySpan[]` with byte range, label, NER type, and optional link target. The renderer overlays these on word spans: 109 + 110 + - **`#speaker-ref`** — renders as a link styled with a subtle blue underline. Clicking navigates to the speaker page or Bluesky profile. 111 + - **`#concept-ref`** — renders as a link with amber underline (matching existing concept highlighting). Clicking navigates to the concept page. 112 + - **`#entity`** (unresolved) — renders as subtly styled text (dotted underline, slightly different color) to indicate a recognized entity without a link. 113 + 114 + These are inline facets that overlay on word spans. A word can have multiple facets (timestamp + entity). The existing `wordConcepts` pattern in `extractData` extends to handle all entity types. 115 + 116 + ### Speaker segments 117 + 118 + Not visually rendered in this phase. The data is stored in facets for future use (speaker-colored text, margin labels, etc.). Getting the attribution data right is the priority. 119 + 120 + ### Topic dividers 121 + 122 + A subtle `<hr>` between paragraphs where a topic break falls: 123 + 124 + ```html 125 + <div class="mb-4"><!-- paragraph --></div> 126 + <hr class="border-neutral-800 my-6" /> 127 + <div class="mb-4"><!-- paragraph --></div> 128 + ``` 129 + 130 + `extractData` returns `topicBreaks: Set<number>` — a set of paragraph indices where topic breaks occur. The renderer checks this set when iterating paragraphs and inserts dividers. 131 + 132 + ## Speaker Lookup Generation 133 + 134 + The Python pipeline reads speaker data directly from the SQLite database (Python's `sqlite3` is in the standard library). The lookup table is built at pipeline startup: 135 + 136 + ```python 137 + speakers = db.execute("SELECT name, handle, speaker_did FROM speakers").fetchall() 138 + lookup = {} 139 + for name, handle, did in speakers: 140 + lookup[name.lower()] = {"name": name, "handle": handle, "did": did} 141 + # Also index by first name for diarization-context matching 142 + first = name.split()[0].lower() 143 + if first not in lookup: 144 + lookup[first] = {"name": name, "handle": handle, "did": did} 145 + ``` 146 + 147 + This is ephemeral — rebuilt each pipeline run from the current speaker records. No separate file to maintain. 148 + 149 + ## Dependencies 150 + 151 + **New Python dependency:** `sentence-transformers>=2.0` (adds torch, transformers, tokenizers — ~2GB install). Build-time only, no runtime impact. 152 + 153 + **spaCy NER:** Zero-cost addition — `en_core_web_sm` already loaded for sentence detection. NER entities are read from `doc.ents` in the same pass. 154 + 155 + **SQLite access:** Python `sqlite3` standard library. Pipeline reads speaker, diarization, and concept records from the same database the appview uses. 156 + 157 + ## Testing Strategy 158 + 159 + **Python pipeline (pytest):** 160 + - Unit tests for speaker lookup construction (name variants, first-name matching) 161 + - Unit tests for entity resolution (exact match, first-name match with diarization context, unresolved fallback) 162 + - Unit tests for topic segmentation (boundary detection, minimum segment length, snap-to-paragraph) 163 + - Integration test: full pipeline on a known transcript, verify entity and topic output 164 + 165 + **TypeScript (vitest):** 166 + - `decodeToDocumentWithStructure` with entity/speaker/topic annotations 167 + - `extractData` with entity facets and topic breaks 168 + - Renderer: entity links, topic dividers between paragraphs 169 + 170 + **Manual validation:** 171 + - Spot-check 5-10 talks: verify entity links point to correct profiles/concepts 172 + - Verify topic breaks land at natural transitions, not mid-thought 173 + - Check that speaker attribution aligns with diarization (correct speaker for each segment)
+299
docs/superpowers/specs/2026-04-12-transcript-formatting-design.md
··· 1 + # Transcript Formatting: NLP Enrichment Pipeline 2 + 3 + **Date:** 2026-04-12 4 + **Status:** Approved 5 + 6 + ## Problem 7 + 8 + Transcripts are currently rendered as an infinitely long, unbroken run of text. Word-level timing and concept facets exist, but there is no structural formatting — no sentences, no paragraphs, no visual hierarchy. The goal is for transcripts to read as though they were essays. 9 + 10 + ## Constraints 11 + 12 + - **Text is immutable.** The pipeline adds structural annotations only — no words are modified, added, or removed. Transcript editing is a separate future concern. 13 + - **Reliability over ambition.** Each enrichment pass must be dependable enough to run unsupervised across all transcripts. Noisy output is worse than no output. 14 + - **Build-time processing.** NLP runs once in the batch pipeline; results are published as AT Protocol records. Zero runtime cost. 15 + - **Python NLP stack.** spaCy for sentence detection and NER; sentence-transformers for topic segmentation. 16 + 17 + ## Schema Design: layers.pub Integration 18 + 19 + The enrichment pipeline uses [layers.pub](https://layers.pub) (`pub.layers.*`) lexicons — composable AT Protocol schemas for linguistic annotation. This gives us a standard, interoperable representation with built-in support for multiple annotation passes, provenance tracking, and manual overrides. 20 + 21 + **Vendoring strategy:** layers.pub is at v0.5.0 draft. We vendor the specific lexicon definitions we use into `lexicons/pub/layers/` in this repo. Panproto lenses provide forward-compatibility — when layers.pub evolves, we define migrations rather than rewriting our pipeline. This follows the project's principle of prioritizing the lens layer for forward-compat. 22 + 23 + ### Record Architecture 24 + 25 + #### 1. Source transcript (existing) 26 + 27 + `tv.ionosphere.transcript` — compact storage format with `text`, `startMs`, and `timings` array. Stays as-is. Source of truth for raw transcription output. 28 + 29 + #### 2. Expression record 30 + 31 + `pub.layers.expression.expression` (kind: `"transcript"`) — the transcript text published as a layers.pub expression. Links back to the ionosphere transcript via `sourceRef`. This is the anchoring point for all annotations. 32 + 33 + #### 3. Segmentation record 34 + 35 + `pub.layers.segmentation.segmentation` — word-level tokenization derived from the transcript's compact timing data. Each token carries: 36 + - `textSpan`: UTF-8 byte offsets (`byteStart`, `byteEnd`) 37 + - `temporalSpan`: timing in milliseconds (`start`, `ending`) 38 + 39 + This replaces the per-word timestamp facets with a standard representation. 40 + 41 + #### 4. Annotation layers 42 + 43 + `pub.layers.annotation.annotationLayer` — one record per enrichment pass: 44 + 45 + | Pass | `kind` | `subkind` | `sourceMethod` | 46 + |------|--------|-----------|----------------| 47 + | Sentence detection | `span` | `sentence-boundary` | `automatic` | 48 + | Paragraph segmentation | `span` | `paragraph-boundary` | `automatic` | 49 + | Topic segmentation (future) | `span` | `topic-segment` | `automatic` | 50 + | Named entity recognition (future) | `span` | `ner` | `automatic` | 51 + | Concept linking (future) | `span` | `concept` | `automatic` | 52 + | Speaker attribution (future) | `span` | `speaker` | `automatic` | 53 + | Manual corrections (future) | varies | varies | `manual-native` | 54 + 55 + Each layer includes `metadata` (agent, tool, confidence, timestamp) for provenance. Pipeline parameters (e.g., paragraph pause threshold) are stored in `metadata.features` so provenance is complete and results are reproducible. 56 + 57 + #### 5. Manual override layer (future) 58 + 59 + A separate annotation layer with `sourceMethod: "manual-native"` and higher `rank`. The merge step prefers higher-ranked layers. Example: correcting "Blue Sky" to link to the Bluesky concept record is an annotation in this layer that supersedes the auto-detected concept. Published as first-class AT Protocol records — auditable, attributable, and preservable across pipeline re-runs. 60 + 61 + ### Replacing `tv.ionosphere.annotation` 62 + 63 + The existing `tv.ionosphere.annotation` record type (concept mentions anchored to byte ranges) is replaced wholesale by layers.pub annotation layers. Since the entire pipeline rebuilds from raw transcripts, there is no migration burden — the next pipeline run produces layers.pub records instead of `tv.ionosphere.annotation` records, and the old records are deleted. 64 + 65 + The existing concept data is re-derived by the NLP pipeline as a concept annotation layer (Phase 2), which will produce better results than the current approach. The `tv.ionosphere.annotation` lexicon and related code (`enrich.ts`, `enrich-all.ts`, `overlayAnnotations` in the appview) are removed in Phase 1. 66 + 67 + ### Panproto Integration 68 + 69 + - **Lenses:** Transform between compact transcript format (`tv.ionosphere.transcript`) and layers.pub expression + segmentation format. Lens definitions live in `formats/tv.ionosphere/lenses/`. 70 + - **Schema validation:** Validate all layers.pub records before publishing to PDS. Runs in the TypeScript publish step (after the Python NLP pipeline outputs JSON). 71 + - **Migration support:** As layers.pub evolves from v0.5.0, panproto migrations keep ionosphere records compatible. Vendored lexicons in `lexicons/pub/layers/` are the pinned source of truth. 72 + - **Pipeline boundary:** The Python NLP pipeline outputs annotation layer JSON files. The TypeScript publish step validates them against panproto-parsed lexicons and publishes to PDS. This reuses the existing panproto TypeScript integration. 73 + 74 + ## Pipeline Architecture 75 + 76 + ``` 77 + transcript record (text + timings) 78 + | 79 + v 80 + +-------------------+ 81 + | Pass 1: Sentences | <-- spaCy sentence boundary detection 82 + +---------+---------+ 83 + | 84 + v 85 + +--------------------+ 86 + | Pass 2: Paragraphs | <-- pause data + sentence boundaries 87 + +---------+----------+ 88 + | 89 + v 90 + +--------------------+ 91 + | Pass N: (future) | <-- topics, entities, speaker linking 92 + +---------+----------+ 93 + | 94 + v 95 + +--------------------+ 96 + | Override layer | <-- manual corrections (higher rank) 97 + +---------+----------+ 98 + | 99 + v 100 + +--------------------+ 101 + | Merge & publish | <-- assemble RelationalText document 102 + +--------------------+ 103 + ``` 104 + 105 + Properties: 106 + - **Each pass is a standalone Python module** with a consistent interface: takes transcript text + timings + prior layer output, returns a new annotation layer. 107 + - **Passes are additive** — they never modify text, only emit new annotations. 108 + - **Override layer applies last** — manual corrections supersede auto-generated annotations at matching byte ranges via `rank`. 109 + - **Idempotent** — re-running the pipeline produces the same output; manual overrides are preserved because they are separate records. 110 + 111 + ### Pass 1: Sentence Boundary Detection 112 + 113 + **Tool:** spaCy with `en_core_web_sm`. The small model is nearly as accurate as the transformer model for sentence boundary detection (its most battle-tested feature), and runs without GPU on a standard dev machine. If accuracy proves insufficient on speech transcripts, upgrade to `en_core_web_trf` in a later pass. 114 + 115 + spaCy's sentence segmenter uses dependency parsing, which is significantly more robust than punctuation-splitting for speech transcripts where Whisper's punctuation can be unreliable. 116 + 117 + **Output:** An annotation layer with one annotation per sentence, anchored by byte span. 118 + 119 + **Reliability:** Very high (95%+ accuracy on messy speech text). 120 + 121 + ### Pass 2: Paragraph Segmentation 122 + 123 + **Tool:** Custom algorithm combining two signals. 124 + 125 + **Signal 1 — Pause duration:** The transcript's timing data encodes silence gaps as negative values. Pauses above a tunable threshold are paragraph boundary candidates. Default threshold: **2.0 seconds** (a conservative starting point — most speech pauses are under 1s; pauses over 2s reliably indicate topic transitions). 126 + 127 + **Signal 2 — Sentence alignment:** Paragraph breaks only occur at sentence boundaries (from Pass 1). A long pause mid-sentence is a speaker thinking, not a paragraph break. 128 + 129 + **Algorithm:** 130 + ``` 131 + for each silence gap > pause_threshold_ms (default: 2000): 132 + find the nearest sentence boundary (from Pass 1) 133 + if the sentence boundary is within proximity_words (default: 5) of the pause: 134 + emit paragraph break at that sentence boundary 135 + ``` 136 + 137 + The proximity constraint of 5 words allows for the common case where a speaker finishes a thought (pause), says a brief connective phrase ("so", "and then"), and starts the next topic — the paragraph break lands at the sentence boundary closest to the actual pause. 138 + 139 + Both `pause_threshold_ms` and `proximity_words` are stored in the annotation layer's `metadata.features` for reproducibility. 140 + 141 + **Reliability:** High. Pause duration is a genuine speech signal, and constraining to sentence boundaries eliminates false positives. 142 + 143 + ## Rendering 144 + 145 + ### Format Lexicon Updates 146 + 147 + Two new facet types added to `tv.ionosphere.facet`: 148 + 149 + | Facet type | `featureClass` | Description | 150 + |---|---|---| 151 + | `tv.ionosphere.facet#sentence` | `inline` | Wraps all words in a sentence as a contiguous inline span | 152 + | `tv.ionosphere.facet#paragraph` | `block` | Groups sentences into a block-level paragraph container | 153 + 154 + Note: the annotation _storage_ format is layers.pub annotation layers (on the PDS). The _rendering_ format is ionosphere facets in the RelationalText document. The document assembly step bridges these — it reads layers.pub annotations and emits ionosphere facets. This separation means the renderer does not need to know about layers.pub. 155 + 156 + ### DOM Structure 157 + 158 + The renderer groups words into sentence spans and sentences into paragraph blocks: 159 + 160 + ```html 161 + <div> <!-- paragraph (block) --> 162 + <span> <!-- sentence (inline) --> 163 + <span>word</span> <span>word</span> <span>word</span> 164 + </span> 165 + <span> <!-- sentence (inline) --> 166 + <span>word</span> <span>word</span> 167 + </span> 168 + </div> 169 + <div> <!-- paragraph (block) --> 170 + <span> <!-- sentence (inline) --> 171 + <span>word</span> <span>word</span> 172 + </span> 173 + </div> 174 + ``` 175 + 176 + This mirrors the layers.pub expression hierarchy (transcript > paragraph > sentence) and maps directly to the format lexicon's `featureClass` system (`block` for paragraphs, `inline` for sentences). 177 + 178 + Sentence spans provide styling hooks for hover, selection, and transitions at sentence granularity. Paragraph blocks provide natural vertical whitespace. 179 + 180 + ### Data Model Changes: `extractData` → Hierarchical Structure 181 + 182 + The current `extractData` function in `src/lib/transcript.ts` returns a flat `{ words: WordSpan[], concepts, wordConcepts }`. This must change to return a hierarchical structure: 183 + 184 + ```typescript 185 + interface ParagraphSpan { 186 + byteStart: number; 187 + byteEnd: number; 188 + sentences: SentenceSpan[]; 189 + } 190 + 191 + interface SentenceSpan { 192 + byteStart: number; 193 + byteEnd: number; 194 + words: WordSpan[]; // existing WordSpan type, unchanged 195 + } 196 + 197 + interface TranscriptStructure { 198 + paragraphs: ParagraphSpan[]; 199 + concepts: ConceptSpan[]; 200 + // wordConcepts lookup remains flat (indexed by global word index) 201 + wordConcepts: ConceptSpan[][]; 202 + } 203 + ``` 204 + 205 + `extractData` builds this hierarchy by: 206 + 1. Extracting all word spans from `#timestamp` facets (existing logic, unchanged). 207 + 2. Reading `#paragraph` facets to get paragraph byte ranges. Sorting by `byteStart`. 208 + 3. Reading `#sentence` facets to get sentence byte ranges. Sorting by `byteStart`. 209 + 4. Assigning each word to its containing sentence (by byte range overlap). 210 + 5. Assigning each sentence to its containing paragraph (by byte range overlap). 211 + 6. Words not covered by any sentence facet form singleton sentences. Sentences not covered by any paragraph facet form singleton paragraphs. This graceful degradation means the renderer works identically on transcripts that have not yet been enriched. 212 + 213 + The brightness gradient system (`boundaryStartTime`/`boundaryEndTime`) continues to use the global word ordering — paragraph visual gaps do not affect the temporal continuity of the gradient. The existing `WordSpanComponent` is reused unchanged inside the sentence/paragraph wrappers. 214 + 215 + ### Document Assembly 216 + 217 + Document assembly is a **build-time step** that runs after the NLP pipeline and before publishing. It: 218 + 1. Reads the compact transcript record (`tv.ionosphere.transcript`). 219 + 2. Reads all layers.pub annotation layer records for this transcript. 220 + 3. Converts layers.pub sentence/paragraph annotations into `#sentence` and `#paragraph` ionosphere facets. 221 + 4. Merges with existing `#timestamp` and `#concept-ref` facets from `decodeToDocument`. 222 + 5. Writes the assembled RelationalText document onto the `tv.ionosphere.talk` record's `document` field. 223 + 224 + This replaces the current runtime assembly in the appview serve path with a pre-computed document. The appview serves the pre-assembled document directly — zero runtime cost. 225 + 226 + Annotation layers of different `subkind` values naturally have overlapping byte ranges (a paragraph span contains sentence spans, which contain word spans). This is expected and correct — they represent different levels of the hierarchy, not conflicting annotations. 227 + 228 + ### Scroll/Time Mapping 229 + 230 + Both `TranscriptView` and `WindowedTranscriptView` must account for paragraph whitespace in their scroll-to-time and time-to-scroll mappings. 231 + 232 + **TranscriptView:** The line-map computation already handles variable-height content. Paragraph `<div>` elements with margin/padding become part of the natural layout — no special handling needed beyond the existing line grouping logic. 233 + 234 + **WindowedTranscriptView:** The `computeMonospaceLayout` function currently returns `LineEntry[]` with uniform `LINE_HEIGHT`. Changes: 235 + - Accept an additional `paragraphBreaks: Set<number>` parameter (set of word indices where a paragraph starts). 236 + - When a word is a paragraph start, insert a gap of `PARAGRAPH_GAP` pixels (default: `LINE_HEIGHT`, i.e., one blank line) before its line entry. 237 + - `LineEntry` gains `isParagraphStart: boolean` for rendering the gap spacer. 238 + - Gap entries have no time range — `timeToScrollY` and `scrollYToTime` skip gaps by treating them as extensions of the preceding line's time range (scrolling through a gap seeks to the end of the previous paragraph). 239 + 240 + ## Testing Strategy 241 + 242 + **Python pipeline (pytest):** 243 + - Golden-file tests: run the sentence/paragraph pipeline on 2-3 known transcripts, compare output annotation layers to curated expected output. These transcripts should cover: a clean well-punctuated talk, a messy conversational panel, and a lightning talk with rapid transitions. 244 + - Unit tests for the paragraph algorithm: verify that paragraph breaks only land at sentence boundaries, that pauses below threshold produce no breaks, and that the proximity constraint works correctly. 245 + 246 + **TypeScript rendering (vitest):** 247 + - Unit tests for the updated `extractData`: verify hierarchical output from facets, and verify graceful degradation when sentence/paragraph facets are absent (flat word array wrapped in singleton sentence/paragraph). 248 + - Snapshot tests for `computeMonospaceLayout` with paragraph gaps. 249 + 250 + **Manual validation:** 251 + - After running the pipeline on all transcripts, spot-check 5-10 talks across different rooms/talk types. Verify paragraph breaks land at natural topic transitions, not mid-thought. Measure average sentences-per-paragraph (expect 3-8 for well-structured talks). 252 + 253 + ## Phase Roadmap 254 + 255 + ### Phase 1 — Structural formatting + layers.pub migration (this work) 256 + 257 + - Vendor layers.pub lexicon definitions into `lexicons/pub/layers/` 258 + - Python NLP pipeline: sentence detection (spaCy) + paragraph segmentation (pause + sentence alignment) 259 + - layers.pub expression + segmentation records for each transcript 260 + - Sentence and paragraph annotation layers 261 + - Panproto lenses: compact transcript <-> layers.pub expression + segmentation 262 + - Document assembly reads annotation layers, emits structural facets 263 + - Renderer: sentences as inline spans, paragraphs as block elements 264 + - Remove `tv.ionosphere.annotation` records, `enrich.ts`/`enrich-all.ts`, `overlayAnnotations` — fully replaced by layers.pub 265 + - **Goal:** Transcripts read as paragraphed prose; all enrichment flows through layers.pub 266 + 267 + ### Phase 2 — Entity recognition + record linking 268 + 269 + - spaCy NER pass in the pipeline 270 + - AT Protocol record resolver: people -> Bluesky profiles (DID resolution via handle/display name lookup), projects -> `tv.ionosphere.concept` records 271 + - Concept annotation layer replaces the old `tv.ionosphere.annotation`-based concept system with richer, NLP-derived results 272 + - Entity annotation layer with `knowledgeRefs` to resolved records 273 + - Renderer: entity spans as links/tooltips to profiles and concept pages 274 + - **Goal:** People and projects mentioned in talks are clickable, linked to real AT Protocol identities 275 + 276 + ### Phase 3 — Topic segmentation 277 + 278 + - Sentence-transformer embedding pass (e.g., `all-MiniLM-L6-v2`) 279 + - Sliding-window cosine similarity topic boundary detection 280 + - Topic segment annotation layer 281 + - Renderer: section dividers or topic labels at major transitions 282 + - UI: topic-based navigation within a talk (jump to "Q&A", "Demo", etc.) 283 + - **Goal:** Long talks become navigable by topic 284 + 285 + ### Phase 4 — Manual curation layer 286 + 287 + - UI for creating manual override annotations (correct a concept link, fix an entity, adjust a paragraph break) 288 + - Published as AT Protocol records with `sourceMethod: "manual-native"`, higher `rank` 289 + - Pipeline respects overrides on re-run 290 + - Multi-user: anyone with write access can contribute corrections 291 + - **Goal:** Community-curated enrichment that improves over time 292 + 293 + ### Phase 5 — Concept enrichment + cross-talk linking 294 + 295 + - Supersede auto-detected concepts with curated concept records 296 + - Cross-reference talks that mention the same entities/concepts 297 + - `tv.ionosphere.facet#talk-xref` links between related talks 298 + - Knowledge graph across the entire conference 299 + - **Goal:** The archive becomes a connected knowledge base, not just isolated transcripts
+113
docs/superpowers/specs/2026-04-13-layers-pub-panproto-preplan.md
··· 1 + # layers.pub Record Publishing + Panproto Lenses — Pre-Plan 2 + 3 + **Status:** Pre-plan for next session 4 + **Depends on:** Phases 1-3 enrichment (complete), concept deduplication (complete) 5 + 6 + ## Context 7 + 8 + The NLP enrichment pipeline produces sentence/paragraph/entity/topic annotations that are currently stored as ionosphere facets in pre-assembled RelationalText documents. The layers.pub lexicons are vendored (`lexicons/pub/layers/`) but no actual AT Protocol records are published. 9 + 10 + This work makes the enrichment data first-class AT Protocol records — publishable, indexable, and interoperable with the broader layers.pub ecosystem. 11 + 12 + ## What Exists 13 + 14 + ### Vendored lexicons (in `lexicons/pub/layers/`) 15 + - `defs.json` — shared types: span, temporalSpan, uuid, tokenRef, anchor, annotationMetadata, feature/featureMap 16 + - `expression/expression.json` — record: id, kind, text, language, sourceRef, parentRef, anchor, metadata 17 + - `segmentation/segmentation.json` — record: expression ref, tokenizations (with textSpan + temporalSpan per token) 18 + - `annotation/annotationLayer.json` — record: expression ref, kind/subkind, sourceMethod, annotations array 19 + 20 + ### Existing panproto integration (`formats/tv.ionosphere/ts/panproto.ts`) 21 + - WASM-based runtime (lazy singleton init) 22 + - `loadSchema()` — parse lexicon JSON into BuiltSchema 23 + - `buildMigration()` — explicit migration between schemas 24 + - `createLens()` — auto-generated lens between schemas 25 + - `autoGenerateWithHints()` — protolens chain with morphism hints 26 + - `createPipeline()` — PipelineBuilder for combinator transforms 27 + - `serializeChain()` / `serializeMigrationSpec()` — serialization for storage 28 + 29 + ### Existing lenses (`formats/tv.ionosphere/lenses/`) 30 + - `openai-whisper-to-transcript.lens.json` 31 + - `transcript-to-document.lens.json` 32 + - `schedule-to-talk.lens.json` 33 + - `vod-to-talk.lens.json` 34 + 35 + ## What Needs to Be Built 36 + 37 + ### 1. Publish layers.pub records to PDS 38 + 39 + For each transcript, publish: 40 + 41 + **Expression record** (`pub.layers.expression.expression`): 42 + - `kind: "transcript"` 43 + - `text`: the transcript text 44 + - `language: "en"` 45 + - `sourceRef`: AT URI of the `tv.ionosphere.transcript` record 46 + - `createdAt`: timestamp 47 + 48 + **Segmentation record** (`pub.layers.segmentation.segmentation`): 49 + - `expression`: AT URI of the expression record above 50 + - One tokenization with `kind: "whitespace"` 51 + - Each token has `textSpan` (byteStart/byteEnd) and `temporalSpan` (start/ending in ms) 52 + - Derived from the compact transcript's timing data 53 + 54 + **Annotation layers** (`pub.layers.annotation.annotationLayer`): 55 + - **Sentence layer**: `kind: "span"`, `subkind: "sentence-boundary"`, `sourceMethod: "automatic"` 56 + - **Paragraph layer**: `kind: "span"`, `subkind: "paragraph-boundary"`, `sourceMethod: "automatic"` 57 + - **Entity layer**: `kind: "span"`, `subkind: "ner"`, `sourceMethod: "automatic"`, with `knowledgeRefs` for resolved entities 58 + - **Topic layer**: `kind: "span"`, `subkind: "topic-segment"`, `sourceMethod: "automatic"` 59 + - Each layer references the expression record and includes `metadata` (tool, confidence, timestamp) 60 + 61 + ### 2. Panproto lenses 62 + 63 + **Lens: compact transcript → layers.pub expression + segmentation** 64 + - Source: `tv.ionosphere.transcript` (text, startMs, timings) 65 + - Target: `pub.layers.expression.expression` + `pub.layers.segmentation.segmentation` 66 + - This is the transform that `decodeToDocument` / `encode` already implement in code — the lens formalizes it 67 + 68 + **Lens: NLP annotations → layers.pub annotation layers** 69 + - Source: NLP pipeline JSON output (sentences, paragraphs, entities, topicBreaks) 70 + - Target: `pub.layers.annotation.annotationLayer` records 71 + - Mostly structural mapping — the NLP output already has byte ranges and labels 72 + 73 + **Lens: layers.pub → ionosphere document facets** 74 + - Source: layers.pub records (expression + segmentation + annotation layers) 75 + - Target: RelationalText document with ionosphere facets (#timestamp, #sentence, #paragraph, etc.) 76 + - This is the reverse of what `decodeToDocumentWithStructure` does — reading layers.pub records and emitting facets 77 + 78 + ### 3. Appview indexer updates 79 + 80 + The appview needs to index layers.pub records from Jetstream: 81 + - Add `pub.layers.expression.expression`, `pub.layers.segmentation.segmentation`, `pub.layers.annotation.annotationLayer` to `IONOSPHERE_COLLECTIONS` 82 + - Create DB tables for these records 83 + - On indexing, rebuild the pre-assembled document from the layers.pub records (using the lens) 84 + 85 + ### 4. Schema versioning 86 + 87 + - Initialize panproto VCS for the layers.pub schemas 88 + - Pin to layers.pub v0.5.0 (current vendored version) 89 + - Define migration strategy for when layers.pub evolves 90 + 91 + ## Architecture Decision: Build-Time vs Runtime 92 + 93 + Currently, document assembly happens at **build time** (publish.ts) and the assembled document is stored on the talk record. With layers.pub records, the assembly could move to **runtime** (appview reads layers.pub records and assembles on the fly). 94 + 95 + **Recommendation:** Keep build-time assembly for the ionosphere document (fast serving), AND publish layers.pub records alongside (for interoperability). The layers.pub records are the canonical source; the ionosphere document is a materialized view. 96 + 97 + ## Suggested Task Order 98 + 99 + 1. Write the publish step for layers.pub expression + segmentation records 100 + 2. Write the publish step for annotation layer records 101 + 3. Define panproto lens: compact transcript → expression + segmentation 102 + 4. Define panproto lens: NLP annotations → annotation layers 103 + 5. Update appview indexer to handle layers.pub records 104 + 6. Initialize panproto VCS, tag v0.5.0 105 + 7. Test round-trip: publish → index → serve → verify in browser 106 + 8. Define panproto lens: layers.pub → ionosphere document facets (reverse lens) 107 + 108 + ## Questions for the Session 109 + 110 + - Should we publish layers.pub records under the ionosphere.tv DID, or a separate account? 111 + - How should the appview discover which annotation layers belong to a given transcript? (By expression URI reference? By convention?) 112 + - Do we want to support third-party annotation layers from other DIDs? (e.g., someone else annotating our transcripts) 113 + - Should the panproto lenses be published as `org.relationaltext.lens` records (like the existing ones)?
+211
docs/superpowers/specs/2026-04-13-layers-pub-publishing-design.md
··· 1 + # layers.pub Record Publishing via Panproto Lenses — Design 2 + 3 + **Status:** Approved 4 + **Date:** 2026-04-13 5 + **Depends on:** NLP enrichment pipeline (complete), concept deduplication (complete) 6 + 7 + ## Overview 8 + 9 + Publish enrichment data as first-class AT Protocol records using the layers.pub schema. Panproto lenses are the authoritative transforms — all data flows through lenses, no parallel TypeScript pipelines. The existing ionosphere document (text + facets embedded on the talk record) becomes a materialized view rebuilt from layers.pub records. 10 + 11 + ## Decisions 12 + 13 + - **DID:** Publish under ionosphere.tv 14 + - **Annotation layer references:** Point to the transcript's AT URI (`tv.ionosphere.transcript`) 15 + - **Third-party layers:** Not supported yet (no moderation). Comments and reactions are unaffected. 16 + - **Lens namespace:** `org.relationaltext.lens` (consistent with existing 4 lenses) 17 + - **Record keys:** Deterministic, derived from talk rkey (e.g., `{talk.rkey}-expression`) 18 + - **Expression kind:** `kind: "transcript"` (no `kindUri` — it requires AT URI format, and there's no meaningful record to reference) 19 + - **Segmentation tokenization:** `kind: "word"` — carries the temporal mapping; annotations use `anchor.textSpan` (byte offsets) directly 20 + - **Publish ordering:** Expression URI pre-computed from DID + rkey; all records publish in parallel 21 + - **Architecture:** Lenses-first (Approach B) — lenses are authoritative, publish step runs data through lenses 22 + 23 + ## Section 1: Record Model & Relationships 24 + 25 + For each transcript, 6 new records published under ionosphere.tv: 26 + 27 + ``` 28 + tv.ionosphere.transcript/{talk.rkey}-transcript (already exists) 29 + 30 + ▼ sourceRef 31 + pub.layers.expression.expression/{talk.rkey}-expression 32 + 33 + ├── pub.layers.segmentation.segmentation/{talk.rkey}-segmentation 34 + │ └── tokenization: kind "word", tokens with textSpan + temporalSpan 35 + 36 + ├── pub.layers.annotation.annotationLayer/{talk.rkey}-sentences 37 + ├── pub.layers.annotation.annotationLayer/{talk.rkey}-paragraphs 38 + ├── pub.layers.annotation.annotationLayer/{talk.rkey}-entities 39 + └── pub.layers.annotation.annotationLayer/{talk.rkey}-topics 40 + ``` 41 + 42 + Example AT URI: `at://did:plc:xxxxxx/pub.layers.expression.expression/atproto-for-everyone-expression` 43 + 44 + > **Future work:** A `-speakers` annotation layer (`subkind: "speaker-segment"`) for diarization spans. 45 + > The NLP pipeline does not yet produce `speakerSegments` data, so this layer is deferred until the 46 + > diarization pipeline is integrated. 47 + 48 + ### Expression record 49 + 50 + | Field | Value | 51 + |---|---| 52 + | `id` | talk rkey | 53 + | `$type` | `"pub.layers.expression.expression"` | 54 + | `kind` | `"transcript"` | 55 + | `text` | full transcript text | 56 + | `language` | `"en"` | 57 + | `sourceRef` | AT URI of `tv.ionosphere.transcript` record | 58 + | `metadata` | `{ tool: "ionosphere-pipeline", timestamp: "<ISO 8601 datetime>" }` | 59 + | `createdAt` | ISO 8601 timestamp | 60 + 61 + ### Segmentation record 62 + 63 + | Field | Value | 64 + |---|---| 65 + | `expression` | AT URI of expression (pre-computed) | 66 + | `tokenizations` | Single tokenization, `kind: "word"` | 67 + | `createdAt` | ISO 8601 timestamp | 68 + 69 + Each token: `tokenIndex` (0-based), `text` (word), `textSpan` (UTF-8 byte offsets), `temporalSpan` (start/ending in ms, derived from compact transcript timings). 70 + 71 + ### Annotation layers 72 + 73 + All records include `$type: "pub.layers.annotation.annotationLayer"`. All reference the expression URI. All use `sourceMethod: "automatic"`. `createdAt` is optional in the lexicon but always included. 74 + 75 + | rkey suffix | kind | subkind | annotations | 76 + |---|---|---|---| 77 + | `-sentences` | `"span"` | `"sentence-boundary"` | One annotation per sentence. `anchor: { textSpan: { byteStart, byteEnd } }`, `label`: first ~50 chars of sentence text. | 78 + | `-paragraphs` | `"span"` | `"paragraph-boundary"` | One annotation per paragraph. `anchor: { textSpan: { byteStart, byteEnd } }`, `label`: `"paragraph"`. | 79 + | `-entities` | `"span"` | `"ner"` | One annotation per entity mention. `anchor: { textSpan: { byteStart, byteEnd } }`, `label`: entity name. `features: { entries: [{ key: "nerType", value: "PERSON" }, { key: "conceptUri", value: "at://..." }] }` — `nerType` always present, `conceptUri` if resolved, plus any future entity keys (e.g., `speakerDid`) forwarded as passthrough. | 80 + | `-topics` | `"span"` | `"topic-segment"` | One annotation per topic break. `anchor: { textSpan: { byteStart, byteEnd } }` where `byteEnd = byteStart` (zero-width span). `label`: `"topic-break"`. | 81 + 82 + `metadata` on all layers: `{ tool: "ionosphere-nlp-pipeline", timestamp: "<ISO 8601 datetime>" }`. 83 + 84 + ## Section 2: Panproto Lens Architecture 85 + 86 + Three lenses. All authoritative — data flows through them. 87 + 88 + ### Lens 1: Compact Transcript → Expression + Segmentation 89 + 90 + - **Source:** `tv.ionosphere.transcript` (text, startMs, timings) 91 + - **Target:** `pub.layers.expression.expression` + `pub.layers.segmentation.segmentation` 92 + - **Transform:** maps text → text, injects kind/language, replays timings array to produce token list with textSpan + temporalSpan 93 + - **Fan-out:** Single source → two target records (protolens chain) 94 + - **Morphism hints:** `text → text`, `startMs + timings → tokenizations[0].tokens` 95 + 96 + ### Lens 2: NLP Annotations → Annotation Layers 97 + 98 + - **Source:** `tv.ionosphere.nlpAnnotations` (new lexicon, not published to PDS — exists as lens source schema) 99 + - **Target:** 4× `pub.layers.annotation.annotationLayer` 100 + - **Transform:** Byte ranges → `anchor.textSpan`, labels → `annotation.label`, entity metadata → `features` 101 + - **Fan-out:** Single source → four target records 102 + 103 + The `tv.ionosphere.nlpAnnotations` lexicon formalizes the NlpAnnotations TypeScript interface as a proper schema that panproto can parse and validate. 104 + 105 + ### Lens 3: Layers.pub → Ionosphere Document Facets (reverse) 106 + 107 + - **Source:** expression + segmentation + annotation layers 108 + - **Target:** RelationalText document with ionosphere facets (`{ text, facets }`) 109 + - **Purpose:** Materialized view builder, used by appview indexer 110 + - **Round-trip property:** Lens 1+2 followed by Lens 3 should reproduce the same document that `decodeToDocumentWithStructure` currently produces. This is the correctness test. 111 + 112 + ### Lens storage 113 + 114 + Published as `org.relationaltext.lens` records (consistent with existing 4 lenses). Rkeys: `transcript-to-expression`, `nlp-to-annotation-layers`, `layers-to-document`. 115 + 116 + ## Section 3: Publish Pipeline 117 + 118 + New Stage 6 in `publish.ts`, runs after transcript publishing. 119 + 120 + For each talk with both transcript and NLP annotation files: 121 + 122 + 1. Load compact transcript (`transcripts/{rkey}.json`) 123 + 2. Load NLP annotations (`nlp/{rkey}.json`) 124 + 3. Run **Lens 1** via panproto WASM → expression + segmentation records 125 + 4. Run **Lens 2** via panproto WASM → 4 annotation layer records 126 + 5. Inject AT URIs (pre-computed from DID + rkey): `sourceRef` on expression, `expression` ref on segmentation and all annotation layers 127 + 6. Publish all 6 records via `PdsClient.putRecord()` (parallel within each talk, sequential across talks) 128 + 129 + **Idempotency:** Deterministic rkeys mean re-publish overwrites, no duplicates. 130 + 131 + **Rate limiting:** ~98 talks × 6 records = ~588 putRecord calls. Records within a single talk publish in parallel (6 concurrent). Talks are processed sequentially. The existing PdsClient writeDelay (100ms) and 429/backoff handling apply. 132 + 133 + **Skip condition:** If a talk has transcript but no NLP annotations, skip layers.pub entirely for that talk (keep as a unit). 134 + 135 + **WASM lifecycle:** Panproto runtime initializes once (lazy singleton), schemas load once at stage start, each talk runs data through compiled lenses. 136 + 137 + ## Section 4: Appview Indexer Updates 138 + 139 + ### New Jetstream subscriptions 140 + 141 + Add to `IONOSPHERE_COLLECTIONS`: 142 + - `pub.layers.expression.expression` 143 + - `pub.layers.segmentation.segmentation` 144 + - `pub.layers.annotation.annotationLayer` 145 + 146 + **DID filter:** Only index records from ionosphere.tv DID (no third-party layers). 147 + 148 + ### New DB tables 149 + 150 + ```sql 151 + layers_expressions: 152 + uri TEXT PRIMARY KEY, rkey TEXT, did TEXT, transcript_uri TEXT, 153 + text TEXT, language TEXT, created_at TEXT 154 + -- uri IS the expression URI; other tables reference it via expression_uri 155 + 156 + layers_segmentations: 157 + rkey TEXT, did TEXT, expression_uri TEXT, 158 + tokens_json TEXT, created_at TEXT 159 + 160 + layers_annotations: 161 + rkey TEXT, did TEXT, expression_uri TEXT, 162 + kind TEXT, subkind TEXT, annotations_json TEXT, created_at TEXT 163 + ``` 164 + 165 + Key indexes: `expression_uri` (find all layers for expression), `transcript_uri` (find expression for transcript). 166 + 167 + ### Document rebuild on ingest 168 + 169 + When any layers.pub record arrives or updates: 170 + 171 + 1. Look up the expression URI → transcript URI 172 + 2. Check for complete set: expression + segmentation + at least one annotation layer 173 + 3. If complete, run **Lens 3** (layers.pub → ionosphere document facets) to produce materialized `{ text, facets }` 174 + 4. Update the talk record's `document` field in DB 175 + 176 + **Deletion:** If an annotation layer is deleted, rebuild with remaining layers (graceful degradation — fewer annotations). If the expression record is deleted, cascade-delete its segmentation and annotation rows from the DB and clear the talk's materialized document. Annotation/segmentation JSON is stored as TEXT blobs — all queries are by expression URI, not individual annotations, so this is sufficient. 177 + 178 + **Backfill:** Add three new collections to existing startup backfill loop; records go through same ingest → rebuild path. 179 + 180 + ## Section 5: Schema Versioning 181 + 182 + ### Panproto VCS initialization 183 + 184 + - `schema init` in project 185 + - Add layers.pub lexicons + ionosphere lexicons + NLP annotations lexicon + all lens definitions 186 + - `schema commit` initial state 187 + - `schema tag v0.5.0` — pin to current vendored layers.pub version 188 + 189 + ### What's tracked 190 + 191 + - `lexicons/pub/layers/*.json` 192 + - `formats/tv.ionosphere/ionosphere.lexicon.json` 193 + - `formats/tv.ionosphere/nlpAnnotations.lexicon.json` (new) 194 + - `formats/tv.ionosphere/lenses/*.lens.json` (existing 4 + new 3) 195 + 196 + ### Migration strategy 197 + 198 + When layers.pub evolves: vendor updated lexicons, `schema diff`, update lenses if needed. The materialized view insulates the frontend — layers.pub can change without affecting ionosphere document format until we choose to update. 199 + 200 + ## Task Order 201 + 202 + 1. Define `tv.ionosphere.nlpAnnotations` lexicon (lens source schema) 203 + 2. Define Lens 1: compact transcript → expression + segmentation 204 + 3. Define Lens 2: NLP annotations → 4 annotation layers 205 + 4. Add publish Stage 6: run lenses, publish 6 records per talk 206 + 5. Define Lens 3: layers.pub → ionosphere document facets (reverse) 207 + 6. Add appview DB tables + indexer for layers.pub collections (depends on 5) 208 + 7. Wire indexer rebuild: on layers.pub ingest, run Lens 3, update talk document 209 + 8. Initialize panproto VCS, tag v0.5.0 210 + 9. Test round-trip: publish → index → rebuild → verify document matches current output 211 + 10. Deploy
+24
formats/tv.ionosphere/ionosphere.lexicon.json
··· 39 39 "featureClass": "meta", 40 40 "expandStart": false, 41 41 "expandEnd": false 42 + }, 43 + { 44 + "typeId": "tv.ionosphere.facet#sentence", 45 + "featureClass": "inline", 46 + "expandStart": false, 47 + "expandEnd": false 48 + }, 49 + { 50 + "typeId": "tv.ionosphere.facet#paragraph", 51 + "featureClass": "block", 52 + "expandStart": false, 53 + "expandEnd": false 54 + }, 55 + { 56 + "typeId": "tv.ionosphere.facet#topic-break", 57 + "featureClass": "block", 58 + "expandStart": false, 59 + "expandEnd": false 60 + }, 61 + { 62 + "typeId": "tv.ionosphere.facet#entity", 63 + "featureClass": "inline", 64 + "expandStart": false, 65 + "expandEnd": false 42 66 } 43 67 ] 44 68 }
+6
formats/tv.ionosphere/lenses/layers-to-document.lens.json
··· 1 + { 2 + "source": ["pub.layers.expression.expression", "pub.layers.segmentation.segmentation", "pub.layers.annotation.annotationLayer"], 3 + "target": "tv.ionosphere.document", 4 + "version": 1, 5 + "description": "Layers.pub records to ionosphere RelationalText document with facets (materialized view builder)" 6 + }
+12
formats/tv.ionosphere/lenses/nlp-to-annotation-layers.lens.json
··· 1 + { 2 + "source": "tv.ionosphere.nlpAnnotations", 3 + "target": ["pub.layers.annotation.annotationLayer"], 4 + "version": 1, 5 + "description": "NLP annotations to 4 annotation layer records (sentences, paragraphs, entities, topics)", 6 + "fanOut": { 7 + "sentences": { "subkind": "sentence-boundary", "from": "sentences" }, 8 + "paragraphs": { "subkind": "paragraph-boundary", "from": "paragraphs" }, 9 + "entities": { "subkind": "ner", "from": "entities" }, 10 + "topics": { "subkind": "topic-segment", "from": "topicBreaks" } 11 + } 12 + }
+10
formats/tv.ionosphere/lenses/transcript-to-expression.lens.json
··· 1 + { 2 + "source": "tv.ionosphere.transcript", 3 + "target": ["pub.layers.expression.expression", "pub.layers.segmentation.segmentation"], 4 + "version": 1, 5 + "description": "Compact transcript to layers.pub expression + segmentation", 6 + "mappings": { 7 + "text": "expression.text", 8 + "startMs + timings": "segmentation.tokenizations[0].tokens" 9 + } 10 + }
+148
formats/tv.ionosphere/nlpAnnotations.lexicon.json
··· 1 + { 2 + "lexicon": 1, 3 + "$type": "com.atproto.lexicon.schema", 4 + "id": "tv.ionosphere.nlpAnnotations", 5 + "revision": 1, 6 + "description": "NLP pipeline output for a conference talk transcript. Formalizes the JSON shape produced by the ionosphere NLP pipeline so panproto can use it as a lens source schema. Not published to PDS.", 7 + "defs": { 8 + "main": { 9 + "type": "record", 10 + "key": "any", 11 + "record": { 12 + "type": "object", 13 + "required": ["talkRkey", "sentences", "paragraphs", "entities", "topicBreaks", "metadata"], 14 + "properties": { 15 + "talkRkey": { 16 + "type": "string", 17 + "description": "The rkey of the tv.ionosphere.talk record this annotation set covers." 18 + }, 19 + "sentences": { 20 + "type": "array", 21 + "items": { 22 + "type": "ref", 23 + "ref": "tv.ionosphere.nlpAnnotations#nlpSentence" 24 + }, 25 + "description": "Sentence-boundary spans detected in the transcript text." 26 + }, 27 + "paragraphs": { 28 + "type": "array", 29 + "items": { 30 + "type": "ref", 31 + "ref": "tv.ionosphere.nlpAnnotations#nlpParagraph" 32 + }, 33 + "description": "Paragraph-boundary spans detected in the transcript text." 34 + }, 35 + "entities": { 36 + "type": "array", 37 + "items": { 38 + "type": "ref", 39 + "ref": "tv.ionosphere.nlpAnnotations#nlpEntity" 40 + }, 41 + "description": "Named entities detected in the transcript text." 42 + }, 43 + "topicBreaks": { 44 + "type": "array", 45 + "items": { 46 + "type": "ref", 47 + "ref": "tv.ionosphere.nlpAnnotations#nlpTopicBreak" 48 + }, 49 + "description": "Byte positions where a topic shift was detected." 50 + }, 51 + "metadata": { 52 + "type": "ref", 53 + "ref": "tv.ionosphere.nlpAnnotations#nlpMetadata", 54 + "description": "Provenance and configuration metadata for this annotation run." 55 + } 56 + } 57 + } 58 + }, 59 + "nlpSentence": { 60 + "type": "object", 61 + "description": "A sentence span identified by the NLP pipeline.", 62 + "required": ["byteStart", "byteEnd"], 63 + "properties": { 64 + "byteStart": { 65 + "type": "integer", 66 + "description": "Inclusive start byte offset into the transcript text." 67 + }, 68 + "byteEnd": { 69 + "type": "integer", 70 + "description": "Exclusive end byte offset into the transcript text." 71 + } 72 + } 73 + }, 74 + "nlpParagraph": { 75 + "type": "object", 76 + "description": "A paragraph span identified by the NLP pipeline.", 77 + "required": ["byteStart", "byteEnd"], 78 + "properties": { 79 + "byteStart": { 80 + "type": "integer", 81 + "description": "Inclusive start byte offset into the transcript text." 82 + }, 83 + "byteEnd": { 84 + "type": "integer", 85 + "description": "Exclusive end byte offset into the transcript text." 86 + } 87 + } 88 + }, 89 + "nlpEntity": { 90 + "type": "object", 91 + "description": "A named entity span identified by the NLP pipeline.", 92 + "required": ["byteStart", "byteEnd", "label", "nerType"], 93 + "properties": { 94 + "byteStart": { 95 + "type": "integer", 96 + "description": "Inclusive start byte offset into the transcript text." 97 + }, 98 + "byteEnd": { 99 + "type": "integer", 100 + "description": "Exclusive end byte offset into the transcript text." 101 + }, 102 + "label": { 103 + "type": "string", 104 + "description": "Surface text of the named entity (e.g. 'Matt')." 105 + }, 106 + "nerType": { 107 + "type": "string", 108 + "description": "NER category label (e.g. PERSON, ORG, GPE)." 109 + }, 110 + "conceptUri": { 111 + "type": "string", 112 + "format": "at-uri", 113 + "description": "AT URI of a canonical concept record for this entity, if resolved." 114 + } 115 + } 116 + }, 117 + "nlpTopicBreak": { 118 + "type": "object", 119 + "description": "A position in the transcript text where the NLP pipeline detected a topic shift.", 120 + "required": ["byteStart"], 121 + "properties": { 122 + "byteStart": { 123 + "type": "integer", 124 + "description": "Byte offset at which the topic shift begins." 125 + } 126 + } 127 + }, 128 + "nlpMetadata": { 129 + "type": "object", 130 + "description": "Provenance and configuration metadata for an NLP annotation run.", 131 + "required": ["tool"], 132 + "properties": { 133 + "tool": { 134 + "type": "string", 135 + "description": "Name and version of the NLP tool used (e.g. 'spacy/en_core_web_sm')." 136 + }, 137 + "pauseThresholdMs": { 138 + "type": "integer", 139 + "description": "Silence duration in milliseconds used to delimit paragraphs." 140 + }, 141 + "proximityWords": { 142 + "type": "integer", 143 + "description": "Word-window radius used when linking entity mentions to concepts." 144 + } 145 + } 146 + } 147 + } 148 + }
+2 -1
formats/tv.ionosphere/package.json
··· 8 8 "./assemble": "./ts/assemble.ts", 9 9 "./lenses": "./ts/lenses.ts", 10 10 "./panproto": "./ts/panproto.ts", 11 - "./transcript-encoding": "./ts/transcript-encoding.ts" 11 + "./transcript-encoding": "./ts/transcript-encoding.ts", 12 + "./layers-pub": "./ts/layers-pub.ts" 12 13 }, 13 14 "dependencies": { 14 15 "@msgpack/msgpack": "^3.1.3",
+472
formats/tv.ionosphere/ts/layers-pub.ts
··· 1 + /** 2 + * Lens transforms between tv.ionosphere records and pub.layers records. 3 + * 4 + * Lens 1: transcriptToLayersPub 5 + * tv.ionosphere.transcript → pub.layers.expression.expression 6 + * + pub.layers.segmentation.segmentation 7 + * 8 + * Lens 2: nlpToAnnotationLayers 9 + * NLP annotations → 4 pub.layers.annotation.annotationLayer records 10 + * 11 + * Lens 3: layersPubToDocument (reverse) 12 + * pub.layers records → tv.ionosphere document with facets 13 + * 14 + * The timings replay algorithm matches decodeToDocument() in 15 + * transcript-encoding.ts — uses TextEncoder for correct UTF-8 byte offsets, 16 + * and indexOf with searchFrom for word position tracking. 17 + */ 18 + 19 + import type { Document, DocumentFacet, CompactTranscript } from './transcript-encoding.js'; 20 + 21 + export interface TranscriptRecord { 22 + $type: string; 23 + talkUri: string; 24 + text: string; 25 + startMs: number; 26 + timings: number[]; 27 + } 28 + 29 + export interface ExpressionRecord { 30 + $type: 'pub.layers.expression.expression'; 31 + id: string; 32 + kind: string; 33 + text: string; 34 + language: string; 35 + sourceRef: string; 36 + metadata: { 37 + tool: string; 38 + timestamp: string; 39 + }; 40 + createdAt: string; 41 + } 42 + 43 + export interface TokenSpan { 44 + byteStart: number; 45 + byteEnd: number; 46 + } 47 + 48 + export interface TemporalSpan { 49 + start: number; 50 + ending: number; 51 + } 52 + 53 + export interface TextToken { 54 + tokenIndex: number; 55 + textSpan: TokenSpan; 56 + } 57 + 58 + export interface TemporalToken { 59 + tokenIndex: number; 60 + temporalSpan: TemporalSpan; 61 + } 62 + 63 + export interface TextTokenization { 64 + kind: string; 65 + tokens: TextToken[]; 66 + } 67 + 68 + export interface TemporalTokenization { 69 + kind: string; 70 + tokens: TemporalToken[]; 71 + } 72 + 73 + export interface SegmentationRecord { 74 + $type: 'pub.layers.segmentation.segmentation'; 75 + expression: string; 76 + tokenizations: TextTokenization[]; 77 + createdAt: string; 78 + } 79 + 80 + export interface TemporalSegmentationRecord { 81 + $type: 'pub.layers.segmentation.segmentation'; 82 + expression: string; 83 + tokenizations: TemporalTokenization[]; 84 + createdAt: string; 85 + } 86 + 87 + /** Maximum tokens per segmentation record to stay under PDS body limits (~200KB CBOR) */ 88 + const MAX_TOKENS_PER_RECORD = 2000; 89 + 90 + export interface LayersPubResult { 91 + expression: ExpressionRecord; 92 + segmentations: SegmentationRecord[]; 93 + temporals: TemporalSegmentationRecord[]; 94 + } 95 + 96 + /** 97 + * Lens 1: Transform a compact transcript record into layers.pub 98 + * expression + segmentation records. 99 + * 100 + * The timings replay algorithm (matching decodeToDocument): 101 + * - Split text by whitespace to get words 102 + * - Use TextEncoder for UTF-8 byte offsets 103 + * - Initialize cursor at startMs 104 + * - Iterate timings: negative = silence gap, positive = word duration 105 + * - Each word becomes a token with text span and temporal span 106 + */ 107 + export async function transcriptToLayersPub( 108 + transcript: TranscriptRecord, 109 + did: string, 110 + talkRkey: string, 111 + ): Promise<LayersPubResult> { 112 + const now = new Date().toISOString(); 113 + 114 + // Build expression record 115 + const expression: ExpressionRecord = { 116 + $type: 'pub.layers.expression.expression', 117 + id: talkRkey, 118 + kind: 'transcript', 119 + text: transcript.text, 120 + language: 'en', 121 + sourceRef: `at://${did}/tv.ionosphere.transcript/${talkRkey}-transcript`, 122 + metadata: { 123 + tool: 'ionosphere-pipeline', 124 + timestamp: now, 125 + }, 126 + createdAt: now, 127 + }; 128 + 129 + // Build segmentation records using timings replay algorithm 130 + // (matches decodeToDocument in transcript-encoding.ts) 131 + // Two records: textSpan-only (word boundaries) and temporalSpan-only (timing) 132 + const encoder = new TextEncoder(); 133 + const words = transcript.text.split(/\s+/).filter((w) => w.length > 0); 134 + const textTokens: TextToken[] = []; 135 + const temporalTokens: TemporalToken[] = []; 136 + 137 + let cursor = transcript.startMs; // ms 138 + let wordIndex = 0; 139 + let searchFrom = 0; 140 + 141 + for (const value of transcript.timings) { 142 + if (value < 0) { 143 + // Silence gap — advance cursor by absolute value 144 + cursor += Math.abs(value); 145 + } else { 146 + // Word duration 147 + if (wordIndex < words.length) { 148 + const word = words[wordIndex]; 149 + const idx = transcript.text.indexOf(word, searchFrom); 150 + if (idx !== -1) { 151 + const byteStart = encoder.encode(transcript.text.slice(0, idx)).length; 152 + const byteEnd = encoder.encode( 153 + transcript.text.slice(0, idx + word.length), 154 + ).length; 155 + 156 + textTokens.push({ 157 + tokenIndex: wordIndex, 158 + textSpan: { byteStart, byteEnd }, 159 + }); 160 + 161 + temporalTokens.push({ 162 + tokenIndex: wordIndex, 163 + temporalSpan: { start: cursor, ending: cursor + value }, 164 + }); 165 + 166 + searchFrom = idx + word.length; 167 + } 168 + cursor += value; 169 + wordIndex++; 170 + } 171 + } 172 + } 173 + 174 + const expressionUri = `at://${did}/pub.layers.expression.expression/${talkRkey}-expression`; 175 + 176 + // Chunk tokens to stay under PDS body limits 177 + const segmentations: SegmentationRecord[] = []; 178 + const temporals: TemporalSegmentationRecord[] = []; 179 + 180 + for (let i = 0; i < textTokens.length; i += MAX_TOKENS_PER_RECORD) { 181 + const textChunk = textTokens.slice(i, i + MAX_TOKENS_PER_RECORD); 182 + const temporalChunk = temporalTokens.slice(i, i + MAX_TOKENS_PER_RECORD); 183 + 184 + segmentations.push({ 185 + $type: 'pub.layers.segmentation.segmentation', 186 + expression: expressionUri, 187 + tokenizations: [{ kind: 'word', tokens: textChunk }], 188 + createdAt: now, 189 + }); 190 + 191 + temporals.push({ 192 + $type: 'pub.layers.segmentation.segmentation', 193 + expression: expressionUri, 194 + tokenizations: [{ kind: 'word-temporal', tokens: temporalChunk }], 195 + createdAt: now, 196 + }); 197 + } 198 + 199 + return { expression, segmentations, temporals }; 200 + } 201 + 202 + /** 203 + * Lens 2: Transform NLP annotations into 4 pub.layers annotation layer records. 204 + * 205 + * Produces: 206 + * - sentences layer (sentence-boundary spans) 207 + * - paragraphs layer (paragraph-boundary spans) 208 + * - entities layer (NER spans with featureMap) 209 + * - topics layer (topic-segment zero-width spans) 210 + */ 211 + 212 + export interface NlpAnnotations { 213 + talkRkey: string; 214 + sentences: Array<{ byteStart: number; byteEnd: number }>; 215 + paragraphs: Array<{ byteStart: number; byteEnd: number }>; 216 + entities: Array<{ 217 + byteStart: number; 218 + byteEnd: number; 219 + label: string; 220 + [key: string]: unknown; 221 + }>; 222 + topicBreaks: Array<{ byteStart: number }>; 223 + metadata: { tool: string; [key: string]: unknown }; 224 + } 225 + 226 + export interface Annotation { 227 + anchor: { textSpan: { byteStart: number; byteEnd: number } }; 228 + label: string; 229 + features?: { entries: Array<{ key: string; value: unknown }> }; 230 + } 231 + 232 + export interface AnnotationLayerRecord { 233 + $type: 'pub.layers.annotation.annotationLayer'; 234 + expression: string; 235 + kind: string; 236 + subkind: string; 237 + sourceMethod: string; 238 + metadata: { tool: string; timestamp: string }; 239 + annotations: Annotation[]; 240 + createdAt: string; 241 + } 242 + 243 + export interface AnnotationLayersResult { 244 + sentences: AnnotationLayerRecord; 245 + paragraphs: AnnotationLayerRecord; 246 + entities: AnnotationLayerRecord; 247 + topics: AnnotationLayerRecord; 248 + } 249 + 250 + export async function nlpToAnnotationLayers( 251 + nlpAnnotations: NlpAnnotations, 252 + did: string, 253 + talkRkey: string, 254 + expressionUri: string, 255 + ): Promise<AnnotationLayersResult> { 256 + const now = new Date().toISOString(); 257 + 258 + const baseMeta = { 259 + tool: 'ionosphere-nlp-pipeline', 260 + timestamp: now, 261 + }; 262 + 263 + // Keys to exclude when forwarding entity fields to featureMap entries 264 + const entityExcludeKeys = new Set(['byteStart', 'byteEnd', 'label']); 265 + 266 + // Sentences layer 267 + const sentences: AnnotationLayerRecord = { 268 + $type: 'pub.layers.annotation.annotationLayer', 269 + expression: expressionUri, 270 + kind: 'span', 271 + subkind: 'sentence-boundary', 272 + sourceMethod: 'automatic', 273 + metadata: { ...baseMeta }, 274 + annotations: nlpAnnotations.sentences.map((s) => ({ 275 + anchor: { textSpan: { byteStart: s.byteStart, byteEnd: s.byteEnd } }, 276 + label: 'sentence', 277 + })), 278 + createdAt: now, 279 + }; 280 + 281 + // Paragraphs layer 282 + const paragraphs: AnnotationLayerRecord = { 283 + $type: 'pub.layers.annotation.annotationLayer', 284 + expression: expressionUri, 285 + kind: 'span', 286 + subkind: 'paragraph-boundary', 287 + sourceMethod: 'automatic', 288 + metadata: { ...baseMeta }, 289 + annotations: nlpAnnotations.paragraphs.map((p) => ({ 290 + anchor: { textSpan: { byteStart: p.byteStart, byteEnd: p.byteEnd } }, 291 + label: 'paragraph', 292 + })), 293 + createdAt: now, 294 + }; 295 + 296 + // Entities layer — forward all extra keys into featureMap entries 297 + const entities: AnnotationLayerRecord = { 298 + $type: 'pub.layers.annotation.annotationLayer', 299 + expression: expressionUri, 300 + kind: 'span', 301 + subkind: 'ner', 302 + sourceMethod: 'automatic', 303 + metadata: { ...baseMeta }, 304 + annotations: nlpAnnotations.entities.map((e) => { 305 + const entries: Array<{ key: string; value: unknown }> = []; 306 + for (const [key, value] of Object.entries(e)) { 307 + if (!entityExcludeKeys.has(key)) { 308 + entries.push({ key, value }); 309 + } 310 + } 311 + return { 312 + anchor: { textSpan: { byteStart: e.byteStart, byteEnd: e.byteEnd } }, 313 + label: e.label, 314 + features: { entries }, 315 + }; 316 + }), 317 + createdAt: now, 318 + }; 319 + 320 + // Topics layer — zero-width spans (byteEnd === byteStart) 321 + const topics: AnnotationLayerRecord = { 322 + $type: 'pub.layers.annotation.annotationLayer', 323 + expression: expressionUri, 324 + kind: 'span', 325 + subkind: 'topic-segment', 326 + sourceMethod: 'automatic', 327 + metadata: { ...baseMeta }, 328 + annotations: nlpAnnotations.topicBreaks.map((t) => ({ 329 + anchor: { textSpan: { byteStart: t.byteStart, byteEnd: t.byteStart } }, 330 + label: 'topic-break', 331 + })), 332 + createdAt: now, 333 + }; 334 + 335 + return { sentences, paragraphs, entities, topics }; 336 + } 337 + 338 + /** 339 + * Lens 3 (reverse): Transform pub.layers records back into an ionosphere 340 + * RelationalText document with facets. 341 + * 342 + * This is the materialized view builder — used by the appview indexer to 343 + * rebuild the talk document when layers.pub records arrive via Jetstream. 344 + * 345 + * Timestamp facets are generated from the compact transcript (text + startMs 346 + * + timings), not from segmentation temporalSpans. This allows the 347 + * segmentation record to remain small (textSpan only) while keeping temporal 348 + * data available separately. 349 + * 350 + * Round-trip property: 351 + * transcriptToLayersPub + nlpToAnnotationLayers + layersPubToDocument 352 + * should produce the SAME document as decodeToDocumentWithStructure. 353 + */ 354 + export async function layersPubToDocument( 355 + expression: ExpressionRecord, 356 + segmentations: SegmentationRecord | SegmentationRecord[], 357 + annotationLayers: AnnotationLayersResult, 358 + compact?: CompactTranscript, 359 + ): Promise<Document> { 360 + const facets: DocumentFacet[] = []; 361 + 362 + // Merge all segmentation chunks into a single token list 363 + const segArray = Array.isArray(segmentations) ? segmentations : [segmentations]; 364 + const allTokens = segArray.flatMap((s) => s.tokenizations[0].tokens); 365 + 366 + // 1. Timestamp facets from compact transcript timings 367 + // Uses the same replay algorithm as decodeToDocument() — the segmentation 368 + // provides byte offsets, the compact transcript provides timing. 369 + if (compact) { 370 + let cursor = compact.startMs; 371 + let tokenIdx = 0; 372 + 373 + for (const value of compact.timings) { 374 + if (value < 0) { 375 + cursor += Math.abs(value); 376 + } else { 377 + if (tokenIdx < allTokens.length) { 378 + const token = allTokens[tokenIdx]; 379 + facets.push({ 380 + index: { 381 + byteStart: token.textSpan.byteStart, 382 + byteEnd: token.textSpan.byteEnd, 383 + }, 384 + features: [ 385 + { 386 + $type: 'tv.ionosphere.facet#timestamp', 387 + startTime: cursor * 1_000_000, // ms → ns 388 + endTime: (cursor + value) * 1_000_000, 389 + }, 390 + ], 391 + }); 392 + cursor += value; 393 + tokenIdx++; 394 + } 395 + } 396 + } 397 + } 398 + 399 + // 2. Sentence facets 400 + for (const ann of annotationLayers.sentences.annotations) { 401 + facets.push({ 402 + index: { 403 + byteStart: ann.anchor.textSpan.byteStart, 404 + byteEnd: ann.anchor.textSpan.byteEnd, 405 + }, 406 + features: [{ $type: 'tv.ionosphere.facet#sentence' }], 407 + }); 408 + } 409 + 410 + // 3. Paragraph facets 411 + for (const ann of annotationLayers.paragraphs.annotations) { 412 + facets.push({ 413 + index: { 414 + byteStart: ann.anchor.textSpan.byteStart, 415 + byteEnd: ann.anchor.textSpan.byteEnd, 416 + }, 417 + features: [{ $type: 'tv.ionosphere.facet#paragraph' }], 418 + }); 419 + } 420 + 421 + // 4. Entity facets — route based on features entries 422 + // conceptUri → #concept-ref, else → #entity 423 + // (speakerDid routing not needed — zero instances in actual data) 424 + for (const ann of annotationLayers.entities.annotations) { 425 + const entries = ann.features?.entries ?? []; 426 + const conceptUriEntry = entries.find((e) => e.key === 'conceptUri'); 427 + const nerTypeEntry = entries.find((e) => e.key === 'nerType'); 428 + 429 + if (conceptUriEntry) { 430 + facets.push({ 431 + index: { 432 + byteStart: ann.anchor.textSpan.byteStart, 433 + byteEnd: ann.anchor.textSpan.byteEnd, 434 + }, 435 + features: [ 436 + { 437 + $type: 'tv.ionosphere.facet#concept-ref', 438 + conceptUri: conceptUriEntry.value, 439 + conceptName: ann.label, 440 + }, 441 + ], 442 + }); 443 + } else { 444 + facets.push({ 445 + index: { 446 + byteStart: ann.anchor.textSpan.byteStart, 447 + byteEnd: ann.anchor.textSpan.byteEnd, 448 + }, 449 + features: [ 450 + { 451 + $type: 'tv.ionosphere.facet#entity', 452 + label: ann.label, 453 + nerType: nerTypeEntry?.value, 454 + }, 455 + ], 456 + }); 457 + } 458 + } 459 + 460 + // 5. Topic break facets 461 + for (const ann of annotationLayers.topics.annotations) { 462 + facets.push({ 463 + index: { 464 + byteStart: ann.anchor.textSpan.byteStart, 465 + byteEnd: ann.anchor.textSpan.byteEnd, 466 + }, 467 + features: [{ $type: 'tv.ionosphere.facet#topic-break' }], 468 + }); 469 + } 470 + 471 + return { text: expression.text, facets }; 472 + }
+82 -1
formats/tv.ionosphere/ts/transcript-encoding.test.ts
··· 1 1 import { describe, it, expect } from "vitest"; 2 - import { encode, decode, decodeToDocument, type CompactTranscript } from "./transcript-encoding.js"; 2 + import { encode, decode, decodeToDocument, decodeToDocumentWithStructure, type CompactTranscript } from "./transcript-encoding.js"; 3 3 import type { TranscriptResult } from "./index.js"; 4 4 5 5 describe("transcript encoding", () => { ··· 117 117 118 118 console.log(`Compact: ${compactSize} bytes, Full: ${fullSize} bytes, Ratio: ${(fullSize / compactSize).toFixed(1)}x`); 119 119 expect(compactSize).toBeLessThan(fullSize); 120 + }); 121 + }); 122 + 123 + describe("decodeToDocumentWithStructure", () => { 124 + it("adds sentence and paragraph facets from NLP annotations", () => { 125 + const compact = encode(contiguous); 126 + const annotations = { 127 + sentences: [ 128 + { byteStart: 0, byteEnd: 11 }, // "hello world" 129 + { byteStart: 12, byteEnd: 26 }, // "this is a test" 130 + ], 131 + paragraphs: [ 132 + { byteStart: 0, byteEnd: 26 }, 133 + ], 134 + }; 135 + const doc = decodeToDocumentWithStructure(compact, annotations); 136 + 137 + const sentenceFacets = doc.facets.filter(f => 138 + f.features.some(feat => feat.$type === "tv.ionosphere.facet#sentence") 139 + ); 140 + const paragraphFacets = doc.facets.filter(f => 141 + f.features.some(feat => feat.$type === "tv.ionosphere.facet#paragraph") 142 + ); 143 + expect(sentenceFacets).toHaveLength(2); 144 + expect(paragraphFacets).toHaveLength(1); 145 + // Original timestamp facets still present 146 + const tsFacets = doc.facets.filter(f => 147 + f.features.some(feat => feat.$type === "tv.ionosphere.facet#timestamp") 148 + ); 149 + expect(tsFacets).toHaveLength(6); 150 + }); 151 + 152 + it("produces valid document without annotations (backward compatible)", () => { 153 + const compact = encode(contiguous); 154 + const doc = decodeToDocumentWithStructure(compact, null); 155 + // Same as decodeToDocument — just timestamp facets 156 + expect(doc.facets.length).toBe(6); 157 + }); 158 + 159 + it("adds entity, speaker-segment, and topic-break facets", () => { 160 + const compact = encode(contiguous); 161 + const annotations = { 162 + sentences: [{ byteStart: 0, byteEnd: 26 }], 163 + paragraphs: [{ byteStart: 0, byteEnd: 26 }], 164 + entities: [ 165 + { byteStart: 0, byteEnd: 5, label: "hello", nerType: "PERSON", speakerDid: "did:plc:abc123" }, 166 + { byteStart: 6, byteEnd: 11, label: "world", nerType: "ORG", conceptUri: "at://did:plc:xyz/tv.ionosphere.concept/test" }, 167 + { byteStart: 12, byteEnd: 16, label: "this", nerType: "PRODUCT" }, 168 + ], 169 + speakerSegments: [ 170 + { byteStart: 0, byteEnd: 26, speakerDid: "did:plc:abc123", speakerName: "Test Speaker" }, 171 + ], 172 + topicBreaks: [{ byteStart: 12 }], 173 + }; 174 + const doc = decodeToDocumentWithStructure(compact, annotations); 175 + 176 + const speakerRefs = doc.facets.filter(f => f.features.some(feat => feat.$type === "tv.ionosphere.facet#speaker-ref")); 177 + const conceptRefs = doc.facets.filter(f => f.features.some(feat => feat.$type === "tv.ionosphere.facet#concept-ref")); 178 + const entities = doc.facets.filter(f => f.features.some(feat => feat.$type === "tv.ionosphere.facet#entity")); 179 + const speakerSegs = doc.facets.filter(f => f.features.some(feat => feat.$type === "tv.ionosphere.facet#speaker-segment")); 180 + const topicBreaks = doc.facets.filter(f => f.features.some(feat => feat.$type === "tv.ionosphere.facet#topic-break")); 181 + 182 + expect(speakerRefs).toHaveLength(1); 183 + expect(speakerRefs[0].features[0].speakerDid).toBe("did:plc:abc123"); 184 + expect(conceptRefs).toHaveLength(1); 185 + expect(conceptRefs[0].features[0].conceptUri).toBe("at://did:plc:xyz/tv.ionosphere.concept/test"); 186 + expect(entities).toHaveLength(1); 187 + expect(entities[0].features[0].label).toBe("this"); 188 + expect(speakerSegs).toHaveLength(1); 189 + expect(topicBreaks).toHaveLength(1); 190 + }); 191 + 192 + it("handles missing optional annotation fields gracefully", () => { 193 + const compact = encode(contiguous); 194 + const annotations = { 195 + sentences: [{ byteStart: 0, byteEnd: 26 }], 196 + paragraphs: [{ byteStart: 0, byteEnd: 26 }], 197 + }; 198 + const doc = decodeToDocumentWithStructure(compact, annotations); 199 + const tsFacets = doc.facets.filter(f => f.features.some(feat => feat.$type === "tv.ionosphere.facet#timestamp")); 200 + expect(tsFacets).toHaveLength(6); 120 201 }); 121 202 }); 122 203 });
+80
formats/tv.ionosphere/ts/transcript-encoding.ts
··· 145 145 146 146 return { text: compact.text, facets }; 147 147 } 148 + 149 + export interface NlpAnnotations { 150 + sentences: Array<{ byteStart: number; byteEnd: number }>; 151 + paragraphs: Array<{ byteStart: number; byteEnd: number }>; 152 + entities?: Array<{ 153 + byteStart: number; byteEnd: number; 154 + label: string; nerType: string; 155 + speakerDid?: string; conceptUri?: string; 156 + }>; 157 + speakerSegments?: Array<{ 158 + byteStart: number; byteEnd: number; 159 + speakerDid: string; speakerName: string; 160 + }>; 161 + topicBreaks?: Array<{ byteStart: number }>; 162 + } 163 + 164 + /** 165 + * Decode compact format into a RelationalText document with timestamp facets 166 + * plus sentence and paragraph structural facets from NLP pipeline output. 167 + */ 168 + export function decodeToDocumentWithStructure( 169 + compact: CompactTranscript, 170 + annotations: NlpAnnotations | null, 171 + ): Document { 172 + const doc = decodeToDocument(compact); 173 + 174 + if (!annotations) return doc; 175 + 176 + for (const s of annotations.sentences) { 177 + doc.facets.push({ 178 + index: { byteStart: s.byteStart, byteEnd: s.byteEnd }, 179 + features: [{ $type: "tv.ionosphere.facet#sentence" }], 180 + }); 181 + } 182 + 183 + for (const p of annotations.paragraphs) { 184 + doc.facets.push({ 185 + index: { byteStart: p.byteStart, byteEnd: p.byteEnd }, 186 + features: [{ $type: "tv.ionosphere.facet#paragraph" }], 187 + }); 188 + } 189 + 190 + // Entity facets — route to speaker-ref, concept-ref, or generic entity 191 + for (const e of annotations.entities ?? []) { 192 + if (e.speakerDid) { 193 + doc.facets.push({ 194 + index: { byteStart: e.byteStart, byteEnd: e.byteEnd }, 195 + features: [{ $type: "tv.ionosphere.facet#speaker-ref", speakerDid: e.speakerDid, label: e.label }], 196 + }); 197 + } else if (e.conceptUri) { 198 + doc.facets.push({ 199 + index: { byteStart: e.byteStart, byteEnd: e.byteEnd }, 200 + features: [{ $type: "tv.ionosphere.facet#concept-ref", conceptUri: e.conceptUri, conceptName: e.label }], 201 + }); 202 + } else { 203 + doc.facets.push({ 204 + index: { byteStart: e.byteStart, byteEnd: e.byteEnd }, 205 + features: [{ $type: "tv.ionosphere.facet#entity", label: e.label, nerType: e.nerType }], 206 + }); 207 + } 208 + } 209 + 210 + // Speaker segment facets 211 + for (const seg of annotations.speakerSegments ?? []) { 212 + doc.facets.push({ 213 + index: { byteStart: seg.byteStart, byteEnd: seg.byteEnd }, 214 + features: [{ $type: "tv.ionosphere.facet#speaker-segment", speakerDid: seg.speakerDid, speakerName: seg.speakerName }], 215 + }); 216 + } 217 + 218 + // Topic break facets 219 + for (const tb of annotations.topicBreaks ?? []) { 220 + doc.facets.push({ 221 + index: { byteStart: tb.byteStart, byteEnd: tb.byteStart }, 222 + features: [{ $type: "tv.ionosphere.facet#topic-break" }], 223 + }); 224 + } 225 + 226 + return doc; 227 + }
+114
lexicons/pub/layers/annotation/annotationLayer.json
··· 1 + { 2 + "lexicon": 1, 3 + "$type": "com.atproto.lexicon.schema", 4 + "id": "pub.layers.annotation.annotationLayer", 5 + "revision": 1, 6 + "description": "An annotation layer attaching typed annotations to a pub.layers.expression. Covers token-tag, span, relation, tree, and other layer kinds. Each annotation has an anchor, a label, and optional confidence and features.", 7 + "defs": { 8 + "main": { 9 + "type": "record", 10 + "key": "any", 11 + "record": { 12 + "type": "object", 13 + "required": ["expression", "kind", "subkind", "sourceMethod", "annotations"], 14 + "properties": { 15 + "expression": { 16 + "type": "string", 17 + "format": "at-uri", 18 + "description": "AT URI of the pub.layers.expression.expression this layer annotates." 19 + }, 20 + "kindUri": { 21 + "type": "string", 22 + "format": "at-uri", 23 + "description": "AT URI of a record formally defining the annotation layer kind." 24 + }, 25 + "kind": { 26 + "type": "string", 27 + "description": "Layer kind: token-tag, span, relation, tree, etc." 28 + }, 29 + "subkindUri": { 30 + "type": "string", 31 + "format": "at-uri", 32 + "description": "AT URI of a record formally defining the annotation subkind (e.g. a specific tag set)." 33 + }, 34 + "subkind": { 35 + "type": "string", 36 + "description": "More specific categorisation within the layer kind (e.g. POS, NER, dependency)." 37 + }, 38 + "sourceMethodUri": { 39 + "type": "string", 40 + "format": "at-uri", 41 + "description": "AT URI of a record formally defining the source method." 42 + }, 43 + "sourceMethod": { 44 + "type": "string", 45 + "description": "How annotations were produced: manual-native, automatic, converted, etc." 46 + }, 47 + "annotations": { 48 + "type": "array", 49 + "items": { 50 + "type": "ref", 51 + "ref": "pub.layers.annotation.annotationLayer#annotation" 52 + }, 53 + "description": "The individual annotations that make up this layer." 54 + }, 55 + "tokenizationId": { 56 + "type": "ref", 57 + "ref": "pub.layers.defs#uuid", 58 + "description": "UUID of the tokenization this layer is aligned to (for token-tag layers)." 59 + }, 60 + "rank": { 61 + "type": "integer", 62 + "description": "Ordering rank when multiple layers of the same kind exist on the same expression." 63 + }, 64 + "metadata": { 65 + "type": "ref", 66 + "ref": "pub.layers.defs#annotationMetadata", 67 + "description": "Provenance metadata for this layer." 68 + }, 69 + "createdAt": { 70 + "type": "string", 71 + "format": "datetime", 72 + "description": "ISO 8601 datetime when this record was created." 73 + } 74 + } 75 + } 76 + }, 77 + "annotation": { 78 + "type": "object", 79 + "description": "A single annotation within an annotation layer.", 80 + "required": ["label"], 81 + "properties": { 82 + "uuid": { 83 + "type": "ref", 84 + "ref": "pub.layers.defs#uuid", 85 + "description": "Stable UUID for this annotation." 86 + }, 87 + "anchor": { 88 + "type": "ref", 89 + "ref": "pub.layers.defs#anchor", 90 + "description": "Position this annotation targets (text span, token, or temporal span)." 91 + }, 92 + "label": { 93 + "type": "string", 94 + "description": "The annotation label (e.g. a POS tag, NER type, sentiment class)." 95 + }, 96 + "text": { 97 + "type": "string", 98 + "description": "The surface text covered by this annotation (optional, for readability)." 99 + }, 100 + "confidence": { 101 + "type": "integer", 102 + "description": "Confidence score in the range 0–1000 (0 = none, 1000 = certain).", 103 + "minimum": 0, 104 + "maximum": 1000 105 + }, 106 + "features": { 107 + "type": "ref", 108 + "ref": "pub.layers.defs#featureMap", 109 + "description": "Additional linguistic features for this annotation." 110 + } 111 + } 112 + } 113 + } 114 + }
+151
lexicons/pub/layers/defs.json
··· 1 + { 2 + "lexicon": 1, 3 + "$type": "com.atproto.lexicon.schema", 4 + "id": "pub.layers.defs", 5 + "revision": 1, 6 + "description": "Shared type definitions for the layers.pub v0.5.0 lexicon family. Covers spans, temporal spans, anchors, token references, annotation metadata, and feature maps.", 7 + "defs": { 8 + "span": { 9 + "type": "object", 10 + "description": "A byte-offset span into a text string, with optional character offsets.", 11 + "required": ["byteStart", "byteEnd"], 12 + "properties": { 13 + "byteStart": { 14 + "type": "integer", 15 + "description": "Inclusive start byte offset." 16 + }, 17 + "byteEnd": { 18 + "type": "integer", 19 + "description": "Exclusive end byte offset." 20 + }, 21 + "charStart": { 22 + "type": "integer", 23 + "description": "Inclusive start Unicode character offset (optional)." 24 + }, 25 + "charEnd": { 26 + "type": "integer", 27 + "description": "Exclusive end Unicode character offset (optional)." 28 + } 29 + } 30 + }, 31 + "temporalSpan": { 32 + "type": "object", 33 + "description": "A time range in milliseconds, e.g. within a media stream.", 34 + "required": ["start", "ending"], 35 + "properties": { 36 + "start": { 37 + "type": "integer", 38 + "description": "Start time in milliseconds." 39 + }, 40 + "ending": { 41 + "type": "integer", 42 + "description": "End time in milliseconds." 43 + } 44 + } 45 + }, 46 + "uuid": { 47 + "type": "object", 48 + "description": "A UUID value wrapper.", 49 + "required": ["value"], 50 + "properties": { 51 + "value": { 52 + "type": "string", 53 + "description": "UUID string (e.g. RFC 4122)." 54 + } 55 + } 56 + }, 57 + "tokenRef": { 58 + "type": "object", 59 + "description": "A reference to a specific token within a named tokenization.", 60 + "required": ["tokenizationId", "tokenIndex"], 61 + "properties": { 62 + "tokenizationId": { 63 + "type": "ref", 64 + "ref": "pub.layers.defs#uuid", 65 + "description": "UUID identifying the tokenization this token belongs to." 66 + }, 67 + "tokenIndex": { 68 + "type": "integer", 69 + "description": "Zero-based index of the token within the tokenization." 70 + } 71 + } 72 + }, 73 + "anchor": { 74 + "type": "object", 75 + "description": "Polymorphic anchor pointing to a text span, a token, or a temporal position. At least one field should be set.", 76 + "properties": { 77 + "textSpan": { 78 + "type": "ref", 79 + "ref": "pub.layers.defs#span", 80 + "description": "Byte-offset span into the expression text." 81 + }, 82 + "tokenRef": { 83 + "type": "ref", 84 + "ref": "pub.layers.defs#tokenRef", 85 + "description": "Reference to a specific token in a tokenization." 86 + }, 87 + "temporalSpan": { 88 + "type": "ref", 89 + "ref": "pub.layers.defs#temporalSpan", 90 + "description": "Time range within a media stream." 91 + } 92 + } 93 + }, 94 + "annotationMetadata": { 95 + "type": "object", 96 + "description": "Provenance metadata for an annotation or layer.", 97 + "properties": { 98 + "agent": { 99 + "type": "string", 100 + "format": "at-uri", 101 + "description": "AT URI of the agent (DID or account) that produced this annotation." 102 + }, 103 + "tool": { 104 + "type": "string", 105 + "description": "Name or identifier of the tool or model used." 106 + }, 107 + "timestamp": { 108 + "type": "string", 109 + "format": "datetime", 110 + "description": "ISO 8601 datetime when the annotation was produced." 111 + }, 112 + "confidence": { 113 + "type": "integer", 114 + "description": "Confidence score in the range 0–1000 (0 = none, 1000 = certain).", 115 + "minimum": 0, 116 + "maximum": 1000 117 + } 118 + } 119 + }, 120 + "feature": { 121 + "type": "object", 122 + "description": "A key-value linguistic feature entry.", 123 + "required": ["key", "value"], 124 + "properties": { 125 + "key": { 126 + "type": "string", 127 + "description": "Feature name (e.g. POS, Gender, Number)." 128 + }, 129 + "value": { 130 + "type": "string", 131 + "description": "Feature value (e.g. NOUN, Masc, Sing)." 132 + } 133 + } 134 + }, 135 + "featureMap": { 136 + "type": "object", 137 + "description": "A set of linguistic feature key-value pairs.", 138 + "required": ["entries"], 139 + "properties": { 140 + "entries": { 141 + "type": "array", 142 + "items": { 143 + "type": "ref", 144 + "ref": "pub.layers.defs#feature" 145 + }, 146 + "description": "List of feature entries." 147 + } 148 + } 149 + } 150 + } 151 + }
+75
lexicons/pub/layers/expression/expression.json
··· 1 + { 2 + "lexicon": 1, 3 + "$type": "com.atproto.lexicon.schema", 4 + "id": "pub.layers.expression.expression", 5 + "revision": 1, 6 + "description": "A linguistic expression record — a unit of text at any granularity (document, transcript, paragraph, sentence, word, morpheme). Expressions may be nested via parentRef and anchored into media via mediaRef and anchor.", 7 + "defs": { 8 + "main": { 9 + "type": "record", 10 + "key": "any", 11 + "record": { 12 + "type": "object", 13 + "required": ["id", "kind", "text", "language", "createdAt"], 14 + "properties": { 15 + "id": { 16 + "type": "string", 17 + "description": "Stable identifier for this expression (e.g. UUID)." 18 + }, 19 + "kindUri": { 20 + "type": "string", 21 + "format": "at-uri", 22 + "description": "AT URI of a record that formally defines the expression kind." 23 + }, 24 + "kind": { 25 + "type": "string", 26 + "description": "Expression granularity: document, transcript, paragraph, sentence, word, morpheme, etc." 27 + }, 28 + "text": { 29 + "type": "string", 30 + "description": "The full text content of this expression." 31 + }, 32 + "language": { 33 + "type": "string", 34 + "description": "BCP 47 language tag (e.g. en, fr, zh-Hant)." 35 + }, 36 + "mediaRef": { 37 + "type": "string", 38 + "format": "at-uri", 39 + "description": "AT URI of the media record this expression derives from (e.g. a video or audio record)." 40 + }, 41 + "sourceRef": { 42 + "type": "string", 43 + "format": "at-uri", 44 + "description": "AT URI of the source record from which this expression was produced (e.g. a transcript record)." 45 + }, 46 + "parentRef": { 47 + "type": "string", 48 + "format": "at-uri", 49 + "description": "AT URI of the parent expression, for nested structure (e.g. sentence within paragraph)." 50 + }, 51 + "anchor": { 52 + "type": "ref", 53 + "ref": "pub.layers.defs#anchor", 54 + "description": "Position of this expression within its parent text or media." 55 + }, 56 + "metadata": { 57 + "type": "ref", 58 + "ref": "pub.layers.defs#annotationMetadata", 59 + "description": "Provenance metadata for this expression." 60 + }, 61 + "features": { 62 + "type": "ref", 63 + "ref": "pub.layers.defs#featureMap", 64 + "description": "Linguistic features associated with this expression." 65 + }, 66 + "createdAt": { 67 + "type": "string", 68 + "format": "datetime", 69 + "description": "ISO 8601 datetime when this record was created." 70 + } 71 + } 72 + } 73 + } 74 + } 75 + }
+101
lexicons/pub/layers/segmentation/segmentation.json
··· 1 + { 2 + "lexicon": 1, 3 + "$type": "com.atproto.lexicon.schema", 4 + "id": "pub.layers.segmentation.segmentation", 5 + "revision": 1, 6 + "description": "A segmentation record attaching one or more tokenizations to a pub.layers.expression. Each tokenization defines a scheme (whitespace, BPE, etc.) and a sequence of indexed tokens with text spans and optional temporal spans.", 7 + "defs": { 8 + "main": { 9 + "type": "record", 10 + "key": "any", 11 + "record": { 12 + "type": "object", 13 + "required": ["expression", "tokenizations", "createdAt"], 14 + "properties": { 15 + "expression": { 16 + "type": "string", 17 + "format": "at-uri", 18 + "description": "AT URI of the pub.layers.expression.expression this segmentation applies to." 19 + }, 20 + "tokenizations": { 21 + "type": "array", 22 + "items": { 23 + "type": "ref", 24 + "ref": "pub.layers.segmentation.segmentation#tokenization" 25 + }, 26 + "description": "One or more tokenization schemes over the expression text." 27 + }, 28 + "metadata": { 29 + "type": "ref", 30 + "ref": "pub.layers.defs#annotationMetadata", 31 + "description": "Provenance metadata for this segmentation." 32 + }, 33 + "features": { 34 + "type": "ref", 35 + "ref": "pub.layers.defs#featureMap", 36 + "description": "Linguistic features associated with this segmentation." 37 + }, 38 + "createdAt": { 39 + "type": "string", 40 + "format": "datetime", 41 + "description": "ISO 8601 datetime when this record was created." 42 + } 43 + } 44 + } 45 + }, 46 + "tokenization": { 47 + "type": "object", 48 + "description": "A single tokenization scheme with its token sequence.", 49 + "required": ["tokens"], 50 + "properties": { 51 + "uuid": { 52 + "type": "ref", 53 + "ref": "pub.layers.defs#uuid", 54 + "description": "Stable UUID identifying this tokenization, for use in tokenRef anchors." 55 + }, 56 + "kindUri": { 57 + "type": "string", 58 + "format": "at-uri", 59 + "description": "AT URI of a record formally defining the tokenization kind." 60 + }, 61 + "kind": { 62 + "type": "string", 63 + "description": "Tokenization scheme: whitespace, bpe, sentencepiece, character, etc." 64 + }, 65 + "tokens": { 66 + "type": "array", 67 + "items": { 68 + "type": "ref", 69 + "ref": "pub.layers.segmentation.segmentation#token" 70 + }, 71 + "description": "Ordered sequence of tokens produced by this tokenization." 72 + } 73 + } 74 + }, 75 + "token": { 76 + "type": "object", 77 + "description": "A single token within a tokenization.", 78 + "required": ["tokenIndex", "text", "textSpan"], 79 + "properties": { 80 + "tokenIndex": { 81 + "type": "integer", 82 + "description": "Zero-based index of this token in the tokenization sequence." 83 + }, 84 + "text": { 85 + "type": "string", 86 + "description": "Surface text of this token." 87 + }, 88 + "textSpan": { 89 + "type": "ref", 90 + "ref": "pub.layers.defs#span", 91 + "description": "Byte-offset span of this token in the parent expression text." 92 + }, 93 + "temporalSpan": { 94 + "type": "ref", 95 + "ref": "pub.layers.defs#temporalSpan", 96 + "description": "Time range of this token within the associated media (optional)." 97 + } 98 + } 99 + } 100 + } 101 + }
+30
panproto.toml
··· 1 + [workspace] 2 + name = "project" 3 + exclude = [ 4 + "target", 5 + "node_modules", 6 + "__pycache__", 7 + "build", 8 + "dist", 9 + ".git", 10 + ] 11 + 12 + [[package]] 13 + name = "ionosphere-workspace" 14 + path = "" 15 + protocol = "typescript" 16 + 17 + [[package]] 18 + name = "ionosphere" 19 + path = "apps/ionosphere" 20 + protocol = "typescript" 21 + 22 + [[package]] 23 + name = "ionosphere-appview" 24 + path = "apps/ionosphere-appview" 25 + protocol = "typescript" 26 + 27 + [[package]] 28 + name = "ionosphere-nlp" 29 + path = "pipeline" 30 + protocol = "python"
pipeline/nlp/__init__.py

This is a binary file and will not be displayed.

+133
pipeline/nlp/apply_clusters.py
··· 1 + """Apply concept clusters to the database. 2 + 3 + For each cluster with multiple members: 4 + 1. Keep the canonical concept record 5 + 2. Update its aliases to include all member names 6 + 3. Rewire talk_concepts references from merged concepts to the canonical 7 + 4. Delete the merged (non-canonical) concept records 8 + """ 9 + 10 + import json 11 + import sqlite3 12 + from pathlib import Path 13 + 14 + 15 + def apply_clusters(db_path: str, clusters_path: str, dry_run: bool = False): 16 + clusters = json.loads(Path(clusters_path).read_text()) 17 + 18 + multi = [c for c in clusters if c["memberCount"] > 1] 19 + print(f"Applying {len(multi)} multi-member clusters to database") 20 + 21 + conn = sqlite3.connect(db_path) 22 + 23 + # Build a map of concept name → URI for all concepts 24 + name_to_uri = {} 25 + for row in conn.execute("SELECT name, uri FROM concepts"): 26 + name_to_uri[row[0]] = row[1] 27 + 28 + merged_count = 0 29 + deleted_count = 0 30 + rewired_count = 0 31 + 32 + for cluster in multi: 33 + canonical_name = cluster["canonical"] 34 + canonical_uri = name_to_uri.get(canonical_name) 35 + if not canonical_uri: 36 + # Try to find by rkey 37 + row = conn.execute("SELECT uri FROM concepts WHERE rkey = ?", (cluster["rkey"],)).fetchone() 38 + if row: 39 + canonical_uri = row[0] 40 + else: 41 + print(f" Warning: canonical '{canonical_name}' not found in DB, skipping") 42 + continue 43 + 44 + # Collect all merged aliases 45 + all_aliases = set(cluster["aliases"]) 46 + 47 + # Find URIs of non-canonical members to merge 48 + member_uris = [] 49 + for member_name in cluster["members"]: 50 + if member_name == canonical_name: 51 + continue 52 + uri = name_to_uri.get(member_name) 53 + if uri and uri != canonical_uri: 54 + member_uris.append(uri) 55 + 56 + if not member_uris: 57 + continue 58 + 59 + if not dry_run: 60 + # Update canonical concept's aliases 61 + alias_json = json.dumps(sorted(all_aliases)) 62 + conn.execute( 63 + "UPDATE concepts SET aliases = ? WHERE uri = ?", 64 + (alias_json, canonical_uri), 65 + ) 66 + 67 + # Rewire talk_concepts from merged → canonical 68 + for old_uri in member_uris: 69 + # Check if canonical already has a link to this talk 70 + rows = conn.execute( 71 + "SELECT talk_uri FROM talk_concepts WHERE concept_uri = ?", 72 + (old_uri,), 73 + ).fetchall() 74 + for (talk_uri,) in rows: 75 + existing = conn.execute( 76 + "SELECT 1 FROM talk_concepts WHERE talk_uri = ? AND concept_uri = ?", 77 + (talk_uri, canonical_uri), 78 + ).fetchone() 79 + if existing: 80 + # Already linked — just delete the old one 81 + conn.execute( 82 + "DELETE FROM talk_concepts WHERE talk_uri = ? AND concept_uri = ?", 83 + (talk_uri, old_uri), 84 + ) 85 + else: 86 + # Rewire 87 + conn.execute( 88 + "UPDATE talk_concepts SET concept_uri = ? WHERE talk_uri = ? AND concept_uri = ?", 89 + (canonical_uri, talk_uri, old_uri), 90 + ) 91 + rewired_count += 1 92 + 93 + # Delete the merged concept 94 + conn.execute("DELETE FROM concepts WHERE uri = ?", (old_uri,)) 95 + deleted_count += 1 96 + 97 + merged_count += 1 98 + 99 + else: 100 + print(f" Would merge {len(member_uris)} concepts into '{canonical_name}'") 101 + 102 + if not dry_run: 103 + conn.commit() 104 + 105 + conn.close() 106 + 107 + print(f"\nResults:") 108 + print(f" Clusters applied: {merged_count}") 109 + print(f" Concepts deleted: {deleted_count}") 110 + print(f" talk_concepts rewired: {rewired_count}") 111 + print(f" Remaining concepts: check with SELECT COUNT(*) FROM concepts") 112 + 113 + 114 + def main(): 115 + db_path = str(Path(__file__).resolve().parent.parent.parent / "apps" / "data" / "ionosphere.sqlite") 116 + clusters_path = str(Path(__file__).resolve().parent.parent / "data" / "concept-clusters.json") 117 + 118 + # Show what we'd do first 119 + print("=== DRY RUN ===") 120 + apply_clusters(db_path, clusters_path, dry_run=True) 121 + 122 + print("\n=== APPLYING ===") 123 + apply_clusters(db_path, clusters_path, dry_run=False) 124 + 125 + # Verify 126 + conn = sqlite3.connect(db_path) 127 + count = conn.execute("SELECT COUNT(*) FROM concepts").fetchone()[0] 128 + print(f"\nFinal concept count: {count}") 129 + conn.close() 130 + 131 + 132 + if __name__ == "__main__": 133 + main()
+305
pipeline/nlp/cluster_concepts.py
··· 1 + """Cluster and deduplicate concepts using name similarity + LLM merge. 2 + 3 + Three-pass approach: 4 + 1. Normalize names: strip parentheticals, punctuation, case 5 + 2. Stem + merge: Porter stemming catches singular/plural (Lexicon/Lexicons) 6 + 3. LLM merge: Claude identifies remaining semantic duplicates (PDS/Personal Data Server) 7 + """ 8 + 9 + import json 10 + import os 11 + import re 12 + import sqlite3 13 + from collections import defaultdict 14 + from pathlib import Path 15 + 16 + import nltk 17 + nltk.download("punkt_tab", quiet=True) 18 + from nltk.stem import PorterStemmer 19 + 20 + _stemmer = PorterStemmer() 21 + 22 + 23 + def load_concepts(db_path: str) -> list[dict]: 24 + """Load all concepts from the database.""" 25 + conn = sqlite3.connect(db_path) 26 + rows = conn.execute("SELECT uri, rkey, name, aliases, description FROM concepts").fetchall() 27 + conn.close() 28 + return [ 29 + {"uri": r[0], "rkey": r[1], "name": r[2], "aliases": r[3] or "[]", "description": r[4] or ""} 30 + for r in rows 31 + ] 32 + 33 + 34 + def normalize_name(name: str) -> str: 35 + """Strip parenthetical qualifiers, punctuation, normalize case/whitespace.""" 36 + name = re.sub(r"\s*\([^)]*\)\s*", " ", name) 37 + parts = name.split("/") 38 + name = parts[0] 39 + name = name.lower().strip() 40 + name = re.sub(r"\s+", " ", name) 41 + name = name.strip(" .,;:-") 42 + return name 43 + 44 + 45 + def stem_form(name: str) -> str: 46 + """Normalize + stem each word + remove spaces/hyphens. 47 + 48 + 'Lexicons' → 'lexicon' 49 + 'Blue Sky' → 'bluesky' (after space removal) 50 + 'Custom feeds' → 'customfeed' 51 + """ 52 + n = normalize_name(name) 53 + words = n.split() 54 + stemmed = [_stemmer.stem(w) for w in words] 55 + return "".join(stemmed) 56 + 57 + 58 + def cluster_by_name(concepts: list[dict]) -> list[list[int]]: 59 + """Cluster concepts by stemmed name form.""" 60 + stem_groups: dict[str, list[int]] = defaultdict(list) 61 + for i, c in enumerate(concepts): 62 + sf = stem_form(c["name"]) 63 + if sf: 64 + stem_groups[sf].append(i) 65 + 66 + # Also try without spaces/hyphens on the normalized form (catches Blue Sky / BlueSky) 67 + base_groups: dict[str, set[str]] = defaultdict(set) 68 + for sf in stem_groups: 69 + base = re.sub(r"[\s\-_]", "", sf) 70 + base_groups[base].add(sf) 71 + 72 + # Merge stem groups that share a base form 73 + visited: set[str] = set() 74 + clusters: list[list[int]] = [] 75 + for base, stems in base_groups.items(): 76 + if not base: 77 + continue 78 + indices = [] 79 + for sf in stems: 80 + if sf not in visited: 81 + visited.add(sf) 82 + indices.extend(stem_groups[sf]) 83 + if indices: 84 + clusters.append(indices) 85 + 86 + # Add unclustered 87 + all_clustered = set() 88 + for cluster in clusters: 89 + all_clustered.update(cluster) 90 + for i in range(len(concepts)): 91 + if i not in all_clustered: 92 + clusters.append([i]) 93 + 94 + return clusters 95 + 96 + 97 + def llm_merge_pass( 98 + cluster_groups: list[dict], 99 + batch_size: int = 100, 100 + ) -> list[list[int]]: 101 + """Use Claude to identify remaining semantic duplicates across clusters. 102 + 103 + Takes the cluster canonicals and asks the LLM which ones should be merged. 104 + Returns a list of merge groups (indices into cluster_groups). 105 + """ 106 + api_key = os.environ.get("ANTHROPIC_API_KEY") 107 + if not api_key: 108 + print(" No ANTHROPIC_API_KEY — skipping LLM merge pass") 109 + return [] 110 + 111 + import anthropic 112 + client = anthropic.Anthropic(api_key=api_key, timeout=30.0) 113 + 114 + # Only send cluster canonicals (not all 2000+ members) 115 + names = [g["canonical"] for g in cluster_groups] 116 + 117 + all_merges: list[list[int]] = [] 118 + 119 + # Process in batches 120 + for batch_start in range(0, len(names), batch_size): 121 + batch = names[batch_start : batch_start + batch_size] 122 + batch_indices = list(range(batch_start, min(batch_start + batch_size, len(names)))) 123 + 124 + prompt = f"""Here is a list of concept names from a conference about the AT Protocol / Bluesky ecosystem. Many are duplicates or near-duplicates that should be merged. 125 + 126 + For each group of duplicates, return the indices (0-based within this batch) that should be merged. 127 + 128 + Only merge concepts that are genuinely THE SAME THING with different names. Do NOT merge concepts that are merely related (e.g., "Bluesky" and "AT Protocol" are different things). 129 + 130 + Examples of valid merges: 131 + - "PDS" and "Personal Data Server" (same thing, abbreviation) 132 + - "DID" and "Decentralized Identifier" (same thing) 133 + - "i18n" and "internationalization" (same thing) 134 + 135 + Examples of INVALID merges: 136 + - "Bluesky" and "AT Protocol" (different things) 137 + - "Ozone" and "Labelers" (related but different) 138 + 139 + Concepts: 140 + {json.dumps([{"idx": i, "name": n} for i, n in enumerate(batch)], indent=1)} 141 + 142 + Return a JSON array of merge groups. Each group is an array of indices that should be merged. 143 + Return ONLY the JSON array, no other text.""" 144 + 145 + try: 146 + response = client.messages.create( 147 + model="claude-haiku-4-5-20251001", 148 + max_tokens=2000, 149 + messages=[{"role": "user", "content": prompt}], 150 + ) 151 + 152 + text = response.content[0].text.strip() 153 + if text.startswith("```"): 154 + text = re.sub(r"^```(?:json)?\n?", "", text) 155 + text = re.sub(r"\n?```$", "", text) 156 + 157 + merges = json.loads(text) 158 + if isinstance(merges, list): 159 + for group in merges: 160 + if isinstance(group, list) and len(group) > 1: 161 + # Convert batch-local indices to global indices 162 + global_indices = [batch_indices[i] for i in group if i < len(batch)] 163 + all_merges.append(global_indices) 164 + 165 + except Exception as e: 166 + print(f" LLM merge batch {batch_start} failed: {e}") 167 + continue 168 + 169 + return all_merges 170 + 171 + 172 + def apply_merges( 173 + cluster_groups: list[dict], 174 + merges: list[list[int]], 175 + concepts: list[dict], 176 + ) -> list[dict]: 177 + """Apply LLM-suggested merges to the cluster groups.""" 178 + if not merges: 179 + return cluster_groups 180 + 181 + # Build a union-find for merge groups 182 + parent = list(range(len(cluster_groups))) 183 + 184 + def find(x): 185 + while parent[x] != x: 186 + parent[x] = parent[parent[x]] 187 + x = parent[x] 188 + return x 189 + 190 + def union(a, b): 191 + ra, rb = find(a), find(b) 192 + if ra != rb: 193 + parent[rb] = ra 194 + 195 + for group in merges: 196 + for i in range(1, len(group)): 197 + union(group[0], group[i]) 198 + 199 + # Rebuild clusters 200 + merged: dict[int, list[int]] = defaultdict(list) 201 + for i in range(len(cluster_groups)): 202 + root = find(i) 203 + merged[root].append(i) 204 + 205 + results = [] 206 + for root, group_indices in merged.items(): 207 + if len(group_indices) == 1: 208 + results.append(cluster_groups[group_indices[0]]) 209 + else: 210 + # Merge all member concepts 211 + all_member_indices = [] 212 + for gi in group_indices: 213 + # Find original concept indices for this cluster group 214 + g = cluster_groups[gi] 215 + for m_name in g["members"]: 216 + for ci, c in enumerate(concepts): 217 + if c["name"] == m_name: 218 + all_member_indices.append(ci) 219 + break 220 + results.append(pick_canonical(concepts, all_member_indices)) 221 + 222 + return results 223 + 224 + 225 + def pick_canonical(concepts: list[dict], indices: list[int]) -> dict: 226 + """Pick the canonical concept from a cluster.""" 227 + candidates = [(concepts[i], i) for i in indices] 228 + candidates.sort(key=lambda x: (not bool(x[0]["description"]), len(x[0]["name"]))) 229 + canonical = candidates[0][0] 230 + 231 + all_names = set() 232 + for i in indices: 233 + all_names.add(concepts[i]["name"]) 234 + try: 235 + aliases = json.loads(concepts[i]["aliases"]) 236 + if isinstance(aliases, list): 237 + all_names.update(a for a in aliases if a) 238 + except (json.JSONDecodeError, TypeError): 239 + pass 240 + all_names.discard(canonical["name"]) 241 + 242 + return { 243 + "canonical": canonical["name"], 244 + "uri": canonical["uri"], 245 + "rkey": canonical["rkey"], 246 + "description": canonical["description"], 247 + "aliases": sorted(all_names), 248 + "memberCount": len(indices), 249 + "members": [concepts[i]["name"] for i in indices], 250 + } 251 + 252 + 253 + def cluster_concepts(db_path: str) -> list[dict]: 254 + """Full pipeline: load, stem-cluster, LLM-merge, pick canonicals.""" 255 + concepts = load_concepts(db_path) 256 + print(f"Loaded {len(concepts)} concepts") 257 + 258 + # Pass 1+2: Name normalization + stemming 259 + clusters = cluster_by_name(concepts) 260 + print(f"After stemming: {len(clusters)} clusters") 261 + 262 + # Build initial groups 263 + groups = [] 264 + multi = 0 265 + for indices in clusters: 266 + g = pick_canonical(concepts, indices) 267 + groups.append(g) 268 + if len(indices) > 1: 269 + multi += 1 270 + print(f" {multi} clusters with multiple members") 271 + 272 + # Pass 3: LLM merge 273 + print("Running LLM merge pass...") 274 + merges = llm_merge_pass(groups) 275 + if merges: 276 + print(f" LLM suggested {len(merges)} additional merges") 277 + groups = apply_merges(groups, merges, concepts) 278 + print(f"After LLM merge: {len(groups)} clusters") 279 + 280 + groups.sort(key=lambda g: g["memberCount"], reverse=True) 281 + return groups 282 + 283 + 284 + def main(): 285 + db_path = str(Path(__file__).resolve().parent.parent.parent / "apps" / "data" / "ionosphere.sqlite") 286 + output_path = Path(__file__).resolve().parent.parent / "data" / "concept-clusters.json" 287 + output_path.parent.mkdir(parents=True, exist_ok=True) 288 + 289 + results = cluster_concepts(db_path) 290 + 291 + output_path.write_text(json.dumps(results, indent=2)) 292 + print(f"\nWrote {len(results)} clusters to {output_path}") 293 + 294 + print("\nTop clusters by member count:") 295 + for g in results[:25]: 296 + if g["memberCount"] > 1: 297 + print(f" {g['canonical']} ({g['memberCount']} members)") 298 + for m in g["members"][:8]: 299 + print(f" - {m}") 300 + if len(g["members"]) > 8: 301 + print(f" ... and {len(g['members']) - 8} more") 302 + 303 + 304 + if __name__ == "__main__": 305 + main()
+30
pipeline/nlp/encoding.py
··· 1 + """Convert word-level transcript format to compact (text + timings) format.""" 2 + 3 + 4 + def words_to_compact(transcript: dict) -> dict: 5 + """Convert TranscriptResult {text, words[{word, start, end}]} to compact {text, startMs, timings}.""" 6 + words = transcript.get("words", []) 7 + if not words: 8 + return {"text": transcript.get("text", ""), "startMs": 0, "timings": []} 9 + 10 + start_ms = round(words[0]["start"] * 1000) 11 + timings = [] 12 + cursor = start_ms 13 + 14 + for w in words: 15 + word_start_ms = round(w["start"] * 1000) 16 + word_end_ms = round(w["end"] * 1000) 17 + duration = word_end_ms - word_start_ms 18 + 19 + gap = word_start_ms - cursor 20 + if gap > 0: 21 + timings.append(-gap) 22 + 23 + timings.append(max(duration, 1)) 24 + cursor = word_end_ms 25 + 26 + return { 27 + "text": transcript["text"], 28 + "startMs": start_ms, 29 + "timings": timings, 30 + }
+193
pipeline/nlp/entities.py
··· 1 + """Pass 3: Named entity recognition + entity linking + concept text matching.""" 2 + 3 + import json 4 + import re 5 + import spacy 6 + 7 + _nlp = None 8 + 9 + # Minimum concept name length to match — avoids noise from short terms 10 + MIN_CONCEPT_LENGTH = 3 11 + 12 + 13 + def _get_nlp(): 14 + global _nlp 15 + if _nlp is None: 16 + _nlp = spacy.load("en_core_web_sm") 17 + return _nlp 18 + 19 + 20 + def _build_concept_lookup(concept_rows: list[dict] | None) -> dict[str, str]: 21 + """Build a lowercase name/alias → URI lookup from concept records.""" 22 + lookup: dict[str, str] = {} 23 + if not concept_rows: 24 + return lookup 25 + for c in concept_rows: 26 + lookup[c["name"].lower()] = c["uri"] 27 + aliases = c.get("aliases", "[]") 28 + if isinstance(aliases, str): 29 + try: 30 + aliases = json.loads(aliases) 31 + except (json.JSONDecodeError, TypeError): 32 + aliases = [] 33 + for alias in aliases: 34 + if alias: 35 + lookup[alias.lower()] = c["uri"] 36 + return lookup 37 + 38 + 39 + def _build_concept_names(concept_rows: list[dict] | None) -> list[tuple[str, str, str]]: 40 + """Build a list of (search_term, display_name, uri) for text matching. 41 + 42 + Returns terms sorted longest-first so longer matches take priority. 43 + Skips terms shorter than MIN_CONCEPT_LENGTH. 44 + """ 45 + terms: list[tuple[str, str, str]] = [] 46 + if not concept_rows: 47 + return terms 48 + for c in concept_rows: 49 + name = c["name"] 50 + uri = c["uri"] 51 + if len(name) >= MIN_CONCEPT_LENGTH: 52 + terms.append((name, name, uri)) 53 + aliases = c.get("aliases", "[]") 54 + if isinstance(aliases, str): 55 + try: 56 + aliases = json.loads(aliases) 57 + except (json.JSONDecodeError, TypeError): 58 + aliases = [] 59 + for alias in aliases: 60 + if alias and len(alias) >= MIN_CONCEPT_LENGTH: 61 + terms.append((alias, name, uri)) 62 + # Sort longest first so "AT Protocol" matches before "AT" 63 + terms.sort(key=lambda t: len(t[0]), reverse=True) 64 + return terms 65 + 66 + 67 + def _scan_concepts( 68 + text: str, 69 + concept_terms: list[tuple[str, str, str]], 70 + occupied_ranges: set[tuple[int, int]], 71 + ) -> list[dict]: 72 + """Scan transcript text for known concept names/aliases. 73 + 74 + Returns concept entities with byte ranges. Skips ranges already 75 + occupied by NER-detected entities to avoid duplicates. 76 + """ 77 + entities = [] 78 + text_lower = text.lower() 79 + # Track which character ranges we've already matched (avoid overlapping matches) 80 + matched_chars: set[int] = set() 81 + # Also add NER-occupied char ranges 82 + for byte_start, byte_end in occupied_ranges: 83 + # Convert byte ranges to approximate char ranges 84 + prefix_len = len(text.encode("utf-8")[:byte_start].decode("utf-8", errors="ignore")) 85 + suffix_len = len(text.encode("utf-8")[:byte_end].decode("utf-8", errors="ignore")) 86 + for i in range(prefix_len, suffix_len): 87 + matched_chars.add(i) 88 + 89 + for search_term, display_name, uri in concept_terms: 90 + pattern = re.compile(re.escape(search_term.lower()), re.IGNORECASE) 91 + for match in pattern.finditer(text_lower): 92 + start_char = match.start() 93 + end_char = match.end() 94 + 95 + # Skip if any character in this range is already matched 96 + if any(i in matched_chars for i in range(start_char, end_char)): 97 + continue 98 + 99 + # Word boundary check — don't match "PDServer" when looking for "PDS" 100 + if start_char > 0 and text[start_char - 1].isalnum(): 101 + continue 102 + if end_char < len(text) and text[end_char].isalnum(): 103 + continue 104 + 105 + byte_start = len(text[:start_char].encode("utf-8")) 106 + byte_end = len(text[:end_char].encode("utf-8")) 107 + 108 + entities.append({ 109 + "byteStart": byte_start, 110 + "byteEnd": byte_end, 111 + "label": text[start_char:end_char], 112 + "nerType": "CONCEPT", 113 + "conceptUri": uri, 114 + }) 115 + 116 + # Mark these characters as matched 117 + for i in range(start_char, end_char): 118 + matched_chars.add(i) 119 + 120 + return entities 121 + 122 + 123 + def detect_entities( 124 + text: str, 125 + speaker_lookup=None, 126 + concept_rows: list[dict] | None = None, 127 + ) -> list[dict]: 128 + """Detect named entities and concepts in transcript text. 129 + 130 + Two-pass approach: 131 + 1. spaCy NER for people, organizations, etc. 132 + 2. Direct text matching for known concept names/aliases 133 + 134 + Returns a list of entity dicts with: 135 + byteStart, byteEnd: UTF-8 byte offsets 136 + label: entity text 137 + nerType: spaCy entity type or "CONCEPT" 138 + speakerDid: (optional) resolved speaker DID 139 + conceptUri: (optional) resolved concept URI 140 + """ 141 + if not text.strip(): 142 + return [] 143 + 144 + nlp = _get_nlp() 145 + doc = nlp(text) 146 + 147 + concept_lookup = _build_concept_lookup(concept_rows) 148 + concept_terms = _build_concept_names(concept_rows) 149 + 150 + entities = [] 151 + occupied_ranges: set[tuple[int, int]] = set() 152 + 153 + # Pass 1: NER entities 154 + for ent in doc.ents: 155 + if ent.label_ not in ("PERSON", "ORG", "PRODUCT", "WORK_OF_ART", "GPE", "EVENT"): 156 + continue 157 + 158 + byte_start = len(text[:ent.start_char].encode("utf-8")) 159 + byte_end = len(text[:ent.end_char].encode("utf-8")) 160 + 161 + entity = { 162 + "byteStart": byte_start, 163 + "byteEnd": byte_end, 164 + "label": ent.text, 165 + "nerType": ent.label_, 166 + } 167 + 168 + if ent.label_ == "PERSON" and speaker_lookup: 169 + match = speaker_lookup.resolve(ent.text) 170 + if match and match.get("did"): 171 + entity["speakerDid"] = match["did"] 172 + 173 + # Concept linking applies across all entity types 174 + # Try exact match, then strip common prefixes ("The", "A", "An") 175 + ent_lower = ent.text.lower() 176 + uri = concept_lookup.get(ent_lower) 177 + if not uri: 178 + for prefix in ("the ", "a ", "an "): 179 + if ent_lower.startswith(prefix): 180 + uri = concept_lookup.get(ent_lower[len(prefix):]) 181 + if uri: 182 + break 183 + if uri: 184 + entity["conceptUri"] = uri 185 + 186 + entities.append(entity) 187 + occupied_ranges.add((byte_start, byte_end)) 188 + 189 + # Pass 2: Direct text matching for known concepts 190 + concept_entities = _scan_concepts(text, concept_terms, occupied_ranges) 191 + entities.extend(concept_entities) 192 + 193 + return entities
+60
pipeline/nlp/export_streams.py
··· 1 + """Export stream transcripts from DB as compact JSON for the NLP pipeline.""" 2 + 3 + import json 4 + import sqlite3 5 + from pathlib import Path 6 + 7 + 8 + def export_stream_transcripts(db_path: str, output_dir: str): 9 + conn = sqlite3.connect(db_path) 10 + 11 + streams = conn.execute("SELECT uri, slug FROM streams").fetchall() 12 + print(f"Found {len(streams)} streams") 13 + 14 + out = Path(output_dir) 15 + out.mkdir(parents=True, exist_ok=True) 16 + 17 + exported = 0 18 + for stream_uri, slug in streams: 19 + chunks = conn.execute( 20 + "SELECT text, start_ms, timings FROM stream_transcripts WHERE stream_uri = ? ORDER BY chunk_index ASC", 21 + (stream_uri,) 22 + ).fetchall() 23 + 24 + if not chunks: 25 + continue 26 + 27 + # Reassemble into a single compact transcript 28 + full_text = "" 29 + all_timings = [] 30 + start_ms = chunks[0][1] 31 + 32 + for text, chunk_start_ms, timings_json in chunks: 33 + timings = json.loads(timings_json) 34 + 35 + if full_text: 36 + # Add a gap between chunks if needed 37 + full_text += " " 38 + 39 + full_text += text 40 + all_timings.extend(timings) 41 + 42 + result = { 43 + "text": full_text, 44 + "startMs": start_ms, 45 + "timings": all_timings, 46 + } 47 + 48 + out_path = out / f"stream-{slug}.json" 49 + out_path.write_text(json.dumps(result)) 50 + print(f" {slug}: {len(full_text)} chars, {len(all_timings)} timing values") 51 + exported += 1 52 + 53 + conn.close() 54 + print(f"Exported {exported} stream transcripts") 55 + 56 + 57 + if __name__ == "__main__": 58 + db_path = str(Path(__file__).resolve().parent.parent.parent / "apps" / "data" / "ionosphere.sqlite") 59 + output_dir = str(Path(__file__).resolve().parent.parent / "data" / "stream-transcripts") 60 + export_stream_transcripts(db_path, output_dir)
+205
pipeline/nlp/llm_concepts.py
··· 1 + """Pass 5: LLM-based concept detection using Claude. 2 + 3 + Sends transcript chunks to Claude to identify domain concepts that 4 + text matching and NER miss — paraphrases, abbreviations, implicit 5 + references, and potential new concepts. 6 + """ 7 + 8 + import json 9 + import os 10 + import re 11 + import anthropic 12 + 13 + # Use Haiku for speed and cost efficiency 14 + MODEL = "claude-haiku-4-5-20251001" 15 + 16 + SYSTEM_PROMPT = """You are analyzing a transcript from ATmosphereConf, a conference about the AT Protocol ecosystem (Bluesky, decentralized social media, open protocols). 17 + 18 + Your job: identify technical concepts, projects, protocols, organizations, and domain-specific terms mentioned in this transcript chunk. 19 + 20 + For each concept you find, return: 21 + - "text": the exact text as it appears in the transcript (verbatim, for byte-range matching) 22 + - "label": the canonical name of the concept (e.g., "AT Protocol" even if the text says "the protocol") 23 + - "isNew": true if this seems like a concept not in the provided known concepts list 24 + 25 + Focus on domain-specific terms. Skip common English words, generic phrases, and obvious things. Be precise about the exact text spans. 26 + 27 + Return valid JSON array only, no other text.""" 28 + 29 + 30 + def detect_llm_concepts( 31 + text: str, 32 + known_concept_names: list[str], 33 + chunk_size: int = 8000, 34 + ) -> list[dict]: 35 + """Use Claude to identify concepts in transcript text. 36 + 37 + Args: 38 + text: full transcript text 39 + known_concept_names: list of known concept names for context 40 + chunk_size: characters per chunk (to stay within context limits) 41 + 42 + Returns: 43 + list of dicts with text, label, isNew 44 + """ 45 + api_key = os.environ.get("ANTHROPIC_API_KEY") 46 + if not api_key: 47 + print(" Warning: ANTHROPIC_API_KEY not set, skipping LLM concept pass") 48 + return [] 49 + 50 + client = anthropic.Anthropic(api_key=api_key, timeout=30.0) 51 + 52 + # Build a concise concept list (top 200 by name length — shorter names are more common) 53 + sorted_concepts = sorted(known_concept_names, key=len)[:200] 54 + concept_list = ", ".join(sorted_concepts) 55 + 56 + # Split text into chunks at sentence boundaries 57 + chunks = _split_into_chunks(text, chunk_size) 58 + all_concepts = [] 59 + 60 + for i, chunk in enumerate(chunks): 61 + user_prompt = f"""Known concepts (subset): {concept_list} 62 + 63 + Transcript chunk ({i + 1}/{len(chunks)}): 64 + \"\"\" 65 + {chunk} 66 + \"\"\" 67 + 68 + Identify all technical concepts, projects, protocols, and domain terms in this chunk. Return a JSON array.""" 69 + 70 + try: 71 + response = client.messages.create( 72 + model=MODEL, 73 + max_tokens=2000, 74 + system=SYSTEM_PROMPT, 75 + messages=[{"role": "user", "content": user_prompt}], 76 + ) 77 + 78 + # Parse JSON from response 79 + response_text = response.content[0].text.strip() 80 + # Handle markdown code blocks 81 + if response_text.startswith("```"): 82 + response_text = re.sub(r"^```(?:json)?\n?", "", response_text) 83 + response_text = re.sub(r"\n?```$", "", response_text) 84 + 85 + concepts = json.loads(response_text) 86 + if isinstance(concepts, list): 87 + all_concepts.extend(concepts) 88 + except (json.JSONDecodeError, anthropic.APIError, IndexError) as e: 89 + print(f" Warning: LLM chunk {i + 1} failed: {e}") 90 + continue 91 + 92 + return all_concepts 93 + 94 + 95 + def resolve_llm_concepts( 96 + text: str, 97 + llm_concepts: list[dict], 98 + concept_lookup: dict[str, str], 99 + occupied_ranges: set[tuple[int, int]], 100 + ) -> list[dict]: 101 + """Resolve LLM-detected concepts to known concept URIs and compute byte ranges. 102 + 103 + Args: 104 + text: full transcript text 105 + llm_concepts: output from detect_llm_concepts 106 + concept_lookup: lowercase name → URI mapping 107 + occupied_ranges: byte ranges already occupied by other entities 108 + 109 + Returns: 110 + list of entity dicts ready to merge into the entities list 111 + """ 112 + entities = [] 113 + text_lower = text.lower() 114 + 115 + # Build set of occupied character ranges for dedup 116 + matched_chars: set[int] = set() 117 + for byte_start, byte_end in occupied_ranges: 118 + prefix_len = len(text.encode("utf-8")[:byte_start].decode("utf-8", errors="ignore")) 119 + suffix_len = len(text.encode("utf-8")[:byte_end].decode("utf-8", errors="ignore")) 120 + for i in range(prefix_len, suffix_len): 121 + matched_chars.add(i) 122 + 123 + for concept in llm_concepts: 124 + search_text = concept.get("text", "").strip() 125 + label = concept.get("label", search_text) 126 + is_new = concept.get("isNew", False) 127 + 128 + if not search_text or len(search_text) < 3: 129 + continue 130 + 131 + # Find the exact text in the transcript 132 + search_lower = search_text.lower() 133 + start = 0 134 + while True: 135 + idx = text_lower.find(search_lower, start) 136 + if idx == -1: 137 + break 138 + 139 + end_idx = idx + len(search_text) 140 + 141 + # Skip if overlaps with existing entities 142 + if any(i in matched_chars for i in range(idx, end_idx)): 143 + start = end_idx 144 + continue 145 + 146 + byte_start = len(text[:idx].encode("utf-8")) 147 + byte_end = len(text[:end_idx].encode("utf-8")) 148 + 149 + # Try to resolve to a known concept 150 + uri = concept_lookup.get(label.lower()) or concept_lookup.get(search_lower) 151 + 152 + entity = { 153 + "byteStart": byte_start, 154 + "byteEnd": byte_end, 155 + "label": text[idx:end_idx], 156 + "nerType": "CONCEPT", 157 + } 158 + if uri: 159 + entity["conceptUri"] = uri 160 + # Skip if it's a "new" concept with no URI — we only emit linked concepts 161 + # (new concept discovery is for Phase 4 manual curation) 162 + elif is_new: 163 + start = end_idx 164 + continue 165 + 166 + entities.append(entity) 167 + 168 + # Mark as occupied 169 + for i in range(idx, end_idx): 170 + matched_chars.add(i) 171 + 172 + # Only match first occurrence per chunk to avoid over-annotation 173 + break 174 + 175 + return entities 176 + 177 + 178 + def _split_into_chunks(text: str, chunk_size: int) -> list[str]: 179 + """Split text into chunks at sentence boundaries.""" 180 + if len(text) <= chunk_size: 181 + return [text] 182 + 183 + chunks = [] 184 + start = 0 185 + while start < len(text): 186 + end = start + chunk_size 187 + if end >= len(text): 188 + chunks.append(text[start:]) 189 + break 190 + 191 + # Find the last sentence boundary before the chunk limit 192 + last_period = text.rfind(". ", start, end) 193 + last_question = text.rfind("? ", start, end) 194 + last_exclaim = text.rfind("! ", start, end) 195 + boundary = max(last_period, last_question, last_exclaim) 196 + 197 + if boundary > start: 198 + chunks.append(text[start : boundary + 1]) 199 + start = boundary + 2 200 + else: 201 + # No sentence boundary found — split at chunk_size 202 + chunks.append(text[start:end]) 203 + start = end 204 + 205 + return chunks
+129
pipeline/nlp/paragraphs.py
··· 1 + """Pass 2: Paragraph segmentation from pause data and sentence boundaries.""" 2 + 3 + 4 + def detect_paragraphs( 5 + text: str, 6 + timings: list[int], 7 + start_ms: int, 8 + sentences: list[dict], 9 + pause_threshold_ms: int = 2000, 10 + proximity_words: int = 5, 11 + ) -> list[dict]: 12 + """Detect paragraph boundaries using pause duration and sentence structure. 13 + 14 + Paragraph breaks are only inserted at sentence boundaries — never mid-sentence. 15 + A long pause (>= pause_threshold_ms) triggers a break only when a sentence 16 + boundary falls within proximity_words of the pause location. 17 + 18 + Args: 19 + text: The full transcript text. 20 + timings: Mixed-sign list where positive values are word durations (ms) 21 + and negative values are silence gaps (absolute value in ms) 22 + before the next word. 23 + start_ms: Absolute time offset of the first word (ms). 24 + sentences: List of sentence dicts with byteStart and byteEnd keys. 25 + pause_threshold_ms: Minimum silence duration to consider a paragraph break. 26 + proximity_words: Max word-index distance from pause to nearest sentence boundary. 27 + 28 + Returns: 29 + List of paragraph dicts with byteStart and byteEnd (UTF-8 byte offsets). 30 + """ 31 + if not text or not sentences: 32 + return [] 33 + 34 + # Build a char→byte offset map once (O(n)) 35 + char_to_byte = [] 36 + byte_pos = 0 37 + for ch in text: 38 + char_to_byte.append(byte_pos) 39 + byte_pos += len(ch.encode("utf-8")) 40 + char_to_byte.append(byte_pos) # sentinel for end-of-string 41 + 42 + # Find word start char offsets (preserving order of words in text) 43 + words = text.split() 44 + word_byte_starts = [] 45 + char_offset = 0 46 + for w in words: 47 + idx = text.index(w, char_offset) 48 + word_byte_starts.append(char_to_byte[idx]) 49 + char_offset = idx + len(w) 50 + 51 + # Map each sentence boundary (byteStart) to its approximate word index. 52 + # We find the word whose byte start is closest to / at the sentence boundary. 53 + def sentence_start_word_index(byte_start: int) -> int: 54 + """Return the word index whose byte start is nearest to byte_start.""" 55 + best_idx = 0 56 + best_dist = abs(word_byte_starts[0] - byte_start) if word_byte_starts else 0 57 + for i, wb in enumerate(word_byte_starts): 58 + dist = abs(wb - byte_start) 59 + if dist < best_dist: 60 + best_dist = dist 61 + best_idx = i 62 + return best_idx 63 + 64 + # Pre-compute word indices for all sentence boundaries (skip index 0 — that's 65 + # always the start of the first paragraph, not a potential break). 66 + sentence_word_indices = [] 67 + for sent in sentences: 68 + sentence_word_indices.append(sentence_start_word_index(sent["byteStart"])) 69 + 70 + # Walk timings to find word indices where long pauses occur. 71 + # The word_index before a pause is the last word of the current span. 72 + # The word after the pause starts the next potential paragraph. 73 + pause_after_word = [] # word indices AFTER which a long pause occurs 74 + word_index = -1 # incremented when we encounter a word duration 75 + for t in timings: 76 + if t >= 0: 77 + # Positive value: duration of the next word 78 + word_index += 1 79 + else: 80 + # Negative value: silence gap before the next word 81 + gap_ms = abs(t) 82 + if gap_ms >= pause_threshold_ms and word_index >= 0: 83 + pause_after_word.append(word_index) 84 + 85 + if not pause_after_word: 86 + # No qualifying pauses — single paragraph spanning everything 87 + return [{"byteStart": sentences[0]["byteStart"], "byteEnd": sentences[-1]["byteEnd"]}] 88 + 89 + # For each long pause, find the nearest sentence boundary within proximity_words. 90 + # A sentence boundary is a candidate break point only if it's a sentence START 91 + # (index > 0, since we never break before the first sentence). 92 + break_byte_starts: set[int] = set() 93 + for pause_word in pause_after_word: 94 + best_sent_idx = None 95 + best_dist = proximity_words + 1 # exclusive upper bound 96 + for si, sw in enumerate(sentence_word_indices): 97 + if si == 0: 98 + continue # can't break before the first sentence 99 + dist = abs(sw - (pause_word + 1)) # distance from word-after-pause to sentence start 100 + if dist <= proximity_words and dist < best_dist: 101 + best_dist = dist 102 + best_sent_idx = si 103 + if best_sent_idx is not None: 104 + break_byte_starts.add(sentences[best_sent_idx]["byteStart"]) 105 + 106 + if not break_byte_starts: 107 + # Pauses exist but no sentence boundaries are nearby — single paragraph 108 + return [{"byteStart": sentences[0]["byteStart"], "byteEnd": sentences[-1]["byteEnd"]}] 109 + 110 + # Build paragraph spans from the collected sentence-boundary break points. 111 + # Sort sentences and group them into paragraphs. 112 + sorted_breaks = sorted(break_byte_starts) 113 + paragraphs = [] 114 + para_start_byte = sentences[0]["byteStart"] 115 + 116 + for sent in sentences[1:]: 117 + if sent["byteStart"] in sorted_breaks: 118 + # Close current paragraph just before this sentence 119 + prev_sent = next( 120 + s for s in reversed(sentences) 121 + if s["byteStart"] < sent["byteStart"] 122 + ) 123 + paragraphs.append({"byteStart": para_start_byte, "byteEnd": prev_sent["byteEnd"]}) 124 + para_start_byte = sent["byteStart"] 125 + 126 + # Close the final paragraph 127 + paragraphs.append({"byteStart": para_start_byte, "byteEnd": sentences[-1]["byteEnd"]}) 128 + 129 + return paragraphs
+147
pipeline/nlp/run.py
··· 1 + """Pipeline orchestrator: run all NLP passes on a transcript.""" 2 + 3 + import json 4 + import sys 5 + from pathlib import Path 6 + from nlp.sentences import detect_sentences 7 + from nlp.paragraphs import detect_paragraphs 8 + from nlp.entities import detect_entities 9 + from nlp.speaker_lookup import build_speaker_lookup 10 + from nlp.topics import detect_topic_breaks 11 + from nlp.llm_concepts import detect_llm_concepts, resolve_llm_concepts 12 + from nlp.entities import _build_concept_lookup 13 + 14 + 15 + def process_transcript( 16 + transcript: dict, 17 + talk_rkey: str, 18 + pause_threshold_ms: int = 2000, 19 + proximity_words: int = 5, 20 + speaker_rows: list[tuple] | None = None, 21 + concept_rows: list[dict] | None = None, 22 + ) -> dict: 23 + """Run all NLP passes on a single transcript. 24 + 25 + Args: 26 + transcript: dict with text, startMs, timings 27 + talk_rkey: the talk's record key (for output naming) 28 + speaker_rows: optional list of (name, handle, did) tuples for entity linking 29 + concept_rows: optional list of concept dicts for entity linking 30 + 31 + Returns: 32 + dict with sentences, paragraphs, entities, topicBreaks, and metadata 33 + """ 34 + text = transcript["text"] 35 + timings = transcript["timings"] 36 + start_ms = transcript["startMs"] 37 + 38 + # Pass 1: Sentence detection 39 + sentences = detect_sentences(text) 40 + 41 + # Pass 2: Paragraph segmentation 42 + paragraphs = detect_paragraphs( 43 + text=text, 44 + timings=timings, 45 + start_ms=start_ms, 46 + sentences=sentences, 47 + pause_threshold_ms=pause_threshold_ms, 48 + proximity_words=proximity_words, 49 + ) 50 + 51 + # Pass 3: NER + entity linking 52 + speaker_lookup = build_speaker_lookup(speaker_rows) if speaker_rows else None 53 + entities = detect_entities(text, speaker_lookup=speaker_lookup, concept_rows=concept_rows) 54 + 55 + # Pass 4: Topic segmentation 56 + sentences_with_text = [] 57 + for s in sentences: 58 + sent_text = text.encode("utf-8")[s["byteStart"]:s["byteEnd"]].decode("utf-8") 59 + sentences_with_text.append({**s, "text": sent_text}) 60 + topic_breaks = detect_topic_breaks(sentences_with_text) 61 + 62 + # Pass 5: LLM concept detection (optional — requires ANTHROPIC_API_KEY) 63 + if concept_rows: 64 + concept_lookup = _build_concept_lookup(concept_rows) 65 + known_names = [c["name"] for c in concept_rows] 66 + llm_concepts = detect_llm_concepts(text, known_names) 67 + if llm_concepts: 68 + occupied = {(e["byteStart"], e["byteEnd"]) for e in entities} 69 + llm_entities = resolve_llm_concepts(text, llm_concepts, concept_lookup, occupied) 70 + entities.extend(llm_entities) 71 + 72 + return { 73 + "talkRkey": talk_rkey, 74 + "sentences": sentences, 75 + "paragraphs": paragraphs, 76 + "entities": entities, 77 + "topicBreaks": [{"byteStart": tb["byteStart"]} for tb in topic_breaks], 78 + "metadata": { 79 + "tool": "spacy/en_core_web_sm", 80 + "pauseThresholdMs": pause_threshold_ms, 81 + "proximityWords": proximity_words, 82 + }, 83 + } 84 + 85 + 86 + def main(): 87 + """CLI: read transcripts from appview data/transcripts/, write results to pipeline/data/nlp/.""" 88 + # Match the path used by publish.ts: apps/ionosphere-appview/data/transcripts/ 89 + transcripts_dir = Path(__file__).resolve().parent.parent.parent / "apps" / "ionosphere-appview" / "data" / "transcripts" 90 + output_dir = Path(__file__).resolve().parent.parent / "data" / "nlp" 91 + output_dir.mkdir(parents=True, exist_ok=True) 92 + 93 + if not transcripts_dir.exists(): 94 + print(f"Transcripts directory not found: {transcripts_dir}") 95 + print("Run from repo root, or ensure appview data/transcripts/ exists.") 96 + sys.exit(1) 97 + 98 + import sqlite3 99 + db_path = Path(__file__).resolve().parent.parent.parent / "apps" / "data" / "ionosphere.sqlite" 100 + speaker_rows = [] 101 + concept_rows = [] 102 + if db_path.exists(): 103 + conn = sqlite3.connect(str(db_path)) 104 + speaker_rows = conn.execute( 105 + "SELECT name, handle, speaker_did FROM speakers" 106 + ).fetchall() 107 + concept_rows = [ 108 + {"name": r[0], "uri": r[1], "aliases": r[2] or "[]"} 109 + for r in conn.execute("SELECT name, uri, aliases FROM concepts").fetchall() 110 + ] 111 + conn.close() 112 + print(f"Loaded {len(speaker_rows)} speakers, {len(concept_rows)} concepts from DB") 113 + else: 114 + print(f"Warning: database not found at {db_path}, entity linking disabled") 115 + 116 + transcript_files = sorted(transcripts_dir.glob("*.json")) 117 + print(f"Processing {len(transcript_files)} transcripts...") 118 + 119 + for tf in transcript_files: 120 + talk_rkey = tf.stem 121 + transcript = json.loads(tf.read_text()) 122 + 123 + # The cached transcript files may be in TranscriptResult format 124 + # (text + words array). Convert to compact format if needed. 125 + if "words" in transcript and "timings" not in transcript: 126 + from nlp.encoding import words_to_compact 127 + compact = words_to_compact(transcript) 128 + else: 129 + compact = transcript 130 + 131 + result = process_transcript( 132 + compact, talk_rkey=talk_rkey, 133 + speaker_rows=speaker_rows, 134 + concept_rows=concept_rows, 135 + ) 136 + 137 + out_path = output_dir / f"{talk_rkey}.json" 138 + out_path.write_text(json.dumps(result, indent=2)) 139 + entity_count = len(result.get("entities", [])) 140 + topic_count = len(result.get("topicBreaks", [])) 141 + print(f" {talk_rkey}: {len(result['sentences'])} sentences, {len(result['paragraphs'])} paragraphs, {entity_count} entities, {topic_count} topics", flush=True) 142 + 143 + print("Done.") 144 + 145 + 146 + if __name__ == "__main__": 147 + main()
+87
pipeline/nlp/run_streams.py
··· 1 + """Run NLP pipeline on stream transcripts (without LLM pass — too large).""" 2 + 3 + import json 4 + import sqlite3 5 + import sys 6 + from pathlib import Path 7 + from nlp.sentences import detect_sentences 8 + from nlp.paragraphs import detect_paragraphs 9 + from nlp.entities import detect_entities 10 + from nlp.speaker_lookup import build_speaker_lookup 11 + from nlp.topics import detect_topic_breaks 12 + 13 + 14 + def main(): 15 + streams_dir = Path(__file__).resolve().parent.parent / "data" / "stream-transcripts" 16 + output_dir = Path(__file__).resolve().parent.parent / "data" / "stream-nlp" 17 + output_dir.mkdir(parents=True, exist_ok=True) 18 + 19 + if not streams_dir.exists(): 20 + print("Run export_streams.py first") 21 + sys.exit(1) 22 + 23 + # Load speaker/concept data 24 + db_path = Path(__file__).resolve().parent.parent.parent / "apps" / "data" / "ionosphere.sqlite" 25 + speaker_rows = [] 26 + concept_rows = [] 27 + if db_path.exists(): 28 + conn = sqlite3.connect(str(db_path)) 29 + speaker_rows = conn.execute("SELECT name, handle, speaker_did FROM speakers").fetchall() 30 + concept_rows = [ 31 + {"name": r[0], "uri": r[1], "aliases": r[2] or "[]"} 32 + for r in conn.execute("SELECT name, uri, aliases FROM concepts").fetchall() 33 + ] 34 + conn.close() 35 + print(f"Loaded {len(speaker_rows)} speakers, {len(concept_rows)} concepts", flush=True) 36 + 37 + speaker_lookup = build_speaker_lookup(speaker_rows) if speaker_rows else None 38 + 39 + for tf in sorted(streams_dir.glob("*.json")): 40 + slug = tf.stem.replace("stream-", "") 41 + transcript = json.loads(tf.read_text()) 42 + text = transcript["text"] 43 + timings = transcript["timings"] 44 + start_ms = transcript["startMs"] 45 + 46 + print(f"Processing {slug} ({len(text)} chars)...", flush=True) 47 + 48 + # Pass 1: Sentences 49 + sentences = detect_sentences(text) 50 + print(f" {len(sentences)} sentences", flush=True) 51 + 52 + # Pass 2: Paragraphs 53 + paragraphs = detect_paragraphs( 54 + text=text, timings=timings, start_ms=start_ms, 55 + sentences=sentences, 56 + ) 57 + print(f" {len(paragraphs)} paragraphs", flush=True) 58 + 59 + # Pass 3: NER + entity linking (no LLM — too large) 60 + entities = detect_entities(text, speaker_lookup=speaker_lookup, concept_rows=concept_rows) 61 + print(f" {len(entities)} entities", flush=True) 62 + 63 + # Pass 4: Topic segmentation 64 + sentences_with_text = [] 65 + for s in sentences: 66 + sent_text = text.encode("utf-8")[s["byteStart"]:s["byteEnd"]].decode("utf-8") 67 + sentences_with_text.append({**s, "text": sent_text}) 68 + topic_breaks = detect_topic_breaks(sentences_with_text) 69 + print(f" {len(topic_breaks)} topics", flush=True) 70 + 71 + result = { 72 + "slug": slug, 73 + "sentences": sentences, 74 + "paragraphs": paragraphs, 75 + "entities": entities, 76 + "topicBreaks": [{"byteStart": tb["byteStart"]} for tb in topic_breaks], 77 + } 78 + 79 + out_path = output_dir / f"stream-{slug}.json" 80 + out_path.write_text(json.dumps(result, indent=2)) 81 + print(f" Done: {slug}", flush=True) 82 + 83 + print("All streams processed.") 84 + 85 + 86 + if __name__ == "__main__": 87 + main()
+38
pipeline/nlp/sentences.py
··· 1 + """Pass 1: Sentence boundary detection using spaCy.""" 2 + 3 + import spacy 4 + 5 + _nlp = None 6 + 7 + 8 + def _get_nlp(): 9 + global _nlp 10 + if _nlp is None: 11 + _nlp = spacy.load("en_core_web_sm") 12 + return _nlp 13 + 14 + 15 + def detect_sentences(text: str) -> list[dict]: 16 + """Detect sentence boundaries and return byte-range spans. 17 + 18 + Returns a list of dicts, each with: 19 + byteStart: int — UTF-8 byte offset of sentence start 20 + byteEnd: int — UTF-8 byte offset of sentence end (exclusive) 21 + """ 22 + if not text.strip(): 23 + return [] 24 + 25 + nlp = _get_nlp() 26 + doc = nlp(text) 27 + sentences = [] 28 + 29 + for sent in doc.sents: 30 + # spaCy gives character offsets; convert to byte offsets 31 + byte_start = len(text[:sent.start_char].encode("utf-8")) 32 + byte_end = len(text[:sent.end_char].encode("utf-8")) 33 + sentences.append({ 34 + "byteStart": byte_start, 35 + "byteEnd": byte_end, 36 + }) 37 + 38 + return sentences
+36
pipeline/nlp/speaker_lookup.py
··· 1 + """Build a speaker lookup table from database records for entity resolution.""" 2 + 3 + 4 + class SpeakerLookup: 5 + def __init__(self): 6 + self._by_full_name: dict[str, dict] = {} 7 + self._by_first_name: dict[str, dict | None] = {} 8 + self._by_handle: dict[str, dict] = {} 9 + 10 + def add(self, name: str, handle: str | None, did: str | None): 11 + entry = {"name": name, "handle": handle, "did": did} 12 + self._by_full_name[name.lower()] = entry 13 + if handle: 14 + self._by_handle[handle.lower()] = entry 15 + first = name.split()[0].lower() 16 + if first in self._by_first_name: 17 + self._by_first_name[first] = None # ambiguous 18 + else: 19 + self._by_first_name[first] = entry 20 + 21 + def resolve(self, name: str) -> dict | None: 22 + key = name.lower().strip() 23 + if key in self._by_full_name: 24 + return self._by_full_name[key] 25 + if key in self._by_handle: 26 + return self._by_handle[key] 27 + if key in self._by_first_name: 28 + return self._by_first_name[key] 29 + return None 30 + 31 + 32 + def build_speaker_lookup(rows: list[tuple]) -> SpeakerLookup: 33 + lookup = SpeakerLookup() 34 + for name, handle, did in rows: 35 + lookup.add(name, handle, did) 36 + return lookup
+57
pipeline/nlp/topics.py
··· 1 + """Pass 4: Topic segmentation using sentence embeddings.""" 2 + 3 + import numpy as np 4 + 5 + _model = None 6 + 7 + 8 + def _get_model(): 9 + global _model 10 + if _model is None: 11 + from sentence_transformers import SentenceTransformer 12 + _model = SentenceTransformer("all-MiniLM-L6-v2") 13 + return _model 14 + 15 + 16 + def detect_topic_breaks( 17 + sentences: list[dict], 18 + window_size: int = 3, 19 + similarity_threshold: float = 0.3, 20 + min_segment_sentences: int = 5, 21 + ) -> list[dict]: 22 + """Detect topic boundaries using sentence embedding similarity. 23 + 24 + Args: 25 + sentences: list of dicts with byteStart, byteEnd, text 26 + window_size: number of sentences per comparison window 27 + similarity_threshold: cosine similarity below this = topic break 28 + min_segment_sentences: minimum sentences between breaks 29 + 30 + Returns: 31 + list of dicts with byteStart and sentenceIndex 32 + """ 33 + if len(sentences) < window_size * 2: 34 + return [] 35 + 36 + model = _get_model() 37 + texts = [s["text"] for s in sentences] 38 + embeddings = model.encode(texts, show_progress_bar=False) 39 + 40 + similarities = [] 41 + for i in range(window_size, len(sentences) - window_size + 1): 42 + left = np.mean(embeddings[i - window_size:i], axis=0) 43 + right = np.mean(embeddings[i:i + window_size], axis=0) 44 + cos_sim = np.dot(left, right) / (np.linalg.norm(left) * np.linalg.norm(right)) 45 + similarities.append((i, float(cos_sim))) 46 + 47 + breaks = [] 48 + last_break = 0 49 + for sent_idx, sim in similarities: 50 + if sim < similarity_threshold and (sent_idx - last_break) >= min_segment_sentences: 51 + breaks.append({ 52 + "byteStart": sentences[sent_idx]["byteStart"], 53 + "sentenceIndex": sent_idx, 54 + }) 55 + last_break = sent_idx 56 + 57 + return breaks
+19
pipeline/pyproject.toml
··· 1 + [project] 2 + name = "ionosphere-nlp" 3 + version = "0.1.0" 4 + description = "NLP enrichment pipeline for ionosphere transcripts" 5 + requires-python = ">=3.12" 6 + dependencies = [ 7 + "spacy>=3.7", 8 + "sentence-transformers>=2.0", 9 + "anthropic>=0.90", 10 + ] 11 + 12 + [project.optional-dependencies] 13 + dev = ["pytest>=8.0"] 14 + 15 + [tool.setuptools.packages.find] 16 + include = ["nlp*"] 17 + 18 + [tool.pytest.ini_options] 19 + testpaths = ["tests"]
pipeline/tests/__init__.py

This is a binary file and will not be displayed.

+119
pipeline/tests/test_entities.py
··· 1 + from nlp.entities import detect_entities 2 + from nlp.speaker_lookup import build_speaker_lookup 3 + 4 + 5 + def test_detects_person_entities(): 6 + text = "Matt Akamatsu is presenting today." 7 + rows = [("Matt Akamatsu", "matsulab.com", "did:plc:matt123")] 8 + lookup = build_speaker_lookup(rows) 9 + 10 + entities = detect_entities(text, speaker_lookup=lookup) 11 + 12 + persons = [e for e in entities if e["nerType"] == "PERSON"] 13 + assert len(persons) >= 1 14 + resolved = [e for e in persons if e.get("speakerDid")] 15 + assert len(resolved) >= 1 16 + assert resolved[0]["speakerDid"] == "did:plc:matt123" 17 + 18 + 19 + def test_detects_org_entities(): 20 + text = "The work at Bluesky is impressive." 21 + concepts = [{"name": "Bluesky", "uri": "at://did/concept/bluesky", "aliases": "[]"}] 22 + 23 + entities = detect_entities(text, concept_rows=concepts) 24 + 25 + orgs = [e for e in entities if e.get("conceptUri")] 26 + assert len(orgs) >= 1 27 + 28 + 29 + def test_unresolved_entities_have_label(): 30 + text = "Barack Obama spoke at the conference." 31 + entities = detect_entities(text) 32 + 33 + persons = [e for e in entities if e["nerType"] == "PERSON"] 34 + assert len(persons) >= 1 35 + assert persons[0].get("speakerDid") is None 36 + assert persons[0]["label"] == "Barack Obama" 37 + 38 + 39 + def test_byte_offsets_correct(): 40 + text = "Matt Akamatsu presented." 41 + entities = detect_entities(text) 42 + if entities: 43 + e = entities[0] 44 + text_at_range = text.encode("utf-8")[e["byteStart"]:e["byteEnd"]].decode("utf-8") 45 + assert e["label"] in text_at_range or text_at_range in e["label"] 46 + 47 + 48 + def test_empty_text(): 49 + entities = detect_entities("") 50 + assert entities == [] 51 + 52 + 53 + # --- Text matching for known concepts --- 54 + 55 + 56 + def test_text_matching_finds_domain_concepts(): 57 + """Concepts like 'AT Protocol' and 'PDS' aren't NER entities but should be found by text matching.""" 58 + text = "The AT Protocol uses a PDS for data storage. Each lexicon defines a schema." 59 + concepts = [ 60 + {"name": "AT Protocol", "uri": "at://did/concept/atp", "aliases": '["atproto"]'}, 61 + {"name": "PDS", "uri": "at://did/concept/pds", "aliases": '["Personal Data Server"]'}, 62 + {"name": "Lexicon", "uri": "at://did/concept/lexicon", "aliases": "[]"}, 63 + ] 64 + 65 + entities = detect_entities(text, concept_rows=concepts) 66 + 67 + concept_entities = [e for e in entities if e.get("conceptUri")] 68 + concept_names = {e["label"] for e in concept_entities} 69 + assert "AT Protocol" in concept_names 70 + assert "PDS" in concept_names 71 + assert "lexicon" in concept_names or "Lexicon" in concept_names 72 + 73 + 74 + def test_text_matching_case_insensitive(): 75 + text = "We use the at protocol for federation." 76 + concepts = [{"name": "AT Protocol", "uri": "at://did/concept/atp", "aliases": "[]"}] 77 + 78 + entities = detect_entities(text, concept_rows=concepts) 79 + 80 + concept_entities = [e for e in entities if e.get("conceptUri")] 81 + # Should match case-insensitively 82 + assert len(concept_entities) >= 1 83 + 84 + 85 + def test_text_matching_finds_aliases(): 86 + text = "The Personal Data Server stores your data." 87 + concepts = [{"name": "PDS", "uri": "at://did/concept/pds", "aliases": '["Personal Data Server"]'}] 88 + 89 + entities = detect_entities(text, concept_rows=concepts) 90 + 91 + concept_entities = [e for e in entities if e.get("conceptUri")] 92 + assert len(concept_entities) >= 1 93 + assert concept_entities[0]["conceptUri"] == "at://did/concept/pds" 94 + 95 + 96 + def test_text_matching_no_duplicates_with_ner(): 97 + """If NER already detected an entity and text matching also finds it, don't duplicate.""" 98 + text = "Bluesky is a social network." 99 + concepts = [{"name": "Bluesky", "uri": "at://did/concept/bluesky", "aliases": "[]"}] 100 + 101 + entities = detect_entities(text, concept_rows=concepts) 102 + 103 + bluesky_entities = [e for e in entities if e["label"] == "Bluesky" or e["label"] == "bluesky"] 104 + # Should have exactly one, not two 105 + assert len(bluesky_entities) <= 2 # NER might split differently, but no exact byte-range duplicates 106 + byte_ranges = {(e["byteStart"], e["byteEnd"]) for e in bluesky_entities} 107 + assert len(byte_ranges) == len(bluesky_entities) # no duplicate ranges 108 + 109 + 110 + def test_text_matching_skips_short_concepts(): 111 + """Very short concept names (1-2 chars) should be skipped to avoid noise.""" 112 + text = "I think we should use AT for this." 113 + concepts = [{"name": "AT", "uri": "at://did/concept/at", "aliases": "[]"}] 114 + 115 + entities = detect_entities(text, concept_rows=concepts) 116 + 117 + # "AT" is too short and common — should not match 118 + concept_entities = [e for e in entities if e.get("conceptUri")] 119 + assert len(concept_entities) == 0
+50
pipeline/tests/test_paragraphs.py
··· 1 + from nlp.paragraphs import detect_paragraphs 2 + 3 + 4 + def test_basic_paragraphs(): 5 + text = "Hello world. This is sentence two. After a long pause here. New topic starts." 6 + sentences = [ 7 + {"byteStart": 0, "byteEnd": 12}, 8 + {"byteStart": 13, "byteEnd": 34}, 9 + {"byteStart": 35, "byteEnd": 59}, 10 + {"byteStart": 60, "byteEnd": 77}, 11 + ] 12 + # Big pause gap (3000ms) between word 5 ("two.") and word 6 ("After") 13 + # Words: Hello(0) world.(1) This(2) is(3) sentence(4) two.(5) 14 + # After(6) a(7) long(8) pause(9) here.(10) New(11) topic(12) starts.(13) 15 + timings = [100, 100, 100, 100, 100, 100, -3000, 100, 100, 100, 100, 100, 100, 100] 16 + start_ms = 0 17 + 18 + paragraphs = detect_paragraphs( 19 + text=text, 20 + timings=timings, 21 + start_ms=start_ms, 22 + sentences=sentences, 23 + pause_threshold_ms=2000, 24 + proximity_words=5, 25 + ) 26 + # Should detect a paragraph break at the sentence boundary near the 3s pause 27 + assert len(paragraphs) == 2 28 + assert paragraphs[0]["byteStart"] == 0 29 + assert paragraphs[1]["byteStart"] == 35 # "After a long pause..." 30 + 31 + 32 + def test_no_long_pauses_single_paragraph(): 33 + text = "One sentence. Two sentence." 34 + sentences = [ 35 + {"byteStart": 0, "byteEnd": 13}, 36 + {"byteStart": 14, "byteEnd": 27}, 37 + ] 38 + timings = [100, 100, 100, 100] 39 + paragraphs = detect_paragraphs( 40 + text=text, timings=timings, start_ms=0, 41 + sentences=sentences, 42 + ) 43 + assert len(paragraphs) == 1 44 + 45 + 46 + def test_empty_input(): 47 + paragraphs = detect_paragraphs( 48 + text="", timings=[], start_ms=0, sentences=[], 49 + ) 50 + assert paragraphs == []
+51
pipeline/tests/test_run.py
··· 1 + import json 2 + from pathlib import Path 3 + from nlp.run import process_transcript 4 + 5 + 6 + def test_process_transcript_produces_output(): 7 + """Integration test: full pipeline on a simple transcript.""" 8 + transcript = { 9 + "text": "Hello world. This is a test. After a long pause. New topic here.", 10 + "startMs": 0, 11 + "timings": [100, 100, 100, 100, 100, 100, -3000, 100, 100, 100, 100, 100, 100, 100], 12 + } 13 + 14 + result = process_transcript(transcript, talk_rkey="test-talk") 15 + 16 + # Should have sentences and paragraphs 17 + assert "sentences" in result 18 + assert "paragraphs" in result 19 + assert len(result["sentences"]) >= 2 20 + assert len(result["paragraphs"]) >= 1 21 + # Each sentence has byte ranges 22 + for s in result["sentences"]: 23 + assert "byteStart" in s 24 + assert "byteEnd" in s 25 + # Metadata present 26 + assert "metadata" in result 27 + assert result["metadata"]["tool"] == "spacy/en_core_web_sm" 28 + 29 + 30 + def test_process_transcript_with_enrichment(): 31 + """Full pipeline with entity and topic passes.""" 32 + transcript = { 33 + "text": "Matt Akamatsu is presenting. The AT Protocol is decentralized. Now we discuss a completely different topic about cooking recipes and baking cakes with flour and sugar and eggs.", 34 + "startMs": 0, 35 + "timings": [100, 100, 100, 100, 100, 100, 100, 100, 100, -3000, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100], 36 + } 37 + speaker_rows = [("Matt Akamatsu", "matsulab.com", "did:plc:matt123")] 38 + concept_rows = [{"name": "AT Protocol", "uri": "at://did/concept/atp", "aliases": "[]"}] 39 + 40 + result = process_transcript( 41 + transcript, talk_rkey="test", 42 + speaker_rows=speaker_rows, 43 + concept_rows=concept_rows, 44 + ) 45 + 46 + assert "entities" in result 47 + assert "topicBreaks" in result 48 + assert len(result["entities"]) >= 1 49 + # At least one resolved entity 50 + resolved = [e for e in result["entities"] if e.get("speakerDid") or e.get("conceptUri")] 51 + assert len(resolved) >= 1
+35
pipeline/tests/test_sentences.py
··· 1 + from nlp.sentences import detect_sentences 2 + 3 + 4 + def test_basic_sentences(): 5 + text = "Hello world. This is a test. And another sentence." 6 + sentences = detect_sentences(text) 7 + assert len(sentences) == 3 8 + # Each sentence is a dict with byteStart and byteEnd 9 + assert sentences[0]["byteStart"] == 0 10 + assert sentences[0]["byteEnd"] == len("Hello world.".encode("utf-8")) 11 + assert sentences[1]["byteStart"] == len("Hello world. ".encode("utf-8")) 12 + 13 + 14 + def test_speech_without_punctuation(): 15 + """spaCy should detect sentence boundaries even with poor punctuation.""" 16 + text = "so the thing is we need to think about this carefully and then we can move on to the next topic which is about protocols" 17 + sentences = detect_sentences(text) 18 + # spaCy should find at least 1 sentence (the whole text if no clear boundary) 19 + assert len(sentences) >= 1 20 + # All sentences should cover the full text 21 + assert sentences[0]["byteStart"] == 0 22 + assert sentences[-1]["byteEnd"] == len(text.encode("utf-8")) 23 + 24 + 25 + def test_empty_text(): 26 + sentences = detect_sentences("") 27 + assert sentences == [] 28 + 29 + 30 + def test_byte_offsets_for_unicode(): 31 + text = "Caf\u00e9 is great. Let\u2019s go." 32 + sentences = detect_sentences(text) 33 + # Byte offsets must account for multi-byte characters 34 + full_bytes = text.encode("utf-8") 35 + assert sentences[-1]["byteEnd"] == len(full_bytes)
+35
pipeline/tests/test_speaker_lookup.py
··· 1 + from nlp.speaker_lookup import build_speaker_lookup 2 + 3 + 4 + def test_build_lookup_from_rows(): 5 + rows = [ 6 + ("Matt Akamatsu", "matsulab.com", "did:plc:matt123"), 7 + ("Rowan Cockett", "row1.ca", "did:plc:rowan456"), 8 + ("Jay Graber", "jay.bsky.team", "did:plc:jay789"), 9 + ] 10 + lookup = build_speaker_lookup(rows) 11 + 12 + assert lookup.resolve("Matt Akamatsu") is not None 13 + assert lookup.resolve("Matt Akamatsu")["did"] == "did:plc:matt123" 14 + assert lookup.resolve("matt akamatsu")["did"] == "did:plc:matt123" 15 + assert lookup.resolve("Matt") is not None 16 + assert lookup.resolve("Matt")["did"] == "did:plc:matt123" 17 + assert lookup.resolve("row1.ca") is not None 18 + assert lookup.resolve("row1.ca")["did"] == "did:plc:rowan456" 19 + assert lookup.resolve("Unknown Person") is None 20 + 21 + 22 + def test_first_name_collision_returns_none(): 23 + rows = [ 24 + ("Matt Akamatsu", "matsulab.com", "did:plc:matt1"), 25 + ("Matt Jones", "mattj.com", "did:plc:matt2"), 26 + ] 27 + lookup = build_speaker_lookup(rows) 28 + 29 + assert lookup.resolve("Matt Akamatsu")["did"] == "did:plc:matt1" 30 + assert lookup.resolve("Matt") is None 31 + 32 + 33 + def test_empty_speakers(): 34 + lookup = build_speaker_lookup([]) 35 + assert lookup.resolve("Anyone") is None
+39
pipeline/tests/test_topics.py
··· 1 + from nlp.topics import detect_topic_breaks 2 + 3 + 4 + def test_detects_topic_change(): 5 + """Distinct topics should produce at least one break.""" 6 + sentences = [ 7 + {"byteStart": 0, "byteEnd": 30, "text": "Today we will make a cake."}, 8 + {"byteStart": 31, "byteEnd": 65, "text": "First mix the flour and sugar."}, 9 + {"byteStart": 66, "byteEnd": 100, "text": "Then add the eggs and butter."}, 10 + {"byteStart": 101, "byteEnd": 135, "text": "Bake at 350 degrees for 30 minutes."}, 11 + {"byteStart": 136, "byteEnd": 170, "text": "Let it cool before adding frosting."}, 12 + {"byteStart": 171, "byteEnd": 210, "text": "NASA launched a new rocket to Mars."}, 13 + {"byteStart": 211, "byteEnd": 250, "text": "The spacecraft will orbit the red planet."}, 14 + {"byteStart": 251, "byteEnd": 295, "text": "Astronauts may visit Mars within ten years."}, 15 + {"byteStart": 296, "byteEnd": 340, "text": "The mission costs billions of dollars."}, 16 + {"byteStart": 341, "byteEnd": 380, "text": "Space exploration advances human knowledge."}, 17 + ] 18 + breaks = detect_topic_breaks(sentences) 19 + assert len(breaks) >= 1 20 + assert any(4 <= b["sentenceIndex"] <= 6 for b in breaks) 21 + 22 + 23 + def test_no_breaks_for_single_topic(): 24 + sentences = [ 25 + {"byteStart": 0, "byteEnd": 30, "text": "The cat sat on the mat."}, 26 + {"byteStart": 31, "byteEnd": 60, "text": "The cat was very happy."}, 27 + {"byteStart": 61, "byteEnd": 90, "text": "It purred loudly all day."}, 28 + ] 29 + breaks = detect_topic_breaks(sentences, min_segment_sentences=2) 30 + assert len(breaks) <= 1 31 + 32 + 33 + def test_empty_input(): 34 + assert detect_topic_breaks([]) == [] 35 + 36 + 37 + def test_too_few_sentences(): 38 + sentences = [{"byteStart": 0, "byteEnd": 10, "text": "Hello."}] 39 + assert detect_topic_breaks(sentences) == []