{"version":3,"file":"runtime-map.cjs","names":["Data","join","existsSync","MANIFEST_VERSION","resolveMountSegment","Effect","readFileSync","Clock","dirname"],"sources":["../../../src/services/codegen/runtime-map.ts"],"sourcesContent":["/**\n * The composition inspector's generator (#591/#594): a *generated,\n * machine- and human-readable* effective route tree for a resolved runtime.\n *\n * Reads every ui source's route manifest (local `src/manifest.gen.json`, or\n * the published `<ui>/manifest.gen.json` for remote sources), applies the\n * same core-wins precedence the host's `constructTree` applies at runtime,\n * and emits:\n *\n *   .bos/generated/runtime-map.json   machine/human inventory\n *   ui/src/lib/runtime-map.gen.ts     typed REMOTE_ROUTES union + metadata\n *\n * This is a *static model* of composition: nav labels are runtime-only (they\n * live in route options, not manifests) and are reported as null.\n *\n * Loud degradation: a remote manifest that can't be fetched is reported as\n * UNRESOLVED and — in strict mode (`bos types gen`) — fails the run, so\n * typecheck catches an upstream rename instead of silently shrinking the\n * map. Dev/build/train paths run warn-mode (a flaky remote must not block a\n * boot; the runtime load fails loudly on its own). Set\n * BOS_MAP_ALLOW_UNRESOLVED=1 for offline work (the map is still written,\n * with the unresolved sources).\n */\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { Clock, Data, Effect } from \"effect\";\n\nexport class RuntimeMapError extends Data.TaggedError(\"RuntimeMapError\")<{\n  readonly message: string;\n  readonly cause?: unknown;\n}> {\n  override toString(): string {\n    return this.message;\n  }\n}\n\nconst envBool = (name: string): boolean => process.env[name] === \"1\";\n\nconst isoNow = (ms: number): string => new Date(ms).toISOString();\n\nimport {\n  MANIFEST_VERSION,\n  type PluginManifest,\n  resolveMountSegment,\n} from \"every-plugin/ui/manifest\";\nimport type { RuntimeConfig } from \"../../types\";\n\nconst CORE_UI_KEY = \"ui\";\nconst FETCH_TIMEOUT_MS = Number(process.env.BOS_MAP_FETCH_TIMEOUT_MS ?? 15_000);\n\nexport interface RouteRecord {\n  id: string;\n  type: string;\n  path?: string;\n  parentId?: string;\n  mount?: string;\n}\n\nexport interface MapSource {\n  key: string;\n  kind: \"core\" | \"auth-ui\" | \"plugin-ui\";\n  source: \"local\" | \"remote\";\n  location: string;\n  manifestPath?: string;\n  manifestUrl?: string;\n  pin?: string;\n  note?: string;\n  manifest: PluginManifest;\n}\n\nexport interface UnresolvedSource {\n  key: string;\n  kind: string;\n  reason: string;\n}\n\nexport interface ComposedRoute {\n  id: string;\n  owner: string;\n  mount: string;\n  type: string;\n  path: string | null;\n  fullPath: string;\n  core: boolean;\n  nav: null;\n}\n\nexport interface ComposedRuntimeMap {\n  mounts: Array<{ id: string; declaredBy: string; recordId: string }>;\n  routes: ComposedRoute[];\n  shadowed: Array<{ id: string; owner: string; kind: \"mount\" | \"route\"; reason: string }>;\n}\n\nfunction joinPath(a: string, b?: string): string {\n  const left = a && a !== \"/\" ? a.replace(/\\/+$/, \"\") : \"\";\n  const right = b && b !== \"/\" ? (b ?? \"\").replace(/^\\/+/, \"\") : \"\";\n  if (!left) return right ? `/${right}` : \"/\";\n  if (!right) return left;\n  return `${left}/${right}`;\n}\n\nfunction isHttp(value: string | undefined): value is string {\n  return typeof value === \"string\" && /^https?:\\/\\//.test(value);\n}\n\nfunction manifestUrlFor(base: string): string {\n  return new URL(\"manifest.gen.json\", base.endsWith(\"/\") ? base : `${base}/`).toString();\n}\n\ninterface SourceDescriptor {\n  key: string;\n  kind: \"core\" | \"auth-ui\" | \"plugin-ui\";\n  source: \"local\" | \"remote\";\n  location: string;\n  manifestPath?: string;\n  manifestUrl?: string;\n  pin?: string;\n  note?: string;\n}\n\nfunction describeSlot(\n  _root: string,\n  key: string,\n  kind: SourceDescriptor[\"kind\"],\n  slot:\n    | { url?: string; localPath?: string; source?: string; pin?: { manifest?: string } }\n    | undefined,\n  unresolved: UnresolvedSource[],\n): SourceDescriptor | null {\n  if (!slot) return null;\n  const pin = slot.pin?.manifest;\n  if (slot.localPath) {\n    const manifestPath = join(slot.localPath, \"src/manifest.gen.json\");\n    if (existsSync(manifestPath)) {\n      return { key, kind, source: \"local\", location: slot.localPath, manifestPath, pin };\n    }\n    if (isHttp(slot.url)) {\n      return {\n        key,\n        kind,\n        source: \"remote\",\n        location: slot.url,\n        manifestUrl: manifestUrlFor(slot.url),\n        pin,\n        note: `local path \"${slot.localPath}\" is absent; using the published bundle`,\n      };\n    }\n    unresolved.push({\n      key,\n      kind,\n      reason: `local path \"${slot.localPath}\" is absent and there is no production target`,\n    });\n    return null;\n  }\n  if (isHttp(slot.url)) {\n    return {\n      key,\n      kind,\n      source: \"remote\",\n      location: slot.url,\n      manifestUrl: manifestUrlFor(slot.url),\n      pin,\n    };\n  }\n  unresolved.push({ key, kind, reason: \"no local workspace or remote target\" });\n  return null;\n}\n\nfunction validateManifest(source: SourceDescriptor, manifest: PluginManifest): void {\n  if (!manifest || typeof manifest !== \"object\" || !Array.isArray(manifest.routes)) {\n    throw new Error(`source \"${source.key}\": manifest is not a route manifest`);\n  }\n  if (manifest.manifestVersion !== MANIFEST_VERSION) {\n    throw new Error(\n      `source \"${source.key}\": manifest version ${manifest.manifestVersion} (expected ${MANIFEST_VERSION})`,\n    );\n  }\n}\n\n/**\n * Static model of every-plugin's `constructTree` precedence: core ui first,\n * then sources by key; core wins route/mount claims, peer collisions throw.\n */\nexport function composeRuntimeMap(\n  sources: Array<SourceDescriptor & { manifest: PluginManifest }>,\n): ComposedRuntimeMap {\n  const ordered = [\n    ...sources.filter((source) => source.key === CORE_UI_KEY),\n    ...sources\n      .filter((source) => source.key !== CORE_UI_KEY)\n      .sort((a, b) => a.key.localeCompare(b.key)),\n  ];\n\n  const mounts = new Map<string, { key: string; recordId: string }>();\n  const mountByLayoutId = new Map<string, string>();\n  const shadowed: ComposedRuntimeMap[\"shadowed\"] = [];\n\n  for (const source of ordered) {\n    for (const record of source.manifest.routes) {\n      if (!record.mount) continue;\n      const existing = mounts.get(record.mount);\n      if (existing) {\n        if (existing.key === CORE_UI_KEY && source.key !== CORE_UI_KEY) {\n          shadowed.push({\n            id: record.id,\n            owner: source.key,\n            kind: \"mount\",\n            reason: `mount \"${record.mount}\" is declared by core ui`,\n          });\n          mountByLayoutId.set(record.id, record.mount);\n          continue;\n        }\n        throw new Error(\n          `mount \"${record.mount}\" declared by multiple sources: \"${existing.key}\" and \"${source.key}\"`,\n        );\n      }\n      mounts.set(record.mount, { key: source.key, recordId: record.id });\n      mountByLayoutId.set(record.id, record.mount);\n    }\n  }\n\n  const routes: ComposedRoute[] = [];\n  const claims = new Map<string, Map<string, string>>();\n\n  for (const source of ordered) {\n    const pending = source.manifest.routes.filter((record) => !record.mount);\n    const byId = new Map<string, { fullPath: string; mount: string }>();\n    const shadowedIds = new Set<string>();\n    let progressed = true;\n\n    while (pending.length > 0 && progressed) {\n      progressed = false;\n      for (let index = 0; index < pending.length; index += 1) {\n        const record = pending[index]!;\n\n        let parent: { fullPath: string; mount: string; key: string };\n        if (record.parentId) {\n          if (shadowedIds.has(record.parentId)) {\n            shadowedIds.add(record.id);\n            shadowed.push({\n              id: record.id,\n              owner: source.key,\n              kind: \"route\",\n              reason: `parent \"${record.parentId}\" is shadowed`,\n            });\n            pending.splice(index, 1);\n            index -= 1;\n            progressed = true;\n            continue;\n          }\n          const local = byId.get(record.parentId);\n          if (local) {\n            parent = {\n              fullPath: local.fullPath,\n              mount: local.mount,\n              key: `${source.key}:${record.parentId}`,\n            };\n          } else if (mountByLayoutId.has(record.parentId)) {\n            const mount = mountByLayoutId.get(record.parentId)!;\n            parent = { fullPath: \"\", mount, key: `mount:${mount}` };\n          } else {\n            continue;\n          }\n        } else {\n          const firstSegment = record.id.split(\"/\")[0] ?? \"\";\n          if (!firstSegment.startsWith(\"_\")) {\n            throw new Error(`route \"${record.id}\" in \"${source.key}\" must live under a mount`);\n          }\n          const mount = resolveMountSegment(firstSegment.slice(1));\n          if (!mount) {\n            throw new Error(\n              `unknown mount \"_${firstSegment.slice(1)}\" (route \"${record.id}\" in \"${source.key}\")`,\n            );\n          }\n          if (!mounts.has(mount)) {\n            throw new Error(\n              `mount \"${mount}\" is not declared by any source (route \"${record.id}\" in \"${source.key}\")`,\n            );\n          }\n          parent = { fullPath: \"\", mount, key: `mount:${mount}` };\n        }\n\n        pending.splice(index, 1);\n        index -= 1;\n        progressed = true;\n\n        const isLayoutRoute = record.type === \"layout\" || record.path === undefined;\n        if (!isLayoutRoute) {\n          const siblings = claims.get(parent.key) ?? new Map<string, string>();\n          const claimant = siblings.get(record.path!);\n          if (claimant) {\n            if (source.key !== CORE_UI_KEY && claimant.startsWith(`${CORE_UI_KEY}:`)) {\n              shadowedIds.add(record.id);\n              shadowed.push({\n                id: record.id,\n                owner: source.key,\n                kind: \"route\",\n                reason: `path \"${record.path}\" is claimed by \"${claimant}\"`,\n              });\n              continue;\n            }\n            throw new Error(\n              `path collision: \"${source.key}\" route \"${record.id}\" declares \"${record.path}\" already claimed by \"${claimant}\"`,\n            );\n          }\n          siblings.set(record.path!, `${source.key}:${record.id}`);\n          claims.set(parent.key, siblings);\n        }\n\n        const fullPath = joinPath(parent.fullPath, record.path);\n        byId.set(record.id, { fullPath, mount: parent.mount });\n        routes.push({\n          id: record.id,\n          owner: source.key,\n          mount: parent.mount,\n          type: record.type,\n          path: record.path ?? null,\n          fullPath,\n          core: source.key === CORE_UI_KEY,\n          nav: null,\n        });\n      }\n    }\n\n    if (pending.length > 0) {\n      throw new Error(\n        `unresolvable parentage in \"${source.key}\": ${pending.map((record) => record.id).join(\", \")}`,\n      );\n    }\n  }\n\n  return {\n    mounts: [...mounts.entries()].map(([id, value]) => ({\n      id,\n      declaredBy: value.key,\n      recordId: value.recordId,\n    })),\n    routes,\n    shadowed,\n  };\n}\n\nasync function fetchRemoteManifest(url: string): Promise<PluginManifest> {\n  const response = await fetch(url, { signal: AbortSignal.timeout(FETCH_TIMEOUT_MS) });\n  if (!response.ok) throw new Error(`HTTP ${response.status} ${response.statusText}`);\n  return (await response.json()) as PluginManifest;\n}\n\nasync function fetchPluginManifestAsset(url: string): Promise<PluginManifestAsset> {\n  const response = await fetch(url, { signal: AbortSignal.timeout(FETCH_TIMEOUT_MS) });\n  if (!response.ok) throw new Error(`HTTP ${response.status} ${response.statusText}`);\n  const asset = (await response.json()) as PluginManifestAsset;\n  if (!asset || typeof asset !== \"object\" || asset.kind !== \"every-plugin/manifest\") {\n    throw new Error(\"not a plugin manifest\");\n  }\n  return asset;\n}\n\nfunction pluginManifestUrlFor(base: string): string {\n  return new URL(\"plugin.manifest.json\", base.endsWith(\"/\") ? base : `${base}/`).toString();\n}\n\n/** The backend inventory (#594 review): host, api, the auth server, and every\n * plugin backend — the \"who serves this runtime, from where\" analog of the ui\n * sources list. Local backends are their own truth (workspace path); remote\n * backends fetch their published `plugin.manifest.json` for the version +\n * contract hash drift signal. The host is source-level only (it ships no\n * manifest asset — it is not an every-plugin module). */\nfunction describeBackend(\n  root: string,\n  key: string,\n  kind: BackendRecord[\"kind\"],\n  slot:\n    | {\n        name?: string;\n        url?: string;\n        localPath?: string;\n        source?: string;\n        remoteUrl?: string;\n        remoteEntry?: string;\n        pin?: { manifest?: string };\n        integrity?: string;\n        dependsOn?: string[];\n      }\n    | undefined,\n): BackendRecord | null {\n  if (!slot) return null;\n  const name = typeof slot.name === \"string\" ? slot.name : null;\n  const pin = slot.pin?.manifest;\n  const dependsOn = slot.dependsOn;\n  if (slot.localPath) {\n    return {\n      key,\n      kind,\n      name,\n      source: \"local\",\n      location: slot.localPath.startsWith(root)\n        ? slot.localPath.slice(root.length + 1)\n        : slot.localPath,\n      ...(pin ? { pin } : {}),\n      ...(slot.integrity ? { integrity: slot.integrity } : {}),\n      ...(dependsOn ? { dependsOn } : {}),\n    };\n  }\n  const remote = slot.remoteUrl ?? slot.url;\n  if (isHttp(remote)) {\n    return {\n      key,\n      kind,\n      name,\n      source: \"remote\",\n      location: remote,\n      // the host ships no plugin manifest asset (it is not an every-plugin\n      // module) — probing it 404s on every real host and, in strict mode,\n      // fails types gen in every scaffolded child\n      ...(kind !== \"host\" ? { pluginManifestUrl: pluginManifestUrlFor(remote) } : {}),\n      ...(pin ? { pin } : {}),\n      ...(slot.integrity ? { integrity: slot.integrity } : {}),\n      ...(dependsOn ? { dependsOn } : {}),\n    };\n  }\n  return null;\n}\n\nexport interface RuntimeMapResult {\n  routeCount: number;\n  remoteCount: number;\n  sourceCount: number;\n  backendCount: number;\n  unresolved: UnresolvedSource[];\n  jsonPath: string;\n  tsPath: string | undefined;\n}\n\n/** The published `plugin.manifest.json` (EmitPluginManifest asset) — the\n * backend inventory's remote drift signal: which plugin version, and which\n * contract bytes, is this runtime actually composing? */\nexport interface PluginManifestAsset {\n  schemaVersion: number;\n  kind: string;\n  plugin?: { name?: string; version?: string };\n  contract?: { types?: { sha256?: string } };\n}\n\nexport interface BackendRecord {\n  key: string;\n  kind: \"host\" | \"api\" | \"auth\" | \"plugin\";\n  name: string | null;\n  source: \"local\" | \"remote\";\n  /** Workspace-relative path (local) or URL (remote). */\n  location: string;\n  pin?: string;\n  integrity?: string;\n  dependsOn?: string[];\n  /** Remote backends only: the composed plugin bundle's version + contract\n   * hash, from its published `plugin.manifest.json`. */\n  pluginVersion?: string;\n  contractSha256?: string;\n  /** Where the remote manifest asset was fetched from. */\n  pluginManifestUrl?: string;\n  note?: string;\n}\n\n/** The TS emission requires a local core ui workspace (`ui/src/lib/`); a\n * remote-only core ui skips it with a note. */\nfunction renderTypeScript(map: GeneratedRuntimeMap): string {\n  const remoteRoutes = map.routes\n    .filter((route) => !route.core)\n    .map((route) => ({\n      id: route.id,\n      path: route.fullPath,\n      mount: route.mount,\n      owner: route.owner,\n      type: route.type,\n    }));\n  const json = (value: unknown) => JSON.stringify(value, null, 2);\n\n  return `// Generated by bos types gen — do not edit.\n// Regenerate with \\`bos types gen\\` (or \\`pnpm run types:gen\\`). A static model of the\n// composed runtime: core ui wins route/mount claims; plugin routes are listed\n// below. Nav labels are runtime-only (route options, not manifests).\n// See docs/agents/runtime-map.md for the investigation workflows.\n\nexport const RUNTIME_MAP_GENERATED_AT = ${JSON.stringify(map.generatedAt)};\nexport const RUNTIME_MAP_ENV = ${JSON.stringify(map.env)};\nexport const RUNTIME_PLATFORM = ${JSON.stringify(map.platform)};\n\nexport const RUNTIME_SOURCES = ${json(map.sources)} as const;\n\n/** The serving side: host, api, the auth server, and every plugin backend —\n * source-level inventory; remote entries carry the composed plugin version\n * and contract hash. */\nexport const RUNTIME_BACKENDS = ${json(map.backends)} as const;\nexport type RuntimeBackend = (typeof RUNTIME_BACKENDS)[number];\n\n/** Routes owned by a plugin/remote ui source (not the core). */\nexport const REMOTE_ROUTES = ${json(remoteRoutes)} as const;\nexport type RemoteRoute = (typeof REMOTE_ROUTES)[number];\nexport type RemotePath = RemoteRoute[\"path\"];\n\nexport const RUNTIME_MOUNTS = ${json(map.mounts)} as const;\nexport const SHADOWED_ROUTES = ${json(map.shadowed)} as const;\n\nexport const UNRESOLVED_SOURCES = ${json(map.unresolved)} as const;\nexport type UnresolvedSource = (typeof UNRESOLVED_SOURCES)[number];\n`;\n}\n\ninterface GeneratedRuntimeMap {\n  generatedAt: string;\n  env: string;\n  platform: string | null;\n  extends: string | null;\n  sources: Array<{\n    key: string;\n    kind: string;\n    source: string;\n    location: string;\n    manifestUrl: string | null;\n    pin: string | null;\n    note: string | null;\n  }>;\n  backends: BackendRecord[];\n  unresolved: UnresolvedSource[];\n  mounts: ComposedRuntimeMap[\"mounts\"];\n  routes: ComposedRuntimeMap[\"routes\"];\n  shadowed: ComposedRuntimeMap[\"shadowed\"];\n}\n\nexport const generateRuntimeMapEffect = Effect.fn(\"generateRuntimeMap\")(function* (\n  configDir: string,\n  runtimeConfig: RuntimeConfig,\n  opts?: { strict?: boolean; env?: string; platform?: string | null; extendsChain?: string[] },\n): Effect.fn.Return<RuntimeMapResult | null, Error> {\n  const allowUnresolved = envBool(\"BOS_MAP_ALLOW_UNRESOLVED\");\n  const unresolved: UnresolvedSource[] = [];\n\n  const descriptors = [\n    describeSlot(configDir, CORE_UI_KEY, \"core\", runtimeConfig.ui, unresolved),\n    describeSlot(configDir, \"auth\", \"auth-ui\", runtimeConfig.auth?.ui, unresolved),\n  ];\n  for (const [key, plugin] of Object.entries(runtimeConfig.plugins ?? {})) {\n    // `plugins.auth` is the auth mirror (the auth app slot's backend owns\n    // it — planner isAuthMirrorFor): its ui is the same source already\n    // described under the \"auth\" key — describing it twice collides with\n    // its own claims.\n    if (key === \"auth\" && runtimeConfig.auth !== undefined) continue;\n    descriptors.push(describeSlot(configDir, key, \"plugin-ui\", plugin.ui, unresolved));\n  }\n\n  const sources: Array<SourceDescriptor & { manifest: PluginManifest }> = [];\n  for (const descriptor of descriptors) {\n    if (!descriptor) continue;\n    if (descriptor.source === \"local\" && descriptor.manifestPath) {\n      const manifest = JSON.parse(readFileSync(descriptor.manifestPath, \"utf8\")) as PluginManifest;\n      validateManifest(descriptor, manifest);\n      sources.push({ ...descriptor, manifest });\n    } else if (descriptor.manifestUrl) {\n      // Effect generators cannot await — the fetch failure degrades to an\n      // unresolved entry inside the promise.\n      yield* Effect.tryPromise({\n        try: async () => {\n          try {\n            const manifest = await fetchRemoteManifest(descriptor.manifestUrl!);\n            validateManifest(descriptor, manifest);\n            sources.push({ ...descriptor, manifest });\n          } catch (error) {\n            unresolved.push({\n              key: descriptor.key,\n              kind: descriptor.kind,\n              reason: `fetch ${descriptor.manifestUrl} failed: ${error instanceof Error ? error.message : String(error)}`,\n            });\n          }\n        },\n        catch: (cause) => new RuntimeMapError({ message: String(cause) }),\n      });\n    }\n  }\n\n  // Backend inventory (#594 review): the auth mirror dedupes against the\n  // auth app slot's backend (same source, same key collision rule). Effect\n  // generators cannot await — the fetch loop runs inside the promise.\n  const backendSlots: Array<BackendRecord | null> = [\n    describeBackend(configDir, \"host\", \"host\", runtimeConfig.host),\n    describeBackend(configDir, \"api\", \"api\", runtimeConfig.api),\n    describeBackend(configDir, \"auth\", \"auth\", runtimeConfig.auth),\n  ];\n  for (const [key, plugin] of Object.entries(runtimeConfig.plugins ?? {})) {\n    if (key === \"auth\" && runtimeConfig.auth !== undefined) continue;\n    backendSlots.push(describeBackend(configDir, key, \"plugin\", plugin));\n  }\n  const backends: BackendRecord[] = yield* Effect.tryPromise({\n    try: async () => {\n      const collected: BackendRecord[] = [];\n      for (const backend of backendSlots) {\n        if (!backend) continue;\n        if (backend.pluginManifestUrl) {\n          try {\n            const asset = await fetchPluginManifestAsset(backend.pluginManifestUrl);\n            collected.push({\n              ...backend,\n              pluginVersion: asset.plugin?.version,\n              contractSha256: asset.contract?.types?.sha256,\n            });\n          } catch (error) {\n            const reason = `plugin manifest ${backend.pluginManifestUrl} failed: ${error instanceof Error ? error.message : String(error)}`;\n            unresolved.push({ key: backend.key, kind: backend.kind, reason });\n            collected.push({ ...backend, note: reason });\n          }\n        } else {\n          collected.push(backend);\n        }\n      }\n      return collected;\n    },\n    catch: (cause) => new RuntimeMapError({ message: String(cause) }),\n  });\n\n  if (sources.length === 0 && unresolved.length === 0 && backends.length === 0) return null;\n\n  if (unresolved.length > 0 && !allowUnresolved) {\n    for (const entry of unresolved) {\n      yield* Effect.logError(\n        `[runtime-map] UNRESOLVED ${entry.key} (${entry.kind}): ${entry.reason}`,\n      );\n    }\n    if (opts?.strict) {\n      // the reasons ride in the error — the wire (e.g. the typesGen JSON)\n      // only sees this message, never the console.error lines above\n      return yield* new RuntimeMapError({\n        message: `runtime map is incomplete — ${unresolved.map((entry) => `${entry.key} (${entry.kind}): ${entry.reason}`).join(\"; \")} — fix the source or set BOS_MAP_ALLOW_UNRESOLVED=1 for offline work`,\n      });\n    }\n  }\n\n  const composed = composeRuntimeMap(sources);\n  const map: GeneratedRuntimeMap = {\n    generatedAt: isoNow(yield* Clock.currentTimeMillis),\n    env: opts?.env ?? \"unknown\",\n    platform: opts?.platform ?? null,\n    extends: opts?.extendsChain?.join(\" → \") ?? null,\n    sources: sources.map((source) => ({\n      key: source.key,\n      kind: source.kind,\n      source: source.source,\n      // workspace-relative for local sources — no absolute paths in the\n      // committed/generated surface\n      location:\n        source.source === \"local\" && source.location.startsWith(configDir)\n          ? source.location.slice(configDir.length + 1)\n          : source.location,\n      manifestUrl: source.manifestUrl ?? null,\n      pin: source.pin ?? null,\n      note: source.note ?? null,\n    })),\n    backends,\n    unresolved,\n    mounts: composed.mounts,\n    routes: composed.routes,\n    shadowed: composed.shadowed,\n  };\n\n  const jsonPath = join(configDir, \".bos/generated/runtime-map.json\");\n  mkdirSync(dirname(jsonPath), { recursive: true });\n  writeFileSync(jsonPath, `${JSON.stringify(map, null, 2)}\\n`);\n\n  // The TS emission requires a local core ui workspace; a remote-only core\n  // ui skips it with a note.\n  let tsPath: string | undefined;\n  const uiLocalPath = runtimeConfig.ui?.source === \"local\" ? runtimeConfig.ui.localPath : undefined;\n  if (uiLocalPath && existsSync(join(uiLocalPath, \"src\"))) {\n    tsPath = join(uiLocalPath, \"src/lib/runtime-map.gen.ts\");\n    mkdirSync(dirname(tsPath), { recursive: true });\n    writeFileSync(tsPath, renderTypeScript(map));\n  }\n\n  const remoteCount = map.routes.filter((route) => !route.core).length;\n  const remoteBackends = backends.filter((backend) => backend.source === \"remote\").length;\n  yield* Effect.log(\n    `[runtime-map] ${map.routes.length} routes (${remoteCount} remote) from ${sources.length} sources; ${backends.length} backends (${remoteBackends} remote)`,\n  );\n  for (const entry of unresolved) {\n    yield* Effect.logWarning(`[runtime-map] unresolved ${entry.key}: ${entry.reason}`);\n  }\n  yield* Effect.log(\n    `[runtime-map] wrote ${jsonPath}${tsPath ? ` + ${tsPath}` : \" (no local core ui — ts emission skipped)\"}`,\n  );\n\n  return {\n    routeCount: map.routes.length,\n    remoteCount,\n    sourceCount: sources.length,\n    backendCount: backends.length,\n    unresolved,\n    jsonPath,\n    tsPath,\n  };\n});\n"],"mappings":"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"}