@utaba/deep-memory-storage-cosmosdb 0.17.0 → 0.18.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +35 -16
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +35 -16
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/CosmosDbProvider.ts","../src/CosmosDbConnection.ts","../src/usage.ts","../src/cosmos-rest-auth.ts","../src/CosmosDocumentClient.ts","../src/mapping.ts","../src/queries/repository.ts","../src/queries/vocabulary.ts","../src/queries/entity.ts","../src/queries/relationship.ts","../src/queries/timeline.ts","../src/queries/adaptive-import.ts","../src/queries/bulk.ts"],"sourcesContent":["// CosmosDbProvider — CosmosDB Gremlin implementation of StorageProvider + GraphTraversalProvider\n\nimport type { StorageProvider, EnsureSchemaResult, EntityReadOptions } from '@utaba/deep-memory/providers';\nimport type { GraphTraversalProvider, GraphTraversalCapabilities } from '@utaba/deep-memory/providers';\nimport type {\n StoredEntity,\n StoredEntityUpdate,\n StoredRelationship,\n RelationshipQueryOptions,\n MemoryVocabulary,\n VocabularyChangeRecord,\n StorageRepositoryConfig,\n StoredRepository,\n StoredRepositorySummary,\n RepositoryFilter,\n RepositoryStats,\n RepositoryUpdate,\n StorageFindQuery,\n StorageExploreOptions,\n StoragePathOptions,\n StorageTimelineOptions,\n PaginationOptions,\n PaginatedResult,\n StorageNeighborhood,\n StorageNeighborhoodLayer,\n StoragePath,\n StoragePathResult,\n StorageTimelineResult,\n BulkImportResult,\n TraversalSpec,\n TraversalStep,\n TraversalResult,\n QueryMetadata,\n UsageSink,\n} from '@utaba/deep-memory/types';\nimport type { ExportChunk, ImportChunk, BulkImportOptions, DeleteProgressCallback } from '@utaba/deep-memory/types';\nimport {\n GremlinCompiler,\n ProviderError,\n InvalidInputError,\n isValidUuid,\n projectEntity,\n createSafeSink,\n matchesPropertyFilters,\n} from '@utaba/deep-memory';\nimport { CosmosDbConnection } from './CosmosDbConnection.js';\nimport { CosmosDocumentClient } from './CosmosDocumentClient.js';\nimport { usageScope } from './usage.js';\nimport type { UsageAccumulator } from './usage.js';\nimport { cosmosRestPut } from './cosmos-rest-auth.js';\nimport { entityFromGremlin, relationshipFromGremlin } from './mapping.js';\nimport * as repoQueries from './queries/repository.js';\nimport * as vocabQueries from './queries/vocabulary.js';\nimport * as entityQueries from './queries/entity.js';\nimport * as relQueries from './queries/relationship.js';\nimport * as timelineQueries from './queries/timeline.js';\nimport * as bulkQueries from './queries/bulk.js';\n\n/** Configuration for CosmosDbProvider. */\nexport interface CosmosDbProviderConfig {\n /** Gremlin WebSocket endpoint (e.g. ws://host.docker.internal:8901/) */\n endpoint: string;\n /** CosmosDB REST endpoint for database/container provisioning (e.g. https://host.docker.internal:8081/) — derived from Gremlin endpoint if omitted */\n restEndpoint?: string;\n /** CosmosDB primary key */\n key: string;\n /** Database name */\n database: string;\n /** Container (graph) name */\n container: string;\n /** Partition key path (default: /repositoryId) */\n partitionKey?: string;\n /** Max retries for transient errors (default: 3) */\n maxRetries?: number;\n /** Default query timeout in ms (default: 30000) */\n defaultTimeoutMs?: number;\n /** Whether to reject unauthorized TLS certs — set false for emulator (default: true) */\n rejectUnauthorized?: boolean;\n /**\n * Optional usage sink. When provided, the provider emits one\n * {@link OperationUsage} record per public method call with the aggregated\n * CosmosDB request charge (RU). Never exposed to AI agents — the MCP server\n * deliberately does not plumb this sink through.\n */\n reportUsage?: UsageSink;\n}\n\nconst PROVIDER_NAME = 'cosmosdb';\nconst SCHEMA_VERSION = 1;\nconst META_VERTEX_ID = '_meta:schema';\n\n/**\n * Indexing-policy paths that `findEntities` SQL relies on. If a container's\n * `excludedPaths` covers any of these (directly or via wildcard), the rewrite\n * falls back to scan — see {@link CosmosDbProvider.runIndexingPolicyDiagnostic}.\n */\nconst GUARDED_INDEX_PATHS = [\n '/entityLabel',\n '/slug',\n '/summary',\n '/entityType',\n '/properties',\n '/repositoryId',\n] as const;\n\n/**\n * Raw, un-projected output from {@link CosmosDbProvider.executeTraversal}.\n * Only the fields relevant to the spec's `returnMode` are populated; the rest\n * remain empty. Used to share the compile + submit + parse pipeline between\n * `traverseInternal` (which projects into the public TraversalResult shape)\n * and the storage-layer rewrites of `exploreNeighborhood` / `findPaths`\n * (which need raw stored entities to rebuild storage-level outputs).\n */\ninterface RawTraversalResult {\n /** Populated when `spec.returnMode === 'terminal'`. */\n terminalEntities: StoredEntity[];\n /** Populated when `spec.returnMode === 'all'`. */\n allEntities: StoredEntity[];\n /** Populated when `spec.returnMode === 'all'`. */\n allRelationships: StoredRelationship[];\n /** Populated when `spec.returnMode === 'path'`. */\n pathRows: Array<{\n entityIds: string[];\n relationshipIds: string[];\n relationshipDirections: Array<'outbound' | 'inbound'>;\n }>;\n /**\n * Lookup table — populated for `'all'` and `'path'` modes. Includes every\n * entity that appears in any returned row.\n */\n entityMap: Map<string, StoredEntity>;\n /**\n * Lookup table — populated for `'all'` and `'path'` modes. Includes every\n * relationship that appears in any returned row.\n */\n relationshipMap: Map<string, StoredRelationship>;\n /**\n * First-seen walk direction per deduped edge id. Populated only for\n * `'path'` mode — the `'all'` mode's deduped union carries no walk context.\n */\n pathRelFirstDirection: Map<string, 'outbound' | 'inbound'>;\n executionTimeMs: number;\n requestCharge: number | undefined;\n compiledQuery: string;\n}\n\n/**\n * Vocabulary TTL for the per-process cache. Vocabulary changes are rare\n * (governance-gated writes); a 60 s window bounds cross-process staleness\n * acceptably while eliminating the one extra round-trip on every traversal.\n */\nconst VOCABULARY_CACHE_TTL_MS = 60_000;\n\n/**\n * CosmosDB Gremlin storage provider for deep-memory.\n * Implements both StorageProvider (full CRUD) and GraphTraversalProvider (native Gremlin traversals).\n */\nexport class CosmosDbProvider implements StorageProvider, GraphTraversalProvider {\n private readonly conn: CosmosDbConnection;\n private readonly docClient: CosmosDocumentClient;\n private readonly config: CosmosDbProviderConfig;\n private readonly compiler = new GremlinCompiler();\n private readonly reportUsage: UsageSink | undefined;\n /**\n * Per-process vocabulary cache, keyed by repositoryId. Read lazily by\n * `traverseImpl` via `getVocabularyCached`; invalidated on `saveVocabulary`.\n * Each provider instance owns its own cache so isolated test providers do\n * not share state.\n */\n private readonly vocabularyCache = new Map<string, { vocab: MemoryVocabulary; expiresAt: number }>();\n\n constructor(config: CosmosDbProviderConfig) {\n this.config = config;\n this.reportUsage = createSafeSink(config.reportUsage);\n this.conn = new CosmosDbConnection({\n endpoint: config.endpoint,\n key: config.key,\n database: config.database,\n container: config.container,\n maxRetries: config.maxRetries,\n defaultTimeoutMs: config.defaultTimeoutMs,\n rejectUnauthorized: config.rejectUnauthorized,\n });\n // Document (NoSQL SQL) endpoint client — used by query paths the Gremlin\n // subset can't express server-side (substring + case-insensitive search,\n // structured property predicates). RU accumulates into the same\n // usageScope as `conn`, so one public-method call emits one usage record\n // even when both endpoints are touched.\n this.docClient = new CosmosDocumentClient({\n restEndpoint: this.getRestEndpoint(),\n key: config.key,\n database: config.database,\n container: config.container,\n rejectUnauthorized: config.rejectUnauthorized ?? true,\n maxRetries: config.maxRetries,\n defaultTimeoutMs: config.defaultTimeoutMs,\n });\n }\n\n /**\n * Run the given operation inside an async-local usage scope. While the\n * operation runs, every `conn.submit()` call accumulates its request charge\n * into a shared accumulator. When the operation completes (success or\n * failure), a single {@link OperationUsage} record is emitted to the sink.\n *\n * Nested public-method calls (e.g. `traverse` internally calls\n * `getVocabulary`) are detected: the inner call joins the outer scope\n * instead of starting a new one, so one user-visible operation produces\n * exactly one usage record covering all its internal round-trips.\n *\n * If no sink is configured, this is a zero-overhead pass-through.\n */\n private async track<T>(\n operation: string,\n repositoryId: string | undefined,\n fn: () => Promise<T>,\n ): Promise<T> {\n if (!this.reportUsage) return fn();\n // Already inside a parent scope — join it rather than emitting a\n // separate record. The outermost call owns emission.\n if (usageScope.getStore()) return fn();\n const acc: UsageAccumulator = { ru: 0, calls: 0, retries: 0 };\n try {\n return await usageScope.run(acc, fn);\n } finally {\n if (acc.calls > 0) {\n this.reportUsage({\n provider: PROVIDER_NAME,\n operation,\n unit: 'RU',\n value: acc.ru,\n ...(repositoryId ? { repositoryId } : {}),\n timestamp: new Date(),\n details: { calls: acc.calls, retries: acc.retries },\n });\n }\n }\n }\n\n /**\n * Reject any repositoryId that is not a valid v4 UUID.\n *\n * Every partition-scoped query filters on repositoryId. Since repositoryId is\n * the CosmosDB partition key, a predicate with a different value would target\n * a different partition. Strict format validation at the provider boundary\n * prevents injection (e.g. strings containing quotes or Gremlin syntax) from\n * ever reaching query construction.\n */\n private assertValidRepositoryId(repositoryId: string): void {\n if (!isValidUuid(repositoryId)) {\n throw new InvalidInputError(\n 'repositoryId',\n `repositoryId must be a valid v4 UUID; got '${repositoryId}'`,\n );\n }\n }\n\n // ─── Lifecycle ─────────────────────────────────────────────────────\n\n async initialize(): Promise<void> {\n await this.conn.connect();\n }\n\n async dispose(): Promise<void> {\n await this.conn.close();\n }\n\n async ensureSchema(): Promise<EnsureSchemaResult> {\n return this.track('ensureSchema', undefined, () => this.ensureSchemaImpl());\n }\n\n private async ensureSchemaImpl(): Promise<EnsureSchemaResult> {\n const restBase = this.getRestEndpoint();\n const partitionKey = this.config.partitionKey ?? '/repositoryId';\n let databaseCreated = false;\n let schemaCreated = false;\n\n try {\n // 1. Create database if not exists\n const dbCreated = await cosmosRestPut(\n restBase,\n this.config.key,\n 'dbs',\n '',\n 'dbs',\n { id: this.config.database },\n this.config.rejectUnauthorized ?? true,\n );\n databaseCreated = dbCreated;\n\n // 2. Create Gremlin graph container if not exists\n const containerCreated = await cosmosRestPut(\n restBase,\n this.config.key,\n `dbs/${this.config.database}/colls`,\n `dbs/${this.config.database}`,\n 'colls',\n {\n id: this.config.container,\n partitionKey: { paths: [partitionKey], kind: 'Hash' },\n },\n this.config.rejectUnauthorized ?? true,\n );\n schemaCreated = containerCreated;\n\n // 3. Reconnect Gremlin client (it may have failed before db/container existed)\n await this.conn.close();\n await this.conn.connect();\n\n // 4. Write schema version meta vertex\n const existing = await this.conn.submit(\n \"g.V().hasId(metaId).hasLabel('_meta').valueMap(true)\",\n { metaId: META_VERTEX_ID },\n );\n\n if (existing.items.length > 0) {\n const props = existing.items[0] as Record<string, unknown>;\n const version = Number(unwrapGremlinValue(props['schemaVersion']) ?? 0);\n if (version < SCHEMA_VERSION || databaseCreated || schemaCreated) {\n await this.conn.submit(\n \"g.V().hasId(metaId).hasLabel('_meta').property('schemaVersion', ver)\",\n { metaId: META_VERTEX_ID, ver: SCHEMA_VERSION },\n );\n }\n } else {\n await this.conn.submit(\n \"g.addV('_meta').property('id', metaId).property('repositoryId', pk).property('schemaVersion', ver)\",\n { metaId: META_VERTEX_ID, pk: '_system', ver: SCHEMA_VERSION },\n );\n schemaCreated = true;\n }\n\n // 5. Bootstrap the `_repository_index` sentinel. Idempotent — first run\n // does a one-time cross-partition scan to backfill existing repos, every\n // subsequent run is a single cheap doc-fetch that returns null.\n await repoQueries.ensureRepositoryIndex(this.conn);\n\n // 6. Step E — indexing-policy diagnostic. Always runs (operators may\n // drift policy between calls). Never fails ensureSchema — see helper.\n await this.runIndexingPolicyDiagnostic();\n\n return {\n databaseCreated,\n schemaCreated,\n alreadyUpToDate: !databaseCreated && !schemaCreated,\n schemaVersion: SCHEMA_VERSION,\n };\n } catch (err: unknown) {\n throw new ProviderError(\n `Failed to ensure CosmosDB schema: ${err instanceof Error ? err.message : String(err)}`,\n 'Verify the CosmosDB REST endpoint is accessible and the Gremlin endpoint is reachable.',\n );\n }\n }\n\n /**\n * Step E — verify the container's indexing policy covers every path that\n * the SQL `findEntities` rewrite hits. The probe (2026-05-26) confirmed\n * code-managed containers get the Cosmos default policy (everything\n * indexed). This guard is for operator-facing protection: externally\n * provisioned containers (ARM/Bicep) can have `excludedPaths` set, which\n * would force `findEntities` to scan rather than index-lookup.\n *\n * Single GET against the colls resource, minimal RU. Never fails\n * `ensureSchema` — a diagnostic must not break provisioning.\n */\n private async runIndexingPolicyDiagnostic(): Promise<void> {\n let policy: { excludedPaths: Array<{ path: string }> };\n try {\n const props = await this.docClient.getContainerProperties();\n policy = props.indexingPolicy;\n } catch (err: unknown) {\n console.warn(\n `[CosmosDbProvider] could not verify indexing policy on container ` +\n `${this.config.container}: ${err instanceof Error ? err.message : String(err)}`,\n );\n return;\n }\n\n const offending: string[] = [];\n for (const entry of policy.excludedPaths) {\n // Cosmos exclusion paths end in `/?` (exact) or `/*` (subtree). Strip\n // the wildcard to get the prefix the exclusion governs.\n const prefix = entry.path.replace(/\\/[?*]$/, '');\n if (prefix === '' || prefix === '/') {\n // Root wildcard — every guarded path is excluded.\n for (const guard of GUARDED_INDEX_PATHS) {\n offending.push(`${guard} (covered by ${entry.path})`);\n }\n break;\n }\n for (const guard of GUARDED_INDEX_PATHS) {\n if (prefix === guard || guard.startsWith(prefix + '/')) {\n offending.push(`${guard} (excluded by ${entry.path})`);\n }\n }\n }\n\n if (offending.length > 0) {\n console.warn(\n `[CosmosDbProvider] Container ${this.config.container} has indexing-policy ` +\n `excludedPaths that cover paths used by findEntities. The query will ` +\n `fall back to scan and may exceed RU budgets:\\n ${offending.join('\\n ')}\\n` +\n `Verify the ARM/Bicep template that provisioned the container.`,\n );\n }\n }\n\n /** Derive the REST endpoint from config — either explicit or from the Gremlin endpoint host. */\n private getRestEndpoint(): string {\n if (this.config.restEndpoint) return this.config.restEndpoint.replace(/\\/+$/, '');\n // Derive from Gremlin endpoint: ws(s)://host:port/ → https://host:8081\n const url = new URL(this.config.endpoint);\n return `https://${url.hostname}:8081`;\n }\n\n // ─── Repository ────────────────────────────────────────────────────\n\n async createRepository(config: StorageRepositoryConfig): Promise<StoredRepository> {\n this.assertValidRepositoryId(config.repositoryId);\n return this.track('createRepository', config.repositoryId, () =>\n repoQueries.createRepository(this.conn, config),\n );\n }\n\n async getRepository(repositoryId: string): Promise<StoredRepository | null> {\n this.assertValidRepositoryId(repositoryId);\n return this.track('getRepository', repositoryId, () =>\n repoQueries.getRepository(this.conn, repositoryId),\n );\n }\n\n async listRepositories(filter?: RepositoryFilter): Promise<PaginatedResult<StoredRepositorySummary>> {\n return this.track('listRepositories', undefined, () =>\n repoQueries.listRepositories(this.conn, filter),\n );\n }\n\n async updateRepository(repositoryId: string, updates: RepositoryUpdate): Promise<StoredRepository> {\n this.assertValidRepositoryId(repositoryId);\n return this.track('updateRepository', repositoryId, () =>\n repoQueries.updateRepository(this.conn, repositoryId, updates),\n );\n }\n\n async deleteRepository(repositoryId: string, onProgress?: DeleteProgressCallback): Promise<void> {\n this.assertValidRepositoryId(repositoryId);\n return this.track('deleteRepository', repositoryId, () =>\n repoQueries.deleteRepository(this.conn, repositoryId, onProgress),\n );\n }\n\n async deleteAllContents(repositoryId: string, onProgress?: DeleteProgressCallback): Promise<{ deletedEntities: number; deletedRelationships: number }> {\n this.assertValidRepositoryId(repositoryId);\n return this.track('deleteAllContents', repositoryId, () =>\n repoQueries.deleteAllContents(this.conn, repositoryId, onProgress),\n );\n }\n\n async getRepositoryStats(repositoryId: string): Promise<RepositoryStats> {\n this.assertValidRepositoryId(repositoryId);\n return this.track('getRepositoryStats', repositoryId, () =>\n repoQueries.getRepositoryStats(this.conn, repositoryId),\n );\n }\n\n // ─── Vocabulary ────────────────────────────────────────────────────\n\n async getVocabulary(repositoryId: string): Promise<MemoryVocabulary> {\n this.assertValidRepositoryId(repositoryId);\n return this.track('getVocabulary', repositoryId, () =>\n vocabQueries.getVocabulary(this.conn, repositoryId),\n );\n }\n\n /**\n * Cached vocabulary read used by traversal compilation. The vocabulary is\n * compile-time context for the GremlinCompiler — it changes on the order of\n * once per session, but the traversal hot path pays one round-trip per call\n * to fetch it. The cache flips that to one round-trip per TTL window.\n *\n * Reads inside an active usage scope are still recorded if a fetch happens\n * (cache miss); cache hits emit no round-trip and therefore no usage entry.\n */\n private async getVocabularyCached(repositoryId: string): Promise<MemoryVocabulary> {\n const now = Date.now();\n const cached = this.vocabularyCache.get(repositoryId);\n if (cached && cached.expiresAt > now) {\n return cached.vocab;\n }\n const vocab = await vocabQueries.getVocabulary(this.conn, repositoryId);\n this.vocabularyCache.set(repositoryId, {\n vocab,\n expiresAt: now + VOCABULARY_CACHE_TTL_MS,\n });\n return vocab;\n }\n\n /** Drop the cache entry for a repository — call after any vocabulary write. */\n private invalidateVocabularyCache(repositoryId: string): void {\n this.vocabularyCache.delete(repositoryId);\n }\n\n async saveVocabulary(repositoryId: string, vocabulary: MemoryVocabulary): Promise<void> {\n this.assertValidRepositoryId(repositoryId);\n return this.track('saveVocabulary', repositoryId, async () => {\n await vocabQueries.saveVocabulary(this.conn, repositoryId, vocabulary);\n this.invalidateVocabularyCache(repositoryId);\n });\n }\n\n async getVocabularyChangeLog(repositoryId: string, options?: PaginationOptions): Promise<PaginatedResult<VocabularyChangeRecord>> {\n this.assertValidRepositoryId(repositoryId);\n return this.track('getVocabularyChangeLog', repositoryId, () =>\n vocabQueries.getVocabularyChangeLog(this.conn, repositoryId, options),\n );\n }\n\n // ─── Entities ──────────────────────────────────────────────────────\n\n async createEntity(repositoryId: string, entity: StoredEntity): Promise<StoredEntity> {\n this.assertValidRepositoryId(repositoryId);\n return this.track('createEntity', repositoryId, () =>\n entityQueries.createEntity(this.conn, repositoryId, entity),\n );\n }\n\n async getEntity(repositoryId: string, entityId: string, options?: EntityReadOptions): Promise<StoredEntity | null> {\n this.assertValidRepositoryId(repositoryId);\n return this.track('getEntity', repositoryId, () =>\n entityQueries.getEntity(this.conn, repositoryId, entityId, options),\n );\n }\n\n async getEntityBySlug(repositoryId: string, slug: string, options?: EntityReadOptions): Promise<StoredEntity | null> {\n this.assertValidRepositoryId(repositoryId);\n return this.track('getEntityBySlug', repositoryId, () =>\n entityQueries.getEntityBySlug(this.conn, repositoryId, slug, options),\n );\n }\n\n async getEntities(repositoryId: string, entityIds: string[], options?: EntityReadOptions): Promise<Map<string, StoredEntity>> {\n this.assertValidRepositoryId(repositoryId);\n return this.track('getEntities', repositoryId, () =>\n entityQueries.getEntities(this.conn, repositoryId, entityIds, options),\n );\n }\n\n async updateEntity(repositoryId: string, entityId: string, updates: StoredEntityUpdate): Promise<StoredEntity> {\n this.assertValidRepositoryId(repositoryId);\n return this.track('updateEntity', repositoryId, () =>\n entityQueries.updateEntity(this.conn, repositoryId, entityId, updates),\n );\n }\n\n async deleteEntity(repositoryId: string, entityId: string): Promise<void> {\n this.assertValidRepositoryId(repositoryId);\n return this.track('deleteEntity', repositoryId, () =>\n entityQueries.deleteEntity(this.conn, repositoryId, entityId),\n );\n }\n\n async deleteEntities(repositoryId: string, ids: string[]): Promise<{ deleted: string[]; notFound: string[] }> {\n if (ids.length === 0) return { deleted: [], notFound: [] };\n this.assertValidRepositoryId(repositoryId);\n return this.track('deleteEntities', repositoryId, () => this.deleteEntitiesImpl(repositoryId, ids));\n }\n\n /**\n * Single round-trip bulk-delete via the aggregate-side-effect pattern:\n * collapses the per-chunk existence-check + drop into one Gremlin call.\n *\n * g.V()...hasId(within(...)).has('entityType')\n * .aggregate('found').by('id') // collects the ids that match\n * .drop() // drops the vertices (and cascaded edges)\n * .cap('found') // emits the bucket as the single result\n *\n * The bucket is always emitted as a single list item — empty when nothing\n * matched (probe-verified 2026-05-25, local-tests/phase7-shape-probe.mjs).\n * `notFound` is derived client-side as the set difference.\n */\n private async deleteEntitiesImpl(repositoryId: string, ids: string[]): Promise<{ deleted: string[]; notFound: string[] }> {\n const deleted: string[] = [];\n const CHUNK = 100;\n\n for (let i = 0; i < ids.length; i += CHUNK) {\n const chunk = ids.slice(i, i + CHUNK);\n\n const bindings: Record<string, unknown> = { rid: repositoryId };\n const idParams: string[] = [];\n for (let j = 0; j < chunk.length; j++) {\n const p = `id${j}`;\n bindings[p] = chunk[j];\n idParams.push(p);\n }\n const withinExpr = `within(${idParams.join(', ')})`;\n const result = await this.conn.submit(\n `g.V().has('repositoryId', rid).hasId(${withinExpr}).has('entityType')` +\n `.aggregate('found').by('id').drop().cap('found')`,\n bindings,\n );\n const bucket = result.items[0];\n if (Array.isArray(bucket)) {\n deleted.push(...(bucket as string[]));\n }\n }\n\n const deletedSet = new Set(deleted);\n return { deleted, notFound: ids.filter((id) => !deletedSet.has(id)) };\n }\n\n async deleteEntitiesByType(repositoryId: string, entityType: string): Promise<{ deletedEntities: number; deletedRelationships: number | undefined }> {\n this.assertValidRepositoryId(repositoryId);\n return this.track('deleteEntitiesByType', repositoryId, () =>\n entityQueries.deleteEntitiesByType(this.conn, repositoryId, entityType),\n );\n }\n\n async findEntities(repositoryId: string, query: StorageFindQuery, options?: EntityReadOptions): Promise<PaginatedResult<StoredEntity>> {\n this.assertValidRepositoryId(repositoryId);\n return this.track('findEntities', repositoryId, () =>\n entityQueries.findEntities(this.docClient, repositoryId, query, options),\n );\n }\n\n // ─── Relationships ─────────────────────────────────────────────────\n\n async createRelationship(repositoryId: string, relationship: StoredRelationship): Promise<StoredRelationship> {\n this.assertValidRepositoryId(repositoryId);\n return this.track('createRelationship', repositoryId, () =>\n relQueries.createRelationship(this.conn, repositoryId, relationship),\n );\n }\n\n async getRelationship(repositoryId: string, relationshipId: string): Promise<StoredRelationship | null> {\n this.assertValidRepositoryId(repositoryId);\n return this.track('getRelationship', repositoryId, () =>\n relQueries.getRelationship(this.conn, repositoryId, relationshipId),\n );\n }\n\n async getEntityRelationships(repositoryId: string, entityId: string, options?: RelationshipQueryOptions): Promise<PaginatedResult<StoredRelationship>> {\n this.assertValidRepositoryId(repositoryId);\n return this.track('getEntityRelationships', repositoryId, () =>\n relQueries.getEntityRelationships(this.conn, repositoryId, entityId, options),\n );\n }\n\n async deleteRelationship(repositoryId: string, relationshipId: string): Promise<void> {\n this.assertValidRepositoryId(repositoryId);\n return this.track('deleteRelationship', repositoryId, () =>\n relQueries.deleteRelationship(this.conn, repositoryId, relationshipId),\n );\n }\n\n async deleteRelationships(repositoryId: string, ids: string[]): Promise<{ deleted: string[]; notFound: string[] }> {\n if (ids.length === 0) return { deleted: [], notFound: [] };\n this.assertValidRepositoryId(repositoryId);\n return this.track('deleteRelationships', repositoryId, () => this.deleteRelationshipsImpl(repositoryId, ids));\n }\n\n /**\n * Single round-trip bulk relationship delete via the aggregate-side-effect\n * pattern: collapses the per-chunk existence-check + drop into one Gremlin\n * call. Gremlin drop on edges is routed by the engine and the bucket gives\n * back the exact ids that were actually dropped, so `notFound` can be\n * derived client-side.\n *\n * Source-id partition routing is not exposed on this method (the public\n * surface accepts only edge ids), so the lookup may fan out across\n * partitions — see [docs/cosmosdb-gremlin-compatibility.md §`g.E().has`\n * doesn't always push partition down]. Callers that already hold a\n * StoredRelationship and want partition-scoped routing should add a\n * dedicated method when the need is concrete.\n */\n private async deleteRelationshipsImpl(repositoryId: string, ids: string[]): Promise<{ deleted: string[]; notFound: string[] }> {\n const deleted: string[] = [];\n const CHUNK = 100;\n\n for (let i = 0; i < ids.length; i += CHUNK) {\n const chunk = ids.slice(i, i + CHUNK);\n\n const bindings: Record<string, unknown> = { rid: repositoryId };\n const idParams: string[] = [];\n for (let j = 0; j < chunk.length; j++) {\n const p = `id${j}`;\n bindings[p] = chunk[j];\n idParams.push(p);\n }\n const withinExpr = `within(${idParams.join(', ')})`;\n const result = await this.conn.submit(\n `g.E().has('repositoryId', rid).hasId(${withinExpr})` +\n `.aggregate('found').by('id').drop().cap('found')`,\n bindings,\n );\n const bucket = result.items[0];\n if (Array.isArray(bucket)) {\n deleted.push(...(bucket as string[]));\n }\n }\n\n const deletedSet = new Set(deleted);\n return { deleted, notFound: ids.filter((id) => !deletedSet.has(id)) };\n }\n\n async deleteRelationshipsByType(repositoryId: string, relationshipType: string): Promise<{ deletedRelationships: number }> {\n this.assertValidRepositoryId(repositoryId);\n return this.track('deleteRelationshipsByType', repositoryId, () =>\n relQueries.deleteRelationshipsByType(this.conn, repositoryId, relationshipType),\n );\n }\n\n // ─── Graph Traversal (StorageProvider) ─────────────────────────────\n\n async exploreNeighborhood(repositoryId: string, entityId: string, options: StorageExploreOptions): Promise<StorageNeighborhood> {\n this.assertValidRepositoryId(repositoryId);\n return this.track('exploreNeighborhood', repositoryId, () =>\n this.exploreNeighborhoodImpl(repositoryId, entityId, options),\n );\n }\n\n /**\n * Compiler-model implementation of exploreNeighborhood.\n *\n * Strategy: for each depth `d` from 1 to `options.depth`, build a\n * cumulative `TraversalSpec` with `d` steps and `returnMode: 'all'`, run\n * it through {@link executeTraversal}, then walk one BFS layer client-side\n * from the previous frontier using the returned edges.\n *\n * The server-side step direction is fixed to `'both'` (catches every edge\n * in either direction). The directional + bidirectional filter is applied\n * client-side per hop — i.e. `direction: 'outbound'` includes inbound edges\n * where `bidirectional` is true. The CosmosDB Gremlin compiler does not\n * natively express the `union(outE, inE.has(bidirectional))` shape that\n * would push this filter server-side, so it stays client-side; the\n * observable contract (which edges count toward \"outbound\" given\n * bidirectionality) is preserved.\n *\n * Round-trips per call: `options.depth` (one per layer). The previous BFS\n * was `1 + fanout + fanout² + …` round-trips for the same depth.\n */\n private async exploreNeighborhoodImpl(\n repositoryId: string,\n entityId: string,\n options: StorageExploreOptions,\n ): Promise<StorageNeighborhood> {\n const layers: StorageNeighborhoodLayer[] = [];\n const visited = new Set<string>([entityId]);\n let frontier = new Set<string>([entityId]);\n\n for (let d = 1; d <= options.depth; d++) {\n if (frontier.size === 0) break;\n\n const spec: TraversalSpec = {\n start: { entityId },\n steps: buildExploreSteps(d, options),\n returnMode: 'all',\n // Each round-trip fetches the cumulative subgraph at depth `d` and\n // we reconstruct layers client-side. The result can include every\n // edge and vertex reachable in ≤d hops in either direction; size\n // the limit generously.\n limit: 10_000,\n // Use 'full' + includeProvenance so executeTraversal returns full\n // StoredEntity rows (StorageNeighborhood embeds StoredEntity).\n detailLevel: 'full',\n includeProvenance: true,\n };\n const raw = await this.executeTraversal(repositoryId, spec);\n\n // Index edges by either endpoint so we can find edges incident to each\n // frontier vertex in O(1).\n const edgesByVertex = new Map<string, StoredRelationship[]>();\n for (const rel of raw.allRelationships) {\n const a = edgesByVertex.get(rel.sourceEntityId);\n if (a) a.push(rel); else edgesByVertex.set(rel.sourceEntityId, [rel]);\n const b = edgesByVertex.get(rel.targetEntityId);\n if (b) b.push(rel); else edgesByVertex.set(rel.targetEntityId, [rel]);\n }\n\n const layer: StorageNeighborhoodLayer = {};\n const nextFrontier = new Set<string>();\n // Dedup edges within a layer: the cumulative-d response can include the\n // same edge multiple times across the deduped union (server-side dedup\n // is by row, not by edge-in-context). The visit set prevents the same\n // (vertex, edge) pairing from contributing twice.\n const layerEdgeSeen = new Set<string>();\n\n for (const fv of frontier) {\n const incident = edgesByVertex.get(fv) ?? [];\n for (const rel of incident) {\n const isSource = rel.sourceEntityId === fv;\n const isTarget = rel.targetEntityId === fv;\n let matchesDirection = false;\n let connectedId: string | undefined;\n\n if (isSource && (options.direction === 'outbound' || options.direction === 'both')) {\n matchesDirection = true;\n connectedId = rel.targetEntityId;\n } else if (isTarget && (options.direction === 'inbound' || options.direction === 'both')) {\n matchesDirection = true;\n connectedId = rel.sourceEntityId;\n } else if (rel.bidirectional) {\n if (isSource && options.direction === 'inbound') {\n matchesDirection = true;\n connectedId = rel.targetEntityId;\n } else if (isTarget && options.direction === 'outbound') {\n matchesDirection = true;\n connectedId = rel.sourceEntityId;\n }\n }\n if (!matchesDirection || !connectedId) continue;\n if (visited.has(connectedId)) continue;\n\n // Relationship property filter — applied client-side per hop, matching\n // the existing BFS. Edges that fail the filter neither populate the\n // layer nor expand the frontier.\n if (options.relationshipPropertyFilters && options.relationshipPropertyFilters.length > 0) {\n if (!matchesPropertyFilters(rel.properties, options.relationshipPropertyFilters)) continue;\n }\n\n const connectedEntity = raw.entityMap.get(connectedId);\n if (!connectedEntity) continue;\n\n // Entity type filter — applied client-side; the server spec walks\n // direction 'both' without entity-type narrowing so deeper layers\n // are still reachable through any intermediate.\n if (options.entityTypes && options.entityTypes.length > 0 &&\n !options.entityTypes.includes(connectedEntity.entityType)) {\n continue;\n }\n\n // Dedup the (vertex-pair, edge) within this layer.\n const edgeKey = `${rel.id}|${fv}->${connectedId}`;\n if (layerEdgeSeen.has(edgeKey)) continue;\n layerEdgeSeen.add(edgeKey);\n\n const relType = rel.relationshipType;\n if (!layer[relType]) {\n layer[relType] = { total: 0, entities: [], relationships: [] };\n }\n layer[relType]!.entities.push(connectedEntity);\n layer[relType]!.relationships.push(rel);\n layer[relType]!.total = layer[relType]!.entities.length;\n nextFrontier.add(connectedId);\n }\n }\n\n // Per-type pagination (matches the existing CosmosDB BFS — total\n // reflects the full pre-slice count).\n for (const relType of Object.keys(layer)) {\n const group = layer[relType]!;\n const start = options.offsetPerType;\n const end = start + options.limitPerType;\n group.entities = group.entities.slice(start, end);\n group.relationships = group.relationships.slice(start, end);\n }\n\n if (Object.keys(layer).length > 0) {\n layers.push(layer);\n }\n\n // Promote nextFrontier to visited AFTER the full layer is processed so\n // the same entity can appear under multiple relationship types within\n // a single layer (matches the existing semantic).\n for (const id of nextFrontier) {\n visited.add(id);\n }\n frontier = nextFrontier;\n }\n\n return { centerId: entityId, layers };\n }\n\n async findPaths(repositoryId: string, sourceId: string, targetId: string, options: StoragePathOptions): Promise<StoragePathResult> {\n this.assertValidRepositoryId(repositoryId);\n return this.track('findPaths', repositoryId, () =>\n this.findPathsImpl(repositoryId, sourceId, targetId, options),\n );\n }\n\n /**\n * Compiler-model implementation of findPaths.\n *\n * Strategy: build a `TraversalSpec` with a single `'both'` direction step\n * in `repeat()` mode with `emitIntermediates: true` and `returnMode:\n * 'path'`, run it once. The compiler always emits `.simplePath()` in path\n * mode for cycle prevention, producing\n * `.emit().repeat(bothE().otherV()).times(maxDepth).simplePath()\n * .range(...).path().by(<v>).by(<e>)`, which yields paths of every length\n * from 0 (the start vertex alone) to `maxDepth`. Live-probed against the\n * Cosmos emulator 2026-05-25 — see local-tests/phase4-repeat-emit-probe.mjs.\n *\n * The pre-Phase-4 Cosmos BFS in (now-deleted) `packages/storage-cosmosdb/\n * src/queries/traversal.ts` traversed edges with unconditional `bothE()`\n * regardless of the `bidirectional` flag (path discovery is reachability,\n * not semantic direction). Mirror that here by using step direction\n * `'both'` and not applying any direction filter. The plan's §6\n * observable-outputs rule requires preserving this.\n *\n * One round-trip total. The previous BFS was up to `1 + fanout + fanout² + …`.\n */\n private async findPathsImpl(\n repositoryId: string,\n sourceId: string,\n targetId: string,\n options: StoragePathOptions,\n ): Promise<StoragePathResult> {\n if (sourceId === targetId) {\n return { paths: [{ entityIds: [sourceId], relationshipIds: [] }], totalPaths: 1 };\n }\n\n const step: TraversalStep = {\n direction: 'both',\n repeat: { maxDepth: options.maxDepth, emitIntermediates: true },\n };\n if (options.relationshipTypes && options.relationshipTypes.length > 0) {\n step.relationshipTypes = options.relationshipTypes;\n }\n if (options.relationshipPropertyFilters && options.relationshipPropertyFilters.length > 0) {\n step.relationshipFilter = options.relationshipPropertyFilters;\n }\n\n const spec: TraversalSpec = {\n start: { entityId: sourceId },\n steps: [step],\n returnMode: 'path',\n // Cycle prevention comes from the compiler unconditionally emitting\n // .simplePath() in path mode — replaces the explicit\n // `state.path.includes(nextId)` guard from the old BFS.\n // Pull the full pool of paths so we can post-filter to those ending at\n // targetId, then paginate. The emulator returns paths of every length\n // 0..maxDepth in one round-trip with the repeat+emit shape; cap\n // generously to ensure all candidates are inspected.\n limit: Math.max(options.limit + options.offset, options.limit) * 10,\n detailLevel: 'full',\n includeProvenance: true,\n };\n\n const raw = await this.executeTraversal(repositoryId, spec);\n\n const matchingPaths: StoragePath[] = [];\n for (const row of raw.pathRows) {\n // The repeat+emit shape includes the 0-hop \"path\" (just the start\n // vertex). source !== target at this point (handled above), so the\n // last-entity check naturally rejects it.\n const last = row.entityIds[row.entityIds.length - 1];\n if (last !== targetId) continue;\n // Apply entity-type filter on intermediate entities (matches the\n // existing CosmosDB BFS — source and target are always allowed).\n if (options.entityTypes && options.entityTypes.length > 0) {\n let rejected = false;\n for (let i = 1; i < row.entityIds.length - 1; i++) {\n const intermediate = raw.entityMap.get(row.entityIds[i]!);\n if (!intermediate) { rejected = true; break; }\n if (!options.entityTypes.includes(intermediate.entityType)) {\n rejected = true;\n break;\n }\n }\n if (rejected) continue;\n }\n matchingPaths.push({\n entityIds: [...row.entityIds],\n relationshipIds: [...row.relationshipIds],\n });\n }\n\n // Pagination — slice the matching set. `totalPaths` reflects the full\n // pre-slice count, matching the existing storage contract.\n const paginated = matchingPaths.slice(options.offset, options.offset + options.limit);\n\n return {\n paths: paginated,\n totalPaths: matchingPaths.length,\n };\n }\n\n // ─── Timeline ──────────────────────────────────────────────────────\n\n async getTimeline(repositoryId: string, entityId: string, options: StorageTimelineOptions): Promise<StorageTimelineResult> {\n this.assertValidRepositoryId(repositoryId);\n return this.track('getTimeline', repositoryId, () =>\n timelineQueries.getTimeline(this.conn, repositoryId, entityId, options),\n );\n }\n\n // ─── Bulk Operations ───────────────────────────────────────────────\n\n exportAll(repositoryId: string): AsyncIterable<ExportChunk> {\n this.assertValidRepositoryId(repositoryId);\n // exportAll is a streaming iterator — each chunk consumed drives new\n // submits. Wrapping the entire iteration in a single usage scope would\n // require holding the scope open across consumer awaits, which breaks\n // the AsyncLocalStorage contract. Instead, wrap each submit as its own\n // sub-operation by running the iterator generator inside the scope.\n return this.trackIterable('exportAll', repositoryId, bulkQueries.exportAll(this.conn, repositoryId));\n }\n\n async importBulk(repositoryId: string, data: ImportChunk[], options?: BulkImportOptions): Promise<BulkImportResult> {\n this.assertValidRepositoryId(repositoryId);\n return this.track('importBulk', repositoryId, () =>\n bulkQueries.importBulk(this.conn, repositoryId, data, options),\n );\n }\n\n /**\n * Wrap an AsyncIterable so every emitted chunk is generated inside the\n * usage scope. On each iteration step, the scope aggregates charges from\n * the next chunk's submits; when the iterator completes (or is closed), a\n * single usage record is emitted for the whole stream.\n */\n private trackIterable<T>(operation: string, repositoryId: string, source: AsyncIterable<T>): AsyncIterable<T> {\n if (!this.reportUsage) return source;\n const sink = this.reportUsage;\n return {\n [Symbol.asyncIterator]: (): AsyncIterator<T> => {\n const iter = source[Symbol.asyncIterator]();\n const acc: UsageAccumulator = { ru: 0, calls: 0, retries: 0 };\n let emitted = false;\n const emit = (): void => {\n if (emitted) return;\n emitted = true;\n if (acc.calls > 0) {\n sink({\n provider: PROVIDER_NAME,\n operation,\n unit: 'RU',\n value: acc.ru,\n repositoryId,\n timestamp: new Date(),\n details: { calls: acc.calls, retries: acc.retries },\n });\n }\n };\n return {\n async next(): Promise<IteratorResult<T>> {\n const step = await usageScope.run(acc, () => iter.next());\n if (step.done) emit();\n return step;\n },\n async return(value?: T): Promise<IteratorResult<T>> {\n emit();\n if (iter.return) return iter.return(value);\n return { done: true, value: value as T };\n },\n async throw(err?: unknown): Promise<IteratorResult<T>> {\n emit();\n if (iter.throw) return iter.throw(err);\n throw err;\n },\n };\n },\n };\n }\n\n // ─── GraphTraversalProvider ────────────────────────────────────────\n\n getCapabilities(): GraphTraversalCapabilities {\n return {\n supportsNativeQuery: true,\n nativeQueryLanguage: 'gremlin',\n maxTraversalDepth: 10,\n supportsRelationshipPropertyFilters: true,\n supportsEntityPropertyFilters: true,\n supportsAggregation: false,\n supportsRepeat: true,\n supportsDedup: true,\n supportsRelationshipSummary: false,\n };\n }\n\n async traverse(\n repositoryId: string,\n spec: TraversalSpec,\n ): Promise<TraversalResult> {\n this.assertValidRepositoryId(repositoryId);\n return this.track('traverse', repositoryId, () => this.traverseInternal(repositoryId, spec));\n }\n\n /**\n * Compile + execute a TraversalSpec against this repository's partition.\n *\n * Internal entrypoint shared by `traverse` (the public surface) and the\n * compiler-model rewrites of `exploreNeighborhood` / `findPaths`. Does NOT\n * wrap in `track()` — the outer public method owns its own usage scope, and\n * inner submits accumulate into that scope (the nested-scope guard in\n * `track()` keeps nested public calls from emitting duplicate records).\n */\n private async traverseInternal(\n repositoryId: string,\n spec: TraversalSpec,\n ): Promise<TraversalResult> {\n const raw = await this.executeTraversal(repositoryId, spec);\n\n // Project stored entities to the requested detail level. This strips\n // embeddings and any other internal fields at every level — the\n // projection contract never surfaces embeddings via traversal results.\n const detailLevel = spec.detailLevel ?? 'summary';\n\n type ProjectedEntity = TraversalResult['entities'][number];\n type ProjectedRelationship = NonNullable<TraversalResult['relationships']>[number];\n\n const projectStoredEntity = (stored: StoredEntity): ProjectedEntity => {\n const projected = projectEntity(stored, detailLevel) as ProjectedEntity;\n if (!spec.includeProvenance) {\n delete (projected as unknown as Record<string, unknown>)['provenance'];\n }\n return projected;\n };\n\n // direction is mode-specific:\n // 'all' — always 'outbound' (stored topology; the deduped union has\n // no walk context). Callers derive walk direction relative\n // to any anchor via sourceEntityId / targetEntityId.\n // 'path' — relative to the last hop within each walk; callers stamp\n // via the `direction` argument.\n const projectStoredRelationship = (\n rel: StoredRelationship,\n direction: 'outbound' | 'inbound' = 'outbound',\n ): ProjectedRelationship => ({\n id: rel.id,\n type: rel.relationshipType,\n sourceEntityId: rel.sourceEntityId,\n targetEntityId: rel.targetEntityId,\n direction,\n properties: rel.properties,\n });\n\n let entities: ProjectedEntity[] = [];\n let relationships: ProjectedRelationship[] | undefined;\n let paths: NonNullable<TraversalResult['paths']> | undefined;\n\n if (spec.returnMode === 'terminal') {\n entities = raw.terminalEntities.map(projectStoredEntity);\n relationships = undefined;\n } else if (spec.returnMode === 'all') {\n entities = raw.allEntities.map(projectStoredEntity);\n relationships = raw.allRelationships.map((r) => projectStoredRelationship(r));\n } else {\n // 'path' — emit one TraversalPath per Gremlin path row, with per-edge\n // walk direction. The outer `relationships` array dedups by rel id and\n // stamps the first-seen direction (first-writer-wins) — this matches\n // the observable contract that callers depend on for path rendering.\n paths = raw.pathRows.map((row) => ({\n length: Math.max(row.entityIds.length - 1, 0),\n entities: row.entityIds.map((id) => {\n const stored = raw.entityMap.get(id);\n if (!stored) {\n throw new ProviderError(\n 'Unpacking Gremlin path: entity referenced by path is missing from the result',\n 'This indicates a Gremlin response shape mismatch — inspect compiledQuery.',\n );\n }\n return projectStoredEntity(stored);\n }),\n relationships: row.relationshipIds.map((id, i) => {\n const stored = raw.relationshipMap.get(id);\n if (!stored) {\n throw new ProviderError(\n 'Unpacking Gremlin path: relationship referenced by path is missing from the result',\n 'This indicates a Gremlin response shape mismatch — inspect compiledQuery.',\n );\n }\n return projectStoredRelationship(stored, row.relationshipDirections[i]!);\n }),\n }));\n relationships = Array.from(raw.relationshipMap.values()).map((rel) =>\n projectStoredRelationship(rel, raw.pathRelFirstDirection.get(rel.id) ?? 'outbound'),\n );\n }\n\n const limit = spec.limit ?? 50;\n // 'all' mode returns an interleaved entity+edge union — total must count\n // both so callers see the true page size.\n let total: number;\n if (spec.returnMode === 'path') {\n total = paths?.length ?? 0;\n } else if (spec.returnMode === 'all') {\n total = entities.length + (relationships?.length ?? 0);\n } else {\n total = entities.length;\n }\n\n const queryMetadata: QueryMetadata = {\n executionTimeMs: raw.executionTimeMs,\n resourceCost: raw.requestCharge != null\n ? { units: 'RU', value: raw.requestCharge }\n : undefined,\n compiledQuery: raw.compiledQuery,\n compiledQueryLanguage: 'gremlin',\n appliedLimits: {\n maxResults: limit,\n maxDepth: spec.steps?.length,\n },\n truncated: total >= limit,\n truncationReason: total >= limit ? 'result_limit' : undefined,\n };\n\n return {\n entities,\n relationships,\n paths,\n total,\n returned: total,\n hasMore: total >= limit,\n queryMetadata,\n };\n }\n\n /**\n * Lower-level traversal helper: compiles a spec, submits to Gremlin, and\n * parses the rows into raw {@link StoredEntity} / {@link StoredRelationship}\n * objects (no detail-level projection, no provenance stripping). Used by\n * `traverseInternal` and by the storage-layer rewrites of\n * `exploreNeighborhood` / `findPaths` that need the full stored shape to\n * rebuild `StorageNeighborhood` / `StoragePathResult`.\n *\n * Returns a discriminated bag — only the fields relevant to `spec.returnMode`\n * are populated:\n * - `'terminal'`: `terminalEntities` (in row order, no dedup beyond what the\n * server emitted).\n * - `'all'`: `allEntities` and `allRelationships`, already server-deduped.\n * - `'path'`: `pathRows` plus the `entityMap` / `relationshipMap` lookup\n * tables and `pathRelFirstDirection` for the first-seen direction per\n * deduped edge id.\n */\n private async executeTraversal(\n repositoryId: string,\n spec: TraversalSpec,\n ): Promise<RawTraversalResult> {\n const startTime = Date.now();\n\n // Vocabulary is compile-time context — fetch from the per-process cache so\n // back-to-back traversals do not each pay the `_vocabulary` round-trip.\n const vocabulary = await this.getVocabularyCached(repositoryId);\n\n // Compile the spec to Gremlin — the provider owns compilation.\n const compiled = this.compiler.compile(spec, vocabulary);\n\n // Scope the traversal to this repository's partition.\n // repositoryId is the CosmosDB partition key — the predicate both filters\n // and routes the query to a single physical partition. Bind it as a\n // parameter (never concatenated) so it cannot become Gremlin syntax even\n // if the upstream GUID check is ever bypassed.\n const scopedQuery = compiled.query.replace(\n 'g.V()',\n \"g.V().has('repositoryId', pRid)\",\n );\n const scopedParams = { ...compiled.params, pRid: repositoryId };\n\n let result;\n try {\n result = await this.conn.submit(scopedQuery, scopedParams);\n } catch (err: unknown) {\n throw new ProviderError(\n `Gremlin traversal failed: ${err instanceof Error ? err.message : String(err)}`,\n 'Check the traversal spec and ensure the CosmosDB connection is healthy.',\n );\n }\n const executionTimeMs = Date.now() - startTime;\n\n const raw: RawTraversalResult = {\n terminalEntities: [],\n allEntities: [],\n allRelationships: [],\n pathRows: [],\n entityMap: new Map(),\n relationshipMap: new Map(),\n pathRelFirstDirection: new Map(),\n executionTimeMs,\n requestCharge: result.requestCharge,\n compiledQuery: scopedQuery,\n };\n\n if (spec.returnMode === 'terminal') {\n // Flat projected vertex rows — one per row.\n for (const item of result.items) {\n const stored = entityFromGremlin(item as Record<string, unknown>);\n raw.terminalEntities.push(stored);\n }\n } else if (spec.returnMode === 'all') {\n // Flat stream of vertex AND edge projected Maps, already server-deduped\n // by id. Each row carries the synthetic `__kind` discriminator from the\n // compiler's per-branch project chain ('v' = vertex, 'e' = edge).\n for (const item of result.items) {\n const props = item as Record<string, unknown>;\n const kind = props['__kind'];\n if (kind === 'v') {\n const stored = entityFromGremlin(props);\n raw.allEntities.push(stored);\n raw.entityMap.set(stored.id, stored);\n } else if (kind === 'e') {\n const stored = relationshipFromGremlin(props);\n raw.allRelationships.push(stored);\n raw.relationshipMap.set(stored.id, stored);\n }\n // Rows without a recognised marker are skipped defensively.\n }\n } else {\n // 'path' — Gremlin Path objects: { objects: [vertex|edge, ...] }\n // where each object is a projected Map with a `__kind` discriminator.\n //\n // Direction per edge is computed during the walk using a lastVertexId\n // cursor: 'outbound' when the walk crossed source → target, 'inbound'\n // when it crossed target → source.\n for (const item of result.items) {\n const pathData = item as { objects?: unknown[] };\n if (!pathData.objects) continue;\n\n const pathEntityIds: string[] = [];\n const pathRelIds: string[] = [];\n const pathRelDirections: Array<'outbound' | 'inbound'> = [];\n let lastVertexId: string | null = null;\n\n for (const obj of pathData.objects) {\n const props = obj as Record<string, unknown>;\n const kind = props['__kind'];\n if (kind === 'v') {\n const stored = entityFromGremlin(props);\n raw.entityMap.set(stored.id, stored);\n pathEntityIds.push(stored.id);\n lastVertexId = stored.id;\n } else if (kind === 'e') {\n const stored = relationshipFromGremlin(props);\n raw.relationshipMap.set(stored.id, stored);\n pathRelIds.push(stored.id);\n const direction: 'outbound' | 'inbound' =\n lastVertexId === stored.sourceEntityId ? 'outbound' : 'inbound';\n pathRelDirections.push(direction);\n if (!raw.pathRelFirstDirection.has(stored.id)) {\n raw.pathRelFirstDirection.set(stored.id, direction);\n }\n }\n // Objects without a recognised marker are skipped defensively.\n }\n\n raw.pathRows.push({\n entityIds: pathEntityIds,\n relationshipIds: pathRelIds,\n relationshipDirections: pathRelDirections,\n });\n }\n }\n\n return raw;\n }\n\n /**\n * Execute a raw Gremlin query with caller-supplied bindings.\n *\n * ⚠️ ELEVATED PRIVILEGE — SYSTEM-LEVEL OPERATION ⚠️\n *\n * This method is an unscoped pass-through: it does not filter by repository,\n * does not inject the partition key, and performs no validation on the query\n * string. A single call can read or mutate any vertex or edge in the\n * container regardless of which repository (partition) it belongs to.\n *\n * DO NOT expose this method to AI agents, end users, or any untrusted caller.\n * It is intended for:\n * - administrative tooling (migrations, diagnostics, repairs)\n * - internal library operations that need cross-partition reach\n *\n * `repositoryId` is accepted for interface symmetry but is intentionally\n * ignored here — the caller is trusted to scope the query themselves.\n *\n * For agent-facing graph queries use {@link traverse}, which enforces the\n * repositoryId partition predicate.\n */\n async executeNativeQuery(\n _repositoryId: string,\n query: string,\n params?: Record<string, unknown>,\n ): Promise<unknown[]> {\n // executeNativeQuery is cross-partition by design; no repositoryId is\n // stamped on the usage record because the query isn't scoped to one.\n return this.track('executeNativeQuery', undefined, () => this.executeNativeQueryImpl(query, params));\n }\n\n private async executeNativeQueryImpl(\n query: string,\n params?: Record<string, unknown>,\n ): Promise<unknown[]> {\n const result = await this.conn.submit(query, params);\n return result.items as unknown[];\n }\n}\n\nfunction unwrapGremlinValue(val: unknown): unknown {\n if (Array.isArray(val) && val.length > 0) return val[0];\n return val;\n}\n\n/**\n * Build the per-step TraversalSpec steps for exploreNeighborhood at a given\n * cumulative depth.\n *\n * Server-side step direction is fixed to `'both'` (catches every edge in\n * either direction). The directional + bidirectional filter and entity-type\n * filter run client-side during layer reconstruction — both because the\n * compiler does not express the `union(outE, inE.has(bidirectional))` shape\n * and because entity-type filtering at intermediate hops is non-propagating\n * in the compiler's `'all'` emission (the prefix walks unfiltered vertices).\n *\n * relationshipTypes IS pushed to the server because the compiler emits it as\n * `bothE(t1, t2, ...)`, which IS part of the prefix walk at every depth.\n */\nfunction buildExploreSteps(depth: number, options: StorageExploreOptions): TraversalStep[] {\n const base: TraversalStep = { direction: 'both' };\n if (options.relationshipTypes && options.relationshipTypes.length > 0) {\n base.relationshipTypes = options.relationshipTypes;\n }\n const steps: TraversalStep[] = [];\n for (let i = 0; i < depth; i++) {\n steps.push({ ...base });\n }\n return steps;\n}\n\n","// CosmosDbConnection — Gremlin client wrapper for CosmosDB\n//\n// Handles WebSocket connection, CosmosDB authentication, TLS for emulator,\n// and retry logic for transient errors (429 throttling, 503 unavailable).\n\n// @ts-expect-error — gremlin has no type declarations\nimport gremlin from 'gremlin';\nimport { usageScope } from './usage.js';\n\nexport interface CosmosDbConnectionConfig {\n /** Gremlin WebSocket endpoint (e.g. wss://localhost:8901/) */\n endpoint: string;\n /** CosmosDB primary key */\n key: string;\n /** Database name */\n database: string;\n /** Container (graph) name */\n container: string;\n /** Max retries for transient errors (default: 3) */\n maxRetries?: number;\n /** Default query timeout in ms (default: 30000) */\n defaultTimeoutMs?: number;\n /** Whether to reject unauthorized TLS certs — set false for emulator (default: true) */\n rejectUnauthorized?: boolean;\n}\n\nexport interface GremlinResult {\n /** Raw result items */\n items: unknown[];\n /** CosmosDB request charge (RU) from response headers */\n requestCharge?: number;\n}\n\n/**\n * Manages a Gremlin WebSocket connection to CosmosDB.\n * Provides `submit()` for parameterized Gremlin queries with retry on transient errors.\n */\nexport class CosmosDbConnection {\n private client: gremlin.driver.Client | null = null;\n private readonly config: Required<Pick<CosmosDbConnectionConfig, 'maxRetries' | 'defaultTimeoutMs' | 'rejectUnauthorized'>> & CosmosDbConnectionConfig;\n\n constructor(config: CosmosDbConnectionConfig) {\n this.config = {\n ...config,\n maxRetries: config.maxRetries ?? 3,\n defaultTimeoutMs: config.defaultTimeoutMs ?? 30000,\n rejectUnauthorized: config.rejectUnauthorized ?? true,\n };\n }\n\n /** Open the WebSocket connection to CosmosDB Gremlin endpoint. */\n async connect(): Promise<void> {\n if (this.client) return;\n\n const authenticator = new gremlin.driver.auth.PlainTextSaslAuthenticator(\n `/dbs/${this.config.database}/colls/${this.config.container}`,\n this.config.key,\n );\n\n this.client = new gremlin.driver.Client(this.config.endpoint, {\n authenticator,\n traversalsource: 'g',\n rejectUnauthorized: this.config.rejectUnauthorized,\n mimeType: 'application/vnd.gremlin-v2.0+json',\n });\n\n await this.client.open();\n }\n\n /** Close the WebSocket connection. */\n async close(): Promise<void> {\n if (this.client) {\n await this.client.close();\n this.client = null;\n }\n }\n\n /**\n * Submit a parameterized Gremlin query with retry on transient errors.\n * All user values should be passed as bindings (never interpolated into the query string).\n */\n async submit(query: string, bindings?: Record<string, unknown>): Promise<GremlinResult> {\n if (!this.client) {\n throw new Error('CosmosDbConnection: not connected. Call connect() first.');\n }\n\n let lastError: unknown;\n for (let attempt = 0; attempt <= this.config.maxRetries; attempt++) {\n try {\n const resultSet = await this.client.submit(query, bindings);\n const items = resultSet.toArray();\n const requestCharge = extractRequestCharge(resultSet);\n const acc = usageScope.getStore();\n if (acc) {\n acc.calls++;\n if (typeof requestCharge === 'number') acc.ru += requestCharge;\n }\n return { items, requestCharge };\n } catch (err: unknown) {\n lastError = err;\n if (isTransientError(err) && attempt < this.config.maxRetries) {\n const retryAfterMs = getRetryAfterMs(err, attempt);\n const acc = usageScope.getStore();\n if (acc) acc.retries++;\n await sleep(retryAfterMs);\n continue;\n }\n throw err;\n }\n }\n throw lastError;\n }\n\n /** Get the underlying Gremlin client (for advanced usage). */\n getClient(): gremlin.driver.Client {\n if (!this.client) {\n throw new Error('CosmosDbConnection: not connected. Call connect() first.');\n }\n return this.client;\n }\n}\n\n/** Check if an error is a transient CosmosDB error (429 or 503). */\nfunction isTransientError(err: unknown): boolean {\n if (err instanceof Error) {\n const msg = err.message;\n // CosmosDB returns status codes in error messages\n if (msg.includes('429') || msg.includes('RequestRateTooLarge')) return true;\n if (msg.includes('503') || msg.includes('ServiceUnavailable')) return true;\n }\n // Check statusCode property if present\n const statusCode = (err as Record<string, unknown>)?.['statusCode'];\n if (statusCode === 429 || statusCode === 503) return true;\n return false;\n}\n\n/** Extract retry-after from error or use exponential backoff. */\nfunction getRetryAfterMs(err: unknown, attempt: number): number {\n // CosmosDB may include x-ms-retry-after-ms in error attributes\n const retryAfter = (err as Record<string, unknown>)?.['retryAfterMs'];\n if (typeof retryAfter === 'number' && retryAfter > 0) {\n return retryAfter;\n }\n // Exponential backoff: 500ms, 1s, 2s, 4s, ...\n return Math.min(500 * Math.pow(2, attempt), 10000);\n}\n\n/**\n * Extract request charge (RU) from a ResultSet's attributes.\n *\n * CosmosDB Gremlin exposes two related attributes on the response message:\n * - `x-ms-request-charge` — RU for this specific response message\n * - `x-ms-total-request-charge` — cumulative RU across the entire query\n *\n * For single-message responses (single-vertex reads, count(), small projections)\n * the two are equal. For streamed multi-message responses (traversals, path\n * queries, large result sets), the gremlin-javascript driver surfaces only\n * the FINAL message's attributes — and the final message's\n * `x-ms-request-charge` is typically 0 (its own delta) while\n * `x-ms-total-request-charge` carries the real cumulative charge.\n *\n * Therefore: always prefer the total. Falling back to the per-message value\n * with `??` (the previous behaviour) silently zeroed out every traversal\n * because 0 is not nullish.\n *\n * Verified against the Cosmos emulator with rate limiting enabled\n * (`local-tests/ru-raw-probe.mjs` 2026-05-25): a depth-2 path traversal\n * returns `{ x-ms-request-charge: 0, x-ms-total-request-charge: 29.72 }`.\n */\nfunction extractRequestCharge(resultSet: gremlin.driver.ResultSet): number | undefined {\n const attrs = resultSet.attributes as Record<string, unknown> | undefined;\n if (!attrs) return undefined;\n const total = attrs['x-ms-total-request-charge'];\n if (typeof total === 'number') return total;\n const single = attrs['x-ms-request-charge'];\n if (typeof single === 'number') return single;\n return undefined;\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms));\n}\n","// Per-operation RU/call/retry accumulator, shared by every Cosmos endpoint.\n//\n// Extracted from CosmosDbConnection.ts so both the Gremlin client and the\n// CosmosDocumentClient (added for the Cosmos SQL findEntities path) write\n// usage into the same AsyncLocalStorage scope. That way a single public\n// method on the provider — which may touch both endpoints in one call — still\n// emits a single per-operation usage record with the combined totals.\n\nimport { AsyncLocalStorage } from 'node:async_hooks';\n\n/** Per-operation RU accumulator kept in async-local storage. */\nexport interface UsageAccumulator {\n /** Total request charge (RU) across all submits in the current operation. */\n ru: number;\n /** Number of underlying client calls (gremlin submit() or document query()). */\n calls: number;\n /** Number of transient-retry waits observed. */\n retries: number;\n}\n\n/**\n * Module-level AsyncLocalStorage so any client call executed inside a\n * `usageScope.run(...)` block contributes its RU/retry counts to the active\n * accumulator. Providers wrap each public method in a scope and read the\n * aggregated result when the method returns.\n */\nexport const usageScope = new AsyncLocalStorage<UsageAccumulator>();\n","// CosmosDB REST API auth + provisioning helpers.\n//\n// Extracted from CosmosDbProvider.ts so both ensureSchema (Gremlin-side\n// provisioning) and CosmosDocumentClient (Document-endpoint queries) can\n// share the same HMAC-token generator without duplicating it.\n\nimport crypto from 'node:crypto';\n\n/**\n * Generate a CosmosDB REST API authorization token.\n * See: https://learn.microsoft.com/en-us/rest/api/cosmos-db/access-control-on-cosmosdb-resources\n */\nexport function cosmosAuthToken(\n verb: string,\n resourceType: string,\n resourceLink: string,\n date: string,\n key: string,\n): string {\n const payload = `${verb.toLowerCase()}\\n${resourceType.toLowerCase()}\\n${resourceLink}\\n${date.toLowerCase()}\\n\\n`;\n const keyBuffer = Buffer.from(key, 'base64');\n const hmac = crypto.createHmac('sha256', keyBuffer);\n hmac.update(payload);\n const signature = hmac.digest('base64');\n return encodeURIComponent(`type=master&ver=1.0&sig=${signature}`);\n}\n\n/**\n * Create a CosmosDB resource (database or container) via REST API.\n * Returns true if the resource was created, false if it already existed.\n */\nexport async function cosmosRestPut(\n restBase: string,\n key: string,\n urlPath: string,\n resourceLink: string,\n resourceType: string,\n body: Record<string, unknown>,\n rejectUnauthorized: boolean,\n): Promise<boolean> {\n const date = new Date().toUTCString();\n const token = cosmosAuthToken('post', resourceType, resourceLink, date, key);\n\n const url = `${restBase}/${urlPath}`;\n\n const options: RequestInit = {\n method: 'POST',\n headers: {\n 'Authorization': token,\n 'x-ms-version': '2018-12-31',\n 'x-ms-date': date,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(body),\n };\n\n // For self-signed certs (emulator), disable TLS verification process-wide.\n // Caller explicitly opted in via rejectUnauthorized: false.\n if (!rejectUnauthorized) {\n process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = '0';\n }\n\n const response = await fetch(url, options);\n\n if (response.status === 201) return true; // Created\n if (response.status === 409) return false; // Already exists\n\n const text = await response.text();\n throw new Error(`CosmosDB REST ${response.status}: ${text}`);\n}\n","// CosmosDocumentClient — Cosmos NoSQL (Document) endpoint client.\n//\n// Used by query paths that the Gremlin subset can't express server-side\n// (substring + case-insensitive matching, structured property predicates).\n// Both this client and CosmosDbConnection (Gremlin) write RU into the active\n// usageScope so a single public method spanning both endpoints emits one\n// usage record.\n//\n// Transport: raw fetch + HMAC, the same pattern as cosmos-rest-auth.ts. No\n// @azure/cosmos SDK dependency — keeps the provider's runtime footprint small\n// and matches what `ensureSchema()` already does for container provisioning.\n\nimport { cosmosAuthToken } from './cosmos-rest-auth.js';\nimport { usageScope } from './usage.js';\n\nexport interface CosmosDocumentClientConfig {\n /** Cosmos NoSQL REST endpoint (e.g. https://host.docker.internal:8081). */\n restEndpoint: string;\n /** CosmosDB primary key (base64). */\n key: string;\n /** Database id. */\n database: string;\n /** Container id. */\n container: string;\n /** Whether to reject unauthorized TLS certs — set false for emulator. */\n rejectUnauthorized: boolean;\n /** Max retries for 429/503 (default: 3). */\n maxRetries?: number;\n /** Default query timeout in ms (default: 30000). Reserved for future use. */\n defaultTimeoutMs?: number;\n}\n\nexport interface CosmosQueryParameter {\n /** Parameter name including the leading '@' (e.g. '@rid'). */\n name: string;\n value: unknown;\n}\n\nexport interface CosmosQueryOptions {\n /**\n * Partition-key value. When provided, the query is partition-scoped and\n * Cosmos charges proportional RU. When omitted, cross-partition is enabled —\n * findEntities always supplies a partition key (repositoryId).\n */\n partitionKey?: string;\n /** Request query metrics in the response (`x-ms-documentdb-query-metrics`). */\n populateMetrics?: boolean;\n /** Continuation token from a previous page, if any. */\n continuationToken?: string | null;\n}\n\nexport interface CosmosQueryResult<T> {\n documents: T[];\n /** Request charge in RU, from `x-ms-request-charge`. */\n requestCharge: number;\n /** Query metrics from `x-ms-documentdb-query-metrics` (only present when populateMetrics is true). */\n queryMetrics: string | null;\n /** Continuation token for the next page, or null if exhausted. */\n continuationToken: string | null;\n}\n\nexport interface CosmosContainerProperties {\n id: string;\n partitionKey: { paths: string[]; kind: string };\n indexingPolicy: {\n indexingMode: string;\n automatic: boolean;\n includedPaths: Array<{ path: string }>;\n excludedPaths: Array<{ path: string }>;\n };\n}\n\n/** Internal — narrow alias for the fetch function so tests can inject a stub. */\ntype FetchLike = typeof fetch;\n\n/**\n * Cosmos NoSQL (Document) endpoint client. Issues parameterised SQL queries\n * and reads container metadata. RU is accumulated into the active usageScope.\n */\nexport class CosmosDocumentClient {\n private readonly config: Required<Pick<CosmosDocumentClientConfig, 'maxRetries' | 'defaultTimeoutMs'>> & CosmosDocumentClientConfig;\n private readonly fetchImpl: FetchLike;\n\n /**\n * `fetchImpl` is for tests only — production code should pass nothing and\n * inherit `globalThis.fetch`. Keeping it on the constructor (rather than\n * stubbing globals) means each test instance is hermetic.\n */\n constructor(config: CosmosDocumentClientConfig, fetchImpl?: FetchLike) {\n this.config = {\n ...config,\n maxRetries: config.maxRetries ?? 3,\n defaultTimeoutMs: config.defaultTimeoutMs ?? 30000,\n };\n this.fetchImpl = fetchImpl ?? fetch;\n }\n\n /**\n * Execute a parameterised Cosmos SQL query against the container's `docs`\n * resource. Retries on 429/503 with the response's `x-ms-retry-after-ms`\n * when present, otherwise exponential backoff. RU is accumulated into the\n * active {@link usageScope}.\n */\n public async query<T = unknown>(\n sql: string,\n parameters: CosmosQueryParameter[],\n options: CosmosQueryOptions,\n ): Promise<CosmosQueryResult<T>> {\n const resourceLink = `dbs/${this.config.database}/colls/${this.config.container}`;\n const url = `${this.restBase()}/${resourceLink}/docs`;\n\n // For self-signed certs (emulator), disable TLS verification process-wide.\n // Caller opted in via rejectUnauthorized: false. Same pattern as cosmosRestPut.\n if (!this.config.rejectUnauthorized) {\n process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = '0';\n }\n\n const body = JSON.stringify({ query: sql, parameters });\n\n for (let attempt = 0; attempt <= this.config.maxRetries; attempt++) {\n const date = new Date().toUTCString();\n const token = cosmosAuthToken('post', 'docs', resourceLink, date, this.config.key);\n const headers: Record<string, string> = {\n 'Authorization': token,\n 'x-ms-version': '2018-12-31',\n 'x-ms-date': date,\n 'Content-Type': 'application/query+json',\n 'x-ms-documentdb-isquery': 'true',\n };\n if (options.partitionKey != null) {\n headers['x-ms-documentdb-partitionkey'] = JSON.stringify([options.partitionKey]);\n } else {\n headers['x-ms-documentdb-query-enablecrosspartition'] = 'true';\n }\n if (options.populateMetrics) {\n headers['x-ms-documentdb-populatequerymetrics'] = 'true';\n }\n if (options.continuationToken) {\n headers['x-ms-continuation'] = options.continuationToken;\n }\n\n const response = await this.fetchImpl(url, { method: 'POST', headers, body });\n\n if (response.status === 429 || response.status === 503) {\n if (attempt < this.config.maxRetries) {\n const waitMs = parseRetryAfterMs(response, attempt);\n const acc = usageScope.getStore();\n if (acc) acc.retries++;\n await sleep(waitMs);\n continue;\n }\n const text = await response.text();\n throw new Error(`CosmosDB Document query ${response.status}: ${text}`);\n }\n\n if (!response.ok) {\n const text = await response.text();\n throw new Error(`CosmosDB Document query ${response.status}: ${text}`);\n }\n\n const json = (await response.json()) as { Documents?: unknown[]; _count?: number };\n const requestCharge = Number(response.headers.get('x-ms-request-charge') ?? '0') || 0;\n const queryMetrics = response.headers.get('x-ms-documentdb-query-metrics');\n const continuationToken = response.headers.get('x-ms-continuation');\n\n const acc = usageScope.getStore();\n if (acc) {\n acc.calls++;\n acc.ru += requestCharge;\n }\n\n return {\n documents: (json.Documents ?? []) as T[],\n requestCharge,\n queryMetrics,\n continuationToken,\n };\n }\n // Unreachable — the loop either returns or throws on the final attempt.\n throw new Error('CosmosDocumentClient.query: retry loop exhausted without resolution');\n }\n\n /**\n * Read container metadata (id, partition key, indexing policy). Used by\n * `ensureSchema()` to warn when externally-provisioned containers have\n * excluded paths the findEntities SQL needs.\n */\n public async getContainerProperties(): Promise<CosmosContainerProperties> {\n const resourceLink = `dbs/${this.config.database}/colls/${this.config.container}`;\n const url = `${this.restBase()}/${resourceLink}`;\n\n if (!this.config.rejectUnauthorized) {\n process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = '0';\n }\n\n const date = new Date().toUTCString();\n const token = cosmosAuthToken('get', 'colls', resourceLink, date, this.config.key);\n\n const response = await this.fetchImpl(url, {\n method: 'GET',\n headers: {\n 'Authorization': token,\n 'x-ms-version': '2018-12-31',\n 'x-ms-date': date,\n },\n });\n\n if (!response.ok) {\n const text = await response.text();\n throw new Error(`CosmosDB Document getContainerProperties ${response.status}: ${text}`);\n }\n\n return (await response.json()) as CosmosContainerProperties;\n }\n\n private restBase(): string {\n return this.config.restEndpoint.replace(/\\/+$/, '');\n }\n}\n\nfunction parseRetryAfterMs(response: Response, attempt: number): number {\n const header = response.headers.get('x-ms-retry-after-ms');\n if (header) {\n const n = Number(header);\n if (Number.isFinite(n) && n > 0) return n;\n }\n return Math.min(500 * Math.pow(2, attempt), 10000);\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms));\n}\n","// Mapping — convert between Gremlin results and StoredEntity/StoredRelationship types\n\nimport type { StoredEntity } from '@utaba/deep-memory/types';\nimport type { StoredRelationship } from '@utaba/deep-memory/types';\nimport type { Provenance } from '@utaba/deep-memory/types';\nimport type { StoredRepository, StoredRepositorySummary } from '@utaba/deep-memory/types';\nimport type { GovernanceConfig } from '@utaba/deep-memory/types';\nimport type { VocabularyChangeRecord } from '@utaba/deep-memory/types';\n\n// ─── Projection field lists ───────────────────────────────────────\n//\n// The GremlinCompiler emits read-path projections listing these exact field\n// names. The mapper functions below (entityFromGremlin, relationshipFromGremlin)\n// consume the same key set. Keeping the two in lockstep is enforced by the\n// cross-package test in mapping.test.ts, which imports the compiler's own\n// list and asserts equality.\n//\n// `embedding` is intentionally excluded — read paths never ship the embedding\n// over the wire. The vector-search path passes an explicit `loadEmbeddings`\n// option to opt back in.\n//\n// Synthetic projection-only fields (`__kind`) are NOT stored properties and\n// are not in this list — the compiler adds them as discriminator markers but\n// the mapper does not read them.\n\nexport const STORED_ENTITY_FIELDS = [\n 'id',\n 'entityType',\n 'entityLabel',\n 'slug',\n 'summary',\n 'properties',\n 'data',\n 'dataFormat',\n 'createdBy',\n 'createdByType',\n 'createdAt',\n 'createdInConversation',\n 'createdFromMessage',\n 'modifiedBy',\n 'modifiedByType',\n 'modifiedAt',\n 'modifiedInConversation',\n 'modifiedFromMessage',\n] as const;\n\nexport const STORED_RELATIONSHIP_FIELDS = [\n 'id',\n 'relationshipType',\n 'sourceEntityId',\n 'targetEntityId',\n 'properties',\n 'bidirectional',\n 'createdBy',\n 'createdByType',\n 'createdAt',\n 'createdInConversation',\n 'createdFromMessage',\n 'modifiedBy',\n 'modifiedByType',\n 'modifiedAt',\n 'modifiedInConversation',\n 'modifiedFromMessage',\n] as const;\n\n// Repository projection — used by getRepository / listRepositories. The\n// compiler does not deal with `_repository` vertices, so the projection chain\n// lives here (no cross-package sync needed). Mirror what `repositoryFromGremlin`\n// and `repositorySummaryFromGremlin` consume.\nexport const STORED_REPOSITORY_FIELDS = [\n 'id',\n 'repositoryId',\n 'repoLabel',\n 'description',\n 'type',\n 'legal',\n 'owner',\n 'governanceConfig',\n 'metadata',\n 'createdAt',\n 'createdBy',\n] as const;\n\n/**\n * Build a Gremlin `.project(...).by(...)...` chain expression for a\n * `_repository` vertex, with no leading dot. Append after a vertex predicate.\n * `repoLabel`, `governanceConfig`, `createdAt`, `createdBy`, and `repositoryId`\n * are always written on create; the optional fields use coalesce-default-empty\n * to avoid the \"by('optionalField') crashes when absent\" failure mode (see\n * docs/cosmosdb-gremlin-compatibility.md §Constraints).\n */\nexport function buildRepositoryProjectChain(): string {\n return [\n `project('id','repositoryId','repoLabel','description','type','legal','owner','governanceConfig','metadata','createdAt','createdBy')`,\n `.by(id)`,\n `.by('repositoryId')`,\n `.by('repoLabel')`,\n `.by(coalesce(values('description'), constant('')))`,\n `.by(coalesce(values('type'), constant('')))`,\n `.by(coalesce(values('legal'), constant('')))`,\n `.by(coalesce(values('owner'), constant('')))`,\n `.by('governanceConfig')`,\n `.by(coalesce(values('metadata'), constant('')))`,\n `.by('createdAt')`,\n `.by('createdBy')`,\n ].join('');\n}\n\n// ─── Gremlin property extraction ──────────────────────────────────\n\n/**\n * Gremlin valueMap(true) returns properties as arrays (multi-value).\n * CosmosDB single-cardinality means each array has exactly one element.\n * This helper unwraps the first value.\n */\nfunction unwrap(val: unknown): unknown {\n if (Array.isArray(val) && val.length > 0) return val[0];\n return val;\n}\n\n/** Safely unwrap a string value from a Gremlin result. */\nfunction unwrapStr(val: unknown): string {\n const v = unwrap(val);\n return typeof v === 'string' ? v : String(v ?? '');\n}\n\n/** Safely unwrap an optional string. */\nfunction unwrapOptStr(val: unknown): string | undefined {\n const v = unwrap(val);\n return v != null && v !== '' ? String(v) : undefined;\n}\n\n/** Safely parse JSON, returning a default on failure. */\nfunction safeParseJson<T>(val: unknown, fallback: T): T {\n if (val == null) return fallback;\n const str = typeof val === 'string' ? val : String(unwrap(val));\n if (!str || str === '') return fallback;\n try {\n return JSON.parse(str) as T;\n } catch {\n return fallback;\n }\n}\n\n// ─── Provenance ───────────────────────────────────────────────────\n\nfunction provenanceFromGremlin(props: Record<string, unknown>): Provenance {\n return {\n createdBy: unwrapStr(props['createdBy']),\n createdByType: (unwrapStr(props['createdByType']) || 'agent') as 'user' | 'agent',\n createdAt: unwrapStr(props['createdAt']),\n createdInConversation: unwrapOptStr(props['createdInConversation']),\n createdFromMessage: unwrapOptStr(props['createdFromMessage']),\n modifiedBy: unwrapStr(props['modifiedBy']),\n modifiedByType: (unwrapStr(props['modifiedByType']) || 'agent') as 'user' | 'agent',\n modifiedAt: unwrapStr(props['modifiedAt']),\n modifiedInConversation: unwrapOptStr(props['modifiedInConversation']),\n modifiedFromMessage: unwrapOptStr(props['modifiedFromMessage']),\n };\n}\n\n// ─── Entity mapping ───────────────────────────────────────────────\n\nexport function entityFromGremlin(props: Record<string, unknown>): StoredEntity {\n const embeddingStr = unwrapOptStr(props['embedding']);\n return {\n id: unwrapStr(props['id']),\n slug: unwrapStr(props['slug']),\n entityType: unwrapStr(props['entityType']),\n label: unwrapStr(props['entityLabel']),\n summary: unwrapOptStr(props['summary']),\n properties: safeParseJson(unwrap(props['properties']), {}),\n data: unwrapOptStr(props['data']),\n dataFormat: unwrapOptStr(props['dataFormat']),\n provenance: provenanceFromGremlin(props),\n embedding: embeddingStr ? (safeParseJson<number[] | undefined>(embeddingStr, undefined)) : undefined,\n };\n}\n\n// ─── Document-endpoint mapping ────────────────────────────────────\n//\n// Cosmos NoSQL (Document) endpoint sees Gremlin-managed properties as\n// `[{ _value, id }]` arrays rather than flat scalars. The Gremlin reserved\n// scalars (`id`, the partition-key `repositoryId`, the vertex `label` token)\n// stay flat on the document. Probed and confirmed 2026-05-26 — see\n// local-tests/baseline/phase-cosmos-sql-shape-probe-results.md.\n\n/** Pluck the underlying value of a Gremlin-managed property from a Document-endpoint doc. */\nfunction pluckDocValue(doc: Record<string, unknown>, key: string): unknown {\n const arr = doc[key];\n if (Array.isArray(arr) && arr.length > 0) {\n const entry = arr[0] as Record<string, unknown> | undefined;\n if (entry && typeof entry === 'object') {\n return entry['_value'];\n }\n }\n return undefined;\n}\n\nfunction pluckDocStr(doc: Record<string, unknown>, key: string): string {\n const v = pluckDocValue(doc, key);\n return typeof v === 'string' ? v : String(v ?? '');\n}\n\nfunction pluckDocOptStr(doc: Record<string, unknown>, key: string): string | undefined {\n const v = pluckDocValue(doc, key);\n return v != null && v !== '' ? String(v) : undefined;\n}\n\nfunction provenanceFromDocument(doc: Record<string, unknown>): Provenance {\n return {\n createdBy: pluckDocStr(doc, 'createdBy'),\n createdByType: (pluckDocStr(doc, 'createdByType') || 'agent') as 'user' | 'agent',\n createdAt: pluckDocStr(doc, 'createdAt'),\n createdInConversation: pluckDocOptStr(doc, 'createdInConversation'),\n createdFromMessage: pluckDocOptStr(doc, 'createdFromMessage'),\n modifiedBy: pluckDocStr(doc, 'modifiedBy'),\n modifiedByType: (pluckDocStr(doc, 'modifiedByType') || 'agent') as 'user' | 'agent',\n modifiedAt: pluckDocStr(doc, 'modifiedAt'),\n modifiedInConversation: pluckDocOptStr(doc, 'modifiedInConversation'),\n modifiedFromMessage: pluckDocOptStr(doc, 'modifiedFromMessage'),\n };\n}\n\n/**\n * Project a Document-endpoint result row into a StoredEntity. Distinct from\n * `entityFromGremlin` (which reads the projected `valueMap`-style shape) —\n * here every Gremlin-managed property is `[{_value, id}]` while `id` and the\n * `label` token are flat. The `entityType` *property* (not the `label` token)\n * is authoritative — see `packages/storage-cosmosdb/src/queries/entity.ts`\n * for the matching write-path decision.\n */\nexport function entityFromDocument(doc: Record<string, unknown>): StoredEntity {\n const id = typeof doc['id'] === 'string' ? doc['id'] : String(doc['id'] ?? '');\n const embeddingStr = pluckDocOptStr(doc, 'embedding');\n return {\n id,\n slug: pluckDocStr(doc, 'slug'),\n entityType: pluckDocStr(doc, 'entityType'),\n label: pluckDocStr(doc, 'entityLabel'),\n summary: pluckDocOptStr(doc, 'summary'),\n properties: safeParseJson(pluckDocValue(doc, 'properties'), {}),\n data: pluckDocOptStr(doc, 'data'),\n dataFormat: pluckDocOptStr(doc, 'dataFormat'),\n provenance: provenanceFromDocument(doc),\n embedding: embeddingStr ? safeParseJson<number[] | undefined>(embeddingStr, undefined) : undefined,\n };\n}\n\n// ─── Relationship mapping ─────────────────────────────────────────\n\nexport function relationshipFromGremlin(props: Record<string, unknown>): StoredRelationship {\n const bidir = unwrap(props['bidirectional']);\n return {\n id: unwrapStr(props['id']),\n relationshipType: unwrapStr(props['relationshipType']),\n sourceEntityId: unwrapStr(props['sourceEntityId']),\n targetEntityId: unwrapStr(props['targetEntityId']),\n properties: safeParseJson(unwrap(props['properties']), {}),\n bidirectional: bidir === true || bidir === 'true',\n provenance: provenanceFromGremlin(props),\n };\n}\n\n// ─── Repository mapping ───────────────────────────────────────────\n\nexport function repositoryFromGremlin(props: Record<string, unknown>): StoredRepository {\n return {\n repositoryId: unwrapStr(props['repositoryId']),\n type: unwrapOptStr(props['type']),\n label: unwrapStr(props['repoLabel']),\n description: unwrapOptStr(props['description']),\n legal: unwrapOptStr(props['legal']),\n owner: unwrapOptStr(props['owner']),\n governanceConfig: safeParseJson<GovernanceConfig>(unwrap(props['governanceConfig']), { mode: 'open' }),\n metadata: safeParseJson(unwrap(props['metadata']), undefined),\n createdAt: unwrapStr(props['createdAt']),\n createdBy: unwrapStr(props['createdBy']),\n };\n}\n\nexport function repositorySummaryFromGremlin(props: Record<string, unknown>): StoredRepositorySummary {\n return {\n repositoryId: unwrapStr(props['repositoryId']),\n type: unwrapOptStr(props['type']),\n label: unwrapStr(props['repoLabel']),\n description: unwrapOptStr(props['description']),\n governanceConfig: safeParseJson<GovernanceConfig>(unwrap(props['governanceConfig']), { mode: 'open' }),\n };\n}\n\n// ─── Vocabulary change-log mapping ────────────────────────────────\n\nexport function changeRecordFromGremlin(props: Record<string, unknown>): VocabularyChangeRecord {\n return {\n changeId: unwrapStr(props['changeId']),\n changeType: unwrapStr(props['changeType']) as VocabularyChangeRecord['changeType'],\n typeName: unwrapStr(props['typeName']),\n previousVersion: unwrapOptStr(props['previousVersion']),\n newVersion: unwrapStr(props['newVersion']),\n proposedBy: unwrapStr(props['proposedBy']),\n proposedAt: unwrapStr(props['proposedAt']),\n approvedBy: unwrapOptStr(props['approvedBy']),\n approvedAt: unwrapOptStr(props['approvedAt']),\n reason: unwrapStr(props['reason']),\n };\n}\n\n// ─── Fixed-shape property ladders ─────────────────────────────────\n//\n// Every addV / addE / upsert write uses a canonical fixed-length property\n// ladder so the Gremlin server can reuse a single compiled plan across all\n// writes of a given vertex/edge family. Required slots emit `.property('key',\n// pN)`; optional slots emit `.choose(__.constant(pN).is(neq(absentSentinel)),\n// __.property('key', pN), __.identity())` — the choose-skip drops the\n// property at runtime when the binding equals the sentinel, keeping the\n// query string constant regardless of which optional fields the caller\n// supplied.\n//\n// `id` and `repositoryId` are NOT part of these ladders — both are written\n// explicitly at create time (`.property('id', vid).property('repositoryId',\n// rid)`) and are immutable on update (Cosmos rejects partition-key mutation).\n//\n// Slot order is FIXED. Adding a new slot goes at the END only; reordering\n// or removing breaks the cached plan + introduces a different query string.\n//\n// Live-validated 2026-05-26 — see docs/cosmosdb-gremlin-compatibility.md\n// (choose-skip / fixed-ladder entries).\n\n/** Binding value used to signal an absent optional string slot. */\nexport const ABSENT_STRING_SENTINEL = '';\n\n/** Binding name in the emitted query referencing the absent-sentinel value. */\nconst SENTINEL_BINDING = 'absentSentinel';\n\nconst ENTITY_REQUIRED_SLOTS = [\n 'entityType',\n 'entityLabel',\n 'slug',\n 'properties',\n 'createdBy',\n 'createdByType',\n 'createdAt',\n 'modifiedBy',\n 'modifiedByType',\n 'modifiedAt',\n] as const;\n\nconst ENTITY_OPTIONAL_SLOTS = [\n 'summary',\n 'data',\n 'dataFormat',\n 'embedding',\n 'createdInConversation',\n 'createdFromMessage',\n 'modifiedInConversation',\n 'modifiedFromMessage',\n] as const;\n\nconst RELATIONSHIP_REQUIRED_SLOTS = [\n 'relationshipType',\n 'sourceEntityId',\n 'targetEntityId',\n 'bidirectional',\n 'properties',\n 'createdBy',\n 'createdByType',\n 'createdAt',\n 'modifiedBy',\n 'modifiedByType',\n 'modifiedAt',\n] as const;\n\nconst RELATIONSHIP_OPTIONAL_SLOTS = [\n 'createdInConversation',\n 'createdFromMessage',\n 'modifiedInConversation',\n 'modifiedFromMessage',\n] as const;\n\nconst REPOSITORY_REQUIRED_SLOTS = [\n 'repoLabel',\n 'governanceConfig',\n 'createdAt',\n 'createdBy',\n] as const;\n\nconst REPOSITORY_OPTIONAL_SLOTS = [\n 'description',\n 'type',\n 'legal',\n 'owner',\n 'metadata',\n] as const;\n\nfunction buildLadder(\n required: readonly string[],\n optional: readonly string[],\n paramPrefix: string,\n): string {\n const parts: string[] = [];\n let i = 0;\n for (const slot of required) {\n parts.push(`.property('${slot}', ${paramPrefix}${i++})`);\n }\n for (const slot of optional) {\n parts.push(\n `.choose(__.constant(${paramPrefix}${i}).is(neq(${SENTINEL_BINDING})),` +\n ` __.property('${slot}', ${paramPrefix}${i}),` +\n ` __.identity())`,\n );\n i++;\n }\n return parts.join('');\n}\n\nfunction buildLadderBindings(\n required: readonly string[],\n optional: readonly string[],\n paramPrefix: string,\n values: Record<string, string | number | boolean | null | undefined>,\n): Record<string, string | number | boolean> {\n const bindings: Record<string, string | number | boolean> = {};\n let i = 0;\n for (const slot of required) {\n const v = values[slot];\n if (v == null) {\n throw new Error(`Fixed-shape ladder: required slot '${slot}' is null/undefined`);\n }\n bindings[`${paramPrefix}${i++}`] = v;\n }\n for (const slot of optional) {\n const v = values[slot];\n bindings[`${paramPrefix}${i++}`] = v ?? ABSENT_STRING_SENTINEL;\n }\n return bindings;\n}\n\n/**\n * Emit the entity property ladder — same Gremlin string for every entity\n * write regardless of which optional fields are present. Prepend the\n * vertex-create prefix (e.g. `addV(vertexLabel).property('id', vid)\n * .property('repositoryId', rid)`) when on a create branch; on an update\n * branch (existing vertex via `unfold()`) use this chain directly.\n */\nexport function buildEntityPropertyLadder(): string {\n return buildLadder(ENTITY_REQUIRED_SLOTS, ENTITY_OPTIONAL_SLOTS, 'p');\n}\n\n/** Build the canonical entity ladder bindings (p0..p17 + absentSentinel). */\nexport function entityToLadderBindings(\n entity: StoredEntity,\n): Record<string, string | number | boolean> {\n const bindings = buildLadderBindings(ENTITY_REQUIRED_SLOTS, ENTITY_OPTIONAL_SLOTS, 'p', {\n entityType: entity.entityType,\n entityLabel: entity.label,\n slug: entity.slug,\n properties: JSON.stringify(entity.properties ?? {}),\n createdBy: entity.provenance.createdBy,\n createdByType: entity.provenance.createdByType,\n createdAt: entity.provenance.createdAt,\n modifiedBy: entity.provenance.modifiedBy,\n modifiedByType: entity.provenance.modifiedByType,\n modifiedAt: entity.provenance.modifiedAt,\n summary: entity.summary,\n data: entity.data,\n dataFormat: entity.dataFormat,\n embedding: entity.embedding != null ? JSON.stringify(entity.embedding) : undefined,\n createdInConversation: entity.provenance.createdInConversation,\n createdFromMessage: entity.provenance.createdFromMessage,\n modifiedInConversation: entity.provenance.modifiedInConversation,\n modifiedFromMessage: entity.provenance.modifiedFromMessage,\n });\n bindings[SENTINEL_BINDING] = ABSENT_STRING_SENTINEL;\n return bindings;\n}\n\n/** Edge counterpart of `buildEntityPropertyLadder()` — different slot list. */\nexport function buildRelationshipPropertyLadder(): string {\n return buildLadder(RELATIONSHIP_REQUIRED_SLOTS, RELATIONSHIP_OPTIONAL_SLOTS, 'p');\n}\n\n/** Build the canonical relationship ladder bindings (p0..p14 + absentSentinel). */\nexport function relationshipToLadderBindings(\n rel: StoredRelationship,\n): Record<string, string | number | boolean> {\n const bindings = buildLadderBindings(\n RELATIONSHIP_REQUIRED_SLOTS,\n RELATIONSHIP_OPTIONAL_SLOTS,\n 'p',\n {\n relationshipType: rel.relationshipType,\n sourceEntityId: rel.sourceEntityId,\n targetEntityId: rel.targetEntityId,\n bidirectional: rel.bidirectional,\n properties: JSON.stringify(rel.properties ?? {}),\n createdBy: rel.provenance.createdBy,\n createdByType: rel.provenance.createdByType,\n createdAt: rel.provenance.createdAt,\n modifiedBy: rel.provenance.modifiedBy,\n modifiedByType: rel.provenance.modifiedByType,\n modifiedAt: rel.provenance.modifiedAt,\n createdInConversation: rel.provenance.createdInConversation,\n createdFromMessage: rel.provenance.createdFromMessage,\n modifiedInConversation: rel.provenance.modifiedInConversation,\n modifiedFromMessage: rel.provenance.modifiedFromMessage,\n },\n );\n bindings[SENTINEL_BINDING] = ABSENT_STRING_SENTINEL;\n return bindings;\n}\n\n/**\n * Repository property ladder — slot list matches the writable surface of\n * StorageRepositoryConfig (the `id` and `repositoryId` slots are written\n * separately by the caller).\n */\nexport function buildRepositoryPropertyLadder(): string {\n return buildLadder(REPOSITORY_REQUIRED_SLOTS, REPOSITORY_OPTIONAL_SLOTS, 'p');\n}\n\n/** Build the canonical repository ladder bindings. */\nexport function repositoryConfigToLadderBindings(\n config: {\n label: string;\n governanceConfig: unknown;\n createdAt: string;\n createdBy: string;\n description?: string;\n type?: string;\n legal?: string;\n owner?: string;\n metadata?: Record<string, unknown>;\n },\n): Record<string, string | number | boolean> {\n const bindings = buildLadderBindings(\n REPOSITORY_REQUIRED_SLOTS,\n REPOSITORY_OPTIONAL_SLOTS,\n 'p',\n {\n repoLabel: config.label,\n governanceConfig: JSON.stringify(config.governanceConfig),\n createdAt: config.createdAt,\n createdBy: config.createdBy,\n description: config.description,\n type: config.type,\n legal: config.legal,\n owner: config.owner,\n metadata: config.metadata != null ? JSON.stringify(config.metadata) : undefined,\n },\n );\n bindings[SENTINEL_BINDING] = ABSENT_STRING_SENTINEL;\n return bindings;\n}\n","// Repository CRUD Gremlin queries\n\nimport type { CosmosDbConnection } from '../CosmosDbConnection.js';\nimport type {\n StorageRepositoryConfig,\n StoredRepository,\n StoredRepositorySummary,\n RepositoryFilter,\n RepositoryStats,\n RepositoryUpdate,\n} from '@utaba/deep-memory/types';\nimport type { PaginatedResult, DeleteProgressCallback } from '@utaba/deep-memory/types';\nimport {\n buildRepositoryProjectChain,\n buildRepositoryPropertyLadder,\n repositoryConfigToLadderBindings,\n repositoryFromGremlin,\n} from '../mapping.js';\nimport { DuplicateRepositoryError, RepositoryNotFoundError } from '@utaba/deep-memory';\n\nconst REPO_LABEL = '_repository';\n\n// Sentinel vertex pinned in a fixed `_index` partition. It mirrors the list of\n// every repository id in the container so `listRepositories` can be a single\n// partition-scoped read rather than a cross-partition scan over every\n// `_repository` vertex. ensureSchema bootstraps the sentinel; createRepository\n// and deleteRepository keep it in sync atomically via single-submit\n// cross-partition `sideEffect` updates.\n//\n// Shape: `repositoryIds: string[]` — flat ids. listRepositories hydrates each\n// id via partition-scoped getRepository in parallel. Pagination and any\n// `filter.type` narrowing happen client-side after hydration.\nexport const REPOSITORY_INDEX_VERTEX_ID = '_repository_index';\nexport const REPOSITORY_INDEX_PARTITION = '_index';\nconst REPOSITORY_INDEX_LABEL = '_repository_index';\n\nfunction repoVertexId(repositoryId: string): string {\n return `repo:${repositoryId}`;\n}\n\n/**\n * Bootstrap the `_repository_index` sentinel vertex.\n *\n * Called once per Cosmos account by {@link CosmosDbProvider.ensureSchema}.\n * If the sentinel is missing, runs the legacy cross-partition\n * `g.V().hasLabel('_repository').values('repositoryId')` scan to collect every\n * existing repository's id and writes the sentinel with that array. This is\n * the only cross-partition Gremlin read remaining after Phase 11 — it runs\n * once per account on first migration and never again.\n *\n * Returns the number of pre-existing repositories the sentinel was backfilled\n * with, or `null` if the sentinel already existed (no migration needed).\n */\nexport async function ensureRepositoryIndex(conn: CosmosDbConnection): Promise<number | null> {\n // Cheap existence check — single doc fetch in the `_index` partition.\n const existing = await conn.submit(\n \"g.V().has('repositoryId', pk).hasId(sid).count()\",\n { pk: REPOSITORY_INDEX_PARTITION, sid: REPOSITORY_INDEX_VERTEX_ID },\n );\n if (Number(existing.items[0] ?? 0) > 0) {\n return null;\n }\n\n // Sentinel missing — run the legacy cross-partition scan ONCE to collect\n // every existing repo id. After this runs the sentinel is authoritative\n // and the legacy scan is never issued again.\n const scan = await conn.submit(\n \"g.V().hasLabel('_repository').values('repositoryId')\",\n {},\n );\n const ids = scan.items\n .map((item) => (typeof item === 'string' ? item : String(item ?? '')))\n .filter((id) => id.length > 0);\n\n await conn.submit(\n \"g.addV('\" + REPOSITORY_INDEX_LABEL + \"')\" +\n \".property('id', sid).property('repositoryId', pk).property('repositoryIds', initial)\",\n {\n pk: REPOSITORY_INDEX_PARTITION,\n sid: REPOSITORY_INDEX_VERTEX_ID,\n initial: JSON.stringify(ids),\n },\n );\n\n return ids.length;\n}\n\n/**\n * Read the `repositoryIds` array from the sentinel. Returns `[]` if the\n * sentinel is missing — callers that need the sentinel to exist should\n * ensure {@link CosmosDbProvider.ensureSchema} has run first.\n */\nasync function readRepositoryIndex(conn: CosmosDbConnection): Promise<string[]> {\n const result = await conn.submit(\n \"g.V().has('repositoryId', pk).hasId(sid).values('repositoryIds')\",\n { pk: REPOSITORY_INDEX_PARTITION, sid: REPOSITORY_INDEX_VERTEX_ID },\n );\n if (result.items.length === 0) return [];\n const raw = result.items[0];\n const json = typeof raw === 'string' ? raw : String(raw ?? '');\n if (!json) return [];\n try {\n const parsed = JSON.parse(json);\n return Array.isArray(parsed) ? parsed.filter((id): id is string => typeof id === 'string') : [];\n } catch {\n return [];\n }\n}\n\n/** Build a .property() chain for Gremlin vertex creation/update. */\nfunction propertyChain(bindings: Record<string, unknown>, props: Record<string, string | number | boolean | null | undefined>, startIndex: number): { chain: string; nextIndex: number } {\n const parts: string[] = [];\n let idx = startIndex;\n for (const [key, value] of Object.entries(props)) {\n if (value == null) continue;\n const paramName = `p${idx++}`;\n bindings[paramName] = value;\n parts.push(`.property('${key}', ${paramName})`);\n }\n return { chain: parts.join(''), nextIndex: idx };\n}\n\n// Fixed-shape property ladder for `_repository` vertex creation. The emitted\n// query string is identical across every createRepository call regardless of\n// which optional fields (description / type / legal / owner / metadata) are\n// set, so the server-side plan cache reuses one compiled plan. A trailing\n// `.sideEffect(...)` step updates the `_repository_index` sentinel in the\n// `_index` partition atomically with the addV — probe-verified single-submit\n// cross-partition mutation on the emulator (2026-05-26).\nconst REPOSITORY_CREATE_QUERY =\n `g.addV('${REPO_LABEL}').property('id', vid).property('repositoryId', rid)${buildRepositoryPropertyLadder()}` +\n \".sideEffect(__.V().has('repositoryId', pk).hasId(sid).property('repositoryIds', updatedIndex))\";\n\nexport async function createRepository(\n conn: CosmosDbConnection,\n config: StorageRepositoryConfig,\n): Promise<StoredRepository> {\n const vertexId = repoVertexId(config.repositoryId);\n\n // Existence check — partition-scoped via `has('repositoryId', rid)` before\n // `hasId(vid)`. hasId alone is post-routing and fans out across partitions.\n const existing = await conn.submit(\n \"g.V().has('repositoryId', rid).hasId(vid).has('label', lbl).count()\",\n { vid: vertexId, rid: config.repositoryId, lbl: REPO_LABEL },\n );\n if (existing.items.length > 0 && Number(existing.items[0]) > 0) {\n throw new DuplicateRepositoryError(config.repositoryId);\n }\n\n // Compute the updated sentinel array client-side before the atomic write.\n // One extra round-trip (the sentinel read), but it lets the actual create\n // submit be a single round-trip that does both the addV and the sentinel\n // update via sideEffect.\n const currentIds = await readRepositoryIndex(conn);\n const updatedIds = currentIds.includes(config.repositoryId)\n ? currentIds\n : [...currentIds, config.repositoryId];\n\n const bindings: Record<string, unknown> = {\n vid: vertexId,\n rid: config.repositoryId,\n pk: REPOSITORY_INDEX_PARTITION,\n sid: REPOSITORY_INDEX_VERTEX_ID,\n updatedIndex: JSON.stringify(updatedIds),\n ...repositoryConfigToLadderBindings(config),\n };\n\n await conn.submit(REPOSITORY_CREATE_QUERY, bindings);\n\n return {\n repositoryId: config.repositoryId,\n type: config.type,\n label: config.label,\n description: config.description,\n legal: config.legal,\n owner: config.owner,\n governanceConfig: config.governanceConfig,\n metadata: config.metadata,\n createdAt: config.createdAt,\n createdBy: config.createdBy,\n };\n}\n\nexport async function getRepository(\n conn: CosmosDbConnection,\n repositoryId: string,\n): Promise<StoredRepository | null> {\n // `has('repositoryId', rid)` scopes the lookup to a single partition before\n // `hasId(vid)`; hasId alone fans out across partitions in Cosmos Gremlin.\n const projection = buildRepositoryProjectChain();\n const result = await conn.submit(\n `g.V().has('repositoryId', rid).hasId(vid).hasLabel('_repository').${projection}`,\n { vid: repoVertexId(repositoryId), rid: repositoryId },\n );\n if (result.items.length === 0) return null;\n return repositoryFromGremlin(result.items[0] as Record<string, unknown>);\n}\n\nexport async function listRepositories(\n conn: CosmosDbConnection,\n filter?: RepositoryFilter,\n): Promise<PaginatedResult<StoredRepositorySummary>> {\n const limit = filter?.limit ?? 20;\n const offset = filter?.offset ?? 0;\n\n // Read the sentinel in the fixed `_index` partition — a single partition-\n // scoped lookup. The previous implementation issued a cross-partition\n // `g.V().hasLabel('_repository')` scan that fanned out across every\n // physical partition.\n const repositoryIds = await readRepositoryIndex(conn);\n\n if (repositoryIds.length === 0) {\n return { items: [], total: 0, hasMore: false, limit, offset };\n }\n\n // Hydrate each id via the partition-scoped `getRepository`. Parallel because\n // each call hits a different partition; the round-trips are independent.\n const hydrated = await Promise.all(\n repositoryIds.map((rid) => getRepository(conn, rid)),\n );\n\n // A null from getRepository means the sentinel references a vertex that no\n // longer exists — happens transiently during a partial create/delete or if\n // the sentinel was rebuilt from stale state. Drop those entries; the next\n // create or delete call will resync the sentinel.\n let summaries: StoredRepositorySummary[] = hydrated\n .filter((r): r is StoredRepository => r != null)\n .map((r) => {\n const summary: StoredRepositorySummary = {\n repositoryId: r.repositoryId,\n label: r.label,\n governanceConfig: r.governanceConfig,\n };\n if (r.type !== undefined) summary.type = r.type;\n if (r.description !== undefined) summary.description = r.description;\n return summary;\n });\n\n if (filter?.type) {\n summaries = summaries.filter((s) => s.type === filter.type);\n }\n\n const total = summaries.length;\n const items = summaries.slice(offset, offset + limit);\n\n return {\n items,\n total,\n hasMore: offset + items.length < total,\n limit,\n offset,\n };\n}\n\n// updateRepository intentionally keeps a variable-shape query (unlike the\n// fixed-shape create path). Partial-update semantics would otherwise need a\n// three-way discriminator per slot, and `_repository` writes are extremely\n// rare (one per repo per config change) so a missed plan-cache is negligible.\nexport async function updateRepository(\n conn: CosmosDbConnection,\n repositoryId: string,\n updates: RepositoryUpdate,\n): Promise<StoredRepository> {\n const vertexId = repoVertexId(repositoryId);\n\n // Verify exists\n const existing = await getRepository(conn, repositoryId);\n if (!existing) throw new RepositoryNotFoundError(repositoryId);\n\n // `has('repositoryId', rid)` scopes the update to one partition before\n // `hasId(vid)`; hasId alone fans out across partitions in Cosmos Gremlin.\n const bindings: Record<string, unknown> = { vid: vertexId, rid: repositoryId };\n const props: Record<string, string | number | boolean | null | undefined> = {};\n\n if (updates.label !== undefined) props['repoLabel'] = updates.label;\n if (updates.description !== undefined) props['description'] = updates.description;\n if (updates.type !== undefined) props['type'] = updates.type;\n if (updates.legal !== undefined) props['legal'] = updates.legal;\n if (updates.owner !== undefined) props['owner'] = updates.owner;\n if (updates.governanceConfig !== undefined) props['governanceConfig'] = JSON.stringify(updates.governanceConfig);\n if (updates.metadata !== undefined) {\n // Shallow merge with existing metadata\n const merged = { ...existing.metadata, ...updates.metadata };\n props['metadata'] = JSON.stringify(merged);\n }\n\n if (Object.keys(props).length === 0) return existing;\n\n const { chain } = propertyChain(bindings, props, 0);\n const query = `g.V().has('repositoryId', rid).hasId(vid).hasLabel('_repository')${chain}`;\n await conn.submit(query, bindings);\n\n return (await getRepository(conn, repositoryId))!;\n}\n\nconst DELETE_BATCH_SIZE = 500;\n\nexport async function deleteRepository(\n conn: CosmosDbConnection,\n repositoryId: string,\n onProgress?: DeleteProgressCallback,\n): Promise<void> {\n // Get totals for progress reporting\n const entityCountResult = await conn.submit(\n \"g.V().has('repositoryId', rid).has('entityType').count()\",\n { rid: repositoryId },\n );\n const totalEntities = Number(entityCountResult.items[0] ?? 0);\n\n const relCountResult = await conn.submit(\n \"g.E().has('repositoryId', rid).count()\",\n { rid: repositoryId },\n );\n const totalRelationships = Number(relCountResult.items[0] ?? 0);\n\n let relationshipsDeleted = 0;\n let entitiesDeleted = 0;\n\n // Drop edges first (avoids orphan-edge errors), then all vertices, in batches.\n // A single unbounded drop() times out on large repositories.\n while (true) {\n await conn.submit(\n \"g.E().has('repositoryId', rid).limit(batchSize).drop()\",\n { rid: repositoryId, batchSize: DELETE_BATCH_SIZE },\n );\n const remaining = await conn.submit(\n \"g.E().has('repositoryId', rid).limit(1).count()\",\n { rid: repositoryId },\n );\n const remainingCount = Number(remaining.items[0] ?? 0);\n relationshipsDeleted = totalRelationships - remainingCount;\n await onProgress?.({ entitiesDeleted, relationshipsDeleted, totalEntities, totalRelationships });\n if (remainingCount === 0) break;\n }\n\n while (true) {\n await conn.submit(\n \"g.V().has('repositoryId', rid).limit(batchSize).drop()\",\n { rid: repositoryId, batchSize: DELETE_BATCH_SIZE },\n );\n const remaining = await conn.submit(\n \"g.V().has('repositoryId', rid).limit(1).count()\",\n { rid: repositoryId },\n );\n const remainingCount = Number(remaining.items[0] ?? 0);\n entitiesDeleted = totalEntities - remainingCount;\n await onProgress?.({ entitiesDeleted, relationshipsDeleted, totalEntities, totalRelationships });\n if (remainingCount === 0) break;\n }\n\n // Remove this repo's id from the sentinel. The drain above already dropped\n // the `_repository` vertex (it lives in the repo's partition), so this is\n // the only remaining cross-partition write — a property update on the\n // sentinel in the `_index` partition.\n const currentIds = await readRepositoryIndex(conn);\n const updatedIds = currentIds.filter((id) => id !== repositoryId);\n if (updatedIds.length !== currentIds.length) {\n await conn.submit(\n \"g.V().has('repositoryId', pk).hasId(sid).property('repositoryIds', updatedIndex)\",\n {\n pk: REPOSITORY_INDEX_PARTITION,\n sid: REPOSITORY_INDEX_VERTEX_ID,\n updatedIndex: JSON.stringify(updatedIds),\n },\n );\n }\n}\n\nexport async function deleteAllContents(\n conn: CosmosDbConnection,\n repositoryId: string,\n onProgress?: DeleteProgressCallback,\n): Promise<{ deletedEntities: number; deletedRelationships: number }> {\n // Count before deleting\n const entityCountResult = await conn.submit(\n \"g.V().has('repositoryId', rid).has('entityType').count()\",\n { rid: repositoryId },\n );\n const totalEntities = Number(entityCountResult.items[0] ?? 0);\n\n const relCountResult = await conn.submit(\n \"g.E().has('repositoryId', rid).count()\",\n { rid: repositoryId },\n );\n const totalRelationships = Number(relCountResult.items[0] ?? 0);\n\n let relationshipsDeleted = 0;\n let entitiesDeleted = 0;\n\n // Drop edges first (avoids orphan-edge errors), then entity vertices, in batches.\n // Preserves system vertices (_repository, _vocabulary).\n while (true) {\n await conn.submit(\n \"g.E().has('repositoryId', rid).limit(batchSize).drop()\",\n { rid: repositoryId, batchSize: DELETE_BATCH_SIZE },\n );\n const remaining = await conn.submit(\n \"g.E().has('repositoryId', rid).limit(1).count()\",\n { rid: repositoryId },\n );\n const remainingCount = Number(remaining.items[0] ?? 0);\n relationshipsDeleted = totalRelationships - remainingCount;\n await onProgress?.({ entitiesDeleted, relationshipsDeleted, totalEntities, totalRelationships });\n if (remainingCount === 0) break;\n }\n\n while (true) {\n await conn.submit(\n \"g.V().has('repositoryId', rid).has('entityType').limit(batchSize).drop()\",\n { rid: repositoryId, batchSize: DELETE_BATCH_SIZE },\n );\n const remaining = await conn.submit(\n \"g.V().has('repositoryId', rid).has('entityType').limit(1).count()\",\n { rid: repositoryId },\n );\n const remainingCount = Number(remaining.items[0] ?? 0);\n entitiesDeleted = totalEntities - remainingCount;\n await onProgress?.({ entitiesDeleted, relationshipsDeleted, totalEntities, totalRelationships });\n if (remainingCount === 0) break;\n }\n\n return { deletedEntities: totalEntities, deletedRelationships: totalRelationships };\n}\n\nexport async function getRepositoryStats(\n conn: CosmosDbConnection,\n repositoryId: string,\n): Promise<RepositoryStats> {\n // Get vocabulary version\n const vocabResult = await conn.submit(\n \"g.V().has('repositoryId', rid).hasLabel('_vocabulary').values('vocabulary')\",\n { rid: repositoryId },\n );\n let vocabVersion = '0.0.0';\n if (vocabResult.items.length > 0) {\n try {\n const vocab = JSON.parse(vocabResult.items[0] as string);\n vocabVersion = vocab.version ?? '0.0.0';\n } catch { /* default */ }\n }\n\n // Count entities by type (exclude system vertices)\n const entityResult = await conn.submit(\n \"g.V().has('repositoryId', rid).has('entityType').group().by('entityType').by(count())\",\n { rid: repositoryId },\n );\n const entityTypeBreakdown: Record<string, number> = {};\n let entityCount = 0;\n if (entityResult.items.length > 0) {\n const grouped = entityResult.items[0] as Record<string, number>;\n for (const [type, count] of Object.entries(grouped)) {\n entityTypeBreakdown[type] = Number(count);\n entityCount += Number(count);\n }\n }\n\n // Count relationships by type\n const relResult = await conn.submit(\n \"g.E().has('repositoryId', rid).group().by('relationshipType').by(count())\",\n { rid: repositoryId },\n );\n const relationshipTypeBreakdown: Record<string, number> = {};\n let relationshipCount = 0;\n if (relResult.items.length > 0) {\n const grouped = relResult.items[0] as Record<string, number>;\n for (const [type, count] of Object.entries(grouped)) {\n relationshipTypeBreakdown[type] = Number(count);\n relationshipCount += Number(count);\n }\n }\n\n return {\n entityCount,\n relationshipCount,\n vocabularyVersion: vocabVersion,\n entityTypeBreakdown,\n relationshipTypeBreakdown,\n };\n}\n","// Vocabulary Gremlin queries\n\nimport type { CosmosDbConnection } from '../CosmosDbConnection.js';\nimport type { MemoryVocabulary, VocabularyChangeRecord } from '@utaba/deep-memory/types';\nimport type { PaginationOptions, PaginatedResult } from '@utaba/deep-memory/types';\nimport { changeRecordFromGremlin } from '../mapping.js';\n\nfunction vocabVertexId(repositoryId: string): string {\n return `vocab:${repositoryId}`;\n}\n\nconst EMPTY_VOCABULARY = (): MemoryVocabulary => ({\n version: '0.0.0',\n lastModified: new Date().toISOString(),\n modifiedBy: 'system',\n entityTypes: [],\n relationshipTypes: [],\n});\n\nexport async function getVocabulary(\n conn: CosmosDbConnection,\n repositoryId: string,\n): Promise<MemoryVocabulary> {\n // We only ever read the JSON-stringified `vocabulary` property; the full\n // valueMap(true) shipped every property on the vocab vertex (label,\n // repositoryId, etc.) for no reason. `.values('vocabulary').limit(1)`\n // returns just the JSON string — smaller wire payload, single column read.\n //\n // `has('repositoryId', rid)` scopes the lookup to a single partition before\n // `hasId(vid)`; `hasId` is post-routing in Cosmos Gremlin and fans out\n // across all partitions without the partition predicate.\n const result = await conn.submit(\n \"g.V().has('repositoryId', rid).hasId(vid).hasLabel('_vocabulary').values('vocabulary').limit(1)\",\n { vid: vocabVertexId(repositoryId), rid: repositoryId },\n );\n if (result.items.length === 0) return EMPTY_VOCABULARY();\n const raw = result.items[0];\n const json = typeof raw === 'string' ? raw : String(raw ?? '');\n if (!json) return EMPTY_VOCABULARY();\n try {\n return JSON.parse(json) as MemoryVocabulary;\n } catch {\n return EMPTY_VOCABULARY();\n }\n}\n\nexport async function saveVocabulary(\n conn: CosmosDbConnection,\n repositoryId: string,\n vocabulary: MemoryVocabulary,\n): Promise<void> {\n const vid = vocabVertexId(repositoryId);\n const vocabJson = JSON.stringify(vocabulary);\n\n // Upsert: try to update existing, create if not found.\n // Both branches scope by `has('repositoryId', rid)` before `hasId(vid)` —\n // hasId alone fans out across all partitions in Cosmos Gremlin.\n const existing = await conn.submit(\n \"g.V().has('repositoryId', rid).hasId(vid).hasLabel('_vocabulary').count()\",\n { vid, rid: repositoryId },\n );\n\n if (Number(existing.items[0] ?? 0) > 0) {\n await conn.submit(\n \"g.V().has('repositoryId', rid).hasId(vid).hasLabel('_vocabulary').property('vocabulary', vocabJson)\",\n { vid, rid: repositoryId, vocabJson },\n );\n } else {\n await conn.submit(\n \"g.addV('_vocabulary').property('id', vid).property('repositoryId', rid).property('vocabulary', vocabJson)\",\n { vid, rid: repositoryId, vocabJson },\n );\n }\n}\n\nexport async function getVocabularyChangeLog(\n conn: CosmosDbConnection,\n repositoryId: string,\n options?: PaginationOptions,\n): Promise<PaginatedResult<VocabularyChangeRecord>> {\n const limit = options?.limit ?? 10;\n const offset = options?.offset ?? 0;\n\n // Count and data round-trips are independent — run them in parallel. No\n // property filters here, so the count is exact and `total` is always a number.\n const [countResult, dataResult] = await Promise.all([\n conn.submit(\n \"g.V().has('repositoryId', rid).hasLabel('_vocabularyChangeLog').count()\",\n { rid: repositoryId },\n ),\n conn.submit(\n \"g.V().has('repositoryId', rid).hasLabel('_vocabularyChangeLog').order().by('proposedAt', decr).range(rangeStart, rangeEnd).valueMap(true)\",\n { rid: repositoryId, rangeStart: offset, rangeEnd: offset + limit },\n ),\n ]);\n\n const total = Number(countResult.items[0] ?? 0);\n const items = (dataResult.items as Record<string, unknown>[]).map(changeRecordFromGremlin);\n\n return {\n items,\n total,\n hasMore: offset + items.length < total,\n limit,\n offset,\n };\n}\n","// Entity CRUD Gremlin queries\n\nimport type { CosmosDbConnection } from '../CosmosDbConnection.js';\nimport type { CosmosDocumentClient, CosmosQueryParameter } from '../CosmosDocumentClient.js';\nimport type { StoredEntity, StoredEntityUpdate } from '@utaba/deep-memory/types';\nimport type { StorageFindQuery, PaginatedResult, PropertyFilter } from '@utaba/deep-memory/types';\nimport type { EntityReadOptions } from '@utaba/deep-memory/providers';\nimport {\n buildEntityPropertyLadder,\n entityFromDocument,\n entityFromGremlin,\n entityToLadderBindings,\n STORED_ENTITY_FIELDS,\n} from '../mapping.js';\nimport {\n DuplicateEntityError,\n EntityNotFoundError,\n buildVertexProjectChain,\n matchesPropertyFilters,\n} from '@utaba/deep-memory';\n\n// Sentinel returned by the duplicate-detection branch of the\n// fold().coalesce(unfold().constant('__duplicate'), addV/addE) pattern. The\n// create succeeds inline or the duplicate path returns this string, which we\n// translate into the typed error — single round-trip either way.\nconst DUPLICATE_SENTINEL = '__duplicate';\n\n// Fixed-shape property ladder — same Gremlin string for every entity create\n// regardless of which optional fields are populated, so the Cosmos plan cache\n// reuses one compiled plan. Computed once at module load.\nconst ENTITY_CREATE_QUERY =\n `g.V().has('repositoryId', rid).hasId(vid).fold().coalesce(` +\n `unfold().constant('${DUPLICATE_SENTINEL}'),` +\n `addV(vertexLabel).property('id', vid).property('repositoryId', rid)${buildEntityPropertyLadder()}` +\n `)`;\n\nexport async function createEntity(\n conn: CosmosDbConnection,\n repositoryId: string,\n entity: StoredEntity,\n): Promise<StoredEntity> {\n const bindings: Record<string, unknown> = {\n rid: repositoryId,\n vid: entity.id,\n vertexLabel: entity.entityType,\n ...entityToLadderBindings(entity),\n };\n\n const result = await conn.submit(ENTITY_CREATE_QUERY, bindings);\n\n if (result.items[0] === DUPLICATE_SENTINEL) {\n throw new DuplicateEntityError(entity.id);\n }\n\n return entity;\n}\n\nexport async function getEntity(\n conn: CosmosDbConnection,\n repositoryId: string,\n entityId: string,\n options?: EntityReadOptions,\n): Promise<StoredEntity | null> {\n const projection = buildVertexProjectChain({ withEmbedding: options?.loadEmbeddings });\n const result = await conn.submit(\n `g.V().has('repositoryId', rid).hasId(eid).has('entityType').${projection}`,\n { rid: repositoryId, eid: entityId },\n );\n if (result.items.length === 0) return null;\n return entityFromGremlin(result.items[0] as Record<string, unknown>);\n}\n\nexport async function getEntityBySlug(\n conn: CosmosDbConnection,\n repositoryId: string,\n slug: string,\n options?: EntityReadOptions,\n): Promise<StoredEntity | null> {\n const projection = buildVertexProjectChain({ withEmbedding: options?.loadEmbeddings });\n const result = await conn.submit(\n `g.V().has('repositoryId', rid).has('slug', slugVal).has('entityType').${projection}`,\n { rid: repositoryId, slugVal: slug },\n );\n if (result.items.length === 0) return null;\n return entityFromGremlin(result.items[0] as Record<string, unknown>);\n}\n\nexport async function getEntities(\n conn: CosmosDbConnection,\n repositoryId: string,\n entityIds: string[],\n options?: EntityReadOptions,\n): Promise<Map<string, StoredEntity>> {\n if (entityIds.length === 0) return new Map();\n\n // Build within() clause with individual params\n const bindings: Record<string, unknown> = { rid: repositoryId };\n const idParams: string[] = [];\n entityIds.forEach((id, i) => {\n const paramName = `eid${i}`;\n bindings[paramName] = id;\n idParams.push(paramName);\n });\n\n const withinClause = `within(${idParams.join(', ')})`;\n const projection = buildVertexProjectChain({ withEmbedding: options?.loadEmbeddings });\n const result = await conn.submit(\n `g.V().has('repositoryId', rid).hasId(${withinClause}).has('entityType').${projection}`,\n bindings,\n );\n\n const map = new Map<string, StoredEntity>();\n for (const item of result.items) {\n const entity = entityFromGremlin(item as Record<string, unknown>);\n map.set(entity.id, entity);\n }\n return map;\n}\n\n// updateEntity intentionally KEEPS a variable-shape query (unlike createEntity).\n// A fixed-shape ladder for updates would require a three-way discriminator per\n// slot (set / drop / leave) with two-level choose-and-sideEffect-drop branches\n// — significant Gremlin complexity for a per-call plan-cache win that matters\n// far less here than on the bulk-import create path. The plan-cache concern is\n// framed around the \"every create is a unique query\" case (issue #20 in\n// plans/performance-issues.md), not partial-update calls. If the reembed loop\n// ever profiles as plan-parse-bound, revisit by introducing a two-sentinel\n// ladder shape — until then variable is fine.\n\nexport async function updateEntity(\n conn: CosmosDbConnection,\n repositoryId: string,\n entityId: string,\n updates: StoredEntityUpdate,\n): Promise<StoredEntity> {\n const bindings: Record<string, unknown> = { rid: repositoryId, eid: entityId };\n const propParts: string[] = [];\n let idx = 0;\n\n const addProp = (key: string, value: string | number | boolean) => {\n const paramName = `p${idx++}`;\n bindings[paramName] = value;\n propParts.push(`.property('${key}', ${paramName})`);\n };\n\n // Gremlin has no \"set to null\" — to clear a property we drop it with a\n // sideEffect step. Drops run before sets because `.sideEffect(...)` is\n // appended to `propParts` in traversal order.\n const dropProp = (key: string) => {\n propParts.push(`.sideEffect(properties('${key}').drop())`);\n };\n\n // Note: entityType drives both the Gremlin vertex label (set at addV) and the\n // `entityType` property. The vertex label is immutable in Gremlin, but every\n // entity query in this provider filters by the `entityType` property rather\n // than vertex label, so updating the property is sufficient for functional\n // correctness. The vertex label becomes a stale hint only.\n if (updates.entityType !== undefined) addProp('entityType', updates.entityType);\n if (updates.label !== undefined) addProp('entityLabel', updates.label);\n if (updates.slug !== undefined) addProp('slug', updates.slug);\n if (updates.summary === null) dropProp('summary');\n else if (updates.summary !== undefined) addProp('summary', updates.summary);\n if (updates.properties !== undefined) addProp('properties', JSON.stringify(updates.properties));\n if (updates.data === null) dropProp('data');\n else if (updates.data !== undefined) addProp('data', updates.data);\n if (updates.dataFormat === null) dropProp('dataFormat');\n else if (updates.dataFormat !== undefined) addProp('dataFormat', updates.dataFormat);\n if (updates.embedding !== undefined) addProp('embedding', JSON.stringify(updates.embedding));\n\n // Provenance\n addProp('modifiedBy', updates.provenance.modifiedBy);\n addProp('modifiedByType', updates.provenance.modifiedByType);\n addProp('modifiedAt', updates.provenance.modifiedAt);\n if (updates.provenance.modifiedInConversation != null) addProp('modifiedInConversation', updates.provenance.modifiedInConversation);\n if (updates.provenance.modifiedFromMessage != null) addProp('modifiedFromMessage', updates.provenance.modifiedFromMessage);\n\n // Append the read-projection onto the update so the updated state comes\n // back in a single round-trip (instead of update + separate getEntity).\n // Embeddings stay off the wire — callers that need the embedding pass the\n // option through the public StorageProvider.getEntity call themselves.\n const projection = buildVertexProjectChain();\n const query = `g.V().has('repositoryId', rid).hasId(eid).has('entityType')${propParts.join('')}.${projection}`;\n const result = await conn.submit(query, bindings);\n\n if (result.items.length === 0) {\n throw new EntityNotFoundError(entityId);\n }\n\n return entityFromGremlin(result.items[0] as Record<string, unknown>);\n}\n\nexport async function deleteEntity(\n conn: CosmosDbConnection,\n repositoryId: string,\n entityId: string,\n): Promise<void> {\n // Gremlin drop() on a vertex also drops connected edges\n await conn.submit(\n \"g.V().has('repositoryId', rid).hasId(eid).has('entityType').drop()\",\n { rid: repositoryId, eid: entityId },\n );\n}\n\n/**\n * Single round-trip type-delete via the aggregate-side-effect pattern: the\n * bucket records the vertex ids that the drop touched, giving an exact entity\n * count. The cascaded edge count is intentionally skipped — computing it\n * required a `bothE().dedup().count()` that walked every incident edge across\n * every partition the type touches, and the value is currently discarded by\n * the only caller (VocabularyEngine.cascadeDeleteData).\n *\n * Returns `deletedRelationships: undefined` to signal the field is genuinely\n * unknown for this provider. SQL Server and in-memory providers continue to\n * return the exact number (rowsAffected / iteration).\n */\nexport async function deleteEntitiesByType(\n conn: CosmosDbConnection,\n repositoryId: string,\n entityType: string,\n): Promise<{ deletedEntities: number; deletedRelationships: number | undefined }> {\n const result = await conn.submit(\n \"g.V().has('repositoryId', rid).has('entityType', etype)\" +\n \".aggregate('found').by('id').drop().cap('found')\",\n { rid: repositoryId, etype: entityType },\n );\n const bucket = result.items[0];\n const deletedEntities = Array.isArray(bucket) ? bucket.length : 0;\n return { deletedEntities, deletedRelationships: undefined };\n}\n\n/**\n * Build the Document-endpoint SQL path for a Gremlin-managed property.\n * Every user property on a Gremlin vertex is stored as `[{_value, id}]` when\n * read through the Document endpoint — so a top-level scalar reference like\n * `c.entityType` silently returns no rows. Always go through `[0]._value`.\n * See local-tests/baseline/phase-cosmos-sql-shape-probe-results.md.\n */\nfunction sqlPath(key: string): string {\n return `c.${key}[0]._value`;\n}\n\n/**\n * Build the `WHERE` clause + parameter array shared by the data query and the\n * `SELECT VALUE COUNT(1)` query, so the two are guaranteed to count the same\n * set by construction.\n *\n * Property filters are emitted as approximate `CONTAINS` on the JSON-stringified\n * `c.properties[0]._value` blob; the caller verifies exact-match client-side\n * (see `findEntities`).\n */\nfunction buildWhereClause(\n query: StorageFindQuery,\n repositoryId: string,\n): { sqlWhere: string; params: CosmosQueryParameter[] } {\n const params: CosmosQueryParameter[] = [{ name: '@rid', value: repositoryId }];\n // `IS_DEFINED(c.entityType)` mirrors the old Gremlin `.has('entityType')`\n // presence check — it excludes the `_repository`, `_vocabulary`, and\n // `_vocabulary_change` system vertices that share the partition with the\n // repository's entities. Without this filter, those vertices leak into\n // both the data page and the COUNT(1), breaking pagination math.\n const predicates: string[] = ['c.repositoryId = @rid', 'IS_DEFINED(c.entityType)'];\n\n if (query.entityTypes && query.entityTypes.length > 0) {\n const typeParamNames: string[] = [];\n query.entityTypes.forEach((t, i) => {\n const name = `@etype${i}`;\n params.push({ name, value: t });\n typeParamNames.push(name);\n });\n // Gotcha: must use the `[0]._value` path even for the type filter — the\n // flat `c.entityType` form returns 0 docs with indexUtilizationRatio=0.00.\n predicates.push(`${sqlPath('entityType')} IN (${typeParamNames.join(', ')})`);\n }\n\n if (query.searchTerm) {\n params.push({ name: '@term', value: query.searchTerm });\n predicates.push(\n `(CONTAINS(${sqlPath('entityLabel')}, @term, true) ` +\n `OR CONTAINS(${sqlPath('slug')}, @term, true) ` +\n `OR CONTAINS(${sqlPath('summary')}, @term, true))`,\n );\n }\n\n if (query.properties != null) {\n let i = 0;\n for (const [key, value] of Object.entries(query.properties)) {\n // JSON.stringify on a single-entry object produces `{\"key\":<json-value>}`;\n // strip the outer braces to get the substring that must appear inside\n // the stored blob. Works uniformly for strings, numbers, booleans, and\n // nested arrays/objects. False positives are filtered client-side via\n // `matchesPropertyFilters` after JSON-parsing each returned doc.\n const fragment = JSON.stringify({ [key]: value }).slice(1, -1);\n const name = `@kv${i++}`;\n params.push({ name, value: fragment });\n // ignoreCase=false: property keys/values are canonical, no case folding.\n predicates.push(`CONTAINS(${sqlPath('properties')}, ${name}, false)`);\n }\n }\n\n return { sqlWhere: `WHERE ${predicates.join(' AND ')}`, params };\n}\n\n/**\n * Build the projection field list for the data SELECT. Mirrors the Gremlin\n * fast path's `buildVertexProjectChain({ withEmbedding })`: embedding is\n * heavy (large JSON-stringified float array) and not shipped unless the\n * caller asks via `EntityReadOptions.loadEmbeddings`.\n */\nfunction buildSelectClause(loadEmbeddings: boolean): string {\n const fields = ['c.id', ...STORED_ENTITY_FIELDS.filter((f) => f !== 'id').map((f) => `c.${f}`)];\n if (loadEmbeddings) fields.push('c.embedding');\n return `SELECT ${fields.join(', ')}`;\n}\n\nexport async function findEntities(\n docClient: CosmosDocumentClient,\n repositoryId: string,\n query: StorageFindQuery,\n options?: EntityReadOptions,\n): Promise<PaginatedResult<StoredEntity>> {\n const { sqlWhere, params } = buildWhereClause(query, repositoryId);\n\n const dataParams: CosmosQueryParameter[] = [\n ...params,\n { name: '@off', value: query.offset },\n { name: '@lim', value: query.limit },\n ];\n const selectClause = buildSelectClause(options?.loadEmbeddings === true);\n // ORDER BY c.id pins pagination order deterministically — without it,\n // Cosmos may return overlapping/missing rows across page requests. c.id is\n // covered by the default indexing policy, so no extra RU on the sort itself.\n const dataSql = `${selectClause} FROM c ${sqlWhere} ORDER BY c.id OFFSET @off LIMIT @lim`;\n const countSql = `SELECT VALUE COUNT(1) FROM c ${sqlWhere}`;\n\n // The properties prefilter is approximate (substring CONTAINS on the\n // JSON-stringified blob), so COUNT(1) over the same WHERE clause would\n // overcount by the false-positive rate. Report `total: undefined` and let\n // callers paginate on `hasMore` instead.\n const skipCount =\n query.properties != null && Object.keys(query.properties).length > 0;\n\n const [dataResult, countResult] = await Promise.all([\n docClient.query<Record<string, unknown>>(dataSql, dataParams, {\n partitionKey: repositoryId,\n }),\n skipCount\n ? Promise.resolve(null)\n : docClient.query<number>(countSql, params, { partitionKey: repositoryId }),\n ]);\n\n let items = dataResult.documents.map(entityFromDocument);\n\n if (query.properties != null && Object.keys(query.properties).length > 0) {\n const filters: PropertyFilter[] = Object.entries(query.properties).map(\n ([key, value]) => ({ key, operator: 'eq', value }),\n );\n items = items.filter((entity) => matchesPropertyFilters(entity.properties, filters));\n }\n\n const total =\n countResult && countResult.documents.length > 0\n ? Number(countResult.documents[0])\n : undefined;\n\n const hasMore =\n total != null\n ? query.offset + items.length < total\n : items.length === query.limit;\n\n return {\n items,\n total,\n hasMore,\n limit: query.limit,\n offset: query.offset,\n };\n}\n","// Relationship CRUD Gremlin queries\n\nimport type { CosmosDbConnection } from '../CosmosDbConnection.js';\nimport type { StoredRelationship, RelationshipQueryOptions } from '@utaba/deep-memory/types';\nimport type { PaginatedResult } from '@utaba/deep-memory/types';\nimport {\n buildRelationshipPropertyLadder,\n relationshipFromGremlin,\n relationshipToLadderBindings,\n} from '../mapping.js';\nimport { DuplicateRelationshipError, matchesPropertyFilters, buildEdgeProjectChain } from '@utaba/deep-memory';\n\n// Sentinel returned by the duplicate-detection branch of the coalesce upsert\n// pattern. Mirrors entity.ts — single round-trip create.\nconst DUPLICATE_SENTINEL = '__duplicate';\n\n// Fixed-shape property ladder — identical query string across every edge\n// create regardless of which optional fields are populated, so the Cosmos\n// plan cache reuses one compiled plan.\nconst RELATIONSHIP_CREATE_QUERY =\n `g.E().has('repositoryId', rid).hasId(relId).fold().coalesce(` +\n `unfold().constant('${DUPLICATE_SENTINEL}'),` +\n `g.V().has('repositoryId', rid).hasId(srcId).has('entityType')` +\n `.addE(edgeLabel)` +\n `.to(g.V().has('repositoryId', rid).hasId(tgtId).has('entityType'))` +\n `.property('id', relId).property('repositoryId', rid)${buildRelationshipPropertyLadder()}` +\n `)`;\n\nexport async function createRelationship(\n conn: CosmosDbConnection,\n repositoryId: string,\n relationship: StoredRelationship,\n): Promise<StoredRelationship> {\n const bindings: Record<string, unknown> = {\n rid: repositoryId,\n relId: relationship.id,\n srcId: relationship.sourceEntityId,\n tgtId: relationship.targetEntityId,\n edgeLabel: relationship.relationshipType,\n ...relationshipToLadderBindings(relationship),\n };\n\n const result = await conn.submit(RELATIONSHIP_CREATE_QUERY, bindings);\n\n if (result.items[0] === DUPLICATE_SENTINEL) {\n throw new DuplicateRelationshipError(relationship.id);\n }\n\n return relationship;\n}\n\nexport async function getRelationship(\n conn: CosmosDbConnection,\n repositoryId: string,\n relationshipId: string,\n): Promise<StoredRelationship | null> {\n const projection = buildEdgeProjectChain();\n // Edge-id lookup: g.E().hasId(relId) is engine-routed by doc id; the\n // `has('repositoryId', rid)` predicate after it still doesn't push partition\n // routing down (issue #2 in plans/performance-issues.md). When the source\n // vertex id is known, callers should partition-route via the vertex instead.\n const result = await conn.submit(\n `g.E().hasId(relId).has('repositoryId', rid).${projection}`,\n { relId: relationshipId, rid: repositoryId },\n );\n if (result.items.length === 0) return null;\n return relationshipFromGremlin(result.items[0] as Record<string, unknown>);\n}\n\nexport async function getEntityRelationships(\n conn: CosmosDbConnection,\n repositoryId: string,\n entityId: string,\n options?: RelationshipQueryOptions,\n): Promise<PaginatedResult<StoredRelationship>> {\n const limit = options?.limit ?? 50;\n const offset = options?.offset ?? 0;\n const direction = options?.direction ?? 'both';\n const hasPropertyFilters =\n options?.propertyFilters != null && options.propertyFilters.length > 0;\n\n const baseBindings: Record<string, unknown> = {\n rid: repositoryId,\n eid: entityId,\n };\n\n // Build edge traversal based on direction\n let edgeTraversal: string;\n switch (direction) {\n case 'outbound':\n edgeTraversal = \"g.V().has('repositoryId', rid).hasId(eid).has('entityType').outE()\";\n break;\n case 'inbound':\n edgeTraversal = \"g.V().has('repositoryId', rid).hasId(eid).has('entityType').inE()\";\n break;\n case 'both':\n default:\n edgeTraversal = \"g.V().has('repositoryId', rid).hasId(eid).has('entityType').bothE()\";\n break;\n }\n\n // Filter by relationship types\n let typeFilter = '';\n if (options?.relationshipTypes && options.relationshipTypes.length > 0) {\n const typeParams: string[] = [];\n options.relationshipTypes.forEach((t, i) => {\n const paramName = `rtype${i}`;\n baseBindings[paramName] = t;\n typeParams.push(paramName);\n });\n typeFilter = `.hasLabel(${typeParams.join(', ')})`;\n }\n\n // For bidirectional support in outbound/inbound:\n // When direction is 'outbound', include inbound edges that are bidirectional\n // When direction is 'inbound', include outbound edges that are bidirectional\n // This requires a union approach.\n let unionQuery: string | null = null;\n if (direction === 'outbound') {\n // outE + inE where bidirectional=true\n unionQuery = `g.V().has('repositoryId', rid).hasId(eid).has('entityType').union(outE()${typeFilter}, inE()${typeFilter}.has('bidirectional', true))`;\n } else if (direction === 'inbound') {\n unionQuery = `g.V().has('repositoryId', rid).hasId(eid).has('entityType').union(inE()${typeFilter}, outE()${typeFilter}.has('bidirectional', true))`;\n }\n\n const baseQuery = unionQuery ?? `${edgeTraversal}${typeFilter}`;\n const projection = buildEdgeProjectChain();\n\n // Count and data round-trips are independent — run them in parallel to halve\n // wall-clock latency. When `propertyFilters` is set the filter runs\n // client-side after the fetch, so a server-side count would overstate the\n // matched total — match the findEntities pattern and surface\n // `total: undefined` in that case.\n const dataBindings = { ...baseBindings, rangeStart: offset, rangeEnd: offset + limit };\n const [countResult, dataResult] = await Promise.all([\n hasPropertyFilters\n ? Promise.resolve(null)\n : conn.submit(`${baseQuery}.dedup().count()`, baseBindings),\n conn.submit(\n `${baseQuery}.dedup().range(rangeStart, rangeEnd).${projection}`,\n dataBindings,\n ),\n ]);\n\n const rawItems = dataResult.items as Record<string, unknown>[];\n let items = rawItems.map(relationshipFromGremlin);\n\n if (hasPropertyFilters) {\n items = items.filter(rel => matchesPropertyFilters(rel.properties, options!.propertyFilters!));\n }\n\n const total = countResult ? Number(countResult.items[0] ?? 0) : undefined;\n const hasMore = total != null ? offset + rawItems.length < total : rawItems.length === limit;\n\n return {\n items,\n total,\n hasMore,\n limit,\n offset,\n };\n}\n\nexport async function deleteRelationship(\n conn: CosmosDbConnection,\n repositoryId: string,\n relationshipId: string,\n): Promise<void> {\n await conn.submit(\n \"g.E().hasId(relId).has('repositoryId', rid).drop()\",\n { relId: relationshipId, rid: repositoryId },\n );\n}\n\n\n/**\n * Single round-trip type-delete via the aggregate-side-effect pattern: the\n * bucket records the edge ids that were actually dropped, giving an exact\n * `deletedRelationships` count without a separate count query.\n */\nexport async function deleteRelationshipsByType(\n conn: CosmosDbConnection,\n repositoryId: string,\n relationshipType: string,\n): Promise<{ deletedRelationships: number }> {\n const result = await conn.submit(\n \"g.E().has('repositoryId', rid).hasLabel(rtype)\" +\n \".aggregate('found').by('id').drop().cap('found')\",\n { rid: repositoryId, rtype: relationshipType },\n );\n const bucket = result.items[0];\n const deletedRelationships = Array.isArray(bucket) ? bucket.length : 0;\n return { deletedRelationships };\n}\n","// Timeline Gremlin queries\n\nimport type { CosmosDbConnection } from '../CosmosDbConnection.js';\nimport type { StorageTimelineOptions } from '@utaba/deep-memory/types';\nimport type { StorageTimelineResult, StorageTimelineEvent } from '@utaba/deep-memory/types';\n\nexport async function getTimeline(\n conn: CosmosDbConnection,\n repositoryId: string,\n entityId: string,\n options: StorageTimelineOptions,\n): Promise<StorageTimelineResult> {\n const events: StorageTimelineEvent[] = [];\n\n // Entity creation event\n const entityResult = await conn.submit(\n \"g.V().has('repositoryId', rid).hasId(eid).has('entityType').valueMap('createdAt', 'modifiedAt')\",\n { rid: repositoryId, eid: entityId },\n );\n\n if (entityResult.items.length > 0) {\n const props = entityResult.items[0] as Record<string, unknown>;\n const createdAt = unwrapValue(props['createdAt']);\n const modifiedAt = unwrapValue(props['modifiedAt']);\n\n if (createdAt && isInTimeRange(createdAt, options.timeRange)) {\n events.push({\n timestamp: createdAt,\n eventType: 'entity_created',\n entityId,\n });\n }\n if (modifiedAt && modifiedAt !== createdAt && isInTimeRange(modifiedAt, options.timeRange)) {\n events.push({\n timestamp: modifiedAt,\n eventType: 'entity_modified',\n entityId,\n });\n }\n }\n\n // Relationship events connected to this entity\n const relResult = await conn.submit(\n \"g.V().has('repositoryId', rid).hasId(eid).has('entityType').bothE().valueMap('id', 'createdAt')\",\n { rid: repositoryId, eid: entityId },\n );\n\n for (const item of relResult.items) {\n const props = item as Record<string, unknown>;\n const relId = unwrapValue(props['id']);\n const relCreatedAt = unwrapValue(props['createdAt']);\n\n if (relCreatedAt && isInTimeRange(relCreatedAt, options.timeRange)) {\n events.push({\n timestamp: relCreatedAt,\n eventType: 'relationship_created',\n entityId,\n relationshipId: relId,\n });\n }\n }\n\n // Sort by timestamp descending\n events.sort((a, b) => b.timestamp.localeCompare(a.timestamp));\n\n // Filter by event types\n let filtered = events;\n if (options.eventTypes && options.eventTypes.length > 0) {\n filtered = events.filter(e => options.eventTypes!.includes(e.eventType));\n }\n\n const total = filtered.length;\n const paged = filtered.slice(options.offset, options.offset + options.limit);\n\n return { events: paged, total };\n}\n\nfunction unwrapValue(val: unknown): string {\n if (Array.isArray(val) && val.length > 0) return String(val[0]);\n return String(val ?? '');\n}\n\nfunction isInTimeRange(\n timestamp: string,\n timeRange?: { from: string; to: string },\n): boolean {\n if (!timeRange) return true;\n return timestamp >= timeRange.from && timestamp <= timeRange.to;\n}\n","// Adaptive concurrency runner for bulk imports.\n//\n// CosmosDB throttles writes (HTTP 429) when the autoscale tier cannot keep up\n// with the offered load. The CosmosDbConnection retries 429s internally, but a\n// burst of N parallel writes that all get throttled creates a retry storm that\n// piles back onto an already-saturated partition. To avoid this we drive bulk\n// imports through a closed-loop controller:\n//\n// • Start at a conservative concurrency.\n// • Each task runs inside its own usageScope sub-accumulator. Any non-zero\n// retry count for that task means a 429 (or 503) was observed — the\n// connection only retries on transient throttle/unavailable errors.\n// • On any throttle: halve concurrency, reset the success streak, set a\n// short cooldown before any new task is dispatched. This gives autoscale\n// time to ramp.\n// • After `increaseAfter` consecutive throttle-free completions: bump\n// concurrency by 1, up to `max`.\n// • Track the highest concurrency at which a throttle was observed as a\n// \"soft ceiling\". Re-approaching this level requires\n// `increaseAfter * throttleCeilingMultiplier` consecutive successes\n// instead of just `increaseAfter`, so a throttle-prone level is not\n// hammered repeatedly.\n//\n// Sub-accumulator counts roll up into the parent usageScope on completion, so\n// the outer track() telemetry continues to report correct aggregate RU/calls/\n// retries for the operation as a whole.\n//\n// The controller is exposed for unit testing; runAdaptive is the production\n// entry point used by importBulk.\n\nimport type {\n AdaptiveConcurrencyAdjustEvent,\n AdaptiveConcurrencyAdjustReason,\n AdaptiveConcurrencyHandle,\n AdaptiveConcurrencyOptions,\n} from '@utaba/deep-memory/types';\nimport { ImportThrottleAbortError } from '@utaba/deep-memory';\nimport { usageScope, type UsageAccumulator } from '../usage.js';\n\nconst DEFAULT_MIN = 1;\nconst DEFAULT_START = 5;\nconst DEFAULT_MAX = 32;\nconst DEFAULT_INCREASE_AFTER = 50;\nconst DEFAULT_COOLDOWN_MS = 1000;\nconst DEFAULT_RAMP_UP_COOLDOWN_MS = 5000;\nconst DEFAULT_MAX_CONSECUTIVE_THROTTLES_AT_MIN = 10;\nconst DEFAULT_THROTTLE_CEILING_MULTIPLIER = 3;\n// Sentinel value meaning \"no soft ceiling currently in effect\". Any concrete\n// concurrency target below this is unconstrained; the controller only treats a\n// finite softCeiling as a constraint.\nconst NO_SOFT_CEILING = Number.POSITIVE_INFINITY;\n\ninterface ResolvedAdaptiveOptions {\n min: number;\n start: number;\n max: number;\n increaseAfter: number;\n cooldownMs: number;\n rampUpCooldownMs: number;\n maxConsecutiveThrottlesAtMin: number;\n throttleCeilingMultiplier: number;\n onAdjust: ((event: AdaptiveConcurrencyAdjustEvent) => void) | undefined;\n}\n\nfunction resolveOptions(opts: AdaptiveConcurrencyOptions | undefined): ResolvedAdaptiveOptions {\n const min = Math.max(1, opts?.min ?? DEFAULT_MIN);\n const max = Math.max(min, opts?.max ?? DEFAULT_MAX);\n const start = Math.min(max, Math.max(min, opts?.start ?? DEFAULT_START));\n const increaseAfter = Math.max(1, opts?.increaseAfter ?? DEFAULT_INCREASE_AFTER);\n const cooldownMs = Math.max(0, opts?.cooldownMs ?? DEFAULT_COOLDOWN_MS);\n const rampUpCooldownMs = Math.max(0, opts?.rampUpCooldownMs ?? DEFAULT_RAMP_UP_COOLDOWN_MS);\n const maxConsecutiveThrottlesAtMin = Math.max(\n 1,\n opts?.maxConsecutiveThrottlesAtMin ?? DEFAULT_MAX_CONSECUTIVE_THROTTLES_AT_MIN,\n );\n const throttleCeilingMultiplier = Math.max(\n 1,\n opts?.throttleCeilingMultiplier ?? DEFAULT_THROTTLE_CEILING_MULTIPLIER,\n );\n return {\n min,\n start,\n max,\n increaseAfter,\n cooldownMs,\n rampUpCooldownMs,\n maxConsecutiveThrottlesAtMin,\n throttleCeilingMultiplier,\n onAdjust: opts?.onAdjust,\n };\n}\n\n/**\n * Internal shape of an {@link AdaptiveConcurrencyHandle} as written to by this\n * package. The handle is declared as opaque in the public API so other storage\n * providers can attach their own state without colliding.\n */\ninterface CosmosAdaptiveHandle extends AdaptiveConcurrencyHandle {\n controller?: AdaptiveConcurrencyController;\n}\n\n/**\n * Resolve a controller from an optional caller-supplied handle, creating one\n * on first use and reusing it on subsequent calls. This is how the controller\n * persists across multiple importBulk calls within a single import operation:\n * RepositoryImporter creates a fresh handle per import and threads it through,\n * so the controller's learned concurrency level, success streak, cooldown,\n * and soft ceiling all carry across chunks instead of resetting at each call.\n *\n * If no handle is supplied, a fresh controller is returned (single-shot use).\n */\nexport function resolveController(\n options: AdaptiveConcurrencyOptions | undefined,\n handle: AdaptiveConcurrencyHandle | undefined,\n): AdaptiveConcurrencyController {\n if (!handle) {\n return new AdaptiveConcurrencyController(options);\n }\n const cosmosHandle = handle as CosmosAdaptiveHandle;\n if (!cosmosHandle.controller) {\n cosmosHandle.controller = new AdaptiveConcurrencyController(options);\n }\n return cosmosHandle.controller;\n}\n\n/**\n * Closed-loop concurrency controller. Stateless about tasks themselves —\n * callers feed it `noteSuccess()` and `noteThrottle()` after each task and\n * read `getConcurrency()` to decide how many tasks may be in flight.\n */\nexport class AdaptiveConcurrencyController {\n private readonly opts: ResolvedAdaptiveOptions;\n private current: number;\n private streak = 0;\n private cooldownUntil = 0;\n private rampFrozenUntil = 0;\n private completed = 0;\n private throttled = 0;\n private startEmitted = false;\n private consecutiveThrottlesAtMin = 0;\n /**\n * Highest concurrency at which a throttle has been observed and the\n * controller actually halved (i.e. concrete evidence the cluster could not\n * sustain that level). Re-approaching this level on subsequent ramp-ups\n * requires `increaseAfter * throttleCeilingMultiplier` consecutive successes\n * instead of just `increaseAfter`. Cleared once we've successfully held the\n * level without further throttling — see noteSuccess.\n */\n private softCeiling: number = NO_SOFT_CEILING;\n\n constructor(opts?: AdaptiveConcurrencyOptions) {\n this.opts = resolveOptions(opts);\n this.current = this.opts.start;\n }\n\n /** Current target concurrency. */\n getConcurrency(): number {\n return this.current;\n }\n\n /** Configured ceiling — used by the runner to size its worker pool. */\n getMaxConcurrency(): number {\n return this.opts.max;\n }\n\n /** Total tasks that have been noted as completed (success or throttle). */\n getCompleted(): number {\n return this.completed;\n }\n\n /** Total tasks that observed at least one throttle. */\n getThrottledCount(): number {\n return this.throttled;\n }\n\n /**\n * Earliest time (ms since epoch) at which a new task may be dispatched. Zero\n * if there is no active cooldown.\n */\n getCooldownUntil(): number {\n return this.cooldownUntil;\n }\n\n /**\n * Emit the initial `start` event the first time the controller is queried\n * for adjustment events. Kept separate so construction has no side effects.\n */\n emitStartIfNeeded(): void {\n if (this.startEmitted) return;\n this.startEmitted = true;\n this.notify('start', this.current);\n }\n\n /** Record a throttle-free task completion. May trigger ramp-up. */\n noteSuccess(now: number = Date.now()): void {\n this.completed++;\n this.consecutiveThrottlesAtMin = 0;\n if (now < this.rampFrozenUntil) return;\n this.streak++;\n if (this.current >= this.opts.max) return;\n const target = this.current + 1;\n // Re-approaching a previously-throttled level requires more sustained\n // success — multiplier × increaseAfter — so the controller does not\n // hammer a level the cluster has already proven it cannot sustain.\n const needed =\n target >= this.softCeiling\n ? this.opts.increaseAfter * this.opts.throttleCeilingMultiplier\n : this.opts.increaseAfter;\n if (this.streak >= needed) {\n const previous = this.current;\n this.current = Math.min(this.opts.max, target);\n this.streak = 0;\n // We've cautiously re-attained (or exceeded) the soft ceiling without\n // further throttling. Drop the constraint — subsequent ramp-ups beyond\n // this level use the normal increaseAfter. A future throttle will\n // re-establish a new ceiling.\n if (this.current >= this.softCeiling) {\n this.softCeiling = NO_SOFT_CEILING;\n }\n this.notify('ramp-up', previous);\n }\n }\n\n /** Record a task that observed at least one throttle. Halves concurrency. */\n noteThrottle(now: number = Date.now()): void {\n this.completed++;\n this.throttled++;\n this.streak = 0;\n const previous = this.current;\n const next = Math.max(this.opts.min, Math.floor(this.current / 2));\n this.cooldownUntil = now + this.opts.cooldownMs;\n this.rampFrozenUntil = now + this.opts.rampUpCooldownMs;\n if (next !== previous) {\n this.current = next;\n // Record this level as a soft ceiling. Only update on actual halving so\n // that subsequent throttles in the same burst (which arrive at lower\n // current values because we already halved) do not falsely lower the\n // ceiling.\n this.softCeiling = previous;\n this.notify('throttle', previous);\n }\n // Track throttles that occur while the controller is already at floor.\n // Mid-ramp-down throttles do not contribute — the controller is still\n // adapting and may yet reach a sustainable level. The streak increments\n // only when the post-throttle concurrency equals min (i.e. we are stuck\n // at the floor and the cluster still cannot accept the load).\n if (this.current === this.opts.min) {\n this.consecutiveThrottlesAtMin++;\n } else {\n this.consecutiveThrottlesAtMin = 0;\n }\n }\n\n /**\n * Current soft ceiling — the highest concurrency at which a throttle was\n * observed and the controller halved. {@link Number.POSITIVE_INFINITY} when\n * no ceiling is in effect. Re-approaching this level requires\n * `increaseAfter * throttleCeilingMultiplier` consecutive successes.\n */\n getSoftCeiling(): number {\n return this.softCeiling;\n }\n\n /** Configured circuit-breaker threshold. */\n getMaxConsecutiveThrottlesAtMin(): number {\n return this.opts.maxConsecutiveThrottlesAtMin;\n }\n\n /** How many consecutive throttles have occurred at min. */\n getConsecutiveThrottlesAtMin(): number {\n return this.consecutiveThrottlesAtMin;\n }\n\n /**\n * Whether the circuit breaker has tripped — runner should stop dispatching\n * new tasks and surface an `ImportThrottleAbortError` to the caller.\n */\n shouldAbort(): boolean {\n return this.consecutiveThrottlesAtMin >= this.opts.maxConsecutiveThrottlesAtMin;\n }\n\n private notify(reason: AdaptiveConcurrencyAdjustReason, previous: number): void {\n const cb = this.opts.onAdjust;\n if (!cb) return;\n try {\n cb({\n concurrency: this.current,\n previousConcurrency: previous,\n reason,\n tasksCompleted: this.completed,\n throttledCount: this.throttled,\n });\n } catch {\n // Operator callback errors are swallowed by design.\n }\n }\n}\n\n/**\n * Run a task inside a nested usageScope so its retries/RU/calls can be\n * inspected independently of any outer scope. Roll the inner counters up into\n * the parent (if any) on completion so outer telemetry remains correct.\n *\n * Returns the task result and the number of retries observed inside the task.\n * A non-zero retry count means the connection layer observed a 429/503 for\n * one of this task's submits, which the adaptive controller treats as a\n * throttle signal — even if the retry ultimately succeeded.\n */\nasync function runTaskWithUsage<R>(fn: () => Promise<R>): Promise<{ result: R; retries: number }> {\n const parent = usageScope.getStore();\n const taskAcc: UsageAccumulator = { ru: 0, calls: 0, retries: 0 };\n try {\n const result = await usageScope.run(taskAcc, fn);\n return { result, retries: taskAcc.retries };\n } finally {\n if (parent) {\n parent.ru += taskAcc.ru;\n parent.calls += taskAcc.calls;\n parent.retries += taskAcc.retries;\n }\n }\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms));\n}\n\n/**\n * Adaptive runner — processes `items` with dynamic concurrency, returning\n * results in input order. Mirrors the contract of the previous fixed-size\n * runWithConcurrency so callers swap one for the other.\n *\n * The runner respects the controller's cooldown: when a throttle has just\n * been observed, no new task is dispatched until the cooldown elapses, even\n * if a worker slot is otherwise free. In-flight tasks are unaffected.\n *\n * Throws {@link ImportThrottleAbortError} if the controller's circuit breaker\n * trips (sustained throttling at minimum concurrency). In-flight tasks are\n * awaited before the throw so observers see consistent state, but no new\n * tasks are dispatched once the breaker has tripped.\n */\nexport async function runAdaptive<T, R>(\n items: T[],\n controller: AdaptiveConcurrencyController,\n fn: (item: T) => Promise<R>,\n): Promise<R[]> {\n if (items.length === 0) return [];\n controller.emitStartIfNeeded();\n\n const results: R[] = new Array(items.length);\n let nextIndex = 0;\n let inFlight = 0;\n let aborted = false;\n\n // Workers wait on `gate` when they cannot dispatch (cooldown active, all\n // slots taken, or the breaker has tripped and we are draining). Any state\n // change re-issues the gate so all waiters wake up and re-check.\n let gate = createGate();\n\n function pokeGate(): void {\n const old = gate;\n gate = createGate();\n old.resolve();\n }\n\n async function worker(): Promise<void> {\n while (nextIndex < items.length) {\n if (aborted) return;\n // Wait until both: a slot is free AND any active cooldown has elapsed.\n while (true) {\n if (aborted || nextIndex >= items.length) return;\n const cooldownRemaining = controller.getCooldownUntil() - Date.now();\n const slotsAvailable = inFlight < controller.getConcurrency();\n if (cooldownRemaining <= 0 && slotsAvailable) break;\n if (cooldownRemaining > 0) {\n await Promise.race([sleep(cooldownRemaining), gate.promise]);\n } else {\n await gate.promise;\n }\n }\n if (aborted || nextIndex >= items.length) return;\n\n const idx = nextIndex++;\n inFlight++;\n try {\n const { result, retries } = await runTaskWithUsage(() => fn(items[idx]!));\n results[idx] = result;\n if (retries > 0) {\n controller.noteThrottle();\n } else {\n controller.noteSuccess();\n }\n if (controller.shouldAbort()) {\n aborted = true;\n }\n } finally {\n inFlight--;\n pokeGate();\n }\n }\n }\n\n // Provision workers up to the configured ceiling so the controller has\n // headroom to ramp up. Idle workers cost nothing — they just await the\n // gate. We never spawn more workers than items.\n const workerCount = Math.min(items.length, controller.getMaxConcurrency());\n const workers: Promise<void>[] = [];\n for (let w = 0; w < workerCount; w++) {\n workers.push(worker());\n }\n\n await Promise.all(workers);\n\n if (aborted) {\n throw new ImportThrottleAbortError(\n controller.getConcurrency(),\n controller.getConsecutiveThrottlesAtMin(),\n controller.getCompleted(),\n controller.getThrottledCount(),\n );\n }\n\n return results;\n}\n\nfunction createGate(): { promise: Promise<void>; resolve: () => void } {\n let resolve!: () => void;\n const promise = new Promise<void>(r => {\n resolve = r;\n });\n return { promise, resolve };\n}\n","// Bulk export/import Gremlin queries — optimized for throughput\n//\n// Import optimizations:\n// 1. Parallel execution with concurrency limiter (avoids sequential round-trips)\n// 2. Direct addV/addE when skipExistenceCheck is true (no existence query needed)\n// 3. Gremlin coalesce pattern for atomic upserts when existence checks are needed\n// (1 query instead of 2)\n//\n// Export optimizations:\n// 1. Cursor-based pagination using ID ordering instead of offset-based range()\n// (avoids O(n²) scan on large repositories)\n//\n// `valueMap(true)` exception: this is the one read path that intentionally\n// keeps it. Export must include every stored property — including the\n// embedding — so a re-import is field-for-field faithful. Do not migrate to\n// the project-chain helpers used elsewhere; they strip fields the import path\n// expects.\n\nimport type { CosmosDbConnection } from '../CosmosDbConnection.js';\nimport type { ExportChunk, ImportChunk, BulkImportOptions } from '@utaba/deep-memory/types';\nimport type { BulkImportResult, StoredEntity, StoredRelationship } from '@utaba/deep-memory/types';\nimport {\n buildEntityPropertyLadder,\n buildRelationshipPropertyLadder,\n entityFromGremlin,\n entityToLadderBindings,\n relationshipFromGremlin,\n relationshipToLadderBindings,\n} from '../mapping.js';\nimport { resolveController, runAdaptive } from './adaptive-import.js';\n\nconst EXPORT_BATCH_SIZE = 100;\n\n// ─── Export ──────────────────────────────────────────────────────\n\nexport async function* exportAll(\n conn: CosmosDbConnection,\n repositoryId: string,\n): AsyncIterable<ExportChunk> {\n let sequence = 0;\n\n // Export entities using cursor-based pagination (ordered by id)\n let cursor = '';\n while (true) {\n const result = cursor === ''\n ? await conn.submit(\n \"g.V().has('repositoryId', rid).has('entityType').order().by('id').limit(batchSize).valueMap(true)\",\n { rid: repositoryId, batchSize: EXPORT_BATCH_SIZE },\n )\n : await conn.submit(\n \"g.V().has('repositoryId', rid).has('entityType').has('id', gt(cursor)).order().by('id').limit(batchSize).valueMap(true)\",\n { rid: repositoryId, cursor, batchSize: EXPORT_BATCH_SIZE },\n );\n\n const entities = (result.items as Record<string, unknown>[]).map(entityFromGremlin);\n const isLast = entities.length < EXPORT_BATCH_SIZE;\n\n if (entities.length > 0) {\n cursor = entities[entities.length - 1]!.id;\n yield {\n type: 'entities',\n data: entities,\n sequence: sequence++,\n isLast,\n };\n }\n\n if (isLast) break;\n }\n\n // Export relationships using cursor-based pagination (ordered by id)\n cursor = '';\n while (true) {\n const result = cursor === ''\n ? await conn.submit(\n \"g.E().has('repositoryId', rid).order().by('id').limit(batchSize).valueMap(true)\",\n { rid: repositoryId, batchSize: EXPORT_BATCH_SIZE },\n )\n : await conn.submit(\n \"g.E().has('repositoryId', rid).has('id', gt(cursor)).order().by('id').limit(batchSize).valueMap(true)\",\n { rid: repositoryId, cursor, batchSize: EXPORT_BATCH_SIZE },\n );\n\n const relationships = (result.items as Record<string, unknown>[]).map(relationshipFromGremlin);\n const isLast = relationships.length < EXPORT_BATCH_SIZE;\n\n if (relationships.length > 0) {\n cursor = relationships[relationships.length - 1]!.id;\n yield {\n type: 'relationships',\n data: relationships,\n sequence: sequence++,\n isLast,\n };\n }\n\n if (isLast) break;\n }\n\n // If nothing was yielded, yield an empty final chunk\n if (sequence === 0) {\n yield {\n type: 'entities',\n data: [],\n sequence: 0,\n isLast: true,\n };\n }\n}\n\n// ─── Import ─────────────────────────────────────────────────────\n\nexport async function importBulk(\n conn: CosmosDbConnection,\n repositoryId: string,\n data: ImportChunk[],\n options?: BulkImportOptions,\n): Promise<BulkImportResult> {\n let entitiesImported = 0;\n let relationshipsImported = 0;\n const errors: Array<{ item: string; error: string }> = [];\n const skipCheck = options?.skipExistenceCheck ?? false;\n\n // Resolve the controller from the caller-supplied handle if any, so the\n // controller's learned state (concurrency level, success streak, cooldown,\n // soft ceiling) carries across multiple importBulk calls within a single\n // import operation. Without a handle, each importBulk call gets a fresh\n // controller — fine for single-shot usage but wrong for streaming imports\n // that issue one importBulk call per chunk. RepositoryImporter creates a\n // handle per import and threads it through automatically.\n const controller = resolveController(options?.adaptiveConcurrency, options?.adaptiveConcurrencyHandle);\n\n for (const chunk of data) {\n if (chunk.entities && chunk.entities.length > 0) {\n const results = await runAdaptive(\n chunk.entities,\n controller,\n async (entity): Promise<{ ok: boolean; id: string; error?: string }> => {\n try {\n if (skipCheck) {\n await insertEntity(conn, repositoryId, entity);\n } else {\n await upsertEntity(conn, repositoryId, entity);\n }\n return { ok: true, id: entity.id };\n } catch (err: unknown) {\n return {\n ok: false,\n id: entity.id,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n },\n );\n\n for (const r of results) {\n if (r.ok) {\n entitiesImported++;\n } else {\n errors.push({ item: `entity:${r.id}`, error: r.error! });\n }\n }\n }\n\n if (chunk.relationships && chunk.relationships.length > 0) {\n const results = await runAdaptive(\n chunk.relationships,\n controller,\n async (rel): Promise<{ ok: boolean; id: string; error?: string }> => {\n try {\n if (skipCheck) {\n await insertRelationship(conn, repositoryId, rel);\n } else {\n await upsertRelationship(conn, repositoryId, rel);\n }\n return { ok: true, id: rel.id };\n } catch (err: unknown) {\n return {\n ok: false,\n id: rel.id,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n },\n );\n\n for (const r of results) {\n if (r.ok) {\n relationshipsImported++;\n } else {\n errors.push({ item: `relationship:${r.id}`, error: r.error! });\n }\n }\n }\n }\n\n return { entitiesImported, relationshipsImported, errors };\n}\n\n// ─── Fixed-shape query templates ─────────────────────────────────\n//\n// Same Gremlin string across every entity/relationship write regardless of\n// which optional fields are populated, so the Cosmos plan cache reuses one\n// compiled plan. Computed once at module load. The upsert update branch\n// reuses the SAME ladder as the create branch — Cosmos already rejects\n// `.property('repositoryId', ...)` after `unfold()`, and the ladder excludes\n// `id` and `repositoryId` (both written explicitly only on the create branch).\n\nconst ENTITY_LADDER_CHAIN = buildEntityPropertyLadder();\nconst RELATIONSHIP_LADDER_CHAIN = buildRelationshipPropertyLadder();\n\nconst INSERT_ENTITY_QUERY =\n `g.addV(vertexLabel).property('id', vid).property('repositoryId', rid)${ENTITY_LADDER_CHAIN}`;\n\nconst INSERT_RELATIONSHIP_QUERY =\n `g.V().has('repositoryId', rid).hasId(srcId).has('entityType')` +\n `.addE(edgeLabel)` +\n `.to(g.V().has('repositoryId', rid).hasId(tgtId).has('entityType'))` +\n `.property('id', relId).property('repositoryId', rid)${RELATIONSHIP_LADDER_CHAIN}`;\n\nconst UPSERT_ENTITY_QUERY =\n `g.V().has('repositoryId', rid).hasId(vid).has('entityType').fold().coalesce(` +\n `unfold()${ENTITY_LADDER_CHAIN},` +\n ` addV(vertexLabel).property('id', vid).property('repositoryId', rid)${ENTITY_LADDER_CHAIN})`;\n\nconst UPSERT_RELATIONSHIP_QUERY =\n `g.E().has('repositoryId', rid).hasId(relId).fold().coalesce(` +\n `unfold()${RELATIONSHIP_LADDER_CHAIN},` +\n ` g.V().has('repositoryId', rid).hasId(srcId).has('entityType').addE(edgeLabel)` +\n `.to(g.V().has('repositoryId', rid).hasId(tgtId).has('entityType'))` +\n `.property('id', relId).property('repositoryId', rid)${RELATIONSHIP_LADDER_CHAIN})`;\n\n// ─── Direct insert (no existence check) ─────────────────────────\n\n/** Insert an entity directly — assumes it does not exist. */\nasync function insertEntity(\n conn: CosmosDbConnection,\n repositoryId: string,\n entity: StoredEntity,\n): Promise<void> {\n const bindings: Record<string, unknown> = {\n rid: repositoryId,\n vid: entity.id,\n vertexLabel: entity.entityType,\n ...entityToLadderBindings(entity),\n };\n await conn.submit(INSERT_ENTITY_QUERY, bindings);\n}\n\n/** Insert a relationship directly — assumes it does not exist. */\nasync function insertRelationship(\n conn: CosmosDbConnection,\n repositoryId: string,\n rel: StoredRelationship,\n): Promise<void> {\n const bindings: Record<string, unknown> = {\n rid: repositoryId,\n relId: rel.id,\n srcId: rel.sourceEntityId,\n tgtId: rel.targetEntityId,\n edgeLabel: rel.relationshipType,\n ...relationshipToLadderBindings(rel),\n };\n await conn.submit(INSERT_RELATIONSHIP_QUERY, bindings);\n}\n\n// ─── Atomic upsert (single query with coalesce) ─────────────────\n\n/**\n * Upsert an entity using Gremlin's coalesce pattern — single query.\n * Replaces the old 2-query check-then-create/update approach.\n *\n * Both branches share the same fixed-shape entity ladder (which omits `id`\n * and `repositoryId`). The create branch prepends `.property('id',\n * vid).property('repositoryId', rid)` to addV; the update branch (after\n * `unfold`) relies on those system properties already being set. Cosmos\n * rejects `.property('repositoryId', ...)` after `unfold()` at parse time,\n * so excluding `repositoryId` from the ladder is required for correctness\n * as well as plan-cache shape.\n */\nasync function upsertEntity(\n conn: CosmosDbConnection,\n repositoryId: string,\n entity: StoredEntity,\n): Promise<void> {\n const bindings: Record<string, unknown> = {\n rid: repositoryId,\n vid: entity.id,\n vertexLabel: entity.entityType,\n ...entityToLadderBindings(entity),\n };\n await conn.submit(UPSERT_ENTITY_QUERY, bindings);\n}\n\n/**\n * Upsert a relationship using Gremlin's coalesce pattern — single query.\n * Replaces the old 2-query check-then-create/update approach.\n *\n * The E() lookup is scoped by repositoryId so an edge with the same id in a\n * different repo cannot be matched and silently overwritten.\n */\nasync function upsertRelationship(\n conn: CosmosDbConnection,\n repositoryId: string,\n rel: StoredRelationship,\n): Promise<void> {\n const bindings: Record<string, unknown> = {\n rid: repositoryId,\n relId: rel.id,\n srcId: rel.sourceEntityId,\n tgtId: rel.targetEntityId,\n edgeLabel: rel.relationshipType,\n ...relationshipToLadderBindings(rel),\n };\n await conn.submit(UPSERT_RELATIONSHIP_QUERY, bindings);\n}\n"],"mappings":"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","names":["matchesPropertyFilters","acc","sleep","matchesPropertyFilters","DUPLICATE_SENTINEL","sleep","matchesPropertyFilters"]}
|
|
1
|
+
{"version":3,"sources":["../src/CosmosDbProvider.ts","../src/CosmosDbConnection.ts","../src/usage.ts","../src/cosmos-rest-auth.ts","../src/CosmosDocumentClient.ts","../src/mapping.ts","../src/queries/repository.ts","../src/queries/vocabulary.ts","../src/queries/entity.ts","../src/queries/relationship.ts","../src/queries/timeline.ts","../src/queries/adaptive-import.ts","../src/queries/bulk.ts"],"sourcesContent":["// CosmosDbProvider — CosmosDB Gremlin implementation of StorageProvider + GraphTraversalProvider\n\nimport type { StorageProvider, EnsureSchemaResult, EntityReadOptions } from '@utaba/deep-memory/providers';\nimport type { GraphTraversalProvider, GraphTraversalCapabilities } from '@utaba/deep-memory/providers';\nimport type {\n StoredEntity,\n StoredEntityUpdate,\n StoredRelationship,\n RelationshipQueryOptions,\n MemoryVocabulary,\n VocabularyChangeRecord,\n StorageRepositoryConfig,\n StoredRepository,\n StoredRepositorySummary,\n RepositoryFilter,\n RepositoryStats,\n RepositoryUpdate,\n StorageFindQuery,\n StorageExploreOptions,\n StoragePathOptions,\n StorageTimelineOptions,\n PaginationOptions,\n PaginatedResult,\n StorageNeighborhood,\n StorageNeighborhoodLayer,\n StoragePath,\n StoragePathResult,\n StorageTimelineResult,\n BulkImportResult,\n TraversalSpec,\n TraversalStep,\n TraversalResult,\n QueryMetadata,\n UsageSink,\n} from '@utaba/deep-memory/types';\nimport type { ExportChunk, ImportChunk, BulkImportOptions, DeleteProgressCallback } from '@utaba/deep-memory/types';\nimport {\n GremlinCompiler,\n ProviderError,\n InvalidInputError,\n isValidUuid,\n projectEntity,\n createSafeSink,\n matchesPropertyFilters,\n} from '@utaba/deep-memory';\nimport { CosmosDbConnection } from './CosmosDbConnection.js';\nimport { CosmosDocumentClient } from './CosmosDocumentClient.js';\nimport { usageScope } from './usage.js';\nimport type { UsageAccumulator } from './usage.js';\nimport { cosmosRestPut } from './cosmos-rest-auth.js';\nimport { entityFromGremlin, relationshipFromGremlin } from './mapping.js';\nimport * as repoQueries from './queries/repository.js';\nimport * as vocabQueries from './queries/vocabulary.js';\nimport * as entityQueries from './queries/entity.js';\nimport * as relQueries from './queries/relationship.js';\nimport * as timelineQueries from './queries/timeline.js';\nimport * as bulkQueries from './queries/bulk.js';\n\n/** Configuration for CosmosDbProvider. */\nexport interface CosmosDbProviderConfig {\n /** Gremlin WebSocket endpoint (e.g. ws://host.docker.internal:8901/) */\n endpoint: string;\n /** CosmosDB REST endpoint for database/container provisioning (e.g. https://host.docker.internal:8081/) — derived from Gremlin endpoint if omitted */\n restEndpoint?: string;\n /** CosmosDB primary key */\n key: string;\n /** Database name */\n database: string;\n /** Container (graph) name */\n container: string;\n /** Partition key path (default: /repositoryId) */\n partitionKey?: string;\n /** Max retries for transient errors (default: 3) */\n maxRetries?: number;\n /** Default query timeout in ms (default: 30000) */\n defaultTimeoutMs?: number;\n /** Whether to reject unauthorized TLS certs — set false for emulator (default: true) */\n rejectUnauthorized?: boolean;\n /**\n * Optional usage sink. When provided, the provider emits one\n * {@link OperationUsage} record per public method call with the aggregated\n * CosmosDB request charge (RU). Never exposed to AI agents — the MCP server\n * deliberately does not plumb this sink through.\n */\n reportUsage?: UsageSink;\n}\n\nconst PROVIDER_NAME = 'cosmosdb';\nconst SCHEMA_VERSION = 1;\nconst META_VERTEX_ID = '_meta:schema';\n\n/**\n * Indexing-policy paths that `findEntities` SQL relies on. If a container's\n * `excludedPaths` covers any of these (directly or via wildcard), the rewrite\n * falls back to scan — see {@link CosmosDbProvider.runIndexingPolicyDiagnostic}.\n */\nconst GUARDED_INDEX_PATHS = [\n '/entityLabel',\n '/slug',\n '/summary',\n '/entityType',\n '/properties',\n '/repositoryId',\n] as const;\n\n/**\n * Raw, un-projected output from {@link CosmosDbProvider.executeTraversal}.\n * Only the fields relevant to the spec's `returnMode` are populated; the rest\n * remain empty. Used to share the compile + submit + parse pipeline between\n * `traverseInternal` (which projects into the public TraversalResult shape)\n * and the storage-layer rewrites of `exploreNeighborhood` / `findPaths`\n * (which need raw stored entities to rebuild storage-level outputs).\n */\ninterface RawTraversalResult {\n /** Populated when `spec.returnMode === 'terminal'`. */\n terminalEntities: StoredEntity[];\n /** Populated when `spec.returnMode === 'all'`. */\n allEntities: StoredEntity[];\n /** Populated when `spec.returnMode === 'all'`. */\n allRelationships: StoredRelationship[];\n /** Populated when `spec.returnMode === 'path'`. */\n pathRows: Array<{\n entityIds: string[];\n relationshipIds: string[];\n relationshipDirections: Array<'out' | 'in'>;\n }>;\n /**\n * Lookup table — populated for `'all'` and `'path'` modes. Includes every\n * entity that appears in any returned row.\n */\n entityMap: Map<string, StoredEntity>;\n /**\n * Lookup table — populated for `'all'` and `'path'` modes. Includes every\n * relationship that appears in any returned row.\n */\n relationshipMap: Map<string, StoredRelationship>;\n /**\n * First-seen walk direction per deduped edge id. Populated only for\n * `'path'` mode — the `'all'` mode's deduped union carries no walk context.\n */\n pathRelFirstDirection: Map<string, 'out' | 'in'>;\n executionTimeMs: number;\n requestCharge: number | undefined;\n compiledQuery: string;\n}\n\n/**\n * Vocabulary TTL for the per-process cache. Vocabulary changes are rare\n * (governance-gated writes); a 60 s window bounds cross-process staleness\n * acceptably while eliminating the one extra round-trip on every traversal.\n */\nconst VOCABULARY_CACHE_TTL_MS = 60_000;\n\n/**\n * CosmosDB Gremlin storage provider for deep-memory.\n * Implements both StorageProvider (full CRUD) and GraphTraversalProvider (native Gremlin traversals).\n */\nexport class CosmosDbProvider implements StorageProvider, GraphTraversalProvider {\n private readonly conn: CosmosDbConnection;\n private readonly docClient: CosmosDocumentClient;\n private readonly config: CosmosDbProviderConfig;\n private readonly compiler = new GremlinCompiler();\n private readonly reportUsage: UsageSink | undefined;\n /**\n * Per-process vocabulary cache, keyed by repositoryId. Read lazily by\n * `traverseImpl` via `getVocabularyCached`; invalidated on `saveVocabulary`.\n * Each provider instance owns its own cache so isolated test providers do\n * not share state.\n */\n private readonly vocabularyCache = new Map<string, { vocab: MemoryVocabulary; expiresAt: number }>();\n\n constructor(config: CosmosDbProviderConfig) {\n this.config = config;\n this.reportUsage = createSafeSink(config.reportUsage);\n this.conn = new CosmosDbConnection({\n endpoint: config.endpoint,\n key: config.key,\n database: config.database,\n container: config.container,\n maxRetries: config.maxRetries,\n defaultTimeoutMs: config.defaultTimeoutMs,\n rejectUnauthorized: config.rejectUnauthorized,\n });\n // Document (NoSQL SQL) endpoint client — used by query paths the Gremlin\n // subset can't express server-side (substring + case-insensitive search,\n // structured property predicates). RU accumulates into the same\n // usageScope as `conn`, so one public-method call emits one usage record\n // even when both endpoints are touched.\n this.docClient = new CosmosDocumentClient({\n restEndpoint: this.getRestEndpoint(),\n key: config.key,\n database: config.database,\n container: config.container,\n rejectUnauthorized: config.rejectUnauthorized ?? true,\n maxRetries: config.maxRetries,\n defaultTimeoutMs: config.defaultTimeoutMs,\n });\n }\n\n /**\n * Run the given operation inside an async-local usage scope. While the\n * operation runs, every `conn.submit()` call accumulates its request charge\n * into a shared accumulator. When the operation completes (success or\n * failure), a single {@link OperationUsage} record is emitted to the sink.\n *\n * Nested public-method calls (e.g. `traverse` internally calls\n * `getVocabulary`) are detected: the inner call joins the outer scope\n * instead of starting a new one, so one user-visible operation produces\n * exactly one usage record covering all its internal round-trips.\n *\n * If no sink is configured, this is a zero-overhead pass-through.\n */\n private async track<T>(\n operation: string,\n repositoryId: string | undefined,\n fn: () => Promise<T>,\n ): Promise<T> {\n if (!this.reportUsage) return fn();\n // Already inside a parent scope — join it rather than emitting a\n // separate record. The outermost call owns emission.\n if (usageScope.getStore()) return fn();\n const acc: UsageAccumulator = { ru: 0, calls: 0, retries: 0 };\n try {\n return await usageScope.run(acc, fn);\n } finally {\n if (acc.calls > 0) {\n this.reportUsage({\n provider: PROVIDER_NAME,\n operation,\n unit: 'RU',\n value: acc.ru,\n ...(repositoryId ? { repositoryId } : {}),\n timestamp: new Date(),\n details: { calls: acc.calls, retries: acc.retries },\n });\n }\n }\n }\n\n /**\n * Reject any repositoryId that is not a valid v4 UUID.\n *\n * Every partition-scoped query filters on repositoryId. Since repositoryId is\n * the CosmosDB partition key, a predicate with a different value would target\n * a different partition. Strict format validation at the provider boundary\n * prevents injection (e.g. strings containing quotes or Gremlin syntax) from\n * ever reaching query construction.\n */\n private assertValidRepositoryId(repositoryId: string): void {\n if (!isValidUuid(repositoryId)) {\n throw new InvalidInputError(\n 'repositoryId',\n `repositoryId must be a valid v4 UUID; got '${repositoryId}'`,\n );\n }\n }\n\n // ─── Lifecycle ─────────────────────────────────────────────────────\n\n async initialize(): Promise<void> {\n await this.conn.connect();\n }\n\n async dispose(): Promise<void> {\n await this.conn.close();\n }\n\n async ensureSchema(): Promise<EnsureSchemaResult> {\n return this.track('ensureSchema', undefined, () => this.ensureSchemaImpl());\n }\n\n private async ensureSchemaImpl(): Promise<EnsureSchemaResult> {\n const restBase = this.getRestEndpoint();\n const partitionKey = this.config.partitionKey ?? '/repositoryId';\n let databaseCreated = false;\n let schemaCreated = false;\n\n try {\n // 1. Create database if not exists\n const dbCreated = await cosmosRestPut(\n restBase,\n this.config.key,\n 'dbs',\n '',\n 'dbs',\n { id: this.config.database },\n this.config.rejectUnauthorized ?? true,\n );\n databaseCreated = dbCreated;\n\n // 2. Create Gremlin graph container if not exists\n const containerCreated = await cosmosRestPut(\n restBase,\n this.config.key,\n `dbs/${this.config.database}/colls`,\n `dbs/${this.config.database}`,\n 'colls',\n {\n id: this.config.container,\n partitionKey: { paths: [partitionKey], kind: 'Hash' },\n },\n this.config.rejectUnauthorized ?? true,\n );\n schemaCreated = containerCreated;\n\n // 3. Reconnect Gremlin client (it may have failed before db/container existed)\n await this.conn.close();\n await this.conn.connect();\n\n // 4. Write schema version meta vertex\n const existing = await this.conn.submit(\n \"g.V().hasId(metaId).hasLabel('_meta').valueMap(true)\",\n { metaId: META_VERTEX_ID },\n );\n\n if (existing.items.length > 0) {\n const props = existing.items[0] as Record<string, unknown>;\n const version = Number(unwrapGremlinValue(props['schemaVersion']) ?? 0);\n if (version < SCHEMA_VERSION || databaseCreated || schemaCreated) {\n await this.conn.submit(\n \"g.V().hasId(metaId).hasLabel('_meta').property('schemaVersion', ver)\",\n { metaId: META_VERTEX_ID, ver: SCHEMA_VERSION },\n );\n }\n } else {\n await this.conn.submit(\n \"g.addV('_meta').property('id', metaId).property('repositoryId', pk).property('schemaVersion', ver)\",\n { metaId: META_VERTEX_ID, pk: '_system', ver: SCHEMA_VERSION },\n );\n schemaCreated = true;\n }\n\n // 5. Bootstrap the `_repository_index` sentinel. Idempotent — first run\n // does a one-time cross-partition scan to backfill existing repos, every\n // subsequent run is a single cheap doc-fetch that returns null.\n await repoQueries.ensureRepositoryIndex(this.conn);\n\n // 6. Step E — indexing-policy diagnostic. Always runs (operators may\n // drift policy between calls). Never fails ensureSchema — see helper.\n await this.runIndexingPolicyDiagnostic();\n\n return {\n databaseCreated,\n schemaCreated,\n alreadyUpToDate: !databaseCreated && !schemaCreated,\n schemaVersion: SCHEMA_VERSION,\n };\n } catch (err: unknown) {\n throw new ProviderError(\n `Failed to ensure CosmosDB schema: ${err instanceof Error ? err.message : String(err)}`,\n 'Verify the CosmosDB REST endpoint is accessible and the Gremlin endpoint is reachable.',\n );\n }\n }\n\n /**\n * Step E — verify the container's indexing policy covers every path that\n * the SQL `findEntities` rewrite hits. The probe (2026-05-26) confirmed\n * code-managed containers get the Cosmos default policy (everything\n * indexed). This guard is for operator-facing protection: externally\n * provisioned containers (ARM/Bicep) can have `excludedPaths` set, which\n * would force `findEntities` to scan rather than index-lookup.\n *\n * Single GET against the colls resource, minimal RU. Never fails\n * `ensureSchema` — a diagnostic must not break provisioning.\n */\n private async runIndexingPolicyDiagnostic(): Promise<void> {\n let policy: { excludedPaths: Array<{ path: string }> };\n try {\n const props = await this.docClient.getContainerProperties();\n policy = props.indexingPolicy;\n } catch (err: unknown) {\n console.warn(\n `[CosmosDbProvider] could not verify indexing policy on container ` +\n `${this.config.container}: ${err instanceof Error ? err.message : String(err)}`,\n );\n return;\n }\n\n const offending: string[] = [];\n for (const entry of policy.excludedPaths) {\n // Cosmos exclusion paths end in `/?` (exact) or `/*` (subtree). Strip\n // the wildcard to get the prefix the exclusion governs.\n const prefix = entry.path.replace(/\\/[?*]$/, '');\n if (prefix === '' || prefix === '/') {\n // Root wildcard — every guarded path is excluded.\n for (const guard of GUARDED_INDEX_PATHS) {\n offending.push(`${guard} (covered by ${entry.path})`);\n }\n break;\n }\n for (const guard of GUARDED_INDEX_PATHS) {\n if (prefix === guard || guard.startsWith(prefix + '/')) {\n offending.push(`${guard} (excluded by ${entry.path})`);\n }\n }\n }\n\n if (offending.length > 0) {\n console.warn(\n `[CosmosDbProvider] Container ${this.config.container} has indexing-policy ` +\n `excludedPaths that cover paths used by findEntities. The query will ` +\n `fall back to scan and may exceed RU budgets:\\n ${offending.join('\\n ')}\\n` +\n `Verify the ARM/Bicep template that provisioned the container.`,\n );\n }\n }\n\n /** Derive the REST endpoint from config — either explicit or from the Gremlin endpoint host. */\n private getRestEndpoint(): string {\n if (this.config.restEndpoint) return this.config.restEndpoint.replace(/\\/+$/, '');\n // Derive from Gremlin endpoint: ws(s)://host:port/ → https://host:8081\n const url = new URL(this.config.endpoint);\n return `https://${url.hostname}:8081`;\n }\n\n // ─── Repository ────────────────────────────────────────────────────\n\n async createRepository(config: StorageRepositoryConfig): Promise<StoredRepository> {\n this.assertValidRepositoryId(config.repositoryId);\n return this.track('createRepository', config.repositoryId, () =>\n repoQueries.createRepository(this.conn, config),\n );\n }\n\n async getRepository(repositoryId: string): Promise<StoredRepository | null> {\n this.assertValidRepositoryId(repositoryId);\n return this.track('getRepository', repositoryId, () =>\n repoQueries.getRepository(this.conn, repositoryId),\n );\n }\n\n async listRepositories(filter?: RepositoryFilter): Promise<PaginatedResult<StoredRepositorySummary>> {\n return this.track('listRepositories', undefined, () =>\n repoQueries.listRepositories(this.conn, filter),\n );\n }\n\n async updateRepository(repositoryId: string, updates: RepositoryUpdate): Promise<StoredRepository> {\n this.assertValidRepositoryId(repositoryId);\n return this.track('updateRepository', repositoryId, () =>\n repoQueries.updateRepository(this.conn, repositoryId, updates),\n );\n }\n\n async deleteRepository(repositoryId: string, onProgress?: DeleteProgressCallback): Promise<void> {\n this.assertValidRepositoryId(repositoryId);\n return this.track('deleteRepository', repositoryId, () =>\n repoQueries.deleteRepository(this.conn, repositoryId, onProgress),\n );\n }\n\n async deleteAllContents(repositoryId: string, onProgress?: DeleteProgressCallback): Promise<{ deletedEntities: number; deletedRelationships: number }> {\n this.assertValidRepositoryId(repositoryId);\n return this.track('deleteAllContents', repositoryId, () =>\n repoQueries.deleteAllContents(this.conn, repositoryId, onProgress),\n );\n }\n\n async getRepositoryStats(repositoryId: string): Promise<RepositoryStats> {\n this.assertValidRepositoryId(repositoryId);\n return this.track('getRepositoryStats', repositoryId, () =>\n repoQueries.getRepositoryStats(this.conn, repositoryId),\n );\n }\n\n // ─── Vocabulary ────────────────────────────────────────────────────\n\n async getVocabulary(repositoryId: string): Promise<MemoryVocabulary> {\n this.assertValidRepositoryId(repositoryId);\n return this.track('getVocabulary', repositoryId, () =>\n vocabQueries.getVocabulary(this.conn, repositoryId),\n );\n }\n\n /**\n * Cached vocabulary read used by traversal compilation. The vocabulary is\n * compile-time context for the GremlinCompiler — it changes on the order of\n * once per session, but the traversal hot path pays one round-trip per call\n * to fetch it. The cache flips that to one round-trip per TTL window.\n *\n * Reads inside an active usage scope are still recorded if a fetch happens\n * (cache miss); cache hits emit no round-trip and therefore no usage entry.\n */\n private async getVocabularyCached(repositoryId: string): Promise<MemoryVocabulary> {\n const now = Date.now();\n const cached = this.vocabularyCache.get(repositoryId);\n if (cached && cached.expiresAt > now) {\n return cached.vocab;\n }\n const vocab = await vocabQueries.getVocabulary(this.conn, repositoryId);\n this.vocabularyCache.set(repositoryId, {\n vocab,\n expiresAt: now + VOCABULARY_CACHE_TTL_MS,\n });\n return vocab;\n }\n\n /** Drop the cache entry for a repository — call after any vocabulary write. */\n private invalidateVocabularyCache(repositoryId: string): void {\n this.vocabularyCache.delete(repositoryId);\n }\n\n async saveVocabulary(repositoryId: string, vocabulary: MemoryVocabulary): Promise<void> {\n this.assertValidRepositoryId(repositoryId);\n return this.track('saveVocabulary', repositoryId, async () => {\n await vocabQueries.saveVocabulary(this.conn, repositoryId, vocabulary);\n this.invalidateVocabularyCache(repositoryId);\n });\n }\n\n async getVocabularyChangeLog(repositoryId: string, options?: PaginationOptions): Promise<PaginatedResult<VocabularyChangeRecord>> {\n this.assertValidRepositoryId(repositoryId);\n return this.track('getVocabularyChangeLog', repositoryId, () =>\n vocabQueries.getVocabularyChangeLog(this.conn, repositoryId, options),\n );\n }\n\n // ─── Entities ──────────────────────────────────────────────────────\n\n async createEntity(repositoryId: string, entity: StoredEntity): Promise<StoredEntity> {\n this.assertValidRepositoryId(repositoryId);\n return this.track('createEntity', repositoryId, () =>\n entityQueries.createEntity(this.conn, repositoryId, entity),\n );\n }\n\n async getEntity(repositoryId: string, entityId: string, options?: EntityReadOptions): Promise<StoredEntity | null> {\n this.assertValidRepositoryId(repositoryId);\n return this.track('getEntity', repositoryId, () =>\n entityQueries.getEntity(this.conn, repositoryId, entityId, options),\n );\n }\n\n async getEntityBySlug(repositoryId: string, slug: string, options?: EntityReadOptions): Promise<StoredEntity | null> {\n this.assertValidRepositoryId(repositoryId);\n return this.track('getEntityBySlug', repositoryId, () =>\n entityQueries.getEntityBySlug(this.conn, repositoryId, slug, options),\n );\n }\n\n async getEntities(repositoryId: string, entityIds: string[], options?: EntityReadOptions): Promise<Map<string, StoredEntity>> {\n this.assertValidRepositoryId(repositoryId);\n return this.track('getEntities', repositoryId, () =>\n entityQueries.getEntities(this.conn, repositoryId, entityIds, options),\n );\n }\n\n async updateEntity(repositoryId: string, entityId: string, updates: StoredEntityUpdate): Promise<StoredEntity> {\n this.assertValidRepositoryId(repositoryId);\n return this.track('updateEntity', repositoryId, () =>\n entityQueries.updateEntity(this.conn, repositoryId, entityId, updates),\n );\n }\n\n async deleteEntity(repositoryId: string, entityId: string): Promise<void> {\n this.assertValidRepositoryId(repositoryId);\n return this.track('deleteEntity', repositoryId, () =>\n entityQueries.deleteEntity(this.conn, repositoryId, entityId),\n );\n }\n\n async deleteEntities(repositoryId: string, ids: string[]): Promise<{ deleted: string[]; notFound: string[] }> {\n if (ids.length === 0) return { deleted: [], notFound: [] };\n this.assertValidRepositoryId(repositoryId);\n return this.track('deleteEntities', repositoryId, () => this.deleteEntitiesImpl(repositoryId, ids));\n }\n\n /**\n * Single round-trip bulk-delete via the aggregate-side-effect pattern:\n * collapses the per-chunk existence-check + drop into one Gremlin call.\n *\n * g.V()...hasId(within(...)).has('entityType')\n * .aggregate('found').by('id') // collects the ids that match\n * .drop() // drops the vertices (and cascaded edges)\n * .cap('found') // emits the bucket as the single result\n *\n * The bucket is always emitted as a single list item — empty when nothing\n * matched (probe-verified 2026-05-25, local-tests/phase7-shape-probe.mjs).\n * `notFound` is derived client-side as the set difference.\n */\n private async deleteEntitiesImpl(repositoryId: string, ids: string[]): Promise<{ deleted: string[]; notFound: string[] }> {\n const deleted: string[] = [];\n const CHUNK = 100;\n\n for (let i = 0; i < ids.length; i += CHUNK) {\n const chunk = ids.slice(i, i + CHUNK);\n\n const bindings: Record<string, unknown> = { rid: repositoryId };\n const idParams: string[] = [];\n for (let j = 0; j < chunk.length; j++) {\n const p = `id${j}`;\n bindings[p] = chunk[j];\n idParams.push(p);\n }\n const withinExpr = `within(${idParams.join(', ')})`;\n const result = await this.conn.submit(\n `g.V().has('repositoryId', rid).hasId(${withinExpr}).has('entityType')` +\n `.aggregate('found').by('id').drop().cap('found')`,\n bindings,\n );\n const bucket = result.items[0];\n if (Array.isArray(bucket)) {\n deleted.push(...(bucket as string[]));\n }\n }\n\n const deletedSet = new Set(deleted);\n return { deleted, notFound: ids.filter((id) => !deletedSet.has(id)) };\n }\n\n async deleteEntitiesByType(repositoryId: string, entityType: string): Promise<{ deletedEntities: number; deletedRelationships: number | undefined }> {\n this.assertValidRepositoryId(repositoryId);\n return this.track('deleteEntitiesByType', repositoryId, () =>\n entityQueries.deleteEntitiesByType(this.conn, repositoryId, entityType),\n );\n }\n\n async findEntities(repositoryId: string, query: StorageFindQuery, options?: EntityReadOptions): Promise<PaginatedResult<StoredEntity>> {\n this.assertValidRepositoryId(repositoryId);\n return this.track('findEntities', repositoryId, () =>\n entityQueries.findEntities(this.docClient, repositoryId, query, options),\n );\n }\n\n // ─── Relationships ─────────────────────────────────────────────────\n\n async createRelationship(repositoryId: string, relationship: StoredRelationship): Promise<StoredRelationship> {\n this.assertValidRepositoryId(repositoryId);\n return this.track('createRelationship', repositoryId, () =>\n relQueries.createRelationship(this.conn, repositoryId, relationship),\n );\n }\n\n async getRelationship(repositoryId: string, relationshipId: string): Promise<StoredRelationship | null> {\n this.assertValidRepositoryId(repositoryId);\n return this.track('getRelationship', repositoryId, () =>\n relQueries.getRelationship(this.conn, repositoryId, relationshipId),\n );\n }\n\n async getEntityRelationships(repositoryId: string, entityId: string, options?: RelationshipQueryOptions): Promise<PaginatedResult<StoredRelationship>> {\n this.assertValidRepositoryId(repositoryId);\n return this.track('getEntityRelationships', repositoryId, () =>\n relQueries.getEntityRelationships(this.conn, repositoryId, entityId, options),\n );\n }\n\n async deleteRelationship(repositoryId: string, relationshipId: string): Promise<void> {\n this.assertValidRepositoryId(repositoryId);\n return this.track('deleteRelationship', repositoryId, () =>\n relQueries.deleteRelationship(this.conn, repositoryId, relationshipId),\n );\n }\n\n async deleteRelationships(repositoryId: string, ids: string[]): Promise<{ deleted: string[]; notFound: string[] }> {\n if (ids.length === 0) return { deleted: [], notFound: [] };\n this.assertValidRepositoryId(repositoryId);\n return this.track('deleteRelationships', repositoryId, () => this.deleteRelationshipsImpl(repositoryId, ids));\n }\n\n /**\n * Single round-trip bulk relationship delete via the aggregate-side-effect\n * pattern: collapses the per-chunk existence-check + drop into one Gremlin\n * call. Gremlin drop on edges is routed by the engine and the bucket gives\n * back the exact ids that were actually dropped, so `notFound` can be\n * derived client-side.\n *\n * Source-id partition routing is not exposed on this method (the public\n * surface accepts only edge ids), so the lookup may fan out across\n * partitions — see [docs/cosmosdb-gremlin-compatibility.md §`g.E().has`\n * doesn't always push partition down]. Callers that already hold a\n * StoredRelationship and want partition-scoped routing should add a\n * dedicated method when the need is concrete.\n */\n private async deleteRelationshipsImpl(repositoryId: string, ids: string[]): Promise<{ deleted: string[]; notFound: string[] }> {\n const deleted: string[] = [];\n const CHUNK = 100;\n\n for (let i = 0; i < ids.length; i += CHUNK) {\n const chunk = ids.slice(i, i + CHUNK);\n\n const bindings: Record<string, unknown> = { rid: repositoryId };\n const idParams: string[] = [];\n for (let j = 0; j < chunk.length; j++) {\n const p = `id${j}`;\n bindings[p] = chunk[j];\n idParams.push(p);\n }\n const withinExpr = `within(${idParams.join(', ')})`;\n const result = await this.conn.submit(\n `g.E().has('repositoryId', rid).hasId(${withinExpr})` +\n `.aggregate('found').by('id').drop().cap('found')`,\n bindings,\n );\n const bucket = result.items[0];\n if (Array.isArray(bucket)) {\n deleted.push(...(bucket as string[]));\n }\n }\n\n const deletedSet = new Set(deleted);\n return { deleted, notFound: ids.filter((id) => !deletedSet.has(id)) };\n }\n\n async deleteRelationshipsByType(repositoryId: string, relationshipType: string): Promise<{ deletedRelationships: number }> {\n this.assertValidRepositoryId(repositoryId);\n return this.track('deleteRelationshipsByType', repositoryId, () =>\n relQueries.deleteRelationshipsByType(this.conn, repositoryId, relationshipType),\n );\n }\n\n // ─── Graph Traversal (StorageProvider) ─────────────────────────────\n\n async exploreNeighborhood(repositoryId: string, entityId: string, options: StorageExploreOptions): Promise<StorageNeighborhood> {\n this.assertValidRepositoryId(repositoryId);\n return this.track('exploreNeighborhood', repositoryId, () =>\n this.exploreNeighborhoodImpl(repositoryId, entityId, options),\n );\n }\n\n /**\n * Compiler-model implementation of exploreNeighborhood.\n *\n * Strategy: for each depth `d` from 1 to `options.depth`, build a\n * cumulative `TraversalSpec` with `d` steps and `returnMode: 'all'`, run\n * it through {@link executeTraversal}, then walk one BFS layer client-side\n * from the previous frontier using the returned edges.\n *\n * The server-side step direction is fixed to `'both'` (catches every edge\n * in either direction). The directional + bidirectional filter is applied\n * client-side per hop — i.e. `direction: 'out'` includes inbound edges\n * where `bidirectional` is true. The CosmosDB Gremlin compiler does not\n * natively express the `union(outE, inE.has(bidirectional))` shape that\n * would push this filter server-side, so it stays client-side; the\n * observable contract (which edges count toward `'out'` given\n * bidirectionality) is preserved.\n *\n * Round-trips per call: `options.depth` (one per layer). The previous BFS\n * was `1 + fanout + fanout² + …` round-trips for the same depth.\n */\n private async exploreNeighborhoodImpl(\n repositoryId: string,\n entityId: string,\n options: StorageExploreOptions,\n ): Promise<StorageNeighborhood> {\n const layers: StorageNeighborhoodLayer[] = [];\n const visited = new Set<string>([entityId]);\n let frontier = new Set<string>([entityId]);\n\n for (let d = 1; d <= options.depth; d++) {\n if (frontier.size === 0) break;\n\n const spec: TraversalSpec = {\n start: { entityId },\n steps: buildExploreSteps(d, options),\n returnMode: 'all',\n // Each round-trip fetches the cumulative subgraph at depth `d` and\n // we reconstruct layers client-side. The result can include every\n // edge and vertex reachable in ≤d hops in either direction; size\n // the limit generously.\n limit: 10_000,\n // Use 'full' + includeProvenance so executeTraversal returns full\n // StoredEntity rows (StorageNeighborhood embeds StoredEntity).\n detailLevel: 'full',\n includeProvenance: true,\n };\n const raw = await this.executeTraversal(repositoryId, spec);\n\n // Index edges by either endpoint so we can find edges incident to each\n // frontier vertex in O(1).\n const edgesByVertex = new Map<string, StoredRelationship[]>();\n for (const rel of raw.allRelationships) {\n const a = edgesByVertex.get(rel.sourceEntityId);\n if (a) a.push(rel); else edgesByVertex.set(rel.sourceEntityId, [rel]);\n const b = edgesByVertex.get(rel.targetEntityId);\n if (b) b.push(rel); else edgesByVertex.set(rel.targetEntityId, [rel]);\n }\n\n const layer: StorageNeighborhoodLayer = {};\n const nextFrontier = new Set<string>();\n // Dedup edges within a layer: the cumulative-d response can include the\n // same edge multiple times across the deduped union (server-side dedup\n // is by row, not by edge-in-context). The visit set prevents the same\n // (vertex, edge) pairing from contributing twice.\n const layerEdgeSeen = new Set<string>();\n\n for (const fv of frontier) {\n const incident = edgesByVertex.get(fv) ?? [];\n for (const rel of incident) {\n const isSource = rel.sourceEntityId === fv;\n const isTarget = rel.targetEntityId === fv;\n let matchesDirection = false;\n let connectedId: string | undefined;\n\n if (isSource && (options.direction === 'out' || options.direction === 'both')) {\n matchesDirection = true;\n connectedId = rel.targetEntityId;\n } else if (isTarget && (options.direction === 'in' || options.direction === 'both')) {\n matchesDirection = true;\n connectedId = rel.sourceEntityId;\n } else if (rel.bidirectional) {\n if (isSource && options.direction === 'in') {\n matchesDirection = true;\n connectedId = rel.targetEntityId;\n } else if (isTarget && options.direction === 'out') {\n matchesDirection = true;\n connectedId = rel.sourceEntityId;\n }\n }\n if (!matchesDirection || !connectedId) continue;\n if (visited.has(connectedId)) continue;\n\n // Relationship property filter — applied client-side per hop, matching\n // the existing BFS. Edges that fail the filter neither populate the\n // layer nor expand the frontier.\n if (options.relationshipPropertyFilters && options.relationshipPropertyFilters.length > 0) {\n if (!matchesPropertyFilters(rel.properties, options.relationshipPropertyFilters)) continue;\n }\n\n const connectedEntity = raw.entityMap.get(connectedId);\n if (!connectedEntity) continue;\n\n // Entity type filter — applied client-side; the server spec walks\n // direction 'both' without entity-type narrowing so deeper layers\n // are still reachable through any intermediate.\n if (options.entityTypes && options.entityTypes.length > 0 &&\n !options.entityTypes.includes(connectedEntity.entityType)) {\n continue;\n }\n\n // Dedup the (vertex-pair, edge) within this layer.\n const edgeKey = `${rel.id}|${fv}->${connectedId}`;\n if (layerEdgeSeen.has(edgeKey)) continue;\n layerEdgeSeen.add(edgeKey);\n\n const relType = rel.relationshipType;\n if (!layer[relType]) {\n layer[relType] = { total: 0, entities: [], relationships: [] };\n }\n layer[relType]!.entities.push(connectedEntity);\n layer[relType]!.relationships.push(rel);\n layer[relType]!.total = layer[relType]!.entities.length;\n nextFrontier.add(connectedId);\n }\n }\n\n // Per-type pagination (matches the existing CosmosDB BFS — total\n // reflects the full pre-slice count).\n for (const relType of Object.keys(layer)) {\n const group = layer[relType]!;\n const start = options.offsetPerType;\n const end = start + options.limitPerType;\n group.entities = group.entities.slice(start, end);\n group.relationships = group.relationships.slice(start, end);\n }\n\n if (Object.keys(layer).length > 0) {\n layers.push(layer);\n }\n\n // Promote nextFrontier to visited AFTER the full layer is processed so\n // the same entity can appear under multiple relationship types within\n // a single layer (matches the existing semantic).\n for (const id of nextFrontier) {\n visited.add(id);\n }\n frontier = nextFrontier;\n }\n\n return { centerId: entityId, layers };\n }\n\n async findPaths(repositoryId: string, sourceId: string, targetId: string, options: StoragePathOptions): Promise<StoragePathResult> {\n this.assertValidRepositoryId(repositoryId);\n return this.track('findPaths', repositoryId, () =>\n this.findPathsImpl(repositoryId, sourceId, targetId, options),\n );\n }\n\n /**\n * Compiler-model implementation of findPaths.\n *\n * Strategy: build a `TraversalSpec` with a single `'both'` direction step\n * in `repeat()` mode with `emitIntermediates: true` and `returnMode:\n * 'path'`, run it once. The compiler always emits `.simplePath()` in path\n * mode for cycle prevention, producing\n * `.emit().repeat(bothE().otherV()).times(maxDepth).simplePath()\n * .range(...).path().by(<v>).by(<e>)`, which yields paths of every length\n * from 0 (the start vertex alone) to `maxDepth`. Live-probed against the\n * Cosmos emulator 2026-05-25 — see local-tests/phase4-repeat-emit-probe.mjs.\n *\n * The pre-Phase-4 Cosmos BFS in (now-deleted) `packages/storage-cosmosdb/\n * src/queries/traversal.ts` traversed edges with unconditional `bothE()`\n * regardless of the `bidirectional` flag (path discovery is reachability,\n * not semantic direction). Mirror that here by using step direction\n * `'both'` and not applying any direction filter. The plan's §6\n * observable-outputs rule requires preserving this.\n *\n * One round-trip total. The previous BFS was up to `1 + fanout + fanout² + …`.\n */\n private async findPathsImpl(\n repositoryId: string,\n sourceId: string,\n targetId: string,\n options: StoragePathOptions,\n ): Promise<StoragePathResult> {\n if (sourceId === targetId) {\n return { paths: [{ entityIds: [sourceId], relationshipIds: [] }], totalPaths: 1 };\n }\n\n const step: TraversalStep = {\n direction: 'both',\n repeat: { maxDepth: options.maxDepth, emitIntermediates: true },\n };\n if (options.relationshipTypes && options.relationshipTypes.length > 0) {\n step.relationshipTypes = options.relationshipTypes;\n }\n if (options.relationshipPropertyFilters && options.relationshipPropertyFilters.length > 0) {\n step.relationshipFilter = options.relationshipPropertyFilters;\n }\n\n const spec: TraversalSpec = {\n start: { entityId: sourceId },\n steps: [step],\n returnMode: 'path',\n // Cycle prevention comes from the compiler unconditionally emitting\n // .simplePath() in path mode — replaces the explicit\n // `state.path.includes(nextId)` guard from the old BFS.\n // Pull the full pool of paths so we can post-filter to those ending at\n // targetId, then paginate. The emulator returns paths of every length\n // 0..maxDepth in one round-trip with the repeat+emit shape; cap\n // generously to ensure all candidates are inspected.\n limit: Math.max(options.limit + options.offset, options.limit) * 10,\n detailLevel: 'full',\n includeProvenance: true,\n };\n\n const raw = await this.executeTraversal(repositoryId, spec);\n\n const matchingPaths: StoragePath[] = [];\n for (const row of raw.pathRows) {\n // The repeat+emit shape includes the 0-hop \"path\" (just the start\n // vertex). source !== target at this point (handled above), so the\n // last-entity check naturally rejects it.\n const last = row.entityIds[row.entityIds.length - 1];\n if (last !== targetId) continue;\n // Apply entity-type filter on intermediate entities (matches the\n // existing CosmosDB BFS — source and target are always allowed).\n if (options.entityTypes && options.entityTypes.length > 0) {\n let rejected = false;\n for (let i = 1; i < row.entityIds.length - 1; i++) {\n const intermediate = raw.entityMap.get(row.entityIds[i]!);\n if (!intermediate) { rejected = true; break; }\n if (!options.entityTypes.includes(intermediate.entityType)) {\n rejected = true;\n break;\n }\n }\n if (rejected) continue;\n }\n matchingPaths.push({\n entityIds: [...row.entityIds],\n relationshipIds: [...row.relationshipIds],\n });\n }\n\n // Pagination — slice the matching set. `totalPaths` reflects the full\n // pre-slice count, matching the existing storage contract.\n const paginated = matchingPaths.slice(options.offset, options.offset + options.limit);\n\n return {\n paths: paginated,\n totalPaths: matchingPaths.length,\n };\n }\n\n // ─── Timeline ──────────────────────────────────────────────────────\n\n async getTimeline(repositoryId: string, entityId: string, options: StorageTimelineOptions): Promise<StorageTimelineResult> {\n this.assertValidRepositoryId(repositoryId);\n return this.track('getTimeline', repositoryId, () =>\n timelineQueries.getTimeline(this.conn, repositoryId, entityId, options),\n );\n }\n\n // ─── Bulk Operations ───────────────────────────────────────────────\n\n exportAll(repositoryId: string): AsyncIterable<ExportChunk> {\n this.assertValidRepositoryId(repositoryId);\n // exportAll is a streaming iterator — each chunk consumed drives new\n // submits. Wrapping the entire iteration in a single usage scope would\n // require holding the scope open across consumer awaits, which breaks\n // the AsyncLocalStorage contract. Instead, wrap each submit as its own\n // sub-operation by running the iterator generator inside the scope.\n return this.trackIterable('exportAll', repositoryId, bulkQueries.exportAll(this.conn, repositoryId));\n }\n\n async importBulk(repositoryId: string, data: ImportChunk[], options?: BulkImportOptions): Promise<BulkImportResult> {\n this.assertValidRepositoryId(repositoryId);\n return this.track('importBulk', repositoryId, () =>\n bulkQueries.importBulk(this.conn, repositoryId, data, options),\n );\n }\n\n /**\n * Wrap an AsyncIterable so every emitted chunk is generated inside the\n * usage scope. On each iteration step, the scope aggregates charges from\n * the next chunk's submits; when the iterator completes (or is closed), a\n * single usage record is emitted for the whole stream.\n */\n private trackIterable<T>(operation: string, repositoryId: string, source: AsyncIterable<T>): AsyncIterable<T> {\n if (!this.reportUsage) return source;\n const sink = this.reportUsage;\n return {\n [Symbol.asyncIterator]: (): AsyncIterator<T> => {\n const iter = source[Symbol.asyncIterator]();\n const acc: UsageAccumulator = { ru: 0, calls: 0, retries: 0 };\n let emitted = false;\n const emit = (): void => {\n if (emitted) return;\n emitted = true;\n if (acc.calls > 0) {\n sink({\n provider: PROVIDER_NAME,\n operation,\n unit: 'RU',\n value: acc.ru,\n repositoryId,\n timestamp: new Date(),\n details: { calls: acc.calls, retries: acc.retries },\n });\n }\n };\n return {\n async next(): Promise<IteratorResult<T>> {\n const step = await usageScope.run(acc, () => iter.next());\n if (step.done) emit();\n return step;\n },\n async return(value?: T): Promise<IteratorResult<T>> {\n emit();\n if (iter.return) return iter.return(value);\n return { done: true, value: value as T };\n },\n async throw(err?: unknown): Promise<IteratorResult<T>> {\n emit();\n if (iter.throw) return iter.throw(err);\n throw err;\n },\n };\n },\n };\n }\n\n // ─── GraphTraversalProvider ────────────────────────────────────────\n\n getCapabilities(): GraphTraversalCapabilities {\n return {\n supportsNativeQuery: true,\n nativeQueryLanguage: 'gremlin',\n maxTraversalDepth: 10,\n supportsRelationshipPropertyFilters: true,\n supportsEntityPropertyFilters: true,\n supportsAggregation: false,\n supportsRepeat: true,\n supportsDedup: true,\n supportsRelationshipSummary: false,\n };\n }\n\n async traverse(\n repositoryId: string,\n spec: TraversalSpec,\n ): Promise<TraversalResult> {\n this.assertValidRepositoryId(repositoryId);\n return this.track('traverse', repositoryId, () => this.traverseInternal(repositoryId, spec));\n }\n\n /**\n * Compile + execute a TraversalSpec against this repository's partition.\n *\n * Internal entrypoint shared by `traverse` (the public surface) and the\n * compiler-model rewrites of `exploreNeighborhood` / `findPaths`. Does NOT\n * wrap in `track()` — the outer public method owns its own usage scope, and\n * inner submits accumulate into that scope (the nested-scope guard in\n * `track()` keeps nested public calls from emitting duplicate records).\n */\n private async traverseInternal(\n repositoryId: string,\n spec: TraversalSpec,\n ): Promise<TraversalResult> {\n const raw = await this.executeTraversal(repositoryId, spec);\n\n // Project stored entities to the requested detail level. This strips\n // embeddings and any other internal fields at every level — the\n // projection contract never surfaces embeddings via traversal results.\n const detailLevel = spec.detailLevel ?? 'summary';\n\n type ProjectedEntity = TraversalResult['entities'][number];\n type ProjectedRelationship = NonNullable<TraversalResult['relationships']>[number];\n\n const projectStoredEntity = (stored: StoredEntity): ProjectedEntity => {\n const projected = projectEntity(stored, detailLevel) as ProjectedEntity;\n if (!spec.includeProvenance) {\n delete (projected as unknown as Record<string, unknown>)['provenance'];\n }\n return projected;\n };\n\n // direction is mode-specific:\n // 'all' — always 'out' (stored topology; the deduped union has\n // no walk context). Callers derive walk direction relative\n // to any anchor via sourceEntityId / targetEntityId.\n // 'path' — relative to the last hop within each walk; callers stamp\n // via the `direction` argument.\n const projectStoredRelationship = (\n rel: StoredRelationship,\n direction: 'out' | 'in' = 'out',\n ): ProjectedRelationship => ({\n id: rel.id,\n type: rel.relationshipType,\n sourceEntityId: rel.sourceEntityId,\n targetEntityId: rel.targetEntityId,\n direction,\n properties: rel.properties,\n });\n\n let entities: ProjectedEntity[] = [];\n let relationships: ProjectedRelationship[] | undefined;\n let paths: NonNullable<TraversalResult['paths']> | undefined;\n\n // Server-side row count BEFORE greedy-expand. The compiler's union emits\n // vertices before edges at each depth so the deduped stream is closed\n // under per-hop entity references; this preserved count is what hasMore /\n // truncated anchor to, independent of any client-side endpoint backfill.\n const rangeRowCount =\n spec.returnMode === 'all'\n ? raw.allEntities.length + raw.allRelationships.length\n : 0;\n\n if (spec.returnMode === 'terminal') {\n entities = raw.terminalEntities.map(projectStoredEntity);\n relationships = undefined;\n } else if (spec.returnMode === 'all') {\n // Greedy-expand: pull endpoint vertices into the page if any edge in\n // the slice references a vertex that fell outside the server-side\n // range window. Happens at multi-hop page boundaries where a deeper\n // edge's near endpoint sits in a prior page. One batched getEntities\n // round-trip; soft-limit cost on the visible page size. The pulled-in\n // vertices will reappear at their natural union position in a later\n // page — that duplication is the documented cost of \"each page is\n // independently usable\".\n const missingIds = new Set<string>();\n for (const rel of raw.allRelationships) {\n if (!raw.entityMap.has(rel.sourceEntityId)) {\n missingIds.add(rel.sourceEntityId);\n }\n if (!raw.entityMap.has(rel.targetEntityId)) {\n missingIds.add(rel.targetEntityId);\n }\n }\n if (missingIds.size > 0) {\n const fetched = await this.getEntities(repositoryId, [...missingIds]);\n for (const stored of fetched.values()) {\n raw.allEntities.push(stored);\n raw.entityMap.set(stored.id, stored);\n }\n }\n entities = raw.allEntities.map(projectStoredEntity);\n relationships = raw.allRelationships.map((r) => projectStoredRelationship(r));\n } else {\n // 'path' — emit one TraversalPath per Gremlin path row, with per-edge\n // walk direction. The outer `relationships` array dedups by rel id and\n // stamps the first-seen direction (first-writer-wins) — this matches\n // the observable contract that callers depend on for path rendering.\n paths = raw.pathRows.map((row) => ({\n length: Math.max(row.entityIds.length - 1, 0),\n entities: row.entityIds.map((id) => {\n const stored = raw.entityMap.get(id);\n if (!stored) {\n throw new ProviderError(\n 'Unpacking Gremlin path: entity referenced by path is missing from the result',\n 'This indicates a Gremlin response shape mismatch — inspect compiledQuery.',\n );\n }\n return projectStoredEntity(stored);\n }),\n relationships: row.relationshipIds.map((id, i) => {\n const stored = raw.relationshipMap.get(id);\n if (!stored) {\n throw new ProviderError(\n 'Unpacking Gremlin path: relationship referenced by path is missing from the result',\n 'This indicates a Gremlin response shape mismatch — inspect compiledQuery.',\n );\n }\n return projectStoredRelationship(stored, row.relationshipDirections[i]!);\n }),\n }));\n relationships = Array.from(raw.relationshipMap.values()).map((rel) =>\n projectStoredRelationship(rel, raw.pathRelFirstDirection.get(rel.id) ?? 'out'),\n );\n }\n\n const limit = spec.limit ?? 50;\n // 'all' mode returns an interleaved entity+edge union — total must count\n // both so callers see the true page size (including any greedy-expanded\n // endpoint vertices).\n let total: number;\n if (spec.returnMode === 'path') {\n total = paths?.length ?? 0;\n } else if (spec.returnMode === 'all') {\n total = entities.length + (relationships?.length ?? 0);\n } else {\n total = entities.length;\n }\n\n // hasMore / truncated anchor to the request's pagination signal, not the\n // post-expand visible page size. 'all' mode uses the pre-expand row count\n // from the server-side .range() — greedy-expand can only inflate the page\n // and would otherwise spuriously trip the >= limit heuristic when the\n // server-side slice was actually short of `limit`.\n const paginationSignal =\n spec.returnMode === 'all' ? rangeRowCount : total;\n const truncated = paginationSignal >= limit;\n\n const queryMetadata: QueryMetadata = {\n executionTimeMs: raw.executionTimeMs,\n resourceCost: raw.requestCharge != null\n ? { units: 'RU', value: raw.requestCharge }\n : undefined,\n compiledQuery: raw.compiledQuery,\n compiledQueryLanguage: 'gremlin',\n appliedLimits: {\n maxResults: limit,\n maxDepth: spec.steps?.length,\n },\n truncated,\n truncationReason: truncated ? 'result_limit' : undefined,\n };\n\n return {\n entities,\n relationships,\n paths,\n total,\n returned: total,\n hasMore: truncated,\n queryMetadata,\n };\n }\n\n /**\n * Lower-level traversal helper: compiles a spec, submits to Gremlin, and\n * parses the rows into raw {@link StoredEntity} / {@link StoredRelationship}\n * objects (no detail-level projection, no provenance stripping). Used by\n * `traverseInternal` and by the storage-layer rewrites of\n * `exploreNeighborhood` / `findPaths` that need the full stored shape to\n * rebuild `StorageNeighborhood` / `StoragePathResult`.\n *\n * Returns a discriminated bag — only the fields relevant to `spec.returnMode`\n * are populated:\n * - `'terminal'`: `terminalEntities` (in row order, no dedup beyond what the\n * server emitted).\n * - `'all'`: `allEntities` and `allRelationships`, already server-deduped.\n * - `'path'`: `pathRows` plus the `entityMap` / `relationshipMap` lookup\n * tables and `pathRelFirstDirection` for the first-seen direction per\n * deduped edge id.\n */\n private async executeTraversal(\n repositoryId: string,\n spec: TraversalSpec,\n ): Promise<RawTraversalResult> {\n const startTime = Date.now();\n\n // Vocabulary is compile-time context — fetch from the per-process cache so\n // back-to-back traversals do not each pay the `_vocabulary` round-trip.\n const vocabulary = await this.getVocabularyCached(repositoryId);\n\n // Compile the spec to Gremlin — the provider owns compilation.\n const compiled = this.compiler.compile(spec, vocabulary);\n\n // Scope the traversal to this repository's partition.\n // repositoryId is the CosmosDB partition key — the predicate both filters\n // and routes the query to a single physical partition. Bind it as a\n // parameter (never concatenated) so it cannot become Gremlin syntax even\n // if the upstream GUID check is ever bypassed.\n const scopedQuery = compiled.query.replace(\n 'g.V()',\n \"g.V().has('repositoryId', pRid)\",\n );\n const scopedParams = { ...compiled.params, pRid: repositoryId };\n\n let result;\n try {\n result = await this.conn.submit(scopedQuery, scopedParams);\n } catch (err: unknown) {\n throw new ProviderError(\n `Gremlin traversal failed: ${err instanceof Error ? err.message : String(err)}`,\n 'Check the traversal spec and ensure the CosmosDB connection is healthy.',\n );\n }\n const executionTimeMs = Date.now() - startTime;\n\n const raw: RawTraversalResult = {\n terminalEntities: [],\n allEntities: [],\n allRelationships: [],\n pathRows: [],\n entityMap: new Map(),\n relationshipMap: new Map(),\n pathRelFirstDirection: new Map(),\n executionTimeMs,\n requestCharge: result.requestCharge,\n compiledQuery: scopedQuery,\n };\n\n if (spec.returnMode === 'terminal') {\n // Flat projected vertex rows — one per row.\n for (const item of result.items) {\n const stored = entityFromGremlin(item as Record<string, unknown>);\n raw.terminalEntities.push(stored);\n }\n } else if (spec.returnMode === 'all') {\n // Flat stream of vertex AND edge projected Maps, already server-deduped\n // by id. Each row carries the synthetic `__kind` discriminator from the\n // compiler's per-branch project chain ('v' = vertex, 'e' = edge).\n for (const item of result.items) {\n const props = item as Record<string, unknown>;\n const kind = props['__kind'];\n if (kind === 'v') {\n const stored = entityFromGremlin(props);\n raw.allEntities.push(stored);\n raw.entityMap.set(stored.id, stored);\n } else if (kind === 'e') {\n const stored = relationshipFromGremlin(props);\n raw.allRelationships.push(stored);\n raw.relationshipMap.set(stored.id, stored);\n }\n // Rows without a recognised marker are skipped defensively.\n }\n } else {\n // 'path' — Gremlin Path objects: { objects: [vertex|edge, ...] }\n // where each object is a projected Map with a `__kind` discriminator.\n //\n // Direction per edge is computed during the walk using a lastVertexId\n // cursor: 'out' when the walk crossed source → target, 'in'\n // when it crossed target → source.\n for (const item of result.items) {\n const pathData = item as { objects?: unknown[] };\n if (!pathData.objects) continue;\n\n const pathEntityIds: string[] = [];\n const pathRelIds: string[] = [];\n const pathRelDirections: Array<'out' | 'in'> = [];\n let lastVertexId: string | null = null;\n\n for (const obj of pathData.objects) {\n const props = obj as Record<string, unknown>;\n const kind = props['__kind'];\n if (kind === 'v') {\n const stored = entityFromGremlin(props);\n raw.entityMap.set(stored.id, stored);\n pathEntityIds.push(stored.id);\n lastVertexId = stored.id;\n } else if (kind === 'e') {\n const stored = relationshipFromGremlin(props);\n raw.relationshipMap.set(stored.id, stored);\n pathRelIds.push(stored.id);\n const direction: 'out' | 'in' =\n lastVertexId === stored.sourceEntityId ? 'out' : 'in';\n pathRelDirections.push(direction);\n if (!raw.pathRelFirstDirection.has(stored.id)) {\n raw.pathRelFirstDirection.set(stored.id, direction);\n }\n }\n // Objects without a recognised marker are skipped defensively.\n }\n\n raw.pathRows.push({\n entityIds: pathEntityIds,\n relationshipIds: pathRelIds,\n relationshipDirections: pathRelDirections,\n });\n }\n }\n\n return raw;\n }\n\n /**\n * Execute a raw Gremlin query with caller-supplied bindings.\n *\n * ⚠️ ELEVATED PRIVILEGE — SYSTEM-LEVEL OPERATION ⚠️\n *\n * This method is an unscoped pass-through: it does not filter by repository,\n * does not inject the partition key, and performs no validation on the query\n * string. A single call can read or mutate any vertex or edge in the\n * container regardless of which repository (partition) it belongs to.\n *\n * DO NOT expose this method to AI agents, end users, or any untrusted caller.\n * It is intended for:\n * - administrative tooling (migrations, diagnostics, repairs)\n * - internal library operations that need cross-partition reach\n *\n * `repositoryId` is accepted for interface symmetry but is intentionally\n * ignored here — the caller is trusted to scope the query themselves.\n *\n * For agent-facing graph queries use {@link traverse}, which enforces the\n * repositoryId partition predicate.\n */\n async executeNativeQuery(\n _repositoryId: string,\n query: string,\n params?: Record<string, unknown>,\n ): Promise<unknown[]> {\n // executeNativeQuery is cross-partition by design; no repositoryId is\n // stamped on the usage record because the query isn't scoped to one.\n return this.track('executeNativeQuery', undefined, () => this.executeNativeQueryImpl(query, params));\n }\n\n private async executeNativeQueryImpl(\n query: string,\n params?: Record<string, unknown>,\n ): Promise<unknown[]> {\n const result = await this.conn.submit(query, params);\n return result.items as unknown[];\n }\n}\n\nfunction unwrapGremlinValue(val: unknown): unknown {\n if (Array.isArray(val) && val.length > 0) return val[0];\n return val;\n}\n\n/**\n * Build the per-step TraversalSpec steps for exploreNeighborhood at a given\n * cumulative depth.\n *\n * Server-side step direction is fixed to `'both'` (catches every edge in\n * either direction). The directional + bidirectional filter and entity-type\n * filter run client-side during layer reconstruction — both because the\n * compiler does not express the `union(outE, inE.has(bidirectional))` shape\n * and because entity-type filtering at intermediate hops is non-propagating\n * in the compiler's `'all'` emission (the prefix walks unfiltered vertices).\n *\n * relationshipTypes IS pushed to the server because the compiler emits it as\n * `bothE(t1, t2, ...)`, which IS part of the prefix walk at every depth.\n */\nfunction buildExploreSteps(depth: number, options: StorageExploreOptions): TraversalStep[] {\n const base: TraversalStep = { direction: 'both' };\n if (options.relationshipTypes && options.relationshipTypes.length > 0) {\n base.relationshipTypes = options.relationshipTypes;\n }\n const steps: TraversalStep[] = [];\n for (let i = 0; i < depth; i++) {\n steps.push({ ...base });\n }\n return steps;\n}\n\n","// CosmosDbConnection — Gremlin client wrapper for CosmosDB\n//\n// Handles WebSocket connection, CosmosDB authentication, TLS for emulator,\n// and retry logic for transient errors (429 throttling, 503 unavailable).\n\n// @ts-expect-error — gremlin has no type declarations\nimport gremlin from 'gremlin';\nimport { usageScope } from './usage.js';\n\nexport interface CosmosDbConnectionConfig {\n /** Gremlin WebSocket endpoint (e.g. wss://localhost:8901/) */\n endpoint: string;\n /** CosmosDB primary key */\n key: string;\n /** Database name */\n database: string;\n /** Container (graph) name */\n container: string;\n /** Max retries for transient errors (default: 3) */\n maxRetries?: number;\n /** Default query timeout in ms (default: 30000) */\n defaultTimeoutMs?: number;\n /** Whether to reject unauthorized TLS certs — set false for emulator (default: true) */\n rejectUnauthorized?: boolean;\n}\n\nexport interface GremlinResult {\n /** Raw result items */\n items: unknown[];\n /** CosmosDB request charge (RU) from response headers */\n requestCharge?: number;\n}\n\n/**\n * Manages a Gremlin WebSocket connection to CosmosDB.\n * Provides `submit()` for parameterized Gremlin queries with retry on transient errors.\n */\nexport class CosmosDbConnection {\n private client: gremlin.driver.Client | null = null;\n private readonly config: Required<Pick<CosmosDbConnectionConfig, 'maxRetries' | 'defaultTimeoutMs' | 'rejectUnauthorized'>> & CosmosDbConnectionConfig;\n\n constructor(config: CosmosDbConnectionConfig) {\n this.config = {\n ...config,\n maxRetries: config.maxRetries ?? 3,\n defaultTimeoutMs: config.defaultTimeoutMs ?? 30000,\n rejectUnauthorized: config.rejectUnauthorized ?? true,\n };\n }\n\n /** Open the WebSocket connection to CosmosDB Gremlin endpoint. */\n async connect(): Promise<void> {\n if (this.client) return;\n\n const authenticator = new gremlin.driver.auth.PlainTextSaslAuthenticator(\n `/dbs/${this.config.database}/colls/${this.config.container}`,\n this.config.key,\n );\n\n this.client = new gremlin.driver.Client(this.config.endpoint, {\n authenticator,\n traversalsource: 'g',\n rejectUnauthorized: this.config.rejectUnauthorized,\n mimeType: 'application/vnd.gremlin-v2.0+json',\n });\n\n await this.client.open();\n }\n\n /** Close the WebSocket connection. */\n async close(): Promise<void> {\n if (this.client) {\n await this.client.close();\n this.client = null;\n }\n }\n\n /**\n * Submit a parameterized Gremlin query with retry on transient errors.\n * All user values should be passed as bindings (never interpolated into the query string).\n */\n async submit(query: string, bindings?: Record<string, unknown>): Promise<GremlinResult> {\n if (!this.client) {\n throw new Error('CosmosDbConnection: not connected. Call connect() first.');\n }\n\n let lastError: unknown;\n for (let attempt = 0; attempt <= this.config.maxRetries; attempt++) {\n try {\n const resultSet = await this.client.submit(query, bindings);\n const items = resultSet.toArray();\n const requestCharge = extractRequestCharge(resultSet);\n const acc = usageScope.getStore();\n if (acc) {\n acc.calls++;\n if (typeof requestCharge === 'number') acc.ru += requestCharge;\n }\n return { items, requestCharge };\n } catch (err: unknown) {\n lastError = err;\n if (isTransientError(err) && attempt < this.config.maxRetries) {\n const retryAfterMs = getRetryAfterMs(err, attempt);\n const acc = usageScope.getStore();\n if (acc) acc.retries++;\n await sleep(retryAfterMs);\n continue;\n }\n throw err;\n }\n }\n throw lastError;\n }\n\n /** Get the underlying Gremlin client (for advanced usage). */\n getClient(): gremlin.driver.Client {\n if (!this.client) {\n throw new Error('CosmosDbConnection: not connected. Call connect() first.');\n }\n return this.client;\n }\n}\n\n/** Check if an error is a transient CosmosDB error (429 or 503). */\nfunction isTransientError(err: unknown): boolean {\n if (err instanceof Error) {\n const msg = err.message;\n // CosmosDB returns status codes in error messages\n if (msg.includes('429') || msg.includes('RequestRateTooLarge')) return true;\n if (msg.includes('503') || msg.includes('ServiceUnavailable')) return true;\n }\n // Check statusCode property if present\n const statusCode = (err as Record<string, unknown>)?.['statusCode'];\n if (statusCode === 429 || statusCode === 503) return true;\n return false;\n}\n\n/** Extract retry-after from error or use exponential backoff. */\nfunction getRetryAfterMs(err: unknown, attempt: number): number {\n // CosmosDB may include x-ms-retry-after-ms in error attributes\n const retryAfter = (err as Record<string, unknown>)?.['retryAfterMs'];\n if (typeof retryAfter === 'number' && retryAfter > 0) {\n return retryAfter;\n }\n // Exponential backoff: 500ms, 1s, 2s, 4s, ...\n return Math.min(500 * Math.pow(2, attempt), 10000);\n}\n\n/**\n * Extract request charge (RU) from a ResultSet's attributes.\n *\n * CosmosDB Gremlin exposes two related attributes on the response message:\n * - `x-ms-request-charge` — RU for this specific response message\n * - `x-ms-total-request-charge` — cumulative RU across the entire query\n *\n * For single-message responses (single-vertex reads, count(), small projections)\n * the two are equal. For streamed multi-message responses (traversals, path\n * queries, large result sets), the gremlin-javascript driver surfaces only\n * the FINAL message's attributes — and the final message's\n * `x-ms-request-charge` is typically 0 (its own delta) while\n * `x-ms-total-request-charge` carries the real cumulative charge.\n *\n * Therefore: always prefer the total. Falling back to the per-message value\n * with `??` (the previous behaviour) silently zeroed out every traversal\n * because 0 is not nullish.\n *\n * Verified against the Cosmos emulator with rate limiting enabled\n * (`local-tests/ru-raw-probe.mjs` 2026-05-25): a depth-2 path traversal\n * returns `{ x-ms-request-charge: 0, x-ms-total-request-charge: 29.72 }`.\n */\nfunction extractRequestCharge(resultSet: gremlin.driver.ResultSet): number | undefined {\n const attrs = resultSet.attributes as Record<string, unknown> | undefined;\n if (!attrs) return undefined;\n const total = attrs['x-ms-total-request-charge'];\n if (typeof total === 'number') return total;\n const single = attrs['x-ms-request-charge'];\n if (typeof single === 'number') return single;\n return undefined;\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms));\n}\n","// Per-operation RU/call/retry accumulator, shared by every Cosmos endpoint.\n//\n// Extracted from CosmosDbConnection.ts so both the Gremlin client and the\n// CosmosDocumentClient (added for the Cosmos SQL findEntities path) write\n// usage into the same AsyncLocalStorage scope. That way a single public\n// method on the provider — which may touch both endpoints in one call — still\n// emits a single per-operation usage record with the combined totals.\n\nimport { AsyncLocalStorage } from 'node:async_hooks';\n\n/** Per-operation RU accumulator kept in async-local storage. */\nexport interface UsageAccumulator {\n /** Total request charge (RU) across all submits in the current operation. */\n ru: number;\n /** Number of underlying client calls (gremlin submit() or document query()). */\n calls: number;\n /** Number of transient-retry waits observed. */\n retries: number;\n}\n\n/**\n * Module-level AsyncLocalStorage so any client call executed inside a\n * `usageScope.run(...)` block contributes its RU/retry counts to the active\n * accumulator. Providers wrap each public method in a scope and read the\n * aggregated result when the method returns.\n */\nexport const usageScope = new AsyncLocalStorage<UsageAccumulator>();\n","// CosmosDB REST API auth + provisioning helpers.\n//\n// Extracted from CosmosDbProvider.ts so both ensureSchema (Gremlin-side\n// provisioning) and CosmosDocumentClient (Document-endpoint queries) can\n// share the same HMAC-token generator without duplicating it.\n\nimport crypto from 'node:crypto';\n\n/**\n * Generate a CosmosDB REST API authorization token.\n * See: https://learn.microsoft.com/en-us/rest/api/cosmos-db/access-control-on-cosmosdb-resources\n */\nexport function cosmosAuthToken(\n verb: string,\n resourceType: string,\n resourceLink: string,\n date: string,\n key: string,\n): string {\n const payload = `${verb.toLowerCase()}\\n${resourceType.toLowerCase()}\\n${resourceLink}\\n${date.toLowerCase()}\\n\\n`;\n const keyBuffer = Buffer.from(key, 'base64');\n const hmac = crypto.createHmac('sha256', keyBuffer);\n hmac.update(payload);\n const signature = hmac.digest('base64');\n return encodeURIComponent(`type=master&ver=1.0&sig=${signature}`);\n}\n\n/**\n * Create a CosmosDB resource (database or container) via REST API.\n * Returns true if the resource was created, false if it already existed.\n */\nexport async function cosmosRestPut(\n restBase: string,\n key: string,\n urlPath: string,\n resourceLink: string,\n resourceType: string,\n body: Record<string, unknown>,\n rejectUnauthorized: boolean,\n): Promise<boolean> {\n const date = new Date().toUTCString();\n const token = cosmosAuthToken('post', resourceType, resourceLink, date, key);\n\n const url = `${restBase}/${urlPath}`;\n\n const options: RequestInit = {\n method: 'POST',\n headers: {\n 'Authorization': token,\n 'x-ms-version': '2018-12-31',\n 'x-ms-date': date,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(body),\n };\n\n // For self-signed certs (emulator), disable TLS verification process-wide.\n // Caller explicitly opted in via rejectUnauthorized: false.\n if (!rejectUnauthorized) {\n process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = '0';\n }\n\n const response = await fetch(url, options);\n\n if (response.status === 201) return true; // Created\n if (response.status === 409) return false; // Already exists\n\n const text = await response.text();\n throw new Error(`CosmosDB REST ${response.status}: ${text}`);\n}\n","// CosmosDocumentClient — Cosmos NoSQL (Document) endpoint client.\n//\n// Used by query paths that the Gremlin subset can't express server-side\n// (substring + case-insensitive matching, structured property predicates).\n// Both this client and CosmosDbConnection (Gremlin) write RU into the active\n// usageScope so a single public method spanning both endpoints emits one\n// usage record.\n//\n// Transport: raw fetch + HMAC, the same pattern as cosmos-rest-auth.ts. No\n// @azure/cosmos SDK dependency — keeps the provider's runtime footprint small\n// and matches what `ensureSchema()` already does for container provisioning.\n\nimport { cosmosAuthToken } from './cosmos-rest-auth.js';\nimport { usageScope } from './usage.js';\n\nexport interface CosmosDocumentClientConfig {\n /** Cosmos NoSQL REST endpoint (e.g. https://host.docker.internal:8081). */\n restEndpoint: string;\n /** CosmosDB primary key (base64). */\n key: string;\n /** Database id. */\n database: string;\n /** Container id. */\n container: string;\n /** Whether to reject unauthorized TLS certs — set false for emulator. */\n rejectUnauthorized: boolean;\n /** Max retries for 429/503 (default: 3). */\n maxRetries?: number;\n /** Default query timeout in ms (default: 30000). Reserved for future use. */\n defaultTimeoutMs?: number;\n}\n\nexport interface CosmosQueryParameter {\n /** Parameter name including the leading '@' (e.g. '@rid'). */\n name: string;\n value: unknown;\n}\n\nexport interface CosmosQueryOptions {\n /**\n * Partition-key value. When provided, the query is partition-scoped and\n * Cosmos charges proportional RU. When omitted, cross-partition is enabled —\n * findEntities always supplies a partition key (repositoryId).\n */\n partitionKey?: string;\n /** Request query metrics in the response (`x-ms-documentdb-query-metrics`). */\n populateMetrics?: boolean;\n /** Continuation token from a previous page, if any. */\n continuationToken?: string | null;\n}\n\nexport interface CosmosQueryResult<T> {\n documents: T[];\n /** Request charge in RU, from `x-ms-request-charge`. */\n requestCharge: number;\n /** Query metrics from `x-ms-documentdb-query-metrics` (only present when populateMetrics is true). */\n queryMetrics: string | null;\n /** Continuation token for the next page, or null if exhausted. */\n continuationToken: string | null;\n}\n\nexport interface CosmosContainerProperties {\n id: string;\n partitionKey: { paths: string[]; kind: string };\n indexingPolicy: {\n indexingMode: string;\n automatic: boolean;\n includedPaths: Array<{ path: string }>;\n excludedPaths: Array<{ path: string }>;\n };\n}\n\n/** Internal — narrow alias for the fetch function so tests can inject a stub. */\ntype FetchLike = typeof fetch;\n\n/**\n * Cosmos NoSQL (Document) endpoint client. Issues parameterised SQL queries\n * and reads container metadata. RU is accumulated into the active usageScope.\n */\nexport class CosmosDocumentClient {\n private readonly config: Required<Pick<CosmosDocumentClientConfig, 'maxRetries' | 'defaultTimeoutMs'>> & CosmosDocumentClientConfig;\n private readonly fetchImpl: FetchLike;\n\n /**\n * `fetchImpl` is for tests only — production code should pass nothing and\n * inherit `globalThis.fetch`. Keeping it on the constructor (rather than\n * stubbing globals) means each test instance is hermetic.\n */\n constructor(config: CosmosDocumentClientConfig, fetchImpl?: FetchLike) {\n this.config = {\n ...config,\n maxRetries: config.maxRetries ?? 3,\n defaultTimeoutMs: config.defaultTimeoutMs ?? 30000,\n };\n this.fetchImpl = fetchImpl ?? fetch;\n }\n\n /**\n * Execute a parameterised Cosmos SQL query against the container's `docs`\n * resource. Retries on 429/503 with the response's `x-ms-retry-after-ms`\n * when present, otherwise exponential backoff. RU is accumulated into the\n * active {@link usageScope}.\n */\n public async query<T = unknown>(\n sql: string,\n parameters: CosmosQueryParameter[],\n options: CosmosQueryOptions,\n ): Promise<CosmosQueryResult<T>> {\n const resourceLink = `dbs/${this.config.database}/colls/${this.config.container}`;\n const url = `${this.restBase()}/${resourceLink}/docs`;\n\n // For self-signed certs (emulator), disable TLS verification process-wide.\n // Caller opted in via rejectUnauthorized: false. Same pattern as cosmosRestPut.\n if (!this.config.rejectUnauthorized) {\n process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = '0';\n }\n\n const body = JSON.stringify({ query: sql, parameters });\n\n for (let attempt = 0; attempt <= this.config.maxRetries; attempt++) {\n const date = new Date().toUTCString();\n const token = cosmosAuthToken('post', 'docs', resourceLink, date, this.config.key);\n const headers: Record<string, string> = {\n 'Authorization': token,\n 'x-ms-version': '2018-12-31',\n 'x-ms-date': date,\n 'Content-Type': 'application/query+json',\n 'x-ms-documentdb-isquery': 'true',\n };\n if (options.partitionKey != null) {\n headers['x-ms-documentdb-partitionkey'] = JSON.stringify([options.partitionKey]);\n } else {\n headers['x-ms-documentdb-query-enablecrosspartition'] = 'true';\n }\n if (options.populateMetrics) {\n headers['x-ms-documentdb-populatequerymetrics'] = 'true';\n }\n if (options.continuationToken) {\n headers['x-ms-continuation'] = options.continuationToken;\n }\n\n const response = await this.fetchImpl(url, { method: 'POST', headers, body });\n\n if (response.status === 429 || response.status === 503) {\n if (attempt < this.config.maxRetries) {\n const waitMs = parseRetryAfterMs(response, attempt);\n const acc = usageScope.getStore();\n if (acc) acc.retries++;\n await sleep(waitMs);\n continue;\n }\n const text = await response.text();\n throw new Error(`CosmosDB Document query ${response.status}: ${text}`);\n }\n\n if (!response.ok) {\n const text = await response.text();\n throw new Error(`CosmosDB Document query ${response.status}: ${text}`);\n }\n\n const json = (await response.json()) as { Documents?: unknown[]; _count?: number };\n const requestCharge = Number(response.headers.get('x-ms-request-charge') ?? '0') || 0;\n const queryMetrics = response.headers.get('x-ms-documentdb-query-metrics');\n const continuationToken = response.headers.get('x-ms-continuation');\n\n const acc = usageScope.getStore();\n if (acc) {\n acc.calls++;\n acc.ru += requestCharge;\n }\n\n return {\n documents: (json.Documents ?? []) as T[],\n requestCharge,\n queryMetrics,\n continuationToken,\n };\n }\n // Unreachable — the loop either returns or throws on the final attempt.\n throw new Error('CosmosDocumentClient.query: retry loop exhausted without resolution');\n }\n\n /**\n * Read container metadata (id, partition key, indexing policy). Used by\n * `ensureSchema()` to warn when externally-provisioned containers have\n * excluded paths the findEntities SQL needs.\n */\n public async getContainerProperties(): Promise<CosmosContainerProperties> {\n const resourceLink = `dbs/${this.config.database}/colls/${this.config.container}`;\n const url = `${this.restBase()}/${resourceLink}`;\n\n if (!this.config.rejectUnauthorized) {\n process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = '0';\n }\n\n const date = new Date().toUTCString();\n const token = cosmosAuthToken('get', 'colls', resourceLink, date, this.config.key);\n\n const response = await this.fetchImpl(url, {\n method: 'GET',\n headers: {\n 'Authorization': token,\n 'x-ms-version': '2018-12-31',\n 'x-ms-date': date,\n },\n });\n\n if (!response.ok) {\n const text = await response.text();\n throw new Error(`CosmosDB Document getContainerProperties ${response.status}: ${text}`);\n }\n\n return (await response.json()) as CosmosContainerProperties;\n }\n\n private restBase(): string {\n return this.config.restEndpoint.replace(/\\/+$/, '');\n }\n}\n\nfunction parseRetryAfterMs(response: Response, attempt: number): number {\n const header = response.headers.get('x-ms-retry-after-ms');\n if (header) {\n const n = Number(header);\n if (Number.isFinite(n) && n > 0) return n;\n }\n return Math.min(500 * Math.pow(2, attempt), 10000);\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms));\n}\n","// Mapping — convert between Gremlin results and StoredEntity/StoredRelationship types\n\nimport type { StoredEntity } from '@utaba/deep-memory/types';\nimport type { StoredRelationship } from '@utaba/deep-memory/types';\nimport type { Provenance } from '@utaba/deep-memory/types';\nimport type { StoredRepository, StoredRepositorySummary } from '@utaba/deep-memory/types';\nimport type { GovernanceConfig } from '@utaba/deep-memory/types';\nimport type { VocabularyChangeRecord } from '@utaba/deep-memory/types';\n\n// ─── Projection field lists ───────────────────────────────────────\n//\n// The GremlinCompiler emits read-path projections listing these exact field\n// names. The mapper functions below (entityFromGremlin, relationshipFromGremlin)\n// consume the same key set. Keeping the two in lockstep is enforced by the\n// cross-package test in mapping.test.ts, which imports the compiler's own\n// list and asserts equality.\n//\n// `embedding` is intentionally excluded — read paths never ship the embedding\n// over the wire. The vector-search path passes an explicit `loadEmbeddings`\n// option to opt back in.\n//\n// Synthetic projection-only fields (`__kind`) are NOT stored properties and\n// are not in this list — the compiler adds them as discriminator markers but\n// the mapper does not read them.\n\nexport const STORED_ENTITY_FIELDS = [\n 'id',\n 'entityType',\n 'entityLabel',\n 'slug',\n 'summary',\n 'properties',\n 'data',\n 'dataFormat',\n 'createdBy',\n 'createdByType',\n 'createdAt',\n 'createdInConversation',\n 'createdFromMessage',\n 'modifiedBy',\n 'modifiedByType',\n 'modifiedAt',\n 'modifiedInConversation',\n 'modifiedFromMessage',\n] as const;\n\nexport const STORED_RELATIONSHIP_FIELDS = [\n 'id',\n 'relationshipType',\n 'sourceEntityId',\n 'targetEntityId',\n 'properties',\n 'bidirectional',\n 'createdBy',\n 'createdByType',\n 'createdAt',\n 'createdInConversation',\n 'createdFromMessage',\n 'modifiedBy',\n 'modifiedByType',\n 'modifiedAt',\n 'modifiedInConversation',\n 'modifiedFromMessage',\n] as const;\n\n// Repository projection — used by getRepository / listRepositories. The\n// compiler does not deal with `_repository` vertices, so the projection chain\n// lives here (no cross-package sync needed). Mirror what `repositoryFromGremlin`\n// and `repositorySummaryFromGremlin` consume.\nexport const STORED_REPOSITORY_FIELDS = [\n 'id',\n 'repositoryId',\n 'repoLabel',\n 'description',\n 'type',\n 'legal',\n 'owner',\n 'governanceConfig',\n 'metadata',\n 'createdAt',\n 'createdBy',\n] as const;\n\n/**\n * Build a Gremlin `.project(...).by(...)...` chain expression for a\n * `_repository` vertex, with no leading dot. Append after a vertex predicate.\n * `repoLabel`, `governanceConfig`, `createdAt`, `createdBy`, and `repositoryId`\n * are always written on create; the optional fields use coalesce-default-empty\n * to avoid the \"by('optionalField') crashes when absent\" failure mode (see\n * docs/cosmosdb-gremlin-compatibility.md §Constraints).\n */\nexport function buildRepositoryProjectChain(): string {\n return [\n `project('id','repositoryId','repoLabel','description','type','legal','owner','governanceConfig','metadata','createdAt','createdBy')`,\n `.by(id)`,\n `.by('repositoryId')`,\n `.by('repoLabel')`,\n `.by(coalesce(values('description'), constant('')))`,\n `.by(coalesce(values('type'), constant('')))`,\n `.by(coalesce(values('legal'), constant('')))`,\n `.by(coalesce(values('owner'), constant('')))`,\n `.by('governanceConfig')`,\n `.by(coalesce(values('metadata'), constant('')))`,\n `.by('createdAt')`,\n `.by('createdBy')`,\n ].join('');\n}\n\n// ─── Gremlin property extraction ──────────────────────────────────\n\n/**\n * Gremlin valueMap(true) returns properties as arrays (multi-value).\n * CosmosDB single-cardinality means each array has exactly one element.\n * This helper unwraps the first value.\n */\nfunction unwrap(val: unknown): unknown {\n if (Array.isArray(val) && val.length > 0) return val[0];\n return val;\n}\n\n/** Safely unwrap a string value from a Gremlin result. */\nfunction unwrapStr(val: unknown): string {\n const v = unwrap(val);\n return typeof v === 'string' ? v : String(v ?? '');\n}\n\n/** Safely unwrap an optional string. */\nfunction unwrapOptStr(val: unknown): string | undefined {\n const v = unwrap(val);\n return v != null && v !== '' ? String(v) : undefined;\n}\n\n/** Safely parse JSON, returning a default on failure. */\nfunction safeParseJson<T>(val: unknown, fallback: T): T {\n if (val == null) return fallback;\n const str = typeof val === 'string' ? val : String(unwrap(val));\n if (!str || str === '') return fallback;\n try {\n return JSON.parse(str) as T;\n } catch {\n return fallback;\n }\n}\n\n// ─── Provenance ───────────────────────────────────────────────────\n\nfunction provenanceFromGremlin(props: Record<string, unknown>): Provenance {\n return {\n createdBy: unwrapStr(props['createdBy']),\n createdByType: (unwrapStr(props['createdByType']) || 'agent') as 'user' | 'agent',\n createdAt: unwrapStr(props['createdAt']),\n createdInConversation: unwrapOptStr(props['createdInConversation']),\n createdFromMessage: unwrapOptStr(props['createdFromMessage']),\n modifiedBy: unwrapStr(props['modifiedBy']),\n modifiedByType: (unwrapStr(props['modifiedByType']) || 'agent') as 'user' | 'agent',\n modifiedAt: unwrapStr(props['modifiedAt']),\n modifiedInConversation: unwrapOptStr(props['modifiedInConversation']),\n modifiedFromMessage: unwrapOptStr(props['modifiedFromMessage']),\n };\n}\n\n// ─── Entity mapping ───────────────────────────────────────────────\n\nexport function entityFromGremlin(props: Record<string, unknown>): StoredEntity {\n const embeddingStr = unwrapOptStr(props['embedding']);\n return {\n id: unwrapStr(props['id']),\n slug: unwrapStr(props['slug']),\n entityType: unwrapStr(props['entityType']),\n label: unwrapStr(props['entityLabel']),\n summary: unwrapOptStr(props['summary']),\n properties: safeParseJson(unwrap(props['properties']), {}),\n data: unwrapOptStr(props['data']),\n dataFormat: unwrapOptStr(props['dataFormat']),\n provenance: provenanceFromGremlin(props),\n embedding: embeddingStr ? (safeParseJson<number[] | undefined>(embeddingStr, undefined)) : undefined,\n };\n}\n\n// ─── Document-endpoint mapping ────────────────────────────────────\n//\n// Cosmos NoSQL (Document) endpoint sees Gremlin-managed properties as\n// `[{ _value, id }]` arrays rather than flat scalars. The Gremlin reserved\n// scalars (`id`, the partition-key `repositoryId`, the vertex `label` token)\n// stay flat on the document. Probed and confirmed 2026-05-26 — see\n// local-tests/baseline/phase-cosmos-sql-shape-probe-results.md.\n\n/** Pluck the underlying value of a Gremlin-managed property from a Document-endpoint doc. */\nfunction pluckDocValue(doc: Record<string, unknown>, key: string): unknown {\n const arr = doc[key];\n if (Array.isArray(arr) && arr.length > 0) {\n const entry = arr[0] as Record<string, unknown> | undefined;\n if (entry && typeof entry === 'object') {\n return entry['_value'];\n }\n }\n return undefined;\n}\n\nfunction pluckDocStr(doc: Record<string, unknown>, key: string): string {\n const v = pluckDocValue(doc, key);\n return typeof v === 'string' ? v : String(v ?? '');\n}\n\nfunction pluckDocOptStr(doc: Record<string, unknown>, key: string): string | undefined {\n const v = pluckDocValue(doc, key);\n return v != null && v !== '' ? String(v) : undefined;\n}\n\nfunction provenanceFromDocument(doc: Record<string, unknown>): Provenance {\n return {\n createdBy: pluckDocStr(doc, 'createdBy'),\n createdByType: (pluckDocStr(doc, 'createdByType') || 'agent') as 'user' | 'agent',\n createdAt: pluckDocStr(doc, 'createdAt'),\n createdInConversation: pluckDocOptStr(doc, 'createdInConversation'),\n createdFromMessage: pluckDocOptStr(doc, 'createdFromMessage'),\n modifiedBy: pluckDocStr(doc, 'modifiedBy'),\n modifiedByType: (pluckDocStr(doc, 'modifiedByType') || 'agent') as 'user' | 'agent',\n modifiedAt: pluckDocStr(doc, 'modifiedAt'),\n modifiedInConversation: pluckDocOptStr(doc, 'modifiedInConversation'),\n modifiedFromMessage: pluckDocOptStr(doc, 'modifiedFromMessage'),\n };\n}\n\n/**\n * Project a Document-endpoint result row into a StoredEntity. Distinct from\n * `entityFromGremlin` (which reads the projected `valueMap`-style shape) —\n * here every Gremlin-managed property is `[{_value, id}]` while `id` and the\n * `label` token are flat. The `entityType` *property* (not the `label` token)\n * is authoritative — see `packages/storage-cosmosdb/src/queries/entity.ts`\n * for the matching write-path decision.\n */\nexport function entityFromDocument(doc: Record<string, unknown>): StoredEntity {\n const id = typeof doc['id'] === 'string' ? doc['id'] : String(doc['id'] ?? '');\n const embeddingStr = pluckDocOptStr(doc, 'embedding');\n return {\n id,\n slug: pluckDocStr(doc, 'slug'),\n entityType: pluckDocStr(doc, 'entityType'),\n label: pluckDocStr(doc, 'entityLabel'),\n summary: pluckDocOptStr(doc, 'summary'),\n properties: safeParseJson(pluckDocValue(doc, 'properties'), {}),\n data: pluckDocOptStr(doc, 'data'),\n dataFormat: pluckDocOptStr(doc, 'dataFormat'),\n provenance: provenanceFromDocument(doc),\n embedding: embeddingStr ? safeParseJson<number[] | undefined>(embeddingStr, undefined) : undefined,\n };\n}\n\n// ─── Relationship mapping ─────────────────────────────────────────\n\nexport function relationshipFromGremlin(props: Record<string, unknown>): StoredRelationship {\n const bidir = unwrap(props['bidirectional']);\n return {\n id: unwrapStr(props['id']),\n relationshipType: unwrapStr(props['relationshipType']),\n sourceEntityId: unwrapStr(props['sourceEntityId']),\n targetEntityId: unwrapStr(props['targetEntityId']),\n properties: safeParseJson(unwrap(props['properties']), {}),\n bidirectional: bidir === true || bidir === 'true',\n provenance: provenanceFromGremlin(props),\n };\n}\n\n// ─── Repository mapping ───────────────────────────────────────────\n\nexport function repositoryFromGremlin(props: Record<string, unknown>): StoredRepository {\n return {\n repositoryId: unwrapStr(props['repositoryId']),\n type: unwrapOptStr(props['type']),\n label: unwrapStr(props['repoLabel']),\n description: unwrapOptStr(props['description']),\n legal: unwrapOptStr(props['legal']),\n owner: unwrapOptStr(props['owner']),\n governanceConfig: safeParseJson<GovernanceConfig>(unwrap(props['governanceConfig']), { mode: 'open' }),\n metadata: safeParseJson(unwrap(props['metadata']), undefined),\n createdAt: unwrapStr(props['createdAt']),\n createdBy: unwrapStr(props['createdBy']),\n };\n}\n\nexport function repositorySummaryFromGremlin(props: Record<string, unknown>): StoredRepositorySummary {\n return {\n repositoryId: unwrapStr(props['repositoryId']),\n type: unwrapOptStr(props['type']),\n label: unwrapStr(props['repoLabel']),\n description: unwrapOptStr(props['description']),\n governanceConfig: safeParseJson<GovernanceConfig>(unwrap(props['governanceConfig']), { mode: 'open' }),\n };\n}\n\n// ─── Vocabulary change-log mapping ────────────────────────────────\n\nexport function changeRecordFromGremlin(props: Record<string, unknown>): VocabularyChangeRecord {\n return {\n changeId: unwrapStr(props['changeId']),\n changeType: unwrapStr(props['changeType']) as VocabularyChangeRecord['changeType'],\n typeName: unwrapStr(props['typeName']),\n previousVersion: unwrapOptStr(props['previousVersion']),\n newVersion: unwrapStr(props['newVersion']),\n proposedBy: unwrapStr(props['proposedBy']),\n proposedAt: unwrapStr(props['proposedAt']),\n approvedBy: unwrapOptStr(props['approvedBy']),\n approvedAt: unwrapOptStr(props['approvedAt']),\n reason: unwrapStr(props['reason']),\n };\n}\n\n// ─── Fixed-shape property ladders ─────────────────────────────────\n//\n// Every addV / addE / upsert write uses a canonical fixed-length property\n// ladder so the Gremlin server can reuse a single compiled plan across all\n// writes of a given vertex/edge family. Required slots emit `.property('key',\n// pN)`; optional slots emit `.choose(__.constant(pN).is(neq(absentSentinel)),\n// __.property('key', pN), __.identity())` — the choose-skip drops the\n// property at runtime when the binding equals the sentinel, keeping the\n// query string constant regardless of which optional fields the caller\n// supplied.\n//\n// `id` and `repositoryId` are NOT part of these ladders — both are written\n// explicitly at create time (`.property('id', vid).property('repositoryId',\n// rid)`) and are immutable on update (Cosmos rejects partition-key mutation).\n//\n// Slot order is FIXED. Adding a new slot goes at the END only; reordering\n// or removing breaks the cached plan + introduces a different query string.\n//\n// Live-validated 2026-05-26 — see docs/cosmosdb-gremlin-compatibility.md\n// (choose-skip / fixed-ladder entries).\n\n/** Binding value used to signal an absent optional string slot. */\nexport const ABSENT_STRING_SENTINEL = '';\n\n/** Binding name in the emitted query referencing the absent-sentinel value. */\nconst SENTINEL_BINDING = 'absentSentinel';\n\nconst ENTITY_REQUIRED_SLOTS = [\n 'entityType',\n 'entityLabel',\n 'slug',\n 'properties',\n 'createdBy',\n 'createdByType',\n 'createdAt',\n 'modifiedBy',\n 'modifiedByType',\n 'modifiedAt',\n] as const;\n\nconst ENTITY_OPTIONAL_SLOTS = [\n 'summary',\n 'data',\n 'dataFormat',\n 'embedding',\n 'createdInConversation',\n 'createdFromMessage',\n 'modifiedInConversation',\n 'modifiedFromMessage',\n] as const;\n\nconst RELATIONSHIP_REQUIRED_SLOTS = [\n 'relationshipType',\n 'sourceEntityId',\n 'targetEntityId',\n 'bidirectional',\n 'properties',\n 'createdBy',\n 'createdByType',\n 'createdAt',\n 'modifiedBy',\n 'modifiedByType',\n 'modifiedAt',\n] as const;\n\nconst RELATIONSHIP_OPTIONAL_SLOTS = [\n 'createdInConversation',\n 'createdFromMessage',\n 'modifiedInConversation',\n 'modifiedFromMessage',\n] as const;\n\nconst REPOSITORY_REQUIRED_SLOTS = [\n 'repoLabel',\n 'governanceConfig',\n 'createdAt',\n 'createdBy',\n] as const;\n\nconst REPOSITORY_OPTIONAL_SLOTS = [\n 'description',\n 'type',\n 'legal',\n 'owner',\n 'metadata',\n] as const;\n\nfunction buildLadder(\n required: readonly string[],\n optional: readonly string[],\n paramPrefix: string,\n): string {\n const parts: string[] = [];\n let i = 0;\n for (const slot of required) {\n parts.push(`.property('${slot}', ${paramPrefix}${i++})`);\n }\n for (const slot of optional) {\n parts.push(\n `.choose(__.constant(${paramPrefix}${i}).is(neq(${SENTINEL_BINDING})),` +\n ` __.property('${slot}', ${paramPrefix}${i}),` +\n ` __.identity())`,\n );\n i++;\n }\n return parts.join('');\n}\n\nfunction buildLadderBindings(\n required: readonly string[],\n optional: readonly string[],\n paramPrefix: string,\n values: Record<string, string | number | boolean | null | undefined>,\n): Record<string, string | number | boolean> {\n const bindings: Record<string, string | number | boolean> = {};\n let i = 0;\n for (const slot of required) {\n const v = values[slot];\n if (v == null) {\n throw new Error(`Fixed-shape ladder: required slot '${slot}' is null/undefined`);\n }\n bindings[`${paramPrefix}${i++}`] = v;\n }\n for (const slot of optional) {\n const v = values[slot];\n bindings[`${paramPrefix}${i++}`] = v ?? ABSENT_STRING_SENTINEL;\n }\n return bindings;\n}\n\n/**\n * Emit the entity property ladder — same Gremlin string for every entity\n * write regardless of which optional fields are present. Prepend the\n * vertex-create prefix (e.g. `addV(vertexLabel).property('id', vid)\n * .property('repositoryId', rid)`) when on a create branch; on an update\n * branch (existing vertex via `unfold()`) use this chain directly.\n */\nexport function buildEntityPropertyLadder(): string {\n return buildLadder(ENTITY_REQUIRED_SLOTS, ENTITY_OPTIONAL_SLOTS, 'p');\n}\n\n/** Build the canonical entity ladder bindings (p0..p17 + absentSentinel). */\nexport function entityToLadderBindings(\n entity: StoredEntity,\n): Record<string, string | number | boolean> {\n const bindings = buildLadderBindings(ENTITY_REQUIRED_SLOTS, ENTITY_OPTIONAL_SLOTS, 'p', {\n entityType: entity.entityType,\n entityLabel: entity.label,\n slug: entity.slug,\n properties: JSON.stringify(entity.properties ?? {}),\n createdBy: entity.provenance.createdBy,\n createdByType: entity.provenance.createdByType,\n createdAt: entity.provenance.createdAt,\n modifiedBy: entity.provenance.modifiedBy,\n modifiedByType: entity.provenance.modifiedByType,\n modifiedAt: entity.provenance.modifiedAt,\n summary: entity.summary,\n data: entity.data,\n dataFormat: entity.dataFormat,\n embedding: entity.embedding != null ? JSON.stringify(entity.embedding) : undefined,\n createdInConversation: entity.provenance.createdInConversation,\n createdFromMessage: entity.provenance.createdFromMessage,\n modifiedInConversation: entity.provenance.modifiedInConversation,\n modifiedFromMessage: entity.provenance.modifiedFromMessage,\n });\n bindings[SENTINEL_BINDING] = ABSENT_STRING_SENTINEL;\n return bindings;\n}\n\n/** Edge counterpart of `buildEntityPropertyLadder()` — different slot list. */\nexport function buildRelationshipPropertyLadder(): string {\n return buildLadder(RELATIONSHIP_REQUIRED_SLOTS, RELATIONSHIP_OPTIONAL_SLOTS, 'p');\n}\n\n/** Build the canonical relationship ladder bindings (p0..p14 + absentSentinel). */\nexport function relationshipToLadderBindings(\n rel: StoredRelationship,\n): Record<string, string | number | boolean> {\n const bindings = buildLadderBindings(\n RELATIONSHIP_REQUIRED_SLOTS,\n RELATIONSHIP_OPTIONAL_SLOTS,\n 'p',\n {\n relationshipType: rel.relationshipType,\n sourceEntityId: rel.sourceEntityId,\n targetEntityId: rel.targetEntityId,\n bidirectional: rel.bidirectional,\n properties: JSON.stringify(rel.properties ?? {}),\n createdBy: rel.provenance.createdBy,\n createdByType: rel.provenance.createdByType,\n createdAt: rel.provenance.createdAt,\n modifiedBy: rel.provenance.modifiedBy,\n modifiedByType: rel.provenance.modifiedByType,\n modifiedAt: rel.provenance.modifiedAt,\n createdInConversation: rel.provenance.createdInConversation,\n createdFromMessage: rel.provenance.createdFromMessage,\n modifiedInConversation: rel.provenance.modifiedInConversation,\n modifiedFromMessage: rel.provenance.modifiedFromMessage,\n },\n );\n bindings[SENTINEL_BINDING] = ABSENT_STRING_SENTINEL;\n return bindings;\n}\n\n/**\n * Repository property ladder — slot list matches the writable surface of\n * StorageRepositoryConfig (the `id` and `repositoryId` slots are written\n * separately by the caller).\n */\nexport function buildRepositoryPropertyLadder(): string {\n return buildLadder(REPOSITORY_REQUIRED_SLOTS, REPOSITORY_OPTIONAL_SLOTS, 'p');\n}\n\n/** Build the canonical repository ladder bindings. */\nexport function repositoryConfigToLadderBindings(\n config: {\n label: string;\n governanceConfig: unknown;\n createdAt: string;\n createdBy: string;\n description?: string;\n type?: string;\n legal?: string;\n owner?: string;\n metadata?: Record<string, unknown>;\n },\n): Record<string, string | number | boolean> {\n const bindings = buildLadderBindings(\n REPOSITORY_REQUIRED_SLOTS,\n REPOSITORY_OPTIONAL_SLOTS,\n 'p',\n {\n repoLabel: config.label,\n governanceConfig: JSON.stringify(config.governanceConfig),\n createdAt: config.createdAt,\n createdBy: config.createdBy,\n description: config.description,\n type: config.type,\n legal: config.legal,\n owner: config.owner,\n metadata: config.metadata != null ? JSON.stringify(config.metadata) : undefined,\n },\n );\n bindings[SENTINEL_BINDING] = ABSENT_STRING_SENTINEL;\n return bindings;\n}\n","// Repository CRUD Gremlin queries\n\nimport type { CosmosDbConnection } from '../CosmosDbConnection.js';\nimport type {\n StorageRepositoryConfig,\n StoredRepository,\n StoredRepositorySummary,\n RepositoryFilter,\n RepositoryStats,\n RepositoryUpdate,\n} from '@utaba/deep-memory/types';\nimport type { PaginatedResult, DeleteProgressCallback } from '@utaba/deep-memory/types';\nimport {\n buildRepositoryProjectChain,\n buildRepositoryPropertyLadder,\n repositoryConfigToLadderBindings,\n repositoryFromGremlin,\n} from '../mapping.js';\nimport { DuplicateRepositoryError, RepositoryNotFoundError } from '@utaba/deep-memory';\n\nconst REPO_LABEL = '_repository';\n\n// Sentinel vertex pinned in a fixed `_index` partition. It mirrors the list of\n// every repository id in the container so `listRepositories` can be a single\n// partition-scoped read rather than a cross-partition scan over every\n// `_repository` vertex. ensureSchema bootstraps the sentinel; createRepository\n// and deleteRepository keep it in sync atomically via single-submit\n// cross-partition `sideEffect` updates.\n//\n// Shape: `repositoryIds: string[]` — flat ids. listRepositories hydrates each\n// id via partition-scoped getRepository in parallel. Pagination and any\n// `filter.type` narrowing happen client-side after hydration.\nexport const REPOSITORY_INDEX_VERTEX_ID = '_repository_index';\nexport const REPOSITORY_INDEX_PARTITION = '_index';\nconst REPOSITORY_INDEX_LABEL = '_repository_index';\n\nfunction repoVertexId(repositoryId: string): string {\n return `repo:${repositoryId}`;\n}\n\n/**\n * Bootstrap the `_repository_index` sentinel vertex.\n *\n * Called once per Cosmos account by {@link CosmosDbProvider.ensureSchema}.\n * If the sentinel is missing, runs the legacy cross-partition\n * `g.V().hasLabel('_repository').values('repositoryId')` scan to collect every\n * existing repository's id and writes the sentinel with that array. This is\n * the only cross-partition Gremlin read remaining after Phase 11 — it runs\n * once per account on first migration and never again.\n *\n * Returns the number of pre-existing repositories the sentinel was backfilled\n * with, or `null` if the sentinel already existed (no migration needed).\n */\nexport async function ensureRepositoryIndex(conn: CosmosDbConnection): Promise<number | null> {\n // Cheap existence check — single doc fetch in the `_index` partition.\n const existing = await conn.submit(\n \"g.V().has('repositoryId', pk).hasId(sid).count()\",\n { pk: REPOSITORY_INDEX_PARTITION, sid: REPOSITORY_INDEX_VERTEX_ID },\n );\n if (Number(existing.items[0] ?? 0) > 0) {\n return null;\n }\n\n // Sentinel missing — run the legacy cross-partition scan ONCE to collect\n // every existing repo id. After this runs the sentinel is authoritative\n // and the legacy scan is never issued again.\n const scan = await conn.submit(\n \"g.V().hasLabel('_repository').values('repositoryId')\",\n {},\n );\n const ids = scan.items\n .map((item) => (typeof item === 'string' ? item : String(item ?? '')))\n .filter((id) => id.length > 0);\n\n await conn.submit(\n \"g.addV('\" + REPOSITORY_INDEX_LABEL + \"')\" +\n \".property('id', sid).property('repositoryId', pk).property('repositoryIds', initial)\",\n {\n pk: REPOSITORY_INDEX_PARTITION,\n sid: REPOSITORY_INDEX_VERTEX_ID,\n initial: JSON.stringify(ids),\n },\n );\n\n return ids.length;\n}\n\n/**\n * Read the `repositoryIds` array from the sentinel. Returns `[]` if the\n * sentinel is missing — callers that need the sentinel to exist should\n * ensure {@link CosmosDbProvider.ensureSchema} has run first.\n */\nasync function readRepositoryIndex(conn: CosmosDbConnection): Promise<string[]> {\n const result = await conn.submit(\n \"g.V().has('repositoryId', pk).hasId(sid).values('repositoryIds')\",\n { pk: REPOSITORY_INDEX_PARTITION, sid: REPOSITORY_INDEX_VERTEX_ID },\n );\n if (result.items.length === 0) return [];\n const raw = result.items[0];\n const json = typeof raw === 'string' ? raw : String(raw ?? '');\n if (!json) return [];\n try {\n const parsed = JSON.parse(json);\n return Array.isArray(parsed) ? parsed.filter((id): id is string => typeof id === 'string') : [];\n } catch {\n return [];\n }\n}\n\n/** Build a .property() chain for Gremlin vertex creation/update. */\nfunction propertyChain(bindings: Record<string, unknown>, props: Record<string, string | number | boolean | null | undefined>, startIndex: number): { chain: string; nextIndex: number } {\n const parts: string[] = [];\n let idx = startIndex;\n for (const [key, value] of Object.entries(props)) {\n if (value == null) continue;\n const paramName = `p${idx++}`;\n bindings[paramName] = value;\n parts.push(`.property('${key}', ${paramName})`);\n }\n return { chain: parts.join(''), nextIndex: idx };\n}\n\n// Fixed-shape property ladder for `_repository` vertex creation. The emitted\n// query string is identical across every createRepository call regardless of\n// which optional fields (description / type / legal / owner / metadata) are\n// set, so the server-side plan cache reuses one compiled plan. A trailing\n// `.sideEffect(...)` step updates the `_repository_index` sentinel in the\n// `_index` partition atomically with the addV — probe-verified single-submit\n// cross-partition mutation on the emulator (2026-05-26).\nconst REPOSITORY_CREATE_QUERY =\n `g.addV('${REPO_LABEL}').property('id', vid).property('repositoryId', rid)${buildRepositoryPropertyLadder()}` +\n \".sideEffect(__.V().has('repositoryId', pk).hasId(sid).property('repositoryIds', updatedIndex))\";\n\nexport async function createRepository(\n conn: CosmosDbConnection,\n config: StorageRepositoryConfig,\n): Promise<StoredRepository> {\n const vertexId = repoVertexId(config.repositoryId);\n\n // Existence check — partition-scoped via `has('repositoryId', rid)` before\n // `hasId(vid)`. hasId alone is post-routing and fans out across partitions.\n const existing = await conn.submit(\n \"g.V().has('repositoryId', rid).hasId(vid).has('label', lbl).count()\",\n { vid: vertexId, rid: config.repositoryId, lbl: REPO_LABEL },\n );\n if (existing.items.length > 0 && Number(existing.items[0]) > 0) {\n throw new DuplicateRepositoryError(config.repositoryId);\n }\n\n // Compute the updated sentinel array client-side before the atomic write.\n // One extra round-trip (the sentinel read), but it lets the actual create\n // submit be a single round-trip that does both the addV and the sentinel\n // update via sideEffect.\n const currentIds = await readRepositoryIndex(conn);\n const updatedIds = currentIds.includes(config.repositoryId)\n ? currentIds\n : [...currentIds, config.repositoryId];\n\n const bindings: Record<string, unknown> = {\n vid: vertexId,\n rid: config.repositoryId,\n pk: REPOSITORY_INDEX_PARTITION,\n sid: REPOSITORY_INDEX_VERTEX_ID,\n updatedIndex: JSON.stringify(updatedIds),\n ...repositoryConfigToLadderBindings(config),\n };\n\n await conn.submit(REPOSITORY_CREATE_QUERY, bindings);\n\n return {\n repositoryId: config.repositoryId,\n type: config.type,\n label: config.label,\n description: config.description,\n legal: config.legal,\n owner: config.owner,\n governanceConfig: config.governanceConfig,\n metadata: config.metadata,\n createdAt: config.createdAt,\n createdBy: config.createdBy,\n };\n}\n\nexport async function getRepository(\n conn: CosmosDbConnection,\n repositoryId: string,\n): Promise<StoredRepository | null> {\n // `has('repositoryId', rid)` scopes the lookup to a single partition before\n // `hasId(vid)`; hasId alone fans out across partitions in Cosmos Gremlin.\n const projection = buildRepositoryProjectChain();\n const result = await conn.submit(\n `g.V().has('repositoryId', rid).hasId(vid).hasLabel('_repository').${projection}`,\n { vid: repoVertexId(repositoryId), rid: repositoryId },\n );\n if (result.items.length === 0) return null;\n return repositoryFromGremlin(result.items[0] as Record<string, unknown>);\n}\n\nexport async function listRepositories(\n conn: CosmosDbConnection,\n filter?: RepositoryFilter,\n): Promise<PaginatedResult<StoredRepositorySummary>> {\n const limit = filter?.limit ?? 20;\n const offset = filter?.offset ?? 0;\n\n // Read the sentinel in the fixed `_index` partition — a single partition-\n // scoped lookup. The previous implementation issued a cross-partition\n // `g.V().hasLabel('_repository')` scan that fanned out across every\n // physical partition.\n const repositoryIds = await readRepositoryIndex(conn);\n\n if (repositoryIds.length === 0) {\n return { items: [], total: 0, hasMore: false, limit, offset };\n }\n\n // Hydrate each id via the partition-scoped `getRepository`. Parallel because\n // each call hits a different partition; the round-trips are independent.\n const hydrated = await Promise.all(\n repositoryIds.map((rid) => getRepository(conn, rid)),\n );\n\n // A null from getRepository means the sentinel references a vertex that no\n // longer exists — happens transiently during a partial create/delete or if\n // the sentinel was rebuilt from stale state. Drop those entries; the next\n // create or delete call will resync the sentinel.\n let summaries: StoredRepositorySummary[] = hydrated\n .filter((r): r is StoredRepository => r != null)\n .map((r) => {\n const summary: StoredRepositorySummary = {\n repositoryId: r.repositoryId,\n label: r.label,\n governanceConfig: r.governanceConfig,\n };\n if (r.type !== undefined) summary.type = r.type;\n if (r.description !== undefined) summary.description = r.description;\n return summary;\n });\n\n if (filter?.type) {\n summaries = summaries.filter((s) => s.type === filter.type);\n }\n\n const total = summaries.length;\n const items = summaries.slice(offset, offset + limit);\n\n return {\n items,\n total,\n hasMore: offset + items.length < total,\n limit,\n offset,\n };\n}\n\n// updateRepository intentionally keeps a variable-shape query (unlike the\n// fixed-shape create path). Partial-update semantics would otherwise need a\n// three-way discriminator per slot, and `_repository` writes are extremely\n// rare (one per repo per config change) so a missed plan-cache is negligible.\nexport async function updateRepository(\n conn: CosmosDbConnection,\n repositoryId: string,\n updates: RepositoryUpdate,\n): Promise<StoredRepository> {\n const vertexId = repoVertexId(repositoryId);\n\n // Verify exists\n const existing = await getRepository(conn, repositoryId);\n if (!existing) throw new RepositoryNotFoundError(repositoryId);\n\n // `has('repositoryId', rid)` scopes the update to one partition before\n // `hasId(vid)`; hasId alone fans out across partitions in Cosmos Gremlin.\n const bindings: Record<string, unknown> = { vid: vertexId, rid: repositoryId };\n const props: Record<string, string | number | boolean | null | undefined> = {};\n\n if (updates.label !== undefined) props['repoLabel'] = updates.label;\n if (updates.description !== undefined) props['description'] = updates.description;\n if (updates.type !== undefined) props['type'] = updates.type;\n if (updates.legal !== undefined) props['legal'] = updates.legal;\n if (updates.owner !== undefined) props['owner'] = updates.owner;\n if (updates.governanceConfig !== undefined) props['governanceConfig'] = JSON.stringify(updates.governanceConfig);\n if (updates.metadata !== undefined) {\n // Shallow merge with existing metadata\n const merged = { ...existing.metadata, ...updates.metadata };\n props['metadata'] = JSON.stringify(merged);\n }\n\n if (Object.keys(props).length === 0) return existing;\n\n const { chain } = propertyChain(bindings, props, 0);\n const query = `g.V().has('repositoryId', rid).hasId(vid).hasLabel('_repository')${chain}`;\n await conn.submit(query, bindings);\n\n return (await getRepository(conn, repositoryId))!;\n}\n\nconst DELETE_BATCH_SIZE = 500;\n\nexport async function deleteRepository(\n conn: CosmosDbConnection,\n repositoryId: string,\n onProgress?: DeleteProgressCallback,\n): Promise<void> {\n // Get totals for progress reporting\n const entityCountResult = await conn.submit(\n \"g.V().has('repositoryId', rid).has('entityType').count()\",\n { rid: repositoryId },\n );\n const totalEntities = Number(entityCountResult.items[0] ?? 0);\n\n const relCountResult = await conn.submit(\n \"g.E().has('repositoryId', rid).count()\",\n { rid: repositoryId },\n );\n const totalRelationships = Number(relCountResult.items[0] ?? 0);\n\n let relationshipsDeleted = 0;\n let entitiesDeleted = 0;\n\n // Drop edges first (avoids orphan-edge errors), then all vertices, in batches.\n // A single unbounded drop() times out on large repositories.\n while (true) {\n await conn.submit(\n \"g.E().has('repositoryId', rid).limit(batchSize).drop()\",\n { rid: repositoryId, batchSize: DELETE_BATCH_SIZE },\n );\n const remaining = await conn.submit(\n \"g.E().has('repositoryId', rid).limit(1).count()\",\n { rid: repositoryId },\n );\n const remainingCount = Number(remaining.items[0] ?? 0);\n relationshipsDeleted = totalRelationships - remainingCount;\n await onProgress?.({ entitiesDeleted, relationshipsDeleted, totalEntities, totalRelationships });\n if (remainingCount === 0) break;\n }\n\n while (true) {\n await conn.submit(\n \"g.V().has('repositoryId', rid).limit(batchSize).drop()\",\n { rid: repositoryId, batchSize: DELETE_BATCH_SIZE },\n );\n const remaining = await conn.submit(\n \"g.V().has('repositoryId', rid).limit(1).count()\",\n { rid: repositoryId },\n );\n const remainingCount = Number(remaining.items[0] ?? 0);\n entitiesDeleted = totalEntities - remainingCount;\n await onProgress?.({ entitiesDeleted, relationshipsDeleted, totalEntities, totalRelationships });\n if (remainingCount === 0) break;\n }\n\n // Remove this repo's id from the sentinel. The drain above already dropped\n // the `_repository` vertex (it lives in the repo's partition), so this is\n // the only remaining cross-partition write — a property update on the\n // sentinel in the `_index` partition.\n const currentIds = await readRepositoryIndex(conn);\n const updatedIds = currentIds.filter((id) => id !== repositoryId);\n if (updatedIds.length !== currentIds.length) {\n await conn.submit(\n \"g.V().has('repositoryId', pk).hasId(sid).property('repositoryIds', updatedIndex)\",\n {\n pk: REPOSITORY_INDEX_PARTITION,\n sid: REPOSITORY_INDEX_VERTEX_ID,\n updatedIndex: JSON.stringify(updatedIds),\n },\n );\n }\n}\n\nexport async function deleteAllContents(\n conn: CosmosDbConnection,\n repositoryId: string,\n onProgress?: DeleteProgressCallback,\n): Promise<{ deletedEntities: number; deletedRelationships: number }> {\n // Count before deleting\n const entityCountResult = await conn.submit(\n \"g.V().has('repositoryId', rid).has('entityType').count()\",\n { rid: repositoryId },\n );\n const totalEntities = Number(entityCountResult.items[0] ?? 0);\n\n const relCountResult = await conn.submit(\n \"g.E().has('repositoryId', rid).count()\",\n { rid: repositoryId },\n );\n const totalRelationships = Number(relCountResult.items[0] ?? 0);\n\n let relationshipsDeleted = 0;\n let entitiesDeleted = 0;\n\n // Drop edges first (avoids orphan-edge errors), then entity vertices, in batches.\n // Preserves system vertices (_repository, _vocabulary).\n while (true) {\n await conn.submit(\n \"g.E().has('repositoryId', rid).limit(batchSize).drop()\",\n { rid: repositoryId, batchSize: DELETE_BATCH_SIZE },\n );\n const remaining = await conn.submit(\n \"g.E().has('repositoryId', rid).limit(1).count()\",\n { rid: repositoryId },\n );\n const remainingCount = Number(remaining.items[0] ?? 0);\n relationshipsDeleted = totalRelationships - remainingCount;\n await onProgress?.({ entitiesDeleted, relationshipsDeleted, totalEntities, totalRelationships });\n if (remainingCount === 0) break;\n }\n\n while (true) {\n await conn.submit(\n \"g.V().has('repositoryId', rid).has('entityType').limit(batchSize).drop()\",\n { rid: repositoryId, batchSize: DELETE_BATCH_SIZE },\n );\n const remaining = await conn.submit(\n \"g.V().has('repositoryId', rid).has('entityType').limit(1).count()\",\n { rid: repositoryId },\n );\n const remainingCount = Number(remaining.items[0] ?? 0);\n entitiesDeleted = totalEntities - remainingCount;\n await onProgress?.({ entitiesDeleted, relationshipsDeleted, totalEntities, totalRelationships });\n if (remainingCount === 0) break;\n }\n\n return { deletedEntities: totalEntities, deletedRelationships: totalRelationships };\n}\n\nexport async function getRepositoryStats(\n conn: CosmosDbConnection,\n repositoryId: string,\n): Promise<RepositoryStats> {\n // Get vocabulary version\n const vocabResult = await conn.submit(\n \"g.V().has('repositoryId', rid).hasLabel('_vocabulary').values('vocabulary')\",\n { rid: repositoryId },\n );\n let vocabVersion = '0.0.0';\n if (vocabResult.items.length > 0) {\n try {\n const vocab = JSON.parse(vocabResult.items[0] as string);\n vocabVersion = vocab.version ?? '0.0.0';\n } catch { /* default */ }\n }\n\n // Count entities by type (exclude system vertices)\n const entityResult = await conn.submit(\n \"g.V().has('repositoryId', rid).has('entityType').group().by('entityType').by(count())\",\n { rid: repositoryId },\n );\n const entityTypeBreakdown: Record<string, number> = {};\n let entityCount = 0;\n if (entityResult.items.length > 0) {\n const grouped = entityResult.items[0] as Record<string, number>;\n for (const [type, count] of Object.entries(grouped)) {\n entityTypeBreakdown[type] = Number(count);\n entityCount += Number(count);\n }\n }\n\n // Count relationships by type\n const relResult = await conn.submit(\n \"g.E().has('repositoryId', rid).group().by('relationshipType').by(count())\",\n { rid: repositoryId },\n );\n const relationshipTypeBreakdown: Record<string, number> = {};\n let relationshipCount = 0;\n if (relResult.items.length > 0) {\n const grouped = relResult.items[0] as Record<string, number>;\n for (const [type, count] of Object.entries(grouped)) {\n relationshipTypeBreakdown[type] = Number(count);\n relationshipCount += Number(count);\n }\n }\n\n return {\n entityCount,\n relationshipCount,\n vocabularyVersion: vocabVersion,\n entityTypeBreakdown,\n relationshipTypeBreakdown,\n };\n}\n","// Vocabulary Gremlin queries\n\nimport type { CosmosDbConnection } from '../CosmosDbConnection.js';\nimport type { MemoryVocabulary, VocabularyChangeRecord } from '@utaba/deep-memory/types';\nimport type { PaginationOptions, PaginatedResult } from '@utaba/deep-memory/types';\nimport { changeRecordFromGremlin } from '../mapping.js';\n\nfunction vocabVertexId(repositoryId: string): string {\n return `vocab:${repositoryId}`;\n}\n\nconst EMPTY_VOCABULARY = (): MemoryVocabulary => ({\n version: '0.0.0',\n lastModified: new Date().toISOString(),\n modifiedBy: 'system',\n entityTypes: [],\n relationshipTypes: [],\n});\n\nexport async function getVocabulary(\n conn: CosmosDbConnection,\n repositoryId: string,\n): Promise<MemoryVocabulary> {\n // We only ever read the JSON-stringified `vocabulary` property; the full\n // valueMap(true) shipped every property on the vocab vertex (label,\n // repositoryId, etc.) for no reason. `.values('vocabulary').limit(1)`\n // returns just the JSON string — smaller wire payload, single column read.\n //\n // `has('repositoryId', rid)` scopes the lookup to a single partition before\n // `hasId(vid)`; `hasId` is post-routing in Cosmos Gremlin and fans out\n // across all partitions without the partition predicate.\n const result = await conn.submit(\n \"g.V().has('repositoryId', rid).hasId(vid).hasLabel('_vocabulary').values('vocabulary').limit(1)\",\n { vid: vocabVertexId(repositoryId), rid: repositoryId },\n );\n if (result.items.length === 0) return EMPTY_VOCABULARY();\n const raw = result.items[0];\n const json = typeof raw === 'string' ? raw : String(raw ?? '');\n if (!json) return EMPTY_VOCABULARY();\n try {\n return JSON.parse(json) as MemoryVocabulary;\n } catch {\n return EMPTY_VOCABULARY();\n }\n}\n\nexport async function saveVocabulary(\n conn: CosmosDbConnection,\n repositoryId: string,\n vocabulary: MemoryVocabulary,\n): Promise<void> {\n const vid = vocabVertexId(repositoryId);\n const vocabJson = JSON.stringify(vocabulary);\n\n // Upsert: try to update existing, create if not found.\n // Both branches scope by `has('repositoryId', rid)` before `hasId(vid)` —\n // hasId alone fans out across all partitions in Cosmos Gremlin.\n const existing = await conn.submit(\n \"g.V().has('repositoryId', rid).hasId(vid).hasLabel('_vocabulary').count()\",\n { vid, rid: repositoryId },\n );\n\n if (Number(existing.items[0] ?? 0) > 0) {\n await conn.submit(\n \"g.V().has('repositoryId', rid).hasId(vid).hasLabel('_vocabulary').property('vocabulary', vocabJson)\",\n { vid, rid: repositoryId, vocabJson },\n );\n } else {\n await conn.submit(\n \"g.addV('_vocabulary').property('id', vid).property('repositoryId', rid).property('vocabulary', vocabJson)\",\n { vid, rid: repositoryId, vocabJson },\n );\n }\n}\n\nexport async function getVocabularyChangeLog(\n conn: CosmosDbConnection,\n repositoryId: string,\n options?: PaginationOptions,\n): Promise<PaginatedResult<VocabularyChangeRecord>> {\n const limit = options?.limit ?? 10;\n const offset = options?.offset ?? 0;\n\n // Count and data round-trips are independent — run them in parallel. No\n // property filters here, so the count is exact and `total` is always a number.\n const [countResult, dataResult] = await Promise.all([\n conn.submit(\n \"g.V().has('repositoryId', rid).hasLabel('_vocabularyChangeLog').count()\",\n { rid: repositoryId },\n ),\n conn.submit(\n \"g.V().has('repositoryId', rid).hasLabel('_vocabularyChangeLog').order().by('proposedAt', decr).range(rangeStart, rangeEnd).valueMap(true)\",\n { rid: repositoryId, rangeStart: offset, rangeEnd: offset + limit },\n ),\n ]);\n\n const total = Number(countResult.items[0] ?? 0);\n const items = (dataResult.items as Record<string, unknown>[]).map(changeRecordFromGremlin);\n\n return {\n items,\n total,\n hasMore: offset + items.length < total,\n limit,\n offset,\n };\n}\n","// Entity CRUD Gremlin queries\n\nimport type { CosmosDbConnection } from '../CosmosDbConnection.js';\nimport type { CosmosDocumentClient, CosmosQueryParameter } from '../CosmosDocumentClient.js';\nimport type { StoredEntity, StoredEntityUpdate } from '@utaba/deep-memory/types';\nimport type { StorageFindQuery, PaginatedResult, PropertyFilter } from '@utaba/deep-memory/types';\nimport type { EntityReadOptions } from '@utaba/deep-memory/providers';\nimport {\n buildEntityPropertyLadder,\n entityFromDocument,\n entityFromGremlin,\n entityToLadderBindings,\n STORED_ENTITY_FIELDS,\n} from '../mapping.js';\nimport {\n DuplicateEntityError,\n EntityNotFoundError,\n buildVertexProjectChain,\n matchesPropertyFilters,\n} from '@utaba/deep-memory';\n\n// Sentinel returned by the duplicate-detection branch of the\n// fold().coalesce(unfold().constant('__duplicate'), addV/addE) pattern. The\n// create succeeds inline or the duplicate path returns this string, which we\n// translate into the typed error — single round-trip either way.\nconst DUPLICATE_SENTINEL = '__duplicate';\n\n// Fixed-shape property ladder — same Gremlin string for every entity create\n// regardless of which optional fields are populated, so the Cosmos plan cache\n// reuses one compiled plan. Computed once at module load.\nconst ENTITY_CREATE_QUERY =\n `g.V().has('repositoryId', rid).hasId(vid).fold().coalesce(` +\n `unfold().constant('${DUPLICATE_SENTINEL}'),` +\n `addV(vertexLabel).property('id', vid).property('repositoryId', rid)${buildEntityPropertyLadder()}` +\n `)`;\n\nexport async function createEntity(\n conn: CosmosDbConnection,\n repositoryId: string,\n entity: StoredEntity,\n): Promise<StoredEntity> {\n const bindings: Record<string, unknown> = {\n rid: repositoryId,\n vid: entity.id,\n vertexLabel: entity.entityType,\n ...entityToLadderBindings(entity),\n };\n\n const result = await conn.submit(ENTITY_CREATE_QUERY, bindings);\n\n if (result.items[0] === DUPLICATE_SENTINEL) {\n throw new DuplicateEntityError(entity.id);\n }\n\n return entity;\n}\n\nexport async function getEntity(\n conn: CosmosDbConnection,\n repositoryId: string,\n entityId: string,\n options?: EntityReadOptions,\n): Promise<StoredEntity | null> {\n const projection = buildVertexProjectChain({ withEmbedding: options?.loadEmbeddings });\n const result = await conn.submit(\n `g.V().has('repositoryId', rid).hasId(eid).has('entityType').${projection}`,\n { rid: repositoryId, eid: entityId },\n );\n if (result.items.length === 0) return null;\n return entityFromGremlin(result.items[0] as Record<string, unknown>);\n}\n\nexport async function getEntityBySlug(\n conn: CosmosDbConnection,\n repositoryId: string,\n slug: string,\n options?: EntityReadOptions,\n): Promise<StoredEntity | null> {\n const projection = buildVertexProjectChain({ withEmbedding: options?.loadEmbeddings });\n const result = await conn.submit(\n `g.V().has('repositoryId', rid).has('slug', slugVal).has('entityType').${projection}`,\n { rid: repositoryId, slugVal: slug },\n );\n if (result.items.length === 0) return null;\n return entityFromGremlin(result.items[0] as Record<string, unknown>);\n}\n\nexport async function getEntities(\n conn: CosmosDbConnection,\n repositoryId: string,\n entityIds: string[],\n options?: EntityReadOptions,\n): Promise<Map<string, StoredEntity>> {\n if (entityIds.length === 0) return new Map();\n\n // Build within() clause with individual params\n const bindings: Record<string, unknown> = { rid: repositoryId };\n const idParams: string[] = [];\n entityIds.forEach((id, i) => {\n const paramName = `eid${i}`;\n bindings[paramName] = id;\n idParams.push(paramName);\n });\n\n const withinClause = `within(${idParams.join(', ')})`;\n const projection = buildVertexProjectChain({ withEmbedding: options?.loadEmbeddings });\n const result = await conn.submit(\n `g.V().has('repositoryId', rid).hasId(${withinClause}).has('entityType').${projection}`,\n bindings,\n );\n\n const map = new Map<string, StoredEntity>();\n for (const item of result.items) {\n const entity = entityFromGremlin(item as Record<string, unknown>);\n map.set(entity.id, entity);\n }\n return map;\n}\n\n// updateEntity intentionally KEEPS a variable-shape query (unlike createEntity).\n// A fixed-shape ladder for updates would require a three-way discriminator per\n// slot (set / drop / leave) with two-level choose-and-sideEffect-drop branches\n// — significant Gremlin complexity for a per-call plan-cache win that matters\n// far less here than on the bulk-import create path. The plan-cache concern is\n// framed around the \"every create is a unique query\" case (issue #20 in\n// plans/performance-issues.md), not partial-update calls. If the reembed loop\n// ever profiles as plan-parse-bound, revisit by introducing a two-sentinel\n// ladder shape — until then variable is fine.\n\nexport async function updateEntity(\n conn: CosmosDbConnection,\n repositoryId: string,\n entityId: string,\n updates: StoredEntityUpdate,\n): Promise<StoredEntity> {\n const bindings: Record<string, unknown> = { rid: repositoryId, eid: entityId };\n const propParts: string[] = [];\n let idx = 0;\n\n const addProp = (key: string, value: string | number | boolean) => {\n const paramName = `p${idx++}`;\n bindings[paramName] = value;\n propParts.push(`.property('${key}', ${paramName})`);\n };\n\n // Gremlin has no \"set to null\" — to clear a property we drop it with a\n // sideEffect step. Drops run before sets because `.sideEffect(...)` is\n // appended to `propParts` in traversal order.\n const dropProp = (key: string) => {\n propParts.push(`.sideEffect(properties('${key}').drop())`);\n };\n\n // Note: entityType drives both the Gremlin vertex label (set at addV) and the\n // `entityType` property. The vertex label is immutable in Gremlin, but every\n // entity query in this provider filters by the `entityType` property rather\n // than vertex label, so updating the property is sufficient for functional\n // correctness. The vertex label becomes a stale hint only.\n if (updates.entityType !== undefined) addProp('entityType', updates.entityType);\n if (updates.label !== undefined) addProp('entityLabel', updates.label);\n if (updates.slug !== undefined) addProp('slug', updates.slug);\n if (updates.summary === null) dropProp('summary');\n else if (updates.summary !== undefined) addProp('summary', updates.summary);\n if (updates.properties !== undefined) addProp('properties', JSON.stringify(updates.properties));\n if (updates.data === null) dropProp('data');\n else if (updates.data !== undefined) addProp('data', updates.data);\n if (updates.dataFormat === null) dropProp('dataFormat');\n else if (updates.dataFormat !== undefined) addProp('dataFormat', updates.dataFormat);\n if (updates.embedding !== undefined) addProp('embedding', JSON.stringify(updates.embedding));\n\n // Provenance\n addProp('modifiedBy', updates.provenance.modifiedBy);\n addProp('modifiedByType', updates.provenance.modifiedByType);\n addProp('modifiedAt', updates.provenance.modifiedAt);\n if (updates.provenance.modifiedInConversation != null) addProp('modifiedInConversation', updates.provenance.modifiedInConversation);\n if (updates.provenance.modifiedFromMessage != null) addProp('modifiedFromMessage', updates.provenance.modifiedFromMessage);\n\n // Append the read-projection onto the update so the updated state comes\n // back in a single round-trip (instead of update + separate getEntity).\n // Embeddings stay off the wire — callers that need the embedding pass the\n // option through the public StorageProvider.getEntity call themselves.\n const projection = buildVertexProjectChain();\n const query = `g.V().has('repositoryId', rid).hasId(eid).has('entityType')${propParts.join('')}.${projection}`;\n const result = await conn.submit(query, bindings);\n\n if (result.items.length === 0) {\n throw new EntityNotFoundError(entityId);\n }\n\n return entityFromGremlin(result.items[0] as Record<string, unknown>);\n}\n\nexport async function deleteEntity(\n conn: CosmosDbConnection,\n repositoryId: string,\n entityId: string,\n): Promise<void> {\n // Gremlin drop() on a vertex also drops connected edges\n await conn.submit(\n \"g.V().has('repositoryId', rid).hasId(eid).has('entityType').drop()\",\n { rid: repositoryId, eid: entityId },\n );\n}\n\n/**\n * Single round-trip type-delete via the aggregate-side-effect pattern: the\n * bucket records the vertex ids that the drop touched, giving an exact entity\n * count. The cascaded edge count is intentionally skipped — computing it\n * required a `bothE().dedup().count()` that walked every incident edge across\n * every partition the type touches, and the value is currently discarded by\n * the only caller (VocabularyEngine.cascadeDeleteData).\n *\n * Returns `deletedRelationships: undefined` to signal the field is genuinely\n * unknown for this provider. SQL Server and in-memory providers continue to\n * return the exact number (rowsAffected / iteration).\n */\nexport async function deleteEntitiesByType(\n conn: CosmosDbConnection,\n repositoryId: string,\n entityType: string,\n): Promise<{ deletedEntities: number; deletedRelationships: number | undefined }> {\n const result = await conn.submit(\n \"g.V().has('repositoryId', rid).has('entityType', etype)\" +\n \".aggregate('found').by('id').drop().cap('found')\",\n { rid: repositoryId, etype: entityType },\n );\n const bucket = result.items[0];\n const deletedEntities = Array.isArray(bucket) ? bucket.length : 0;\n return { deletedEntities, deletedRelationships: undefined };\n}\n\n/**\n * Build the Document-endpoint SQL path for a Gremlin-managed property.\n * Every user property on a Gremlin vertex is stored as `[{_value, id}]` when\n * read through the Document endpoint — so a top-level scalar reference like\n * `c.entityType` silently returns no rows. Always go through `[0]._value`.\n * See local-tests/baseline/phase-cosmos-sql-shape-probe-results.md.\n */\nfunction sqlPath(key: string): string {\n return `c.${key}[0]._value`;\n}\n\n/**\n * Build the `WHERE` clause + parameter array shared by the data query and the\n * `SELECT VALUE COUNT(1)` query, so the two are guaranteed to count the same\n * set by construction.\n *\n * Property filters are emitted as approximate `CONTAINS` on the JSON-stringified\n * `c.properties[0]._value` blob; the caller verifies exact-match client-side\n * (see `findEntities`).\n */\nfunction buildWhereClause(\n query: StorageFindQuery,\n repositoryId: string,\n): { sqlWhere: string; params: CosmosQueryParameter[] } {\n const params: CosmosQueryParameter[] = [{ name: '@rid', value: repositoryId }];\n // `IS_DEFINED(c.entityType)` mirrors the old Gremlin `.has('entityType')`\n // presence check — it excludes the `_repository`, `_vocabulary`, and\n // `_vocabulary_change` system vertices that share the partition with the\n // repository's entities. Without this filter, those vertices leak into\n // both the data page and the COUNT(1), breaking pagination math.\n const predicates: string[] = ['c.repositoryId = @rid', 'IS_DEFINED(c.entityType)'];\n\n if (query.entityTypes && query.entityTypes.length > 0) {\n const typeParamNames: string[] = [];\n query.entityTypes.forEach((t, i) => {\n const name = `@etype${i}`;\n params.push({ name, value: t });\n typeParamNames.push(name);\n });\n // Gotcha: must use the `[0]._value` path even for the type filter — the\n // flat `c.entityType` form returns 0 docs with indexUtilizationRatio=0.00.\n predicates.push(`${sqlPath('entityType')} IN (${typeParamNames.join(', ')})`);\n }\n\n if (query.searchTerm) {\n params.push({ name: '@term', value: query.searchTerm });\n predicates.push(\n `(CONTAINS(${sqlPath('entityLabel')}, @term, true) ` +\n `OR CONTAINS(${sqlPath('slug')}, @term, true) ` +\n `OR CONTAINS(${sqlPath('summary')}, @term, true))`,\n );\n }\n\n if (query.properties != null) {\n let i = 0;\n for (const [key, value] of Object.entries(query.properties)) {\n // JSON.stringify on a single-entry object produces `{\"key\":<json-value>}`;\n // strip the outer braces to get the substring that must appear inside\n // the stored blob. Works uniformly for strings, numbers, booleans, and\n // nested arrays/objects. False positives are filtered client-side via\n // `matchesPropertyFilters` after JSON-parsing each returned doc.\n const fragment = JSON.stringify({ [key]: value }).slice(1, -1);\n const name = `@kv${i++}`;\n params.push({ name, value: fragment });\n // ignoreCase=false: property keys/values are canonical, no case folding.\n predicates.push(`CONTAINS(${sqlPath('properties')}, ${name}, false)`);\n }\n }\n\n return { sqlWhere: `WHERE ${predicates.join(' AND ')}`, params };\n}\n\n/**\n * Build the projection field list for the data SELECT. Mirrors the Gremlin\n * fast path's `buildVertexProjectChain({ withEmbedding })`: embedding is\n * heavy (large JSON-stringified float array) and not shipped unless the\n * caller asks via `EntityReadOptions.loadEmbeddings`.\n */\nfunction buildSelectClause(loadEmbeddings: boolean): string {\n const fields = ['c.id', ...STORED_ENTITY_FIELDS.filter((f) => f !== 'id').map((f) => `c.${f}`)];\n if (loadEmbeddings) fields.push('c.embedding');\n return `SELECT ${fields.join(', ')}`;\n}\n\nexport async function findEntities(\n docClient: CosmosDocumentClient,\n repositoryId: string,\n query: StorageFindQuery,\n options?: EntityReadOptions,\n): Promise<PaginatedResult<StoredEntity>> {\n const { sqlWhere, params } = buildWhereClause(query, repositoryId);\n\n const dataParams: CosmosQueryParameter[] = [\n ...params,\n { name: '@off', value: query.offset },\n { name: '@lim', value: query.limit },\n ];\n const selectClause = buildSelectClause(options?.loadEmbeddings === true);\n // ORDER BY c.id pins pagination order deterministically — without it,\n // Cosmos may return overlapping/missing rows across page requests. c.id is\n // covered by the default indexing policy, so no extra RU on the sort itself.\n const dataSql = `${selectClause} FROM c ${sqlWhere} ORDER BY c.id OFFSET @off LIMIT @lim`;\n const countSql = `SELECT VALUE COUNT(1) FROM c ${sqlWhere}`;\n\n // The properties prefilter is approximate (substring CONTAINS on the\n // JSON-stringified blob), so COUNT(1) over the same WHERE clause would\n // overcount by the false-positive rate. Report `total: undefined` and let\n // callers paginate on `hasMore` instead.\n const skipCount =\n query.properties != null && Object.keys(query.properties).length > 0;\n\n const [dataResult, countResult] = await Promise.all([\n docClient.query<Record<string, unknown>>(dataSql, dataParams, {\n partitionKey: repositoryId,\n }),\n skipCount\n ? Promise.resolve(null)\n : docClient.query<number>(countSql, params, { partitionKey: repositoryId }),\n ]);\n\n let items = dataResult.documents.map(entityFromDocument);\n\n if (query.properties != null && Object.keys(query.properties).length > 0) {\n const filters: PropertyFilter[] = Object.entries(query.properties).map(\n ([key, value]) => ({ key, operator: 'eq', value }),\n );\n items = items.filter((entity) => matchesPropertyFilters(entity.properties, filters));\n }\n\n const total =\n countResult && countResult.documents.length > 0\n ? Number(countResult.documents[0])\n : undefined;\n\n const hasMore =\n total != null\n ? query.offset + items.length < total\n : items.length === query.limit;\n\n return {\n items,\n total,\n hasMore,\n limit: query.limit,\n offset: query.offset,\n };\n}\n","// Relationship CRUD Gremlin queries\n\nimport type { CosmosDbConnection } from '../CosmosDbConnection.js';\nimport type { StoredRelationship, RelationshipQueryOptions } from '@utaba/deep-memory/types';\nimport type { PaginatedResult } from '@utaba/deep-memory/types';\nimport {\n buildRelationshipPropertyLadder,\n relationshipFromGremlin,\n relationshipToLadderBindings,\n} from '../mapping.js';\nimport { DuplicateRelationshipError, matchesPropertyFilters, buildEdgeProjectChain } from '@utaba/deep-memory';\n\n// Sentinel returned by the duplicate-detection branch of the coalesce upsert\n// pattern. Mirrors entity.ts — single round-trip create.\nconst DUPLICATE_SENTINEL = '__duplicate';\n\n// Fixed-shape property ladder — identical query string across every edge\n// create regardless of which optional fields are populated, so the Cosmos\n// plan cache reuses one compiled plan.\nconst RELATIONSHIP_CREATE_QUERY =\n `g.E().has('repositoryId', rid).hasId(relId).fold().coalesce(` +\n `unfold().constant('${DUPLICATE_SENTINEL}'),` +\n `g.V().has('repositoryId', rid).hasId(srcId).has('entityType')` +\n `.addE(edgeLabel)` +\n `.to(g.V().has('repositoryId', rid).hasId(tgtId).has('entityType'))` +\n `.property('id', relId).property('repositoryId', rid)${buildRelationshipPropertyLadder()}` +\n `)`;\n\nexport async function createRelationship(\n conn: CosmosDbConnection,\n repositoryId: string,\n relationship: StoredRelationship,\n): Promise<StoredRelationship> {\n const bindings: Record<string, unknown> = {\n rid: repositoryId,\n relId: relationship.id,\n srcId: relationship.sourceEntityId,\n tgtId: relationship.targetEntityId,\n edgeLabel: relationship.relationshipType,\n ...relationshipToLadderBindings(relationship),\n };\n\n const result = await conn.submit(RELATIONSHIP_CREATE_QUERY, bindings);\n\n if (result.items[0] === DUPLICATE_SENTINEL) {\n throw new DuplicateRelationshipError(relationship.id);\n }\n\n return relationship;\n}\n\nexport async function getRelationship(\n conn: CosmosDbConnection,\n repositoryId: string,\n relationshipId: string,\n): Promise<StoredRelationship | null> {\n const projection = buildEdgeProjectChain();\n // Edge-id lookup: g.E().hasId(relId) is engine-routed by doc id; the\n // `has('repositoryId', rid)` predicate after it still doesn't push partition\n // routing down (issue #2 in plans/performance-issues.md). When the source\n // vertex id is known, callers should partition-route via the vertex instead.\n const result = await conn.submit(\n `g.E().hasId(relId).has('repositoryId', rid).${projection}`,\n { relId: relationshipId, rid: repositoryId },\n );\n if (result.items.length === 0) return null;\n return relationshipFromGremlin(result.items[0] as Record<string, unknown>);\n}\n\nexport async function getEntityRelationships(\n conn: CosmosDbConnection,\n repositoryId: string,\n entityId: string,\n options?: RelationshipQueryOptions,\n): Promise<PaginatedResult<StoredRelationship>> {\n const limit = options?.limit ?? 50;\n const offset = options?.offset ?? 0;\n const direction = options?.direction ?? 'both';\n const hasPropertyFilters =\n options?.propertyFilters != null && options.propertyFilters.length > 0;\n\n const baseBindings: Record<string, unknown> = {\n rid: repositoryId,\n eid: entityId,\n };\n\n // Build edge traversal based on direction\n let edgeTraversal: string;\n switch (direction) {\n case 'out':\n edgeTraversal = \"g.V().has('repositoryId', rid).hasId(eid).has('entityType').outE()\";\n break;\n case 'in':\n edgeTraversal = \"g.V().has('repositoryId', rid).hasId(eid).has('entityType').inE()\";\n break;\n case 'both':\n default:\n edgeTraversal = \"g.V().has('repositoryId', rid).hasId(eid).has('entityType').bothE()\";\n break;\n }\n\n // Filter by relationship types\n let typeFilter = '';\n if (options?.relationshipTypes && options.relationshipTypes.length > 0) {\n const typeParams: string[] = [];\n options.relationshipTypes.forEach((t, i) => {\n const paramName = `rtype${i}`;\n baseBindings[paramName] = t;\n typeParams.push(paramName);\n });\n typeFilter = `.hasLabel(${typeParams.join(', ')})`;\n }\n\n // For bidirectional support in outbound/inbound:\n // When direction is 'out', include inbound edges that are bidirectional\n // When direction is 'in', include outbound edges that are bidirectional\n // This requires a union approach.\n let unionQuery: string | null = null;\n if (direction === 'out') {\n // outE + inE where bidirectional=true\n unionQuery = `g.V().has('repositoryId', rid).hasId(eid).has('entityType').union(outE()${typeFilter}, inE()${typeFilter}.has('bidirectional', true))`;\n } else if (direction === 'in') {\n unionQuery = `g.V().has('repositoryId', rid).hasId(eid).has('entityType').union(inE()${typeFilter}, outE()${typeFilter}.has('bidirectional', true))`;\n }\n\n const baseQuery = unionQuery ?? `${edgeTraversal}${typeFilter}`;\n const projection = buildEdgeProjectChain();\n\n // Count and data round-trips are independent — run them in parallel to halve\n // wall-clock latency. When `propertyFilters` is set the filter runs\n // client-side after the fetch, so a server-side count would overstate the\n // matched total — match the findEntities pattern and surface\n // `total: undefined` in that case.\n const dataBindings = { ...baseBindings, rangeStart: offset, rangeEnd: offset + limit };\n const [countResult, dataResult] = await Promise.all([\n hasPropertyFilters\n ? Promise.resolve(null)\n : conn.submit(`${baseQuery}.dedup().count()`, baseBindings),\n conn.submit(\n `${baseQuery}.dedup().range(rangeStart, rangeEnd).${projection}`,\n dataBindings,\n ),\n ]);\n\n const rawItems = dataResult.items as Record<string, unknown>[];\n let items = rawItems.map(relationshipFromGremlin);\n\n if (hasPropertyFilters) {\n items = items.filter(rel => matchesPropertyFilters(rel.properties, options!.propertyFilters!));\n }\n\n const total = countResult ? Number(countResult.items[0] ?? 0) : undefined;\n const hasMore = total != null ? offset + rawItems.length < total : rawItems.length === limit;\n\n return {\n items,\n total,\n hasMore,\n limit,\n offset,\n };\n}\n\nexport async function deleteRelationship(\n conn: CosmosDbConnection,\n repositoryId: string,\n relationshipId: string,\n): Promise<void> {\n await conn.submit(\n \"g.E().hasId(relId).has('repositoryId', rid).drop()\",\n { relId: relationshipId, rid: repositoryId },\n );\n}\n\n\n/**\n * Single round-trip type-delete via the aggregate-side-effect pattern: the\n * bucket records the edge ids that were actually dropped, giving an exact\n * `deletedRelationships` count without a separate count query.\n */\nexport async function deleteRelationshipsByType(\n conn: CosmosDbConnection,\n repositoryId: string,\n relationshipType: string,\n): Promise<{ deletedRelationships: number }> {\n const result = await conn.submit(\n \"g.E().has('repositoryId', rid).hasLabel(rtype)\" +\n \".aggregate('found').by('id').drop().cap('found')\",\n { rid: repositoryId, rtype: relationshipType },\n );\n const bucket = result.items[0];\n const deletedRelationships = Array.isArray(bucket) ? bucket.length : 0;\n return { deletedRelationships };\n}\n","// Timeline Gremlin queries\n\nimport type { CosmosDbConnection } from '../CosmosDbConnection.js';\nimport type { StorageTimelineOptions } from '@utaba/deep-memory/types';\nimport type { StorageTimelineResult, StorageTimelineEvent } from '@utaba/deep-memory/types';\n\nexport async function getTimeline(\n conn: CosmosDbConnection,\n repositoryId: string,\n entityId: string,\n options: StorageTimelineOptions,\n): Promise<StorageTimelineResult> {\n const events: StorageTimelineEvent[] = [];\n\n // Entity creation event\n const entityResult = await conn.submit(\n \"g.V().has('repositoryId', rid).hasId(eid).has('entityType').valueMap('createdAt', 'modifiedAt')\",\n { rid: repositoryId, eid: entityId },\n );\n\n if (entityResult.items.length > 0) {\n const props = entityResult.items[0] as Record<string, unknown>;\n const createdAt = unwrapValue(props['createdAt']);\n const modifiedAt = unwrapValue(props['modifiedAt']);\n\n if (createdAt && isInTimeRange(createdAt, options.timeRange)) {\n events.push({\n timestamp: createdAt,\n eventType: 'entity_created',\n entityId,\n });\n }\n if (modifiedAt && modifiedAt !== createdAt && isInTimeRange(modifiedAt, options.timeRange)) {\n events.push({\n timestamp: modifiedAt,\n eventType: 'entity_modified',\n entityId,\n });\n }\n }\n\n // Relationship events connected to this entity\n const relResult = await conn.submit(\n \"g.V().has('repositoryId', rid).hasId(eid).has('entityType').bothE().valueMap('id', 'createdAt')\",\n { rid: repositoryId, eid: entityId },\n );\n\n for (const item of relResult.items) {\n const props = item as Record<string, unknown>;\n const relId = unwrapValue(props['id']);\n const relCreatedAt = unwrapValue(props['createdAt']);\n\n if (relCreatedAt && isInTimeRange(relCreatedAt, options.timeRange)) {\n events.push({\n timestamp: relCreatedAt,\n eventType: 'relationship_created',\n entityId,\n relationshipId: relId,\n });\n }\n }\n\n // Sort by timestamp descending\n events.sort((a, b) => b.timestamp.localeCompare(a.timestamp));\n\n // Filter by event types\n let filtered = events;\n if (options.eventTypes && options.eventTypes.length > 0) {\n filtered = events.filter(e => options.eventTypes!.includes(e.eventType));\n }\n\n const total = filtered.length;\n const paged = filtered.slice(options.offset, options.offset + options.limit);\n\n return { events: paged, total };\n}\n\nfunction unwrapValue(val: unknown): string {\n if (Array.isArray(val) && val.length > 0) return String(val[0]);\n return String(val ?? '');\n}\n\nfunction isInTimeRange(\n timestamp: string,\n timeRange?: { from: string; to: string },\n): boolean {\n if (!timeRange) return true;\n return timestamp >= timeRange.from && timestamp <= timeRange.to;\n}\n","// Adaptive concurrency runner for bulk imports.\n//\n// CosmosDB throttles writes (HTTP 429) when the autoscale tier cannot keep up\n// with the offered load. The CosmosDbConnection retries 429s internally, but a\n// burst of N parallel writes that all get throttled creates a retry storm that\n// piles back onto an already-saturated partition. To avoid this we drive bulk\n// imports through a closed-loop controller:\n//\n// • Start at a conservative concurrency.\n// • Each task runs inside its own usageScope sub-accumulator. Any non-zero\n// retry count for that task means a 429 (or 503) was observed — the\n// connection only retries on transient throttle/unavailable errors.\n// • On any throttle: halve concurrency, reset the success streak, set a\n// short cooldown before any new task is dispatched. This gives autoscale\n// time to ramp.\n// • After `increaseAfter` consecutive throttle-free completions: bump\n// concurrency by 1, up to `max`.\n// • Track the highest concurrency at which a throttle was observed as a\n// \"soft ceiling\". Re-approaching this level requires\n// `increaseAfter * throttleCeilingMultiplier` consecutive successes\n// instead of just `increaseAfter`, so a throttle-prone level is not\n// hammered repeatedly.\n//\n// Sub-accumulator counts roll up into the parent usageScope on completion, so\n// the outer track() telemetry continues to report correct aggregate RU/calls/\n// retries for the operation as a whole.\n//\n// The controller is exposed for unit testing; runAdaptive is the production\n// entry point used by importBulk.\n\nimport type {\n AdaptiveConcurrencyAdjustEvent,\n AdaptiveConcurrencyAdjustReason,\n AdaptiveConcurrencyHandle,\n AdaptiveConcurrencyOptions,\n} from '@utaba/deep-memory/types';\nimport { ImportThrottleAbortError } from '@utaba/deep-memory';\nimport { usageScope, type UsageAccumulator } from '../usage.js';\n\nconst DEFAULT_MIN = 1;\nconst DEFAULT_START = 5;\nconst DEFAULT_MAX = 32;\nconst DEFAULT_INCREASE_AFTER = 50;\nconst DEFAULT_COOLDOWN_MS = 1000;\nconst DEFAULT_RAMP_UP_COOLDOWN_MS = 5000;\nconst DEFAULT_MAX_CONSECUTIVE_THROTTLES_AT_MIN = 10;\nconst DEFAULT_THROTTLE_CEILING_MULTIPLIER = 3;\n// Sentinel value meaning \"no soft ceiling currently in effect\". Any concrete\n// concurrency target below this is unconstrained; the controller only treats a\n// finite softCeiling as a constraint.\nconst NO_SOFT_CEILING = Number.POSITIVE_INFINITY;\n\ninterface ResolvedAdaptiveOptions {\n min: number;\n start: number;\n max: number;\n increaseAfter: number;\n cooldownMs: number;\n rampUpCooldownMs: number;\n maxConsecutiveThrottlesAtMin: number;\n throttleCeilingMultiplier: number;\n onAdjust: ((event: AdaptiveConcurrencyAdjustEvent) => void) | undefined;\n}\n\nfunction resolveOptions(opts: AdaptiveConcurrencyOptions | undefined): ResolvedAdaptiveOptions {\n const min = Math.max(1, opts?.min ?? DEFAULT_MIN);\n const max = Math.max(min, opts?.max ?? DEFAULT_MAX);\n const start = Math.min(max, Math.max(min, opts?.start ?? DEFAULT_START));\n const increaseAfter = Math.max(1, opts?.increaseAfter ?? DEFAULT_INCREASE_AFTER);\n const cooldownMs = Math.max(0, opts?.cooldownMs ?? DEFAULT_COOLDOWN_MS);\n const rampUpCooldownMs = Math.max(0, opts?.rampUpCooldownMs ?? DEFAULT_RAMP_UP_COOLDOWN_MS);\n const maxConsecutiveThrottlesAtMin = Math.max(\n 1,\n opts?.maxConsecutiveThrottlesAtMin ?? DEFAULT_MAX_CONSECUTIVE_THROTTLES_AT_MIN,\n );\n const throttleCeilingMultiplier = Math.max(\n 1,\n opts?.throttleCeilingMultiplier ?? DEFAULT_THROTTLE_CEILING_MULTIPLIER,\n );\n return {\n min,\n start,\n max,\n increaseAfter,\n cooldownMs,\n rampUpCooldownMs,\n maxConsecutiveThrottlesAtMin,\n throttleCeilingMultiplier,\n onAdjust: opts?.onAdjust,\n };\n}\n\n/**\n * Internal shape of an {@link AdaptiveConcurrencyHandle} as written to by this\n * package. The handle is declared as opaque in the public API so other storage\n * providers can attach their own state without colliding.\n */\ninterface CosmosAdaptiveHandle extends AdaptiveConcurrencyHandle {\n controller?: AdaptiveConcurrencyController;\n}\n\n/**\n * Resolve a controller from an optional caller-supplied handle, creating one\n * on first use and reusing it on subsequent calls. This is how the controller\n * persists across multiple importBulk calls within a single import operation:\n * RepositoryImporter creates a fresh handle per import and threads it through,\n * so the controller's learned concurrency level, success streak, cooldown,\n * and soft ceiling all carry across chunks instead of resetting at each call.\n *\n * If no handle is supplied, a fresh controller is returned (single-shot use).\n */\nexport function resolveController(\n options: AdaptiveConcurrencyOptions | undefined,\n handle: AdaptiveConcurrencyHandle | undefined,\n): AdaptiveConcurrencyController {\n if (!handle) {\n return new AdaptiveConcurrencyController(options);\n }\n const cosmosHandle = handle as CosmosAdaptiveHandle;\n if (!cosmosHandle.controller) {\n cosmosHandle.controller = new AdaptiveConcurrencyController(options);\n }\n return cosmosHandle.controller;\n}\n\n/**\n * Closed-loop concurrency controller. Stateless about tasks themselves —\n * callers feed it `noteSuccess()` and `noteThrottle()` after each task and\n * read `getConcurrency()` to decide how many tasks may be in flight.\n */\nexport class AdaptiveConcurrencyController {\n private readonly opts: ResolvedAdaptiveOptions;\n private current: number;\n private streak = 0;\n private cooldownUntil = 0;\n private rampFrozenUntil = 0;\n private completed = 0;\n private throttled = 0;\n private startEmitted = false;\n private consecutiveThrottlesAtMin = 0;\n /**\n * Highest concurrency at which a throttle has been observed and the\n * controller actually halved (i.e. concrete evidence the cluster could not\n * sustain that level). Re-approaching this level on subsequent ramp-ups\n * requires `increaseAfter * throttleCeilingMultiplier` consecutive successes\n * instead of just `increaseAfter`. Cleared once we've successfully held the\n * level without further throttling — see noteSuccess.\n */\n private softCeiling: number = NO_SOFT_CEILING;\n\n constructor(opts?: AdaptiveConcurrencyOptions) {\n this.opts = resolveOptions(opts);\n this.current = this.opts.start;\n }\n\n /** Current target concurrency. */\n getConcurrency(): number {\n return this.current;\n }\n\n /** Configured ceiling — used by the runner to size its worker pool. */\n getMaxConcurrency(): number {\n return this.opts.max;\n }\n\n /** Total tasks that have been noted as completed (success or throttle). */\n getCompleted(): number {\n return this.completed;\n }\n\n /** Total tasks that observed at least one throttle. */\n getThrottledCount(): number {\n return this.throttled;\n }\n\n /**\n * Earliest time (ms since epoch) at which a new task may be dispatched. Zero\n * if there is no active cooldown.\n */\n getCooldownUntil(): number {\n return this.cooldownUntil;\n }\n\n /**\n * Emit the initial `start` event the first time the controller is queried\n * for adjustment events. Kept separate so construction has no side effects.\n */\n emitStartIfNeeded(): void {\n if (this.startEmitted) return;\n this.startEmitted = true;\n this.notify('start', this.current);\n }\n\n /** Record a throttle-free task completion. May trigger ramp-up. */\n noteSuccess(now: number = Date.now()): void {\n this.completed++;\n this.consecutiveThrottlesAtMin = 0;\n if (now < this.rampFrozenUntil) return;\n this.streak++;\n if (this.current >= this.opts.max) return;\n const target = this.current + 1;\n // Re-approaching a previously-throttled level requires more sustained\n // success — multiplier × increaseAfter — so the controller does not\n // hammer a level the cluster has already proven it cannot sustain.\n const needed =\n target >= this.softCeiling\n ? this.opts.increaseAfter * this.opts.throttleCeilingMultiplier\n : this.opts.increaseAfter;\n if (this.streak >= needed) {\n const previous = this.current;\n this.current = Math.min(this.opts.max, target);\n this.streak = 0;\n // We've cautiously re-attained (or exceeded) the soft ceiling without\n // further throttling. Drop the constraint — subsequent ramp-ups beyond\n // this level use the normal increaseAfter. A future throttle will\n // re-establish a new ceiling.\n if (this.current >= this.softCeiling) {\n this.softCeiling = NO_SOFT_CEILING;\n }\n this.notify('ramp-up', previous);\n }\n }\n\n /** Record a task that observed at least one throttle. Halves concurrency. */\n noteThrottle(now: number = Date.now()): void {\n this.completed++;\n this.throttled++;\n this.streak = 0;\n const previous = this.current;\n const next = Math.max(this.opts.min, Math.floor(this.current / 2));\n this.cooldownUntil = now + this.opts.cooldownMs;\n this.rampFrozenUntil = now + this.opts.rampUpCooldownMs;\n if (next !== previous) {\n this.current = next;\n // Record this level as a soft ceiling. Only update on actual halving so\n // that subsequent throttles in the same burst (which arrive at lower\n // current values because we already halved) do not falsely lower the\n // ceiling.\n this.softCeiling = previous;\n this.notify('throttle', previous);\n }\n // Track throttles that occur while the controller is already at floor.\n // Mid-ramp-down throttles do not contribute — the controller is still\n // adapting and may yet reach a sustainable level. The streak increments\n // only when the post-throttle concurrency equals min (i.e. we are stuck\n // at the floor and the cluster still cannot accept the load).\n if (this.current === this.opts.min) {\n this.consecutiveThrottlesAtMin++;\n } else {\n this.consecutiveThrottlesAtMin = 0;\n }\n }\n\n /**\n * Current soft ceiling — the highest concurrency at which a throttle was\n * observed and the controller halved. {@link Number.POSITIVE_INFINITY} when\n * no ceiling is in effect. Re-approaching this level requires\n * `increaseAfter * throttleCeilingMultiplier` consecutive successes.\n */\n getSoftCeiling(): number {\n return this.softCeiling;\n }\n\n /** Configured circuit-breaker threshold. */\n getMaxConsecutiveThrottlesAtMin(): number {\n return this.opts.maxConsecutiveThrottlesAtMin;\n }\n\n /** How many consecutive throttles have occurred at min. */\n getConsecutiveThrottlesAtMin(): number {\n return this.consecutiveThrottlesAtMin;\n }\n\n /**\n * Whether the circuit breaker has tripped — runner should stop dispatching\n * new tasks and surface an `ImportThrottleAbortError` to the caller.\n */\n shouldAbort(): boolean {\n return this.consecutiveThrottlesAtMin >= this.opts.maxConsecutiveThrottlesAtMin;\n }\n\n private notify(reason: AdaptiveConcurrencyAdjustReason, previous: number): void {\n const cb = this.opts.onAdjust;\n if (!cb) return;\n try {\n cb({\n concurrency: this.current,\n previousConcurrency: previous,\n reason,\n tasksCompleted: this.completed,\n throttledCount: this.throttled,\n });\n } catch {\n // Operator callback errors are swallowed by design.\n }\n }\n}\n\n/**\n * Run a task inside a nested usageScope so its retries/RU/calls can be\n * inspected independently of any outer scope. Roll the inner counters up into\n * the parent (if any) on completion so outer telemetry remains correct.\n *\n * Returns the task result and the number of retries observed inside the task.\n * A non-zero retry count means the connection layer observed a 429/503 for\n * one of this task's submits, which the adaptive controller treats as a\n * throttle signal — even if the retry ultimately succeeded.\n */\nasync function runTaskWithUsage<R>(fn: () => Promise<R>): Promise<{ result: R; retries: number }> {\n const parent = usageScope.getStore();\n const taskAcc: UsageAccumulator = { ru: 0, calls: 0, retries: 0 };\n try {\n const result = await usageScope.run(taskAcc, fn);\n return { result, retries: taskAcc.retries };\n } finally {\n if (parent) {\n parent.ru += taskAcc.ru;\n parent.calls += taskAcc.calls;\n parent.retries += taskAcc.retries;\n }\n }\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms));\n}\n\n/**\n * Adaptive runner — processes `items` with dynamic concurrency, returning\n * results in input order. Mirrors the contract of the previous fixed-size\n * runWithConcurrency so callers swap one for the other.\n *\n * The runner respects the controller's cooldown: when a throttle has just\n * been observed, no new task is dispatched until the cooldown elapses, even\n * if a worker slot is otherwise free. In-flight tasks are unaffected.\n *\n * Throws {@link ImportThrottleAbortError} if the controller's circuit breaker\n * trips (sustained throttling at minimum concurrency). In-flight tasks are\n * awaited before the throw so observers see consistent state, but no new\n * tasks are dispatched once the breaker has tripped.\n */\nexport async function runAdaptive<T, R>(\n items: T[],\n controller: AdaptiveConcurrencyController,\n fn: (item: T) => Promise<R>,\n): Promise<R[]> {\n if (items.length === 0) return [];\n controller.emitStartIfNeeded();\n\n const results: R[] = new Array(items.length);\n let nextIndex = 0;\n let inFlight = 0;\n let aborted = false;\n\n // Workers wait on `gate` when they cannot dispatch (cooldown active, all\n // slots taken, or the breaker has tripped and we are draining). Any state\n // change re-issues the gate so all waiters wake up and re-check.\n let gate = createGate();\n\n function pokeGate(): void {\n const old = gate;\n gate = createGate();\n old.resolve();\n }\n\n async function worker(): Promise<void> {\n while (nextIndex < items.length) {\n if (aborted) return;\n // Wait until both: a slot is free AND any active cooldown has elapsed.\n while (true) {\n if (aborted || nextIndex >= items.length) return;\n const cooldownRemaining = controller.getCooldownUntil() - Date.now();\n const slotsAvailable = inFlight < controller.getConcurrency();\n if (cooldownRemaining <= 0 && slotsAvailable) break;\n if (cooldownRemaining > 0) {\n await Promise.race([sleep(cooldownRemaining), gate.promise]);\n } else {\n await gate.promise;\n }\n }\n if (aborted || nextIndex >= items.length) return;\n\n const idx = nextIndex++;\n inFlight++;\n try {\n const { result, retries } = await runTaskWithUsage(() => fn(items[idx]!));\n results[idx] = result;\n if (retries > 0) {\n controller.noteThrottle();\n } else {\n controller.noteSuccess();\n }\n if (controller.shouldAbort()) {\n aborted = true;\n }\n } finally {\n inFlight--;\n pokeGate();\n }\n }\n }\n\n // Provision workers up to the configured ceiling so the controller has\n // headroom to ramp up. Idle workers cost nothing — they just await the\n // gate. We never spawn more workers than items.\n const workerCount = Math.min(items.length, controller.getMaxConcurrency());\n const workers: Promise<void>[] = [];\n for (let w = 0; w < workerCount; w++) {\n workers.push(worker());\n }\n\n await Promise.all(workers);\n\n if (aborted) {\n throw new ImportThrottleAbortError(\n controller.getConcurrency(),\n controller.getConsecutiveThrottlesAtMin(),\n controller.getCompleted(),\n controller.getThrottledCount(),\n );\n }\n\n return results;\n}\n\nfunction createGate(): { promise: Promise<void>; resolve: () => void } {\n let resolve!: () => void;\n const promise = new Promise<void>(r => {\n resolve = r;\n });\n return { promise, resolve };\n}\n","// Bulk export/import Gremlin queries — optimized for throughput\n//\n// Import optimizations:\n// 1. Parallel execution with concurrency limiter (avoids sequential round-trips)\n// 2. Direct addV/addE when skipExistenceCheck is true (no existence query needed)\n// 3. Gremlin coalesce pattern for atomic upserts when existence checks are needed\n// (1 query instead of 2)\n//\n// Export optimizations:\n// 1. Cursor-based pagination using ID ordering instead of offset-based range()\n// (avoids O(n²) scan on large repositories)\n//\n// `valueMap(true)` exception: this is the one read path that intentionally\n// keeps it. Export must include every stored property — including the\n// embedding — so a re-import is field-for-field faithful. Do not migrate to\n// the project-chain helpers used elsewhere; they strip fields the import path\n// expects.\n\nimport type { CosmosDbConnection } from '../CosmosDbConnection.js';\nimport type { ExportChunk, ImportChunk, BulkImportOptions } from '@utaba/deep-memory/types';\nimport type { BulkImportResult, StoredEntity, StoredRelationship } from '@utaba/deep-memory/types';\nimport {\n buildEntityPropertyLadder,\n buildRelationshipPropertyLadder,\n entityFromGremlin,\n entityToLadderBindings,\n relationshipFromGremlin,\n relationshipToLadderBindings,\n} from '../mapping.js';\nimport { resolveController, runAdaptive } from './adaptive-import.js';\n\nconst EXPORT_BATCH_SIZE = 100;\n\n// ─── Export ──────────────────────────────────────────────────────\n\nexport async function* exportAll(\n conn: CosmosDbConnection,\n repositoryId: string,\n): AsyncIterable<ExportChunk> {\n let sequence = 0;\n\n // Export entities using cursor-based pagination (ordered by id)\n let cursor = '';\n while (true) {\n const result = cursor === ''\n ? await conn.submit(\n \"g.V().has('repositoryId', rid).has('entityType').order().by('id').limit(batchSize).valueMap(true)\",\n { rid: repositoryId, batchSize: EXPORT_BATCH_SIZE },\n )\n : await conn.submit(\n \"g.V().has('repositoryId', rid).has('entityType').has('id', gt(cursor)).order().by('id').limit(batchSize).valueMap(true)\",\n { rid: repositoryId, cursor, batchSize: EXPORT_BATCH_SIZE },\n );\n\n const entities = (result.items as Record<string, unknown>[]).map(entityFromGremlin);\n const isLast = entities.length < EXPORT_BATCH_SIZE;\n\n if (entities.length > 0) {\n cursor = entities[entities.length - 1]!.id;\n yield {\n type: 'entities',\n data: entities,\n sequence: sequence++,\n isLast,\n };\n }\n\n if (isLast) break;\n }\n\n // Export relationships using cursor-based pagination (ordered by id)\n cursor = '';\n while (true) {\n const result = cursor === ''\n ? await conn.submit(\n \"g.E().has('repositoryId', rid).order().by('id').limit(batchSize).valueMap(true)\",\n { rid: repositoryId, batchSize: EXPORT_BATCH_SIZE },\n )\n : await conn.submit(\n \"g.E().has('repositoryId', rid).has('id', gt(cursor)).order().by('id').limit(batchSize).valueMap(true)\",\n { rid: repositoryId, cursor, batchSize: EXPORT_BATCH_SIZE },\n );\n\n const relationships = (result.items as Record<string, unknown>[]).map(relationshipFromGremlin);\n const isLast = relationships.length < EXPORT_BATCH_SIZE;\n\n if (relationships.length > 0) {\n cursor = relationships[relationships.length - 1]!.id;\n yield {\n type: 'relationships',\n data: relationships,\n sequence: sequence++,\n isLast,\n };\n }\n\n if (isLast) break;\n }\n\n // If nothing was yielded, yield an empty final chunk\n if (sequence === 0) {\n yield {\n type: 'entities',\n data: [],\n sequence: 0,\n isLast: true,\n };\n }\n}\n\n// ─── Import ─────────────────────────────────────────────────────\n\nexport async function importBulk(\n conn: CosmosDbConnection,\n repositoryId: string,\n data: ImportChunk[],\n options?: BulkImportOptions,\n): Promise<BulkImportResult> {\n let entitiesImported = 0;\n let relationshipsImported = 0;\n const errors: Array<{ item: string; error: string }> = [];\n const skipCheck = options?.skipExistenceCheck ?? false;\n\n // Resolve the controller from the caller-supplied handle if any, so the\n // controller's learned state (concurrency level, success streak, cooldown,\n // soft ceiling) carries across multiple importBulk calls within a single\n // import operation. Without a handle, each importBulk call gets a fresh\n // controller — fine for single-shot usage but wrong for streaming imports\n // that issue one importBulk call per chunk. RepositoryImporter creates a\n // handle per import and threads it through automatically.\n const controller = resolveController(options?.adaptiveConcurrency, options?.adaptiveConcurrencyHandle);\n\n for (const chunk of data) {\n if (chunk.entities && chunk.entities.length > 0) {\n const results = await runAdaptive(\n chunk.entities,\n controller,\n async (entity): Promise<{ ok: boolean; id: string; error?: string }> => {\n try {\n if (skipCheck) {\n await insertEntity(conn, repositoryId, entity);\n } else {\n await upsertEntity(conn, repositoryId, entity);\n }\n return { ok: true, id: entity.id };\n } catch (err: unknown) {\n return {\n ok: false,\n id: entity.id,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n },\n );\n\n for (const r of results) {\n if (r.ok) {\n entitiesImported++;\n } else {\n errors.push({ item: `entity:${r.id}`, error: r.error! });\n }\n }\n }\n\n if (chunk.relationships && chunk.relationships.length > 0) {\n const results = await runAdaptive(\n chunk.relationships,\n controller,\n async (rel): Promise<{ ok: boolean; id: string; error?: string }> => {\n try {\n if (skipCheck) {\n await insertRelationship(conn, repositoryId, rel);\n } else {\n await upsertRelationship(conn, repositoryId, rel);\n }\n return { ok: true, id: rel.id };\n } catch (err: unknown) {\n return {\n ok: false,\n id: rel.id,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n },\n );\n\n for (const r of results) {\n if (r.ok) {\n relationshipsImported++;\n } else {\n errors.push({ item: `relationship:${r.id}`, error: r.error! });\n }\n }\n }\n }\n\n return { entitiesImported, relationshipsImported, errors };\n}\n\n// ─── Fixed-shape query templates ─────────────────────────────────\n//\n// Same Gremlin string across every entity/relationship write regardless of\n// which optional fields are populated, so the Cosmos plan cache reuses one\n// compiled plan. Computed once at module load. The upsert update branch\n// reuses the SAME ladder as the create branch — Cosmos already rejects\n// `.property('repositoryId', ...)` after `unfold()`, and the ladder excludes\n// `id` and `repositoryId` (both written explicitly only on the create branch).\n\nconst ENTITY_LADDER_CHAIN = buildEntityPropertyLadder();\nconst RELATIONSHIP_LADDER_CHAIN = buildRelationshipPropertyLadder();\n\nconst INSERT_ENTITY_QUERY =\n `g.addV(vertexLabel).property('id', vid).property('repositoryId', rid)${ENTITY_LADDER_CHAIN}`;\n\nconst INSERT_RELATIONSHIP_QUERY =\n `g.V().has('repositoryId', rid).hasId(srcId).has('entityType')` +\n `.addE(edgeLabel)` +\n `.to(g.V().has('repositoryId', rid).hasId(tgtId).has('entityType'))` +\n `.property('id', relId).property('repositoryId', rid)${RELATIONSHIP_LADDER_CHAIN}`;\n\nconst UPSERT_ENTITY_QUERY =\n `g.V().has('repositoryId', rid).hasId(vid).has('entityType').fold().coalesce(` +\n `unfold()${ENTITY_LADDER_CHAIN},` +\n ` addV(vertexLabel).property('id', vid).property('repositoryId', rid)${ENTITY_LADDER_CHAIN})`;\n\nconst UPSERT_RELATIONSHIP_QUERY =\n `g.E().has('repositoryId', rid).hasId(relId).fold().coalesce(` +\n `unfold()${RELATIONSHIP_LADDER_CHAIN},` +\n ` g.V().has('repositoryId', rid).hasId(srcId).has('entityType').addE(edgeLabel)` +\n `.to(g.V().has('repositoryId', rid).hasId(tgtId).has('entityType'))` +\n `.property('id', relId).property('repositoryId', rid)${RELATIONSHIP_LADDER_CHAIN})`;\n\n// ─── Direct insert (no existence check) ─────────────────────────\n\n/** Insert an entity directly — assumes it does not exist. */\nasync function insertEntity(\n conn: CosmosDbConnection,\n repositoryId: string,\n entity: StoredEntity,\n): Promise<void> {\n const bindings: Record<string, unknown> = {\n rid: repositoryId,\n vid: entity.id,\n vertexLabel: entity.entityType,\n ...entityToLadderBindings(entity),\n };\n await conn.submit(INSERT_ENTITY_QUERY, bindings);\n}\n\n/** Insert a relationship directly — assumes it does not exist. */\nasync function insertRelationship(\n conn: CosmosDbConnection,\n repositoryId: string,\n rel: StoredRelationship,\n): Promise<void> {\n const bindings: Record<string, unknown> = {\n rid: repositoryId,\n relId: rel.id,\n srcId: rel.sourceEntityId,\n tgtId: rel.targetEntityId,\n edgeLabel: rel.relationshipType,\n ...relationshipToLadderBindings(rel),\n };\n await conn.submit(INSERT_RELATIONSHIP_QUERY, bindings);\n}\n\n// ─── Atomic upsert (single query with coalesce) ─────────────────\n\n/**\n * Upsert an entity using Gremlin's coalesce pattern — single query.\n * Replaces the old 2-query check-then-create/update approach.\n *\n * Both branches share the same fixed-shape entity ladder (which omits `id`\n * and `repositoryId`). The create branch prepends `.property('id',\n * vid).property('repositoryId', rid)` to addV; the update branch (after\n * `unfold`) relies on those system properties already being set. Cosmos\n * rejects `.property('repositoryId', ...)` after `unfold()` at parse time,\n * so excluding `repositoryId` from the ladder is required for correctness\n * as well as plan-cache shape.\n */\nasync function upsertEntity(\n conn: CosmosDbConnection,\n repositoryId: string,\n entity: StoredEntity,\n): Promise<void> {\n const bindings: Record<string, unknown> = {\n rid: repositoryId,\n vid: entity.id,\n vertexLabel: entity.entityType,\n ...entityToLadderBindings(entity),\n };\n await conn.submit(UPSERT_ENTITY_QUERY, bindings);\n}\n\n/**\n * Upsert a relationship using Gremlin's coalesce pattern — single query.\n * Replaces the old 2-query check-then-create/update approach.\n *\n * The E() lookup is scoped by repositoryId so an edge with the same id in a\n * different repo cannot be matched and silently overwritten.\n */\nasync function upsertRelationship(\n conn: CosmosDbConnection,\n repositoryId: string,\n rel: StoredRelationship,\n): Promise<void> {\n const bindings: Record<string, unknown> = {\n rid: repositoryId,\n relId: rel.id,\n srcId: rel.sourceEntityId,\n tgtId: rel.targetEntityId,\n edgeLabel: rel.relationshipType,\n ...relationshipToLadderBindings(rel),\n };\n await conn.submit(UPSERT_RELATIONSHIP_QUERY, bindings);\n}\n"],"mappings":"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","names":["matchesPropertyFilters","acc","sleep","matchesPropertyFilters","DUPLICATE_SENTINEL","sleep","matchesPropertyFilters"]}
|