{"version":3,"file":"session-repo.d.ts","sourceRoot":"","sources":["../../../../../src/harness/session/testing/benchmark/session-repo.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAEnE,OAAO,EAA8B,KAAK,uBAAuB,EAAE,MAAM,eAAe,CAAC;AAGzF,MAAM,WAAW,kCAAkC;IAClD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;CAC9B;AAED,UAAU,uCAAuC;IAChD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,OAAO,EAAE,kCAAkC,GAAG,MAAM,CAAC;IACpE,GAAG,CAAC,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CACxC;AAED,UAAU,yCAAyC;IAClD,GAAG,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;CACvB;AAED,UAAU,wCAAwC;IACjD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,OAAO,CAAC,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,yCAAyC,CAAC,CAAC;CAC/E;AAED,UAAU,qCAAqC;IAC9C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,OAAO,EAAE,uBAAuB,GAAG,MAAM,CAAC;IACzD,GAAG,CAAC,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,eAAe,EAAE,OAAO,EAAE,uBAAuB,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CACnG;AAED,0FAA0F;AAC1F,wBAAgB,6BAA6B,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEnE;AAYD,+EAA+E;AAC/E,eAAO,MAAM,uCAAuC,EAAE,SAAS,kCAAkC,EAIhG,CAAC;AAEF,0FAA0F;AAC1F,wBAAsB,+BAA+B,CACpD,IAAI,EAAE,WAAW,EACjB,OAAO,EAAE,kCAAkC,GACzC,OAAO,CAAC,eAAe,EAAE,CAAC,CAQ5B;AAED,gFAAgF;AAChF,eAAO,MAAM,6CAA6C,EAAE,SAAS,uCAAuC,EAU3G,CAAC;AAEF,wGAAwG;AACxG,eAAO,MAAM,8CAA8C,EAAE,SAAS,wCAAwC,EA2C7G,CAAC;AAEF,6GAA6G;AAC7G,eAAO,MAAM,oCAAoC,EAAE,SAAS,uBAAuB,EAGlF,CAAC;AAEF,6EAA6E;AAC7E,wBAAsB,4BAA4B,CACjD,IAAI,EAAE,WAAW,EACjB,OAAO,EAAE,uBAAuB,GAC9B,OAAO,CAAC,eAAe,CAAC,CAsB1B;AAED,qFAAqF;AACrF,eAAO,MAAM,2CAA2C,EAAE,SAAS,qCAAqC,EAiBvG,CAAC","sourcesContent":["import { BACKGROUND_CONTEXT } from \"../../../context.ts\";\nimport type { SessionMetadata, SessionRepo } from \"../../types.ts\";\nimport { branchTip, laneConfig, laneState, setValue } from \"../../values.ts\";\nimport { STORAGE_BENCHMARK_DATASETS, type StorageBenchmarkDataset } from \"./datasets.ts\";\nimport { generateStorageBenchmarkSeedTransactions } from \"./storage.ts\";\n\nexport interface SessionRepoCatalogBenchmarkDataset {\n\treadonly name: string;\n\treadonly sessionCount: number;\n}\n\ninterface SessionRepoCatalogReadBenchmarkScenario {\n\treadonly name: string;\n\texpectedResult(dataset: SessionRepoCatalogBenchmarkDataset): number;\n\trun(repo: SessionRepo): Promise<number>;\n}\n\ninterface SessionRepoCatalogWriteBenchmarkOperation {\n\trun(): Promise<number>;\n}\n\ninterface SessionRepoCatalogWriteBenchmarkScenario {\n\treadonly name: string;\n\treadonly expectedResult: number;\n\tprepare(repo: SessionRepo): Promise<SessionRepoCatalogWriteBenchmarkOperation>;\n}\n\ninterface SessionRepoForkWriteBenchmarkScenario {\n\treadonly name: string;\n\texpectedResult(dataset: StorageBenchmarkDataset): number;\n\trun(repo: SessionRepo, source: SessionMetadata, dataset: StorageBenchmarkDataset): Promise<number>;\n}\n\n/** Package-internal deterministic session id shared by repository benchmark workloads. */\nexport function sessionRepoBenchmarkSessionId(index: number): string {\n\treturn `benchmark-session-${index.toString().padStart(8, \"0\")}`;\n}\n\nconst BENCHMARK_SESSION_ID = sessionRepoBenchmarkSessionId(0);\nconst FORK_DESTINATION_SESSION_ID = sessionRepoBenchmarkSessionId(1);\n\nfunction createCatalogDataset(scale: string, sessionCount: number): SessionRepoCatalogBenchmarkDataset {\n\treturn {\n\t\tname: `synthetic catalog: ${scale} closed sessions`,\n\t\tsessionCount,\n\t};\n}\n\n/** Deterministic closed-session catalogs shared by repository measurements. */\nexport const SESSION_REPO_CATALOG_BENCHMARK_DATASETS: readonly SessionRepoCatalogBenchmarkDataset[] = [\n\tcreateCatalogDataset(\"100\", 100),\n\tcreateCatalogDataset(\"1k\", 1_000),\n\tcreateCatalogDataset(\"10k\", 10_000),\n];\n\n/** Seeds one deterministic catalog and returns its durable metadata in creation order. */\nexport async function seedSessionRepoCatalogBenchmark(\n\trepo: SessionRepo,\n\tdataset: SessionRepoCatalogBenchmarkDataset,\n): Promise<SessionMetadata[]> {\n\tconst metadata: SessionMetadata[] = [];\n\tfor (let index = 0; index < dataset.sessionCount; index++) {\n\t\tconst session = await repo.create({ id: sessionRepoBenchmarkSessionId(index) }, BACKGROUND_CONTEXT);\n\t\tmetadata.push(session.metadata);\n\t\tawait session.close(BACKGROUND_CONTEXT);\n\t}\n\treturn metadata;\n}\n\n/** Shared catalog reads. Returning a number ensures each result is consumed. */\nexport const SESSION_REPO_CATALOG_READ_BENCHMARK_SCENARIOS: readonly SessionRepoCatalogReadBenchmarkScenario[] = [\n\t{\n\t\tname: \"list sessions\",\n\t\texpectedResult(dataset) {\n\t\t\treturn dataset.sessionCount;\n\t\t},\n\t\tasync run(repo) {\n\t\t\treturn (await repo.list(undefined, BACKGROUND_CONTEXT)).length;\n\t\t},\n\t},\n];\n\n/** Shared catalog writes. Every invocation receives an equivalent independently prepared repository. */\nexport const SESSION_REPO_CATALOG_WRITE_BENCHMARK_SCENARIOS: readonly SessionRepoCatalogWriteBenchmarkScenario[] = [\n\t{\n\t\tname: \"create empty session\",\n\t\texpectedResult: 1,\n\t\tprepare(repo) {\n\t\t\treturn Promise.resolve({\n\t\t\t\tasync run() {\n\t\t\t\t\tconst session = await repo.create({ id: BENCHMARK_SESSION_ID }, BACKGROUND_CONTEXT);\n\t\t\t\t\treturn session.metadata.id === BENCHMARK_SESSION_ID ? 1 : 0;\n\t\t\t\t},\n\t\t\t});\n\t\t},\n\t},\n\t{\n\t\tname: \"open closed empty session\",\n\t\texpectedResult: 1,\n\t\tasync prepare(repo) {\n\t\t\tconst session = await repo.create({ id: BENCHMARK_SESSION_ID }, BACKGROUND_CONTEXT);\n\t\t\tconst { metadata } = session;\n\t\t\tawait session.close(BACKGROUND_CONTEXT);\n\t\t\treturn {\n\t\t\t\tasync run() {\n\t\t\t\t\tconst reopened = await repo.open(metadata, BACKGROUND_CONTEXT);\n\t\t\t\t\treturn reopened.metadata.id === metadata.id ? 1 : 0;\n\t\t\t\t},\n\t\t\t};\n\t\t},\n\t},\n\t{\n\t\tname: \"delete closed empty session\",\n\t\texpectedResult: 1,\n\t\tasync prepare(repo) {\n\t\t\tconst session = await repo.create({ id: BENCHMARK_SESSION_ID }, BACKGROUND_CONTEXT);\n\t\t\tconst { metadata } = session;\n\t\t\tawait session.close(BACKGROUND_CONTEXT);\n\t\t\treturn {\n\t\t\t\tasync run() {\n\t\t\t\t\tawait repo.delete(metadata, BACKGROUND_CONTEXT);\n\t\t\t\t\treturn 1;\n\t\t\t\t},\n\t\t\t};\n\t\t},\n\t},\n];\n\n/** Initial fork timing uses a bounded source because each iteration owns an equivalent seeded repository. */\nexport const SESSION_REPO_FORK_BENCHMARK_DATASETS: readonly StorageBenchmarkDataset[] = [\n\tSTORAGE_BENCHMARK_DATASETS[0]!,\n\tSTORAGE_BENCHMARK_DATASETS[1]!,\n];\n\n/** Seeds one deterministic open source session with a linear main branch. */\nexport async function seedSessionRepoForkBenchmark(\n\trepo: SessionRepo,\n\tdataset: StorageBenchmarkDataset,\n): Promise<SessionMetadata> {\n\tconst session = await repo.create({ id: BENCHMARK_SESSION_ID }, BACKGROUND_CONTEXT);\n\tfor (const transaction of generateStorageBenchmarkSeedTransactions(dataset)) {\n\t\tawait session.mutate((mutator) => mutator.commit(transaction, BACKGROUND_CONTEXT), BACKGROUND_CONTEXT);\n\t}\n\tawait session.mutate(\n\t\t(mutator) =>\n\t\t\tmutator.commit(\n\t\t\t\t[\n\t\t\t\t\tsetValue(branchTip(\"main\"), dataset.tipId),\n\t\t\t\t\tsetValue(laneConfig(\"main\"), {\n\t\t\t\t\t\tmodel: { provider: \"benchmark\", modelId: \"benchmark\" },\n\t\t\t\t\t\tthinkingLevel: \"off\",\n\t\t\t\t\t\tactiveToolNames: [],\n\t\t\t\t\t}),\n\t\t\t\t\tsetValue(laneState(\"main\"), { currentOperationId: null, lastOperationId: null, inbox: [] }),\n\t\t\t\t],\n\t\t\t\tBACKGROUND_CONTEXT,\n\t\t\t),\n\t\tBACKGROUND_CONTEXT,\n\t);\n\treturn session.metadata;\n}\n\n/** Shared fork writes. Every invocation receives an equivalent source repository. */\nexport const SESSION_REPO_FORK_WRITE_BENCHMARK_SCENARIOS: readonly SessionRepoForkWriteBenchmarkScenario[] = [\n\t{\n\t\tname: \"fork open current branch\",\n\t\texpectedResult(dataset) {\n\t\t\treturn dataset.entryCount;\n\t\t},\n\t\tasync run(repo, source, dataset) {\n\t\t\tconst fork = await repo.fork(\n\t\t\t\tsource,\n\t\t\t\t{ id: FORK_DESTINATION_SESSION_ID, scope: \"branch\", branch: \"main\" },\n\t\t\t\tBACKGROUND_CONTEXT,\n\t\t\t);\n\t\t\treturn fork.metadata.id === FORK_DESTINATION_SESSION_ID && fork.metadata.parentSessionId === source.id\n\t\t\t\t? dataset.entryCount\n\t\t\t\t: 0;\n\t\t},\n\t},\n];\n"]}