{"version":3,"sources":["../src/registry/catalog.ts","../src/internal/validate-runtime-row.ts","../src/internal/wait-for-asset.ts","../src/internal/catalog-session.ts","../src/internal/load-asset.ts"],"names":["err","ok","current"],"mappings":"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","file":"internal.mjs","sourcesContent":["import { decodeCatalogWire } from '@forgeax/engine-pack';\nimport { err, ok, type Result } from '@forgeax/engine-rhi';\nimport {\n  ASSET_ERROR_HINTS,\n  type Asset,\n  type AssetAuthoringCapability,\n  type AssetEnvelope,\n  AssetError,\n  type AssetPublicationEnvelope,\n  type AssetRelation,\n  authoringCapabilityForAssetKind,\n  type CatalogDiagnostic,\n  type CatalogEntry,\n  type CatalogProjection,\n  type ProviderProvenance,\n  type ResourceRevision,\n  type RuntimeAssetBinding,\n  type SourceOverrideDescriptor,\n  type SourceOverrideMap,\n} from '@forgeax/engine-types';\nimport type { AssetRegistry } from '../asset-registry';\nimport { jsonOf, type PackageFetcher, readPackage } from '../internal/package-read.js';\n\n/**\n * Runtime catalog row parsed from the shared pack-index POD shape. GUID is the\n * catalog key, and inline assets have no source declaration to navigate.\n */\nexport type CatalogRecord = Omit<CatalogEntry, 'guid' | 'sourcePath'> & {\n  readonly sourcePath?: string;\n};\n\n/** Build the canonical row for an inline asset without inventing producer facts. */\nexport function createInlineCatalogRecord(\n  envelope: AssetEnvelope<Asset>,\n  name: string,\n): CatalogRecord {\n  return {\n    packageUrl: '',\n    kind: envelope.payload.kind,\n    authoring: authoringCapabilityForAssetKind(envelope.payload.kind),\n    name,\n    ...(envelope.refs.length > 0 ? { refs: envelope.refs.map((ref) => ref.guid) } : {}),\n  };\n}\n\nfunction parseError(\n  expected: string,\n  detail?: object,\n  hint = ASSET_ERROR_HINTS['asset-parse-failed'],\n): AssetError {\n  return new AssetError({\n    code: 'asset-parse-failed',\n    expected,\n    hint,\n    ...(detail === undefined ? {} : { detail: detail as never }),\n  });\n}\n\nfunction sameRevision(left: ResourceRevision, right: ResourceRevision): boolean {\n  return (\n    left.digest === right.digest &&\n    left.observedAt === right.observedAt &&\n    left.rootId === right.rootId\n  );\n}\n\nexport function checkExpectedRevision(\n  records: readonly CatalogRecord[],\n  expectedRevision: ResourceRevision | undefined,\n): AssetError | undefined {\n  if (expectedRevision === undefined || records.length === 0) return undefined;\n  const actualRevisions = records.flatMap((record) =>\n    record.revision === undefined ? [] : [record.revision],\n  );\n  if (\n    actualRevisions.length > 0 &&\n    actualRevisions.every((revision) => sameRevision(revision, expectedRevision))\n  ) {\n    return undefined;\n  }\n  return parseError(\n    'every catalog entry to carry the expected producer revision',\n    { expectedRevision, actualRevisions },\n    'restore a verified catalog revision before applying the source',\n  );\n}\n\n/** Resolve a catalog entry URL against the configured pack-index URL. */\nexport function resolveCatalogAssetUrl(\n  registry: Pick<AssetRegistry, 'packIndexUrl'>,\n  packageUrl: string,\n): string {\n  const packIndexUrl = registry.packIndexUrl;\n  if (packIndexUrl === undefined) return packageUrl;\n\n  try {\n    const baseUrl = new URL(packIndexUrl, globalThis.location?.href).href;\n    return new URL(packageUrl, baseUrl).href;\n  } catch {\n    return packageUrl;\n  }\n}\n\nfunction isRawSourceLocator(packageUrl: string): boolean {\n  const path = packageUrl.split(/[?#]/, 1)[0]?.toLowerCase() ?? packageUrl.toLowerCase();\n  if (path.endsWith('.pack.json')) return false;\n  return (\n    /\\.(bin|fbx|gltf|glb|hdr|jpg|jpeg|png|wav|mp3|ogg|ttf|otf|woff|woff2|svg)$/.test(path) ||\n    path.endsWith('.particle-effect.json')\n  );\n}\n\n/** Parse the shared pack-index/catalog wire shape without loading payloads. */\nexport function parseCatalog(\n  raw: unknown,\n  resolveUrl: (packageUrl: string) => string = (packageUrl) => packageUrl,\n  expectedRevision?: ResourceRevision,\n  expectedScope?: Pick<RuntimeAssetBinding, 'scopeId' | 'generation'>,\n): Result<Map<string, CatalogRecord>, AssetError> {\n  let rows: readonly unknown[];\n  if (expectedScope !== undefined) {\n    if (raw === null || typeof raw !== 'object' || Array.isArray(raw)) {\n      return err(\n        parseError(\n          'scoped catalog snapshot to be an object with schema, scopeId, generation, authority, and entries',\n        ),\n      );\n    }\n    const snapshot = raw as Record<string, unknown>;\n    if (\n      snapshot.schemaVersion !== 'runtime-catalog-snapshot-v1' ||\n      typeof snapshot.scopeId !== 'string' ||\n      typeof snapshot.generation !== 'number' ||\n      !Number.isSafeInteger(snapshot.generation) ||\n      !Array.isArray(snapshot.entries)\n    ) {\n      return err(parseError('scoped catalog snapshot to satisfy its runtime schema'));\n    }\n    if (\n      snapshot.scopeId !== expectedScope.scopeId ||\n      snapshot.generation !== expectedScope.generation\n    ) {\n      return err(\n        parseError('scoped catalog snapshot to match the active scope and generation', {\n          expectedScope,\n          actualScope: { scopeId: snapshot.scopeId, generation: snapshot.generation },\n        }),\n      );\n    }\n    if (snapshot.authority !== 'authoritative') {\n      return err(\n        parseError(\n          'scoped catalog snapshot authority to be authoritative before identity lookup',\n          { authority: snapshot.authority, diagnostics: snapshot.diagnostics },\n          'repair the active game catalog before loading assets',\n        ),\n      );\n    }\n    rows = snapshot.entries;\n  } else {\n    const decoded = decodeCatalogWire(raw);\n    if (!decoded.ok) return decoded;\n    rows = decoded.value;\n  }\n\n  const catalog = new Map<string, CatalogRecord>();\n  for (const item of rows) {\n    if (item === null || typeof item !== 'object') {\n      return err(parseError('each catalog row to be an object'));\n    }\n    const rawRow = item as Record<string, unknown>;\n    const legacyLocator = ['relative', 'Url'].join('');\n    if (\n      legacyLocator in rawRow ||\n      'metadata' in rawRow ||\n      'compression' in rawRow ||\n      'artifacts' in rawRow ||\n      'assetCodec' in rawRow ||\n      'contentEncoding' in rawRow\n    ) {\n      return err(parseError('catalog rows to expose navigation fields only'));\n    }\n    if (\n      typeof rawRow.guid !== 'string' ||\n      rawRow.guid.length === 0 ||\n      typeof rawRow.packageUrl !== 'string' ||\n      rawRow.packageUrl.length === 0 ||\n      typeof rawRow.kind !== 'string' ||\n      rawRow.kind.length === 0\n    ) {\n      return err(parseError('each catalog row to contain guid, packageUrl, and kind strings'));\n    }\n    if (isRawSourceLocator(rawRow.packageUrl)) {\n      return err(\n        parseError(`catalog packageUrl ${rawRow.packageUrl} to identify a cooked package`),\n      );\n    }\n    const guid = rawRow.guid.toLowerCase();\n    if (catalog.has(guid)) return err(parseError(`catalog GUID ${rawRow.guid} to be unique`));\n    const refs = rawRow.refs;\n    if (\n      refs !== undefined &&\n      (!Array.isArray(refs) || !refs.every((ref) => typeof ref === 'string'))\n    ) {\n      return err(parseError(`catalog refs for GUID ${rawRow.guid} to be a string array`));\n    }\n    if (\n      rawRow.sourceOverrides !== undefined &&\n      (rawRow.sourceOverrides === null ||\n        typeof rawRow.sourceOverrides !== 'object' ||\n        Array.isArray(rawRow.sourceOverrides))\n    ) {\n      return err(parseError(`catalog sourceOverrides for GUID ${rawRow.guid} to be an object`));\n    }\n    if (\n      rawRow.sourceOverrideDescriptors !== undefined &&\n      !Array.isArray(rawRow.sourceOverrideDescriptors)\n    ) {\n      return err(\n        parseError(`catalog sourceOverrideDescriptors for GUID ${rawRow.guid} to be an array`),\n      );\n    }\n    let resolvedUrl: string;\n    try {\n      resolvedUrl = resolveUrl(rawRow.packageUrl);\n    } catch (error) {\n      return err(\n        parseError(`catalog entry ${rawRow.guid} to resolve its packageUrl`, {\n          packageUrl: rawRow.packageUrl,\n          reason: error instanceof Error ? error.message : String(error),\n        }),\n      );\n    }\n    const row: CatalogRecord = {\n      packageUrl: resolvedUrl,\n      kind: rawRow.kind,\n      ...(rawRow.authoring !== undefined\n        ? { authoring: rawRow.authoring as AssetAuthoringCapability }\n        : {}),\n      ...(typeof rawRow.name === 'string' ? { name: rawRow.name } : {}),\n      ...(typeof rawRow.sourcePath === 'string' ? { sourcePath: rawRow.sourcePath } : {}),\n      ...(refs !== undefined ? { refs: refs as readonly string[] } : {}),\n      ...(typeof rawRow.cookReceiptUrl === 'string'\n        ? { cookReceiptUrl: rawRow.cookReceiptUrl }\n        : {}),\n      ...(typeof rawRow.packageId === 'string' ? { packageId: rawRow.packageId } : {}),\n      ...(rawRow.provenance !== undefined\n        ? { provenance: rawRow.provenance as ProviderProvenance }\n        : {}),\n      ...(rawRow.revision !== undefined ? { revision: rawRow.revision as ResourceRevision } : {}),\n      ...(typeof rawRow.sourceKey === 'string' ? { sourceKey: rawRow.sourceKey } : {}),\n      ...(typeof rawRow.sourceIndex === 'number' ? { sourceIndex: rawRow.sourceIndex } : {}),\n      ...(rawRow.sourceOverrides !== undefined\n        ? { sourceOverrides: rawRow.sourceOverrides as SourceOverrideMap }\n        : {}),\n      ...(rawRow.sourceOverrideDescriptors !== undefined\n        ? {\n            sourceOverrideDescriptors:\n              rawRow.sourceOverrideDescriptors as readonly SourceOverrideDescriptor[],\n          }\n        : {}),\n      ...(Array.isArray(rawRow.relations)\n        ? { relations: rawRow.relations as readonly AssetRelation[] }\n        : {}),\n      ...(Array.isArray(rawRow.diagnostics)\n        ? { diagnostics: rawRow.diagnostics as readonly CatalogDiagnostic[] }\n        : {}),\n      ...(rawRow.subject === 'internal-asset' || rawRow.subject === 'imported-output'\n        ? { subject: rawRow.subject }\n        : {}),\n      ...(rawRow.execution === 'direct' || rawRow.execution === 'cooked'\n        ? { execution: rawRow.execution }\n        : {}),\n      ...(rawRow.lifecycle === 'missing' ||\n      rawRow.lifecycle === 'cooking' ||\n      rawRow.lifecycle === 'current' ||\n      rawRow.lifecycle === 'stale' ||\n      rawRow.lifecycle === 'failed'\n        ? { lifecycle: rawRow.lifecycle }\n        : {}),\n      ...(rawRow.projection !== undefined\n        ? { projection: rawRow.projection as CatalogProjection }\n        : {}),\n      ...(rawRow.publication !== undefined\n        ? { publication: rawRow.publication as AssetPublicationEnvelope }\n        : {}),\n    };\n    catalog.set(guid, row);\n  }\n  const revisionError = checkExpectedRevision([...catalog.values()], expectedRevision);\n  if (revisionError !== undefined) return err(revisionError);\n  return ok(catalog);\n}\n\n/** Fetch and parse a catalog using the shared JSON/error boundary. */\nexport async function fetchCatalog(\n  url: string,\n  fetch: PackageFetcher,\n  resolveUrl?: (packageUrl: string) => string,\n  expectedRevision?: ResourceRevision,\n  expectedScope?: Pick<RuntimeAssetBinding, 'scopeId' | 'generation'>,\n  requestInit?: { readonly cache?: 'no-store' },\n): Promise<Result<Map<string, CatalogRecord>, AssetError>> {\n  const read = await readPackage(fetch, url, jsonOf, requestInit);\n  if (!read.ok) {\n    return err(\n      new AssetError({\n        code: 'asset-fetch-failed',\n        expected: `${read.error.malformed ? 'JSON' : 'readable'} catalog at ${url}`,\n        hint: `${read.error.observed} after ${read.error.attempts} request(s); ${ASSET_ERROR_HINTS['asset-fetch-failed']}`,\n        detail: { field: 'request', value: url, reason: read.error.observed },\n      }),\n    );\n  }\n  const raw = read.value;\n  return parseCatalog(raw, resolveUrl, expectedRevision, expectedScope);\n}\n\nexport function fetchPackIndex(\n  registry: AssetRegistry,\n): Promise<Result<Map<string, CatalogRecord>, AssetError>> {\n  const expectedScope =\n    registry.runtimeBinding !== undefined &&\n    registry.packIndexUrl === registry.runtimeBinding.catalogUrl\n      ? registry.runtimeBinding\n      : undefined;\n  return fetchCatalog(\n    registry.packIndexUrl as string,\n    globalThis.fetch,\n    (packageUrl) => resolveCatalogAssetUrl(registry, packageUrl),\n    undefined,\n    expectedScope,\n    { cache: 'no-store' },\n  );\n}\n","import type { CatalogEntry } from '@forgeax/engine-types';\nimport { type AssetLoadError, err, ok, type Result } from '@forgeax/engine-types';\n\nexport interface RuntimeCatalogRow extends CatalogEntry {\n  readonly publication: NonNullable<CatalogEntry['publication']>;\n}\n\nfunction invalidRow(guid: string, reason: string): Result<never, AssetLoadError> {\n  return err({\n    code: 'asset-package-invalid',\n    expected: 'one complete current runtime Catalog row',\n    hint: 'rebuild the producer Catalog and publish one Pack v2 tuple',\n    detail: { guid, reason },\n  });\n}\n\nexport function validateCatalogRow(row: CatalogEntry): Result<CatalogEntry, AssetLoadError> {\n  if (row === null || typeof row !== 'object') return invalidRow('', 'row');\n  const candidate = row as Partial<CatalogEntry>;\n  const guid = typeof candidate.guid === 'string' ? candidate.guid : '';\n  if (guid.trim().length === 0) return invalidRow(guid, 'guid');\n  if (typeof candidate.kind !== 'string' || candidate.kind.trim().length === 0)\n    return invalidRow(guid, 'kind');\n  if (typeof candidate.packageUrl !== 'string' || candidate.packageUrl.trim().length === 0)\n    return invalidRow(guid, 'packageUrl');\n  if (typeof candidate.sourcePath !== 'string' || candidate.sourcePath.trim().length === 0)\n    return invalidRow(guid, 'sourcePath');\n  return ok(Object.freeze({ ...candidate, guid }) as CatalogEntry);\n}\n\nexport function validateRuntimeRow(row: CatalogEntry): Result<RuntimeCatalogRow, AssetLoadError> {\n  const navigation = validateCatalogRow(row);\n  if (!navigation.ok) return navigation;\n  const candidate = navigation.value;\n  const guid = candidate.guid;\n  if (!Number.isSafeInteger(candidate.publication?.generation))\n    return invalidRow(guid, 'publication generation');\n  if (candidate.publication === undefined) return invalidRow(guid, 'publication');\n  const publication = candidate.publication;\n  if (\n    publication.schemaVersion !== 'asset-publication/1' ||\n    typeof publication.sourcePath !== 'string' ||\n    publication.sourcePath.trim().length === 0 ||\n    typeof publication.sourceRevision !== 'string' ||\n    publication.sourceRevision.trim().length === 0 ||\n    publication.generation < 0 ||\n    typeof publication.digest !== 'string' ||\n    publication.digest.trim().length === 0 ||\n    typeof publication.outputSetDigest !== 'string' ||\n    publication.outputSetDigest.trim().length === 0 ||\n    !Array.isArray(publication.outputs) ||\n    publication.receipt === null ||\n    typeof publication.receipt !== 'object' ||\n    !Array.isArray(publication.externalEvidence)\n  ) {\n    return invalidRow(guid, 'publication tuple');\n  }\n  return ok(Object.freeze({ ...candidate, guid, publication }) as RuntimeCatalogRow);\n}\n","import { type AssetLoadError, err, type Result } from '@forgeax/engine-types';\n\n/** Cancel one wait without cancelling the owner's shared operation. */\nexport function waitForAsset<T>(\n  request: Promise<Result<T, AssetLoadError>>,\n  signal: AbortSignal,\n  guid: string,\n): Promise<Result<T, AssetLoadError>> {\n  if (signal.aborted) return Promise.resolve(err(assetLoadCancelled(guid)));\n  return new Promise((resolve, reject) => {\n    const abort = () => resolve(err(assetLoadCancelled(guid)));\n    signal.addEventListener('abort', abort, { once: true });\n    request.then(\n      (result) => {\n        signal.removeEventListener('abort', abort);\n        resolve(result);\n      },\n      (cause: unknown) => {\n        signal.removeEventListener('abort', abort);\n        reject(cause);\n      },\n    );\n  });\n}\n\nexport function assetLoadCancelled(guid: string): AssetLoadError {\n  return {\n    code: 'asset-load-cancelled',\n    expected: 'the request AbortSignal to remain live until the load completes',\n    hint: 'retry with a live AbortSignal when the request is still needed',\n    detail: { guid },\n  };\n}\n","import type {\n  CatalogDelta,\n  CatalogDiagnostic,\n  CatalogEntry,\n  ResourceRevision,\n} from '@forgeax/engine-types';\nimport { type AssetLoadError, err, ok, type Result } from '@forgeax/engine-types';\nimport type { CatalogSource } from '../catalog-source.js';\nimport { resolveCatalogAssetUrl } from '../registry/catalog.js';\nimport {\n  type RuntimeCatalogRow,\n  validateCatalogRow,\n  validateRuntimeRow,\n} from './validate-runtime-row.js';\nimport { waitForAsset } from './wait-for-asset.js';\n\nexport interface CatalogSessionOptions {\n  readonly scopeId?: string;\n  readonly generation?: number;\n}\n\nexport interface CatalogSessionSnapshot {\n  readonly scopeId: string;\n  readonly generation: number;\n  readonly epoch: number;\n  readonly revision?: ResourceRevision;\n  readonly entries: readonly CatalogEntry[];\n  readonly changed: readonly string[];\n  readonly removed: readonly string[];\n  readonly diagnostics: readonly CatalogDiagnostic[];\n  readonly listenerFailures: number;\n  readonly stale: boolean;\n}\n\ntype SessionResult = Result<CatalogSessionSnapshot, AssetLoadError>;\ntype SessionListener = (snapshot: CatalogSessionSnapshot) => void;\n\nfunction runtimeError(\n  code: AssetLoadError['code'],\n  guid: string,\n  detail: Record<string, unknown>,\n): AssetLoadError {\n  if (code === 'catalog-discontinuous') {\n    return {\n      code,\n      expected: 'an ordered catalog revision window',\n      hint: 'reconcile the current Catalog before consuming this delta',\n      detail: {\n        scopeId: String(detail.scopeId ?? 'unknown'),\n        expectedGeneration: Number(detail.expectedGeneration ?? 0),\n        actualGeneration: Number(detail.actualGeneration ?? 0),\n      },\n    };\n  }\n  return {\n    code: 'asset-package-invalid',\n    expected: 'a verified Catalog source',\n    hint: 'repair the producer Catalog and retry with the current publication',\n    detail: { guid, reason: String(detail.reason ?? 'catalog source failed') },\n  };\n}\n\nfunction freezeSnapshot(snapshot: CatalogSessionSnapshot): CatalogSessionSnapshot {\n  return Object.freeze({\n    ...snapshot,\n    entries: Object.freeze([...snapshot.entries]),\n    changed: Object.freeze([...snapshot.changed]),\n    removed: Object.freeze([...snapshot.removed]),\n    diagnostics: Object.freeze([...snapshot.diagnostics]),\n  });\n}\n\nfunction sameEntry(left: CatalogEntry, right: CatalogEntry): boolean {\n  return JSON.stringify(left) === JSON.stringify(right);\n}\n\nfunction key(guid: string): string {\n  return guid.toLowerCase();\n}\n\nfunction validateSessionRow(row: CatalogEntry): Result<CatalogEntry, AssetLoadError> {\n  if (row?.lifecycle === 'missing' && row.publication === undefined) {\n    return validateCatalogRow(row);\n  }\n  return validateRuntimeRow(row);\n}\n\nexport class CatalogSession {\n  private readonly source: CatalogSource;\n  private readonly scopeId: string;\n  private readonly generation: number;\n  private readonly entries = new Map<string, CatalogEntry>();\n  private readonly reads = new Map<string, Promise<Result<RuntimeCatalogRow, AssetLoadError>>>();\n  private readonly lifetime = new AbortController();\n  private readonly listeners = new Set<SessionListener>();\n  private unsubscribe: (() => void) | undefined;\n  private baselinePromise: Promise<SessionResult> | undefined;\n  private reconcilePromise: Promise<SessionResult> | undefined;\n  private pending: CatalogDelta[] = [];\n  private currentSnapshot: CatalogSessionSnapshot;\n  private revision: ResourceRevision | undefined;\n  private diagnostics: CatalogDiagnostic[] = [];\n  private listenerFailures = 0;\n  private changed = new Set<string>();\n  private removed = new Set<string>();\n  private epoch = 0;\n  private stale = false;\n  private staleGeneration = 0;\n  private started = false;\n  private disposed = false;\n\n  constructor(source: CatalogSource, options: CatalogSessionOptions = {}) {\n    this.source = source;\n    this.scopeId = options.scopeId ?? source.expectedScope?.scopeId ?? 'asset-runtime';\n    this.generation = options.generation ?? source.expectedScope?.generation ?? 0;\n    this.currentSnapshot = freezeSnapshot({\n      scopeId: this.scopeId,\n      generation: this.generation,\n      epoch: 0,\n      entries: [],\n      changed: [],\n      removed: [],\n      diagnostics: [],\n      listenerFailures: 0,\n      stale: false,\n    });\n  }\n\n  start(): Promise<SessionResult> {\n    if (this.baselinePromise !== undefined) return this.baselinePromise;\n    if (this.disposed) return Promise.resolve(err(this.disposedError()));\n    this.unsubscribe = this.source.subscribe((delta) => this.receive(delta));\n    const promise = this.source\n      .enumerate()\n      .then((result) => {\n        if (!result.ok) {\n          this.markStale();\n          this.publish();\n          return err(runtimeError('asset-package-invalid', '', { reason: result.error.code }));\n        }\n        this.entries.clear();\n        for (const entry of result.value) {\n          const validated = validateSessionRow(this.resolveRow(entry));\n          if (!validated.ok) {\n            this.markStale();\n            this.publish();\n            return err(validated.error);\n          }\n          this.entries.set(key(validated.value.guid), validated.value);\n        }\n        this.started = true;\n        this.stale = false;\n        this.staleGeneration = this.generation;\n        this.diagnostics = [];\n        for (const delta of this.pending) this.fold(delta, false);\n        this.pending = [];\n        this.publish();\n        return ok(this.currentSnapshot);\n      })\n      .catch((cause: unknown) => {\n        this.markStale();\n        this.addDiagnostic('catalog-degraded-rows', 'Catalog enumeration must resolve a Result');\n        this.publish();\n        return err(\n          runtimeError('asset-package-invalid', '', {\n            reason: cause instanceof Error ? cause.message : String(cause),\n          }),\n        );\n      });\n    this.baselinePromise = promise;\n    void promise.then(\n      (result) => {\n        if (!result.ok) this.baselinePromise = undefined;\n      },\n      () => {\n        this.baselinePromise = undefined;\n      },\n    );\n    return promise;\n  }\n\n  reconcile(): Promise<SessionResult> {\n    if (this.disposed) return Promise.resolve(err(this.disposedError()));\n    if (this.reconcilePromise !== undefined) return this.reconcilePromise;\n    this.unsubscribe?.();\n    this.unsubscribe = undefined;\n    this.started = false;\n    this.reads.clear();\n    this.pending = [];\n    this.baselinePromise = undefined;\n    this.epoch += 1;\n    const promise = this.start();\n    this.reconcilePromise = promise;\n    void promise.then(\n      () => {\n        if (this.reconcilePromise === promise) this.reconcilePromise = undefined;\n      },\n      () => {\n        if (this.reconcilePromise === promise) this.reconcilePromise = undefined;\n      },\n    );\n    return promise;\n  }\n\n  current(guid: string): CatalogEntry | undefined {\n    return this.entries.get(key(guid));\n  }\n\n  get(guid: string): Promise<Result<RuntimeCatalogRow, AssetLoadError>> {\n    const row = this.current(guid);\n    const get = this.source.get?.bind(this.source);\n    if (this.disposed) return Promise.resolve(err(this.disposedError()));\n    if (row === undefined)\n      return Promise.resolve(\n        err({\n          code: 'asset-not-found',\n          expected: 'the current Catalog to declare the requested GUID',\n          hint: 'inspect the producer Catalog',\n          detail: { guid },\n        }),\n      );\n    if (row.lifecycle !== 'missing' || row.publication !== undefined || get === undefined) {\n      return Promise.resolve(validateRuntimeRow(row));\n    }\n    const id = key(guid);\n    const existing = this.reads.get(id);\n    if (existing) return existing;\n    const baseline = [...this.entries.values()].filter(\n      (candidate) => candidate.sourcePath === row.sourcePath,\n    );\n    const current = () => this.reads.get(id) === request;\n    const request = (async (): Promise<Result<RuntimeCatalogRow, AssetLoadError>> => {\n      const imported = await waitForAsset(\n        Promise.resolve()\n          .then(() => get(guid))\n          .then((result) =>\n            result.ok\n              ? ok(result.value)\n              : err(runtimeError('asset-package-invalid', guid, { reason: result.error.code })),\n          )\n          .catch((cause: unknown) =>\n            err(\n              runtimeError('asset-package-invalid', guid, {\n                reason: cause instanceof Error ? cause.message : String(cause),\n              }),\n            ),\n          ),\n        this.lifetime.signal,\n        guid,\n      );\n      if (this.disposed) return err(this.disposedError());\n      if (!current())\n        return err({\n          code: 'asset-superseded',\n          expected: 'the same declared GUID until publication completes',\n          hint: 'retry the current Catalog publication',\n          detail: { guid, generation: this.generation },\n        });\n      const discontinuity = this.discontinuity();\n      if (discontinuity) return err(discontinuity);\n      if (!imported.ok) return imported;\n      const rows: RuntimeCatalogRow[] = [];\n      for (const candidate of imported.value) {\n        const validated = validateRuntimeRow(this.resolveRow(candidate));\n        if (!validated.ok) return validated;\n        rows.push(validated.value);\n      }\n      const published = rows.find((candidate) => key(candidate.guid) === id);\n      if (published === undefined)\n        return err(\n          runtimeError('asset-package-invalid', guid, {\n            reason: 'producer omitted the requested GUID',\n          }),\n        );\n      for (const candidate of rows) {\n        const prior = baseline.find((entry) => key(entry.guid) === key(candidate.guid));\n        const current = this.current(candidate.guid);\n        if (\n          (prior !== undefined && current === undefined) ||\n          (current !== undefined &&\n            !sameEntry(current, candidate) &&\n            (prior === undefined || current !== prior))\n        ) {\n          return err({\n            code: 'asset-superseded',\n            expected: 'the same declared source until publication completes',\n            hint: 'retry the current Catalog publication',\n            detail: { guid: candidate.guid, generation: this.generation },\n          });\n        }\n      }\n      this.fold(\n        {\n          added: rows,\n          changed: [],\n          removed: [],\n          scopeId: this.scopeId,\n          generation: this.generation,\n        },\n        true,\n      );\n      return ok(published);\n    })();\n    this.reads.set(id, request);\n    void request.finally(() => {\n      if (this.reads.get(id) === request) this.reads.delete(id);\n    });\n    return request;\n  }\n\n  snapshot(): CatalogSessionSnapshot {\n    return this.currentSnapshot;\n  }\n\n  discontinuity(): AssetLoadError | undefined {\n    if (!this.stale) return undefined;\n    return {\n      code: 'catalog-discontinuous',\n      expected: 'an ordered, authoritative catalog revision window',\n      hint: 'reconcile the Catalog source and retry the current publication',\n      detail: {\n        scopeId: this.scopeId,\n        expectedGeneration: this.generation,\n        actualGeneration: this.staleGeneration,\n      },\n    };\n  }\n\n  subscribe(listener: SessionListener): () => void {\n    this.listeners.add(listener);\n    return () => this.listeners.delete(listener);\n  }\n\n  dispose(): void {\n    if (this.disposed) return;\n    this.disposed = true;\n    this.lifetime.abort();\n    this.unsubscribe?.();\n    this.unsubscribe = undefined;\n    this.pending = [];\n    this.reads.clear();\n    this.listeners.clear();\n  }\n\n  private receive(delta: CatalogDelta): void {\n    if (this.disposed) return;\n    if (!this.started) {\n      this.pending.push(delta);\n      return;\n    }\n    this.fold(delta, true);\n  }\n\n  private resolveRow(row: CatalogEntry): CatalogEntry {\n    if (this.source.url === undefined || typeof row?.packageUrl !== 'string') return row;\n    const packageUrl = resolveCatalogAssetUrl({ packIndexUrl: this.source.url }, row.packageUrl);\n    return packageUrl === row.packageUrl ? row : { ...row, packageUrl };\n  }\n\n  private fold(delta: CatalogDelta, publish: boolean): void {\n    if (\n      (delta.scopeId !== undefined && delta.scopeId !== this.scopeId) ||\n      (delta.generation !== undefined && delta.generation !== this.generation)\n    ) {\n      this.markStale(delta.generation);\n      this.addDiagnostic('catalog-scope-mismatch', 'delta scope does not match the session');\n      if (publish) this.publish();\n      return;\n    }\n    if (delta.authority === 'degraded') {\n      this.markStale(delta.generation);\n      this.addDiagnostic('catalog-degraded-rows', 'degraded rows are not identity-bearing');\n      if (publish) this.publish();\n      return;\n    }\n    if (delta.revisions !== undefined) {\n      const baseline = delta.revisions.baseline;\n      const current = delta.revisions.current;\n      const valid =\n        baseline.length === current.length &&\n        current.every((point) => {\n          const prior = baseline.find((item) => item.rootId === point.rootId);\n          return prior !== undefined && point.revision === prior.revision + 1;\n        });\n      if (!valid) {\n        this.markStale(delta.generation);\n        this.addDiagnostic('catalog-gap', 'delta revision window is not contiguous');\n        if (publish) this.publish();\n        return;\n      }\n    }\n    let changed = false;\n    for (const entry of [...delta.added, ...delta.changed]) {\n      const validated = validateSessionRow(this.resolveRow(entry));\n      if (!validated.ok) {\n        this.markStale(delta.generation);\n        this.addDiagnostic('catalog-degraded-rows', 'delta contains an invalid runtime row');\n        if (publish) this.publish();\n        return;\n      }\n      const entryKey = key(validated.value.guid);\n      const prior = this.entries.get(entryKey);\n      if (prior === undefined || !sameEntry(prior, validated.value)) {\n        this.entries.set(entryKey, validated.value);\n        this.changed.add(entryKey);\n        changed = true;\n        if (validated.value.revision !== undefined) this.revision = validated.value.revision;\n      }\n    }\n    for (const guid of delta.removed) {\n      const entryKey = key(guid);\n      this.reads.delete(entryKey);\n      if (this.entries.delete(entryKey)) {\n        this.removed.add(entryKey);\n        changed = true;\n      }\n    }\n    if (changed) this.epoch += 1;\n    if (publish) this.publish();\n  }\n\n  private addDiagnostic(code: CatalogDiagnostic['code'], expected: string): void {\n    if (this.diagnostics.some((diagnostic) => diagnostic.code === code)) return;\n    this.diagnostics.push({\n      code,\n      severity: 'blocking',\n      expected,\n      hint: 'reconcile the Catalog before loading the affected publication',\n      authority: 'catalog',\n    });\n  }\n\n  private markStale(actualGeneration = this.generation): void {\n    this.stale = true;\n    this.staleGeneration = actualGeneration;\n    this.epoch += 1;\n  }\n\n  private publish(): void {\n    this.currentSnapshot = freezeSnapshot({\n      scopeId: this.scopeId,\n      generation: this.generation,\n      epoch: this.epoch,\n      ...(this.revision === undefined ? {} : { revision: this.revision }),\n      entries: [...this.entries.values()].sort((left, right) =>\n        key(left.guid).localeCompare(key(right.guid)),\n      ),\n      changed: [...this.changed].sort(),\n      removed: [...this.removed].sort(),\n      diagnostics: this.diagnostics,\n      listenerFailures: this.listenerFailures,\n      stale: this.stale,\n    });\n    this.changed.clear();\n    this.removed.clear();\n    for (const listener of [...this.listeners]) {\n      try {\n        listener(this.currentSnapshot);\n      } catch {\n        this.listenerFailures = Math.min(1024, this.listenerFailures + 1);\n        this.currentSnapshot = freezeSnapshot({\n          ...this.currentSnapshot,\n          listenerFailures: this.listenerFailures,\n        });\n      }\n    }\n  }\n\n  private disposedError(): AssetLoadError {\n    return {\n      code: 'asset-runtime-disposed',\n      expected: 'a live asset runtime',\n      hint: 'create a new runtime after disposal',\n      detail: { scopeId: this.scopeId },\n    };\n  }\n}\n","import { validateArtifactPath } from '@forgeax/engine-pack/artifact-path';\nimport type {\n  Asset,\n  AssetArtifactReader,\n  AssetDecoder,\n  AssetDecoderInput,\n  AssetDecoderLease,\n  AssetKind,\n  AssetLoadError,\n  AssetPublicationTuple,\n  BuiltinAssetKind,\n  BuiltinAssetPayload,\n  PluginAssetDefinition,\n  Result,\n} from '@forgeax/engine-types';\nimport { err, ok } from '@forgeax/engine-types';\nimport { defineAssetKind } from '../asset-kind.js';\nimport type { CatalogSource } from '../catalog-source.js';\nimport { pluginAssetDecoder } from '../loaders/plugin.js';\nimport { ArtifactCache } from './artifact-cache.js';\nimport { AssetGraph, type AssetGraphSnapshot } from './asset-graph.js';\nimport { CatalogSession, type CatalogSessionOptions } from './catalog-session.js';\nimport { DecoderRegistry } from './decoder-registry.js';\nimport { freezeRuntimePayload } from './immutable-payload.js';\nimport { PackReader } from './pack-reader.js';\nimport { bytesOf, readPackage } from './package-read.js';\nimport { validatePublicationReferences } from './publication-references.js';\nimport type { RuntimeCatalogRow } from './validate-runtime-row.js';\nimport { validateRuntimeRow } from './validate-runtime-row.js';\nimport { assetLoadCancelled, waitForAsset } from './wait-for-asset.js';\n\nexport interface AssetRegistryOptions extends CatalogSessionOptions {\n  readonly catalog: CatalogSource;\n  readonly fetcher?: typeof globalThis.fetch;\n  readonly maxConcurrentReads?: number;\n}\n\nexport interface AssetLoadOptions {\n  readonly signal?: AbortSignal;\n}\n\nexport type AssetRegistrySnapshot = AssetGraphSnapshot;\n\nexport interface AssetRegistry {\n  readPluginDefinition(guid: string): Promise<Result<PluginAssetDefinition, AssetLoadError>>;\n  installDecoder<P, K extends string>(\n    kind: AssetKind<P, K>,\n    decoder: AssetDecoder<P>,\n  ): AssetDecoderLease;\n  load<K extends BuiltinAssetKind>(\n    guid: string,\n    kind: K,\n    options?: AssetLoadOptions,\n  ): Promise<Result<BuiltinAssetPayload<K>, AssetLoadError>>;\n  load<P, K extends string>(\n    guid: string,\n    kind: AssetKind<P, K>,\n    options?: AssetLoadOptions,\n  ): Promise<Result<P, AssetLoadError>>;\n  snapshot(): AssetRegistrySnapshot;\n  subscribe(listener: (snapshot: AssetRegistrySnapshot) => void): () => void;\n  dispose(): void;\n}\n\n/** Internal render projection; the root Registry keeps only its five actions. */\nexport interface AssetRegistryResolver {\n  readonly epoch: number;\n  lookup<T extends Asset>(guid: string): T | undefined;\n  guidOf(asset: Asset): string | undefined;\n}\n\nconst REGISTRY_RESOLVER = Symbol.for('forgeax.assets-runtime.registry-resolver');\ntype RegistryWithResolver = AssetRegistry & {\n  [REGISTRY_RESOLVER]?: AssetRegistryResolver;\n};\n\nexport function getAssetRegistryResolver(registry: AssetRegistry): AssetRegistryResolver {\n  const resolver = (registry as RegistryWithResolver)[REGISTRY_RESOLVER];\n  if (resolver === undefined) {\n    throw new TypeError('AssetRegistry resolver is not owned by this asset runtime');\n  }\n  return resolver;\n}\n\nfunction missing(guid: string): AssetLoadError {\n  return {\n    code: 'asset-not-found',\n    expected: `the current Catalog to contain GUID \"${guid}\"`,\n    hint: 'inspect the producer Catalog and rebuild the missing publication',\n    detail: { guid },\n  };\n}\n\nfunction mismatch(guid: string, expectedKind: string, actualKind: string): AssetLoadError {\n  return {\n    code: 'asset-kind-mismatch',\n    expected: `Catalog kind \"${actualKind}\" to match \"${expectedKind}\"`,\n    hint: 'pass the Catalog kind or the matching custom AssetKind token',\n    detail: { guid, expectedKind, actualKind },\n  };\n}\n\nfunction artifactError(guid: string, reason: string): AssetLoadError {\n  return {\n    code: 'asset-integrity-failed',\n    expected: 'the verified artifact byte length and digest',\n    hint: 'verify the artifact digest and recook the Pack',\n    detail: {\n      guid,\n      artifactKey: reason,\n      expectedDigest: 'descriptor integrity',\n      actualDigest: reason,\n    },\n  };\n}\n\nconst ASSET_GUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\n\nfunction invalidGuid(guid: string): AssetLoadError {\n  return {\n    code: 'asset-guid-invalid',\n    expected: 'a 36-character dash-form asset GUID',\n    hint: 'pass the producer GUID from the current Catalog row',\n    detail: { guid },\n  };\n}\n\nexport function createAssetRegistry(options: AssetRegistryOptions): AssetRegistry {\n  const session = new CatalogSession(options.catalog, options);\n  const admit = async (\n    guid: string,\n    seen = new Set<string>(),\n  ): Promise<Result<RuntimeCatalogRow, AssetLoadError>> => {\n    const admitted = await session.get(guid);\n    if (\n      !admitted.ok ||\n      seen.has(guid.toLowerCase()) ||\n      decoders.referencePolicy(admitted.value.kind) === 'deferred'\n    )\n      return admitted;\n    seen.add(guid.toLowerCase());\n    for (const ref of admitted.value.publication.outputs.find(\n      (output) => output.guid.toLowerCase() === guid.toLowerCase(),\n    )?.refs ?? []) {\n      const dependency = await admit(ref, seen);\n      if (!dependency.ok) return dependency;\n    }\n    return admitted;\n  };\n  const reader = new PackReader(options.fetcher === undefined ? {} : { fetcher: options.fetcher });\n  const cache = new ArtifactCache();\n  const decoders = new DecoderRegistry(\n    options.scopeId === undefined ? {} : { scopeId: options.scopeId },\n  );\n  decoders.install(defineAssetKind('plugin'), pluginAssetDecoder);\n  const graph = new AssetGraph<{\n    readonly value: unknown;\n    readonly refs: readonly string[];\n    readonly publication: AssetPublicationTuple;\n    readonly references: 'eager' | 'deferred';\n  }>({\n    ...(options.maxConcurrentReads === undefined\n      ? {}\n      : { maxConcurrentReads: options.maxConcurrentReads }),\n    read: async (guid, signal) => {\n      const row = session.current(guid);\n      if (row === undefined) return err(missing(guid));\n      const fetcher =\n        options.catalog.openPackage?.(row.packageUrl) ??\n        options.fetcher ??\n        globalThis.fetch.bind(globalThis);\n      const validated = validateRuntimeRow(row);\n      if (!validated.ok) return validated;\n      const publication = validated.value.publication;\n      const tuple = {\n        scopeId: session.snapshot().scopeId,\n        generation: publication.generation,\n        digest: publication.digest,\n        outputSetDigest: publication.outputSetDigest,\n      };\n      const pack = await reader.read(row.packageUrl, tuple, signal, fetcher);\n      if (!pack.ok) return pack;\n      const envelope = pack.value.assets.find(\n        (asset) => asset.guid.toLowerCase() === guid.toLowerCase(),\n      );\n      if (envelope === undefined) return err(missing(guid));\n      const artifacts: AssetArtifactReader = {\n        locate: (descriptor) => {\n          const path = validateArtifactPath(descriptor.path, {\n            packageRoot: row.packageUrl,\n            guid,\n            artifactKey: descriptor.path,\n          });\n          return path.ok ? resolveArtifactUrl(row.packageUrl, path.value) : undefined;\n        },\n        read: (descriptor) => {\n          const integrity = descriptor.integrity;\n          if (integrity === undefined)\n            return Promise.resolve(err(artifactError(guid, descriptor.path)));\n          const key = `${tuple.scopeId}:${tuple.generation}:${tuple.outputSetDigest}:${integrity.digest}`;\n          return cache.read(key, async () => {\n            const url = resolveArtifactUrl(row.packageUrl, descriptor.path);\n            const read = await readPackage(fetcher, url, bytesOf, { signal });\n            if (!read.ok) return err(artifactError(guid, descriptor.path));\n            const bytes = read.value;\n            if (descriptor.byteLength === undefined || bytes.byteLength !== descriptor.byteLength) {\n              return err(artifactError(guid, descriptor.path));\n            }\n            const actualDigest = await sha256(bytes);\n            if (actualDigest !== descriptor.integrity?.digest.toLowerCase()) {\n              return err(artifactError(guid, `${descriptor.path}:${actualDigest}`));\n            }\n            return ok(bytes);\n          });\n        },\n      };\n      const input: AssetDecoderInput<unknown> = { envelope, artifacts, signal };\n      const decoded = await decoders.loadByKind(envelope.kind, input);\n      if (!decoded.ok) return decoded;\n      return ok({\n        value: freezeRuntimePayload(decoded.value),\n        refs: [\n          ...new Set([\n            ...envelope.refs,\n            ...publication.externalEvidence\n              .filter((edge) => edge.usage !== 'content')\n              .map((edge) => edge.guid),\n          ]),\n        ],\n        publication: tuple,\n        references: decoders.referencePolicy(envelope.kind),\n      });\n    },\n  });\n\n  let catalogEpoch = session.snapshot().epoch;\n  const unsubscribeCatalog = session.subscribe((snapshot) => {\n    if (snapshot.epoch === catalogEpoch) return;\n    catalogEpoch = snapshot.epoch;\n    graph.invalidateForCatalogChange(\n      snapshot.stale ? undefined : [...snapshot.changed, ...snapshot.removed],\n    );\n  });\n\n  const registry: AssetRegistry = {\n    readPluginDefinition: async (guid) => {\n      const loaded = await registry.load(guid, 'plugin');\n      if (!loaded.ok) return loaded;\n      const snapshot = await graph.load(guid);\n      if (!snapshot.ok) return snapshot;\n      const checked = checkCurrent(guid, snapshot.value.publication);\n      if (!checked.ok) return checked;\n      const asset = snapshot.value.value as Asset;\n      if (asset.kind !== 'plugin') return err(mismatch(guid, 'plugin', asset.kind));\n      return ok({\n        guid,\n        asset,\n        evidence: { kind: 'publication', publication: snapshot.value.publication },\n      });\n    },\n    installDecoder: (kind, decoder) => decoders.install(kind, decoder),\n    load: (async (\n      guid: string,\n      kind: BuiltinAssetKind | AssetKind<unknown, string>,\n      loadOptions: AssetLoadOptions = {},\n    ): Promise<Result<unknown, AssetLoadError>> => {\n      if (!ASSET_GUID_PATTERN.test(guid)) return err(invalidGuid(guid));\n      if (loadOptions.signal?.aborted) return err(assetLoadCancelled(guid));\n      const request = (async () => {\n        const expectedKind = typeof kind === 'string' ? kind : kind.kind;\n        const started = await session.start();\n        if (!started.ok) return err(started.error);\n        if (session.snapshot().stale) {\n          const reconciled = await session.reconcile();\n          if (!reconciled.ok) return err(reconciled.error);\n          const discontinuity = session.discontinuity();\n          if (discontinuity !== undefined) return err(discontinuity);\n        }\n        const declared = session.current(guid);\n        if (declared !== undefined && declared.kind !== expectedKind)\n          return err(mismatch(guid, expectedKind, declared.kind));\n        const admitted = await admit(guid);\n        if (!admitted.ok) return admitted;\n        const row = admitted.value;\n        if (row.kind !== expectedKind) return err(mismatch(guid, expectedKind, row.kind));\n        const before = validatePublicationReferences(guid, row, (guid) => session.current(guid));\n        if (!before.ok) {\n          graph.invalidate(guid);\n          return before;\n        }\n        const result = await graph.load(guid, loadOptions.signal);\n        if (!result.ok) return result;\n        const current = checkCurrent(guid, result.value.publication);\n        if (!current.ok) return current;\n        const after = validatePublicationReferences(guid, row, (guid) => session.current(guid));\n        if (!after.ok) {\n          graph.invalidate(guid);\n          return after;\n        }\n        return result.ok ? ok(result.value.value) : result;\n      })();\n      return loadOptions.signal === undefined\n        ? request\n        : waitForAsset(request, loadOptions.signal, guid);\n    }) as AssetRegistry['load'],\n    snapshot: () => graph.snapshot(),\n    subscribe: (listener) => graph.subscribe(listener),\n    dispose: () => {\n      graph.dispose();\n      reader.dispose();\n      unsubscribeCatalog();\n      decoders.dispose();\n      cache.clear();\n      session.dispose();\n    },\n  };\n  function checkCurrent(\n    guid: string,\n    expected: AssetPublicationTuple,\n  ): Result<void, AssetLoadError> {\n    const row = session.current(guid);\n    const actual = row?.publication;\n    if (\n      session.snapshot().stale ||\n      expected.scopeId !== session.snapshot().scopeId ||\n      actual?.generation !== expected.generation ||\n      actual.digest !== expected.digest ||\n      actual.outputSetDigest !== expected.outputSetDigest\n    ) {\n      graph.invalidate(guid);\n      return err({\n        code: 'asset-superseded',\n        expected: 'the same root publication until its read completes',\n        hint: 'load the current Catalog publication',\n        detail: { guid, generation: expected.generation },\n      });\n    }\n    const references = validatePublicationReferences(guid, row, (guid) => session.current(guid));\n    if (!references.ok) graph.invalidate(guid);\n    return references;\n  }\n  const resolver: AssetRegistryResolver = {\n    get epoch() {\n      return graph.snapshot().epoch;\n    },\n    lookup: <T extends Asset>(guid: string) => graph.lookup(guid) as T | undefined,\n    guidOf: (asset: Asset) => graph.guidOf(asset),\n  };\n  Object.defineProperty(registry, REGISTRY_RESOLVER, {\n    value: resolver,\n    enumerable: false,\n  });\n  return registry;\n}\n\nasync function sha256(bytes: Uint8Array): Promise<string> {\n  const digest = await globalThis.crypto.subtle.digest('SHA-256', bytes as unknown as BufferSource);\n  return `sha256:${Array.from(new Uint8Array(digest), (byte) =>\n    byte.toString(16).padStart(2, '0'),\n  ).join('')}`;\n}\n\nfunction resolveArtifactUrl(packageUrl: string, path: string): string {\n  const separator = packageUrl.lastIndexOf('/');\n  const packageDirectory = separator < 0 ? '' : packageUrl.slice(0, separator + 1);\n  try {\n    return new URL(path, new URL(packageDirectory, globalThis.location?.href)).toString();\n  } catch {\n    return `${packageDirectory}${path.replace(/^\\//, '')}`;\n  }\n}\n"]}