{"version":3,"file":"index.cjs","names":["isRecord","OFFICIAL_REGISTRY_NAME","readFileSync","collectionsRegistriesConfigPath","getWorkspaceRoot","ONE_SECOND_MS","FETCH_TIMEOUT_MS","STATUS_BAD_GATEWAY","STATUS_UNAVAILABLE","OFFICIAL_REGISTRY_NAME","fetchWithTimeout","errorMessage","parseRegistryIndex","ONE_SECOND_MS","STATUS_BAD_GATEWAY","STATUS_NOT_FOUND","fetchWithTimeout","errorMessage","isRecord","isRecord","isUnknownArray","STATUS_NOT_FOUND","STATUS_UNPROCESSABLE","stat","isRecord","path","readdir","readFile","skillsStagingDir","projectSkillsDir","claudeSkillDir","CollectionSchemaZ","acceptParsedSchema","mkdir","writeFile","safeRecordId","isSafeActionTemplatePath","rm","writeFileAtomic","rename","errorMessage","stat","path","cp","readdir","mkdir","readFile","writeFile","rm","toPosixRelPath","readFile","isRecord","loadCollection","path"],"sources":["../../../../src/collection/registry/server/registriesConfig.ts","../../../../src/collection/registry/server/client.ts","../../../../src/collection/registry/server/collectionFiles.ts","../../../../src/collection/registry/server/importCollection.ts","../../../../src/collection/registry/server/importWriter.ts","../../../../src/collection/registry/server/exportCollection.ts","../../../../src/collection/registry/server/skillDescription.ts","../../../../src/collection/registry/server/performExport.ts","../../../../src/collection/registry/server/index.ts"],"sourcesContent":["// User-supplied list of extra collection registries (`config/collections-registries.json`).\n// The official receptron/mulmoclaude-collections registry is always loaded; this\n// file adds more on top so a community / org / private registry shows up in the\n// same Discover catalog.\n//\n// Shape on disk:\n//   [\n//     { \"name\": \"myorg\", \"indexUrl\": \"https://...\", \"rawBaseUrl\": \"https://...\" }\n//   ]\n//\n// Validation rules (a bad entry is dropped + logged; the rest still load):\n//   - `name` matches `[A-Za-z0-9][A-Za-z0-9_-]{0,31}` and is NOT the reserved\n//     `official` (which is always synthesized by client.ts)\n//   - Both URLs are HTTPS, parseable, and have no userinfo/credentials\n//   - Names are unique (later duplicates are dropped, first wins)\n//\n// Pure read + parse — no network. Caller invalidates by re-reading the file.\n\nimport { readFileSync } from \"node:fs\";\n\nimport { isRecord } from \"../guards.js\";\nimport { OFFICIAL_REGISTRY_NAME, type RegistryConfigEntry } from \"../types.js\";\nimport { collectionsRegistriesConfigPath, getWorkspaceRoot, log } from \"../../server/host.js\";\n\n/** Which workspace a registry read is scoped to. Omitted ⇒ the host's\n *  configured root (and, under an explicit-root binding, a loud throw rather\n *  than a silent read of another project's config). */\nexport interface RegistryScope {\n  workspaceRoot?: string | undefined;\n}\n\nexport { OFFICIAL_REGISTRY_NAME, type RegistryConfigEntry };\n\nconst NAME_RE = /^[A-Za-z0-9][A-Za-z0-9_-]{0,31}$/;\n\nfunction isValidHttpsUrl(value: unknown): value is string {\n  if (typeof value !== \"string\" || value.length === 0) return false;\n  let url: URL;\n  try {\n    url = new URL(value);\n  } catch {\n    return false;\n  }\n  if (url.protocol !== \"https:\") return false;\n  if (url.username !== \"\" || url.password !== \"\") return false;\n  return true;\n}\n\nfunction parseEntry(value: unknown, index: number): RegistryConfigEntry | string {\n  if (!isRecord(value)) return `entry[${index}] is not an object`;\n  const { name, indexUrl, rawBaseUrl } = value;\n  if (typeof name !== \"string\" || !NAME_RE.test(name)) {\n    return `entry[${index}].name must match ${NAME_RE.source}`;\n  }\n  if (name === OFFICIAL_REGISTRY_NAME) {\n    return `entry[${index}].name \"${OFFICIAL_REGISTRY_NAME}\" is reserved`;\n  }\n  if (!isValidHttpsUrl(indexUrl)) return `entry[${index}].indexUrl must be a valid HTTPS URL (no credentials)`;\n  if (!isValidHttpsUrl(rawBaseUrl)) return `entry[${index}].rawBaseUrl must be a valid HTTPS URL (no credentials)`;\n  // `rawBaseUrl` gets joined as `${rawBaseUrl}/<path>` downstream — a query or\n  // fragment would land in the middle of the composed URL and break every\n  // collection-file fetch on that registry (CodeRabbit review on #1837). The\n  // index URL is fetched directly so a query is fine there; only rawBase\n  // needs the constraint.\n  if (rawBaseUrl.includes(\"?\") || rawBaseUrl.includes(\"#\")) {\n    return `entry[${index}].rawBaseUrl must not contain a query (?) or fragment (#) — it's joined as a path prefix`;\n  }\n  // Strip trailing slashes so `${rawBaseUrl}/${path}` joins cleanly regardless\n  // of what the user wrote. Plain-loop trim instead of a regex — the linter\n  // flags any unanchored-quantifier regex as ReDoS-suspect even when it's\n  // safe, and the loop is just as clear at this size.\n  let normalizedRawBase = rawBaseUrl;\n  while (normalizedRawBase.endsWith(\"/\")) normalizedRawBase = normalizedRawBase.slice(0, -1);\n  return { name, indexUrl, rawBaseUrl: normalizedRawBase };\n}\n\n/** Parse the JSON text of `config/collections-registries.json`. Bad entries\n *  drop with a warning; valid entries are returned in source order. Exported\n *  for unit testing — the I/O wrapper `loadRegistriesConfig` below reads the\n *  workspace file and delegates here. */\nexport function parseRegistriesConfig(raw: unknown): RegistryConfigEntry[] {\n  if (!Array.isArray(raw)) {\n    log.warn(\"collections-registry\", \"registries config is not an array — ignoring\");\n    return [];\n  }\n  const seen = new Set<string>();\n  const out: RegistryConfigEntry[] = [];\n  for (let i = 0; i < raw.length; i++) {\n    const parsed = parseEntry(raw[i], i);\n    if (typeof parsed === \"string\") {\n      log.warn(\"collections-registry\", \"registry config entry rejected\", { reason: parsed });\n      continue;\n    }\n    if (seen.has(parsed.name)) {\n      log.warn(\"collections-registry\", \"registry config duplicate name dropped\", { name: parsed.name });\n      continue;\n    }\n    seen.add(parsed.name);\n    out.push(parsed);\n  }\n  return out;\n}\n\n// Missing file ⇒ null (the most common case — most users only want the official\n// registry). Other read errors propagate, matching the host's prior behavior.\nfunction readConfigTextOrNull(filePath: string): string | null {\n  try {\n    return readFileSync(filePath, \"utf-8\");\n  } catch (err) {\n    if (isRecord(err) && err.code === \"ENOENT\") return null;\n    throw err;\n  }\n}\n\n/** Read `config/collections-registries.json` for a workspace. `workspaceRoot`\n *  defaults to the host's configured root; a multi-root host passes the project\n *  it is serving. Missing file ⇒ empty list. Malformed JSON or rejected entries\n *  log but never throw. */\nexport function loadRegistriesConfig(opts: RegistryScope = {}): RegistryConfigEntry[] {\n  const text = readConfigTextOrNull(collectionsRegistriesConfigPath(opts.workspaceRoot ?? getWorkspaceRoot()));\n  if (text === null) return [];\n  let parsed: unknown;\n  try {\n    parsed = JSON.parse(text);\n  } catch (err) {\n    log.warn(\"collections-registry\", \"registries config is not valid JSON — ignoring\", {\n      error: err instanceof Error ? err.message : String(err),\n    });\n    return [];\n  }\n  return parseRegistriesConfig(parsed);\n}\n","// Server-side client for the curated collection registries' published index.json\n// files. The official registry (receptron/mulmoclaude-collections via GitHub Pages)\n// is always loaded; users can append more via `config/collections-registries.json`.\n// Each index is fetched over HTTPS with a timeout, validated against the index\n// contract, and memo-cached per-registry so the Discover tab doesn't hammer the\n// upstreams. On a transient upstream failure we serve that registry's last good\n// index rather than failing the whole Discover view.\n\nimport { fetchWithTimeout } from \"../../../utils/fetch.js\";\nimport { errorMessage, ONE_SECOND_MS } from \"../../server/util.js\";\nimport { log } from \"../../server/host.js\";\nimport { parseRegistryIndex, type RegistryEntry, type RegistryIndex } from \"../registryIndex.js\";\nimport { loadRegistriesConfig, OFFICIAL_REGISTRY_NAME, type RegistryConfigEntry, type RegistryScope } from \"./registriesConfig.js\";\n\nconst DEFAULT_OFFICIAL_INDEX_URL = \"https://receptron.github.io/mulmoclaude-collections/index.json\";\nconst DEFAULT_OFFICIAL_RAW_BASE = \"https://raw.githubusercontent.com/receptron/mulmoclaude-collections/main\";\nexport const CACHE_TTL_MS = 5 * 60 * ONE_SECOND_MS;\n// During an outage (cache past TTL + failing upstream) don't re-hit the network\n// more than once per this window — serve stale immediately in between, so a down\n// upstream can't add its full timeout to every request.\nexport const STALE_RETRY_BACKOFF_MS = 60 * ONE_SECOND_MS;\nconst FETCH_TIMEOUT_MS = 10 * ONE_SECOND_MS;\nconst STATUS_BAD_GATEWAY = 502;\nconst STATUS_UNAVAILABLE = 503;\n\n/** Per-registry fetch outcome. `ok: false` is reported per-registry — the\n *  merged Discover response still succeeds when at least one registry is\n *  reachable; failed registries just contribute zero entries. */\nexport type FetchIndexResult = { ok: true; index: RegistryIndex; stale: boolean } | { ok: false; status: number; error: string };\n\ninterface CacheEntry {\n  index: RegistryIndex;\n  atMs: number;\n}\n\nconst cache = new Map<string, CacheEntry>();\nconst lastFailureMs = new Map<string, number>();\n\n/** Resolved descriptor for one registry the host should fetch — name + URLs.\n *  `official` is always synthesized; further entries come from\n *  `config/collections-registries.json`. Currently structurally identical to\n *  `RegistryConfigEntry`; aliased so we can add server-only fields (e.g.\n *  auth headers) without touching the on-disk config schema. */\nexport type RegistryDescriptor = RegistryConfigEntry;\n\nfunction officialDescriptor(): RegistryDescriptor {\n  return {\n    name: OFFICIAL_REGISTRY_NAME,\n    indexUrl: process.env.COLLECTIONS_REGISTRY_URL ?? DEFAULT_OFFICIAL_INDEX_URL,\n    rawBaseUrl: process.env.COLLECTIONS_REGISTRY_RAW_BASE ?? DEFAULT_OFFICIAL_RAW_BASE,\n  };\n}\n\n/** The full ordered registry list: official first, then user-configured ones.\n *  Re-reads the config file on every call so a Discover refresh picks up edits\n *  without a server restart (the config is small + read-rarely). */\nexport function listRegistries(scope: RegistryScope = {}): RegistryDescriptor[] {\n  return [officialDescriptor(), ...loadRegistriesConfig(scope)];\n}\n\n/** Look up one registry descriptor by name. Used by the preview / import path,\n *  which has the registry label from the entry and needs the rawBase. */\nexport function findRegistry(name: string, scope: RegistryScope = {}): RegistryDescriptor | null {\n  return listRegistries(scope).find((reg) => reg.name === name) ?? null;\n}\n\nasync function loadFromNetwork(descriptor: RegistryDescriptor): Promise<FetchIndexResult> {\n  let res: Response;\n  try {\n    res = await fetchWithTimeout(descriptor.indexUrl, { timeoutMs: FETCH_TIMEOUT_MS, headers: { accept: \"application/json\" } });\n  } catch (err) {\n    log.warn(\"collections-registry\", \"index fetch failed\", { registry: descriptor.name, url: descriptor.indexUrl, error: errorMessage(err) });\n    return { ok: false, status: STATUS_UNAVAILABLE, error: \"registry unreachable\" };\n  }\n  if (!res.ok) return { ok: false, status: STATUS_BAD_GATEWAY, error: `registry responded ${res.status}` };\n  const json: unknown = await res.json().catch(() => null);\n  const parsed = parseRegistryIndex(json, descriptor.name);\n  if (!parsed.ok) {\n    log.warn(\"collections-registry\", \"index invalid\", { registry: descriptor.name, url: descriptor.indexUrl, error: parsed.error });\n    return { ok: false, status: STATUS_BAD_GATEWAY, error: `registry index invalid: ${parsed.error}` };\n  }\n  return { ok: true, index: parsed.index, stale: false };\n}\n\nexport type IndexLoader = (descriptor: RegistryDescriptor) => Promise<FetchIndexResult>;\n\n/** Cache key incorporates BOTH URLs so editing `indexUrl` or `rawBaseUrl` for\n *  an existing registry name invalidates the cached index automatically — same\n *  refresh cycle as if the user had renamed it (CodeRabbit review on #1837).\n *  Without this, the Discover catalog could keep serving the old upstream's\n *  entries while preview / import resolved the new rawBase, drifting until TTL\n *  expiry. Tab + key-content guarantees no collision between e.g. swapped\n *  name/url pairs. */\nfunction descriptorCacheKey(descriptor: RegistryDescriptor): string {\n  return `${descriptor.name}\\t${descriptor.indexUrl}\\t${descriptor.rawBaseUrl}`;\n}\n\n/** Fetch one registry's index. Same cache + stale-on-failure semantics as the\n *  original single-registry implementation — just keyed by descriptor identity\n *  (name + both URLs) so multiple registries don't fight over one slot AND a\n *  reconfigured registry doesn't serve a stale index from the prior URL. */\nexport async function fetchRegistryIndex(\n  descriptor: RegistryDescriptor,\n  opts: { force?: boolean; nowMs?: number; loader?: IndexLoader } = {},\n): Promise<FetchIndexResult> {\n  const nowMs = opts.nowMs ?? Date.now();\n  const loader = opts.loader ?? loadFromNetwork;\n  const key = descriptorCacheKey(descriptor);\n  const cached = cache.get(key);\n  if (!opts.force && cached && nowMs - cached.atMs < CACHE_TTL_MS) {\n    return { ok: true, index: cached.index, stale: false };\n  }\n  const failedAt = lastFailureMs.get(key);\n  if (!opts.force && cached && failedAt !== undefined && nowMs - failedAt < STALE_RETRY_BACKOFF_MS) {\n    return { ok: true, index: cached.index, stale: true };\n  }\n  const fresh = await loader(descriptor);\n  if (fresh.ok) {\n    cache.set(key, { index: fresh.index, atMs: nowMs });\n    lastFailureMs.delete(key);\n    return { ok: true, index: fresh.index, stale: false };\n  }\n  lastFailureMs.set(key, nowMs);\n  if (cached) return { ok: true, index: cached.index, stale: true };\n  return fresh;\n}\n\n/** One registry's contribution to the merged Discover view. `failed` registries\n *  surface in the response so the UI can show a per-registry error badge while\n *  still rendering the entries from the registries that did work. */\nexport interface MergedRegistryResult {\n  name: string;\n  status: \"ok\" | \"stale\" | \"failed\";\n  generatedAt: string | null;\n  error: string | null;\n  entries: RegistryEntry[];\n}\n\n/** Fetch every configured registry in parallel and return per-registry\n *  outcomes. Callers (the Discover route) concatenate `entries` from each.\n *  Failure of any single registry doesn't abort the others — that's the point\n *  of supporting multiple registries. */\nexport async function fetchAllRegistries(\n  opts: { force?: boolean; nowMs?: number; loader?: IndexLoader } & RegistryScope = {},\n): Promise<MergedRegistryResult[]> {\n  const descriptors = listRegistries(opts);\n  return await Promise.all(\n    descriptors.map(async (descriptor): Promise<MergedRegistryResult> => {\n      const result = await fetchRegistryIndex(descriptor, opts);\n      if (!result.ok) {\n        return { name: descriptor.name, status: \"failed\", generatedAt: null, error: result.error, entries: [] };\n      }\n      return {\n        name: descriptor.name,\n        status: result.stale ? \"stale\" : \"ok\",\n        generatedAt: result.index.generatedAt,\n        error: null,\n        entries: result.index.collections,\n      };\n    }),\n  );\n}\n\n/** Test seam: reset the module cache + failure backoff state (all registries). */\nexport function resetRegistryCache(): void {\n  cache.clear();\n  lastFailureMs.clear();\n}\n","// Fetch individual files of a registry collection (schema.json, meta.json, …)\n// from the registry repo's raw content. The collection's repo-relative dir comes\n// from a trusted index entry (never raw user input), so the host can only fetch\n// files of collections that actually appear in the published index.\n//\n// The index itself is served from GitHub Pages (see client.ts); per-collection\n// files are served from raw.githubusercontent. With multi-registry support the\n// rawBase is no longer a single module-level value — it comes from the entry's\n// source registry descriptor, so user-added registries can live anywhere.\n\nimport { fetchWithTimeout } from \"../../../utils/fetch.js\";\nimport { errorMessage, ONE_SECOND_MS } from \"../../server/util.js\";\nimport { isRecord } from \"../guards.js\";\nimport { fetchAllRegistries, findRegistry } from \"./client.js\";\nimport type { RegistryScope } from \"./registriesConfig.js\";\nimport type { RegistryEntry } from \"../registryIndex.js\";\n\nconst FETCH_TIMEOUT_MS = 10 * ONE_SECOND_MS;\nconst STATUS_BAD_GATEWAY = 502;\nconst STATUS_UNAVAILABLE = 503;\nconst STATUS_NOT_FOUND = 404;\n\n/** Compose the raw URL for `<dirPath>/<relFile>` under a given registry's\n *  rawBase. Empty and traversal (`.`/`..`) segments are dropped so the URL can\n *  never escape the base, even if an upstream check is bypassed (the index\n *  parser already rejects such identifiers — this is defense-in-depth). The\n *  rawBase is trailing-slash-normalized: `parseRegistriesConfig` already trims\n *  user-config trailing slashes, but the official descriptor and any test\n *  bypass parse — repeating the trim here keeps the join `${base}/${path}`\n *  from producing `//` even when the caller bypassed config validation\n *  (CodeRabbit review on #1837). */\nexport function collectionFileUrl(rawBase: string, dirPath: string, relFile: string): string {\n  let base = rawBase;\n  while (base.endsWith(\"/\")) base = base.slice(0, -1);\n  const segments = dirPath.split(\"/\").filter((segment) => segment.length > 0 && segment !== \".\" && segment !== \"..\");\n  return `${base}/${segments.join(\"/\")}/${relFile}`;\n}\n\nexport type FileResult = { ok: true; text: string } | { ok: false; status: number; error: string };\n\n/** Fetch one file out of a registry collection. `rawBase` comes from the\n *  entry's source registry (`findRegistry(entry.registryName).rawBaseUrl`),\n *  not a module-level setting — that's what makes additional user-configured\n *  registries reachable. */\nexport async function fetchCollectionFile(rawBase: string, dirPath: string, relFile: string): Promise<FileResult> {\n  const url = collectionFileUrl(rawBase, dirPath, relFile);\n  let res: Response;\n  try {\n    res = await fetchWithTimeout(url, { timeoutMs: FETCH_TIMEOUT_MS });\n  } catch (err) {\n    return { ok: false, status: STATUS_UNAVAILABLE, error: `fetch failed: ${errorMessage(err)}` };\n  }\n  if (!res.ok) return { ok: false, status: STATUS_BAD_GATEWAY, error: `${relFile} responded ${res.status}` };\n  return { ok: true, text: await res.text() };\n}\n\nexport type JsonObjectResult = { ok: true; value: Record<string, unknown> } | { ok: false; error: string };\n\nexport function parseJsonObject(text: string, label: string): JsonObjectResult {\n  let parsed: unknown;\n  try {\n    parsed = JSON.parse(text);\n  } catch {\n    return { ok: false, error: `${label} is not valid JSON` };\n  }\n  if (!isRecord(parsed)) return { ok: false, error: `${label} is not an object` };\n  return { ok: true, value: parsed };\n}\n\nasync function fetchJsonObject(\n  rawBase: string,\n  dirPath: string,\n  relFile: string,\n  label: string,\n): Promise<{ ok: true; value: Record<string, unknown> } | { ok: false; status: number; error: string }> {\n  const file = await fetchCollectionFile(rawBase, dirPath, relFile);\n  if (!file.ok) return { ok: false, status: file.status, error: `${label}: ${file.error}` };\n  const parsed = parseJsonObject(file.text, label);\n  if (!parsed.ok) return { ok: false, status: STATUS_BAD_GATEWAY, error: parsed.error };\n  return { ok: true, value: parsed.value };\n}\n\n/** Resolve an entry's rawBase from its `registryName`. A missing match (the\n *  user removed the registry from config while a cached index still references\n *  it) returns null — the caller surfaces it as a 404 rather than crashing. */\nexport function rawBaseForEntry(entry: Pick<RegistryEntry, \"registryName\">, scope: RegistryScope = {}): string | null {\n  const registry = findRegistry(entry.registryName, scope);\n  return registry?.rawBaseUrl ?? null;\n}\n\nexport type PreviewResult =\n  { ok: true; entry: RegistryEntry; schema: Record<string, unknown>; meta: Record<string, unknown> } | { ok: false; status: number; error: string };\n\n/** Resolve an entry by author+slug across every cached registry's entries.\n *  When `registry` is passed we constrain to that registry — needed because\n *  multiple registries can publish the same author/slug, and the UI should\n *  follow the card it just clicked. */\nfunction findEntryInMergedView(\n  merged: { name: string; entries: RegistryEntry[] }[],\n  author: string,\n  slug: string,\n  registry: string | null,\n): RegistryEntry | null {\n  for (const reg of merged) {\n    if (registry !== null && reg.name !== registry) continue;\n    const match = reg.entries.find((candidate) => candidate.author === author && candidate.slug === slug);\n    if (match) return match;\n  }\n  return null;\n}\n\n/** Preview a registry collection: confirm it's in some registry's published\n *  index, then fetch + parse its schema.json + meta.json so the Discover tab\n *  can show fields/views before import. With multi-registry support the\n *  `registry` arg disambiguates same-name collections from different sources. */\nexport async function previewCollection(author: string, slug: string, registry: string | null = null, scope: RegistryScope = {}): Promise<PreviewResult> {\n  const merged = await fetchAllRegistries(scope);\n  const entry = findEntryInMergedView(merged, author, slug, registry);\n  if (!entry) return { ok: false, status: STATUS_NOT_FOUND, error: `unknown collection: ${author}/${slug}` };\n  const rawBase = rawBaseForEntry(entry, scope);\n  if (!rawBase) return { ok: false, status: STATUS_NOT_FOUND, error: `registry \"${entry.registryName}\" is no longer configured` };\n  const schema = await fetchJsonObject(rawBase, entry.path, \"schema.json\", \"schema.json\");\n  if (!schema.ok) return schema;\n  const meta = await fetchJsonObject(rawBase, entry.path, \"meta.json\", \"meta.json\");\n  if (!meta.ok) return meta;\n  return { ok: true, entry, schema: schema.value, meta: meta.value };\n}\n","// Import-side fetch + transform helpers for a registry collection. The writer\n// (writes into .claude/skills/, materializes seed, records provenance) builds on\n// these; kept separate so the pure, security-critical parts are unit-tested.\n//\n// Files to fetch come from the collection's manifest.json (published by the\n// registry's build-index). Every manifest path is re-checked for safety here —\n// the host must never write outside the target skill dir even if the manifest is\n// malformed/poisoned.\n\nimport { isUnknownArray } from \"@mulmoclaude/common\";\nimport { isRecord } from \"../guards.js\";\nimport { fetchCollectionFile, parseJsonObject, rawBaseForEntry } from \"./collectionFiles.js\";\nimport type { RegistryEntry } from \"../registryIndex.js\";\nimport type { RegistryScope } from \"./registriesConfig.js\";\n\nconst MANIFEST_FILE = \"manifest.json\";\nconst STATUS_BAD_GATEWAY = 502;\n\n/** A manifest entry must be a relative path that stays inside the collection dir:\n *  no absolute paths, no backslashes, no empty / `.` / `..` segments. */\nexport function isSafeBundlePath(rel: unknown): rel is string {\n  if (typeof rel !== \"string\" || rel.length === 0) return false;\n  if (rel.startsWith(\"/\") || rel.includes(\"\\\\\")) return false;\n  return !rel.split(\"/\").some((segment) => segment === \"\" || segment === \".\" || segment === \"..\");\n}\n\nexport type ManifestResult = { ok: true; files: string[] } | { ok: false; error: string };\n\n/** A rejected entry, rendered for the error message. A string prints as itself —\n *  the overwhelmingly common case, and what this always used to print. Anything\n *  else goes through JSON so a poisoned manifest shows its actual value rather\n *  than `[object Object]`.\n *\n *  Never throws. This runs only on the REJECTION path, so a throw here would\n *  turn a `{ ok: false }` the caller can handle into an exception it cannot —\n *  and the input is `unknown`, i.e. whatever a caller passed. */\nconst showUnsafe = (entry: unknown): string => {\n  if (typeof entry === \"string\") return entry;\n  try {\n    // `?? String(entry)`: JSON renders undefined / a function / a symbol as\n    // the value `undefined`, and those still deserve a name in the message.\n    return JSON.stringify(entry) ?? String(entry);\n  } catch {\n    // EVERY other rendering runs user code and can throw again: `String` calls\n    // `toString`/`valueOf`, `Object.prototype.toString` reads\n    // `Symbol.toStringTag`, and a proxy traps all of them. `typeof` reads\n    // nothing off the value, so it is the only one that cannot fail.\n    return `<unprintable ${typeof entry}>`;\n  }\n};\n\nexport function parseManifest(value: unknown): ManifestResult {\n  // `isUnknownArray`, not `Array.isArray`: the latter narrows `unknown` to\n  // `any[]`, so every element read below would be `any`. The elements stay\n  // `unknown` until `isSafeBundlePath`, a type predicate, narrows them.\n  const files = isRecord(value) ? value.files : undefined;\n  if (!isUnknownArray(files)) return { ok: false, error: \"manifest is missing a files[] array\" };\n  // `findIndex`, not `find`: `find` answers `undefined` both for \"nothing\n  // unsafe\" and for \"the unsafe entry IS `undefined`\", so an `undefined` (or a\n  // hole) read as a clean manifest and `filter` then dropped it silently.\n  const unsafeIndex = files.findIndex((file) => !isSafeBundlePath(file));\n  if (unsafeIndex !== -1) return { ok: false, error: `manifest contains an unsafe path: ${showUnsafe(files[unsafeIndex])}` };\n  return { ok: true, files: files.filter(isSafeBundlePath) };\n}\n\n/** `data/collections/<localSlug>/items` — the host owns dataPath, never the\n *  registry's authored value, so imported collections can't collide on disk. */\nexport function normalizedDataPath(localSlug: string): string {\n  return `data/collections/${localSlug}/items`;\n}\n\nexport function withNormalizedDataPath(schema: Record<string, unknown>, localSlug: string): Record<string, unknown> {\n  return { ...schema, dataPath: normalizedDataPath(localSlug) };\n}\n\nexport type ManifestFetch = { ok: true; files: string[] } | { ok: false; status: number; error: string };\n\nexport async function fetchManifest(entry: RegistryEntry, scope: RegistryScope = {}): Promise<ManifestFetch> {\n  const rawBase = rawBaseForEntry(entry, scope);\n  if (!rawBase) return { ok: false, status: STATUS_BAD_GATEWAY, error: `registry \"${entry.registryName}\" is no longer configured` };\n  const file = await fetchCollectionFile(rawBase, entry.path, MANIFEST_FILE);\n  if (!file.ok) return { ok: false, status: file.status, error: `manifest.json: ${file.error}` };\n  const obj = parseJsonObject(file.text, \"manifest.json\");\n  if (!obj.ok) return { ok: false, status: STATUS_BAD_GATEWAY, error: obj.error };\n  const manifest = parseManifest(obj.value);\n  if (!manifest.ok) return { ok: false, status: STATUS_BAD_GATEWAY, error: manifest.error };\n  return { ok: true, files: manifest.files };\n}\n\nexport type BundleFetch = { ok: true; files: Map<string, string> } | { ok: false; status: number; error: string };\n\n/** Fetch every manifest file. Paths are already safety-checked by parseManifest. */\nexport async function fetchBundle(entry: RegistryEntry, fileList: readonly string[], scope: RegistryScope = {}): Promise<BundleFetch> {\n  const rawBase = rawBaseForEntry(entry, scope);\n  if (!rawBase) return { ok: false, status: STATUS_BAD_GATEWAY, error: `registry \"${entry.registryName}\" is no longer configured` };\n  const files = new Map<string, string>();\n  for (const rel of fileList) {\n    const file = await fetchCollectionFile(rawBase, entry.path, rel);\n    if (!file.ok) return { ok: false, status: file.status, error: `${rel}: ${file.error}` };\n    files.set(rel, file.text);\n  }\n  return { ok: true, files };\n}\n","// Import a registry collection into the active workspace. The writer fetches\n// the bundle, re-validates the schema with the host's own gates (R7 — the\n// index is not a trust boundary), writes the bundle into `data/skills/<localSlug>/`\n// with a host-owned dataPath (R3), materializes any seed records into that\n// dataPath when it's empty, and records provenance in `.origin.json` for\n// update detection (R5/R8). After the data-skills swap, the bundle's\n// allowlisted files (SKILL.md, schema.json, templates/<safe>) are mirrored\n// 1:1 into `.claude/skills/<localSlug>/` via the same skill-bridge rules an\n// agent-authored skill would go through — so an authored and an imported\n// collection live in EXACTLY the same place on disk, and the user can edit\n// either one identically.\n//\n// `.origin.json` lives ONLY in `data/skills/<slug>/.origin.json` and is NOT\n// mirrored — the skill-bridge allowlist deliberately excludes host\n// bookkeeping. Its presence is what distinguishes \"imported\" from\n// \"user-authored\" in every downstream tool.\n//\n// `writeImportedCollection` takes the already-fetched bundle + an explicit\n// workspaceRoot/clock so it is unit-testable against a temp workspace with\n// no network; `performImport` is the thin glue that fetches and calls it.\n\nimport { mkdir, readFile, readdir, rename, rm, stat, writeFile } from \"node:fs/promises\";\nimport type { Dirent } from \"node:fs\";\nimport path from \"node:path\";\n\nimport { acceptParsedSchema, CollectionSchemaZ, isSafeActionTemplatePath, safeRecordId } from \"../../server/index.js\";\nimport type { CollectionSchema } from \"../../index.js\";\nimport { claudeSkillDir, dataSkillDir, mirrorSkillWrite } from \"../../../skill-bridge/index.js\";\n\nimport { log, projectSkillsDir, skillsStagingDir } from \"../../server/host.js\";\nimport { errorMessage } from \"../../server/util.js\";\nimport { writeFileAtomic } from \"../../../files/atomic.js\";\nimport { isRecord } from \"../guards.js\";\nimport { fetchAllRegistries } from \"./client.js\";\nimport { fetchBundle, fetchManifest, normalizedDataPath } from \"./importCollection.js\";\nimport type { RegistryEntry } from \"../registryIndex.js\";\n\nconst ORIGIN_FILE = \".origin.json\";\nconst SEED_PREFIX = \"seed/items/\";\nconst SCHEMA_FILE = \"schema.json\";\nconst SKILL_FILE = \"SKILL.md\";\nconst STATUS_NOT_FOUND = 404;\nconst STATUS_CONFLICT = 409;\nconst STATUS_UNPROCESSABLE = 422;\n\nexport interface ImportOrigin {\n  registry: string;\n  author: string;\n  slug: string;\n  version: string;\n  contentSha: string;\n  importedAt: string;\n}\n\nexport type ImportResult =\n  { ok: true; localSlug: string; updated: boolean; seedWritten: number; seedSkipped: boolean } | { ok: false; status: number; error: string };\n\nasync function statType(target: string): Promise<\"dir\" | \"other\" | \"absent\"> {\n  try {\n    return (await stat(target)).isDirectory() ? \"dir\" : \"other\";\n  } catch (err) {\n    // EACCES etc. are path-shape conflicts mkdir would later throw on → \"other\".\n    // A file ancestor surfaces as ENOTDIR on POSIX but ENOENT on Windows (which\n    // reports the whole path as missing), so ENOENT can't be trusted as \"absent\"\n    // until we've confirmed no existing ancestor is a non-directory file.\n    if (!(isRecord(err) && err.code === \"ENOENT\")) return \"other\";\n    return (await hasNonDirAncestor(target)) ? \"other\" : \"absent\";\n  }\n}\n\n// Walk up from `target` to the nearest ancestor that exists: a non-directory\n// file there means `target` can never be mkdir'd (a path-shape conflict → 409),\n// whichever errno the platform's `stat(target)` chose. An all-absent-or-directory\n// chain up to the filesystem root is a genuine \"absent\".\nasync function hasNonDirAncestor(target: string): Promise<boolean> {\n  let current = path.dirname(target);\n  while (current !== path.dirname(current)) {\n    try {\n      return !(await stat(current)).isDirectory();\n    } catch (err) {\n      if (isRecord(err) && err.code === \"ENOENT\") {\n        current = path.dirname(current);\n        continue;\n      }\n      return true;\n    }\n  }\n  return false;\n}\n\nasync function isEmptyOrAbsentDir(target: string): Promise<boolean> {\n  try {\n    return (await readdir(target)).length === 0;\n  } catch {\n    return true;\n  }\n}\n\nfunction originMatches(origin: unknown, registry: string, author: string, slug: string): boolean {\n  return isRecord(origin) && origin.registry === registry && origin.author === author && origin.slug === slug;\n}\n\nasync function readOrigin(targetDir: string): Promise<unknown> {\n  try {\n    return JSON.parse(await readFile(path.join(targetDir, ORIGIN_FILE), \"utf-8\"));\n  } catch {\n    return null;\n  }\n}\n\ntype TargetResolution = { targetDir: string; localSlug: string; updated: boolean } | { conflict: string };\n\n// Only bounds the fresh-slug search (a safety cap, far above any realistic\n// number of same-named collections — the first free slug is normally found in\n// 1–2 iterations). An EXISTING install is found via the directory scan below,\n// not this loop, so updates are never missed regardless of how high the rename\n// suffix is.\nconst MAX_SLUG_ATTEMPTS = 10000;\n\nconst renameCandidate = (slug: string, attempt: number): string => (attempt === 0 ? slug : `${slug}-${attempt + 1}`);\n\n// True when `name` is the registry slug or a `<slug>-<n>` rename of it.\nfunction isRenameOf(name: string, slug: string): boolean {\n  if (name === slug) return true;\n  if (!name.startsWith(`${slug}-`)) return false;\n  const suffix = name.slice(slug.length + 1);\n  return suffix.length > 0 && /^\\d+$/.test(suffix);\n}\n\n// Find an existing install of this registry collection at ANY rename suffix\n// by scanning `data/skills/` — independent of any candidate bound, so a\n// re-import always updates the existing install rather than duplicating it\n// (even if an earlier slug freed up). An authored skill without `.origin.json`\n// is invisible to this scan and so never collides with an update.\nasync function findMatchingInstall(skillsDir: string, registry: string, entry: RegistryEntry): Promise<string | null> {\n  const names = await readdir(skillsDir).catch((): string[] => []);\n  for (const name of names) {\n    if (!isRenameOf(name, entry.slug)) continue;\n    const dir = path.join(skillsDir, name);\n    if ((await statType(dir)) === \"dir\" && originMatches(await readOrigin(dir), registry, entry.author, entry.slug)) return name;\n  }\n  return null;\n}\n\n// Pick the local install slug (rename-on-collision, R8). First reuse an\n// existing matching install (update). Otherwise install fresh at the first\n// free slug — the registry slug, else `<slug>-2`, `-3`, … — never clobbering\n// a user's own same-named collection.\n//\n// A slug is \"free\" only when BOTH `data/skills/<slug>/` AND\n// `.claude/skills/<slug>/` are absent. The mirror check matters because\n// `mirrorToClaudeSkills` overwrites the mirror dir's allowlisted files and\n// prunes anything else — if the user has a manually-installed Claude skill\n// at `.claude/skills/<slug>/` with no corresponding `data/skills/<slug>/`\n// (e.g. installed by the Claude CLI directly, or a legacy pre-refactor\n// import we never migrated), picking that slug would silently overwrite\n// their SKILL.md/schema.json and prune the rest of their files (CodeRabbit\n// review on #1839).\n/** Where an import INSTALLS in this root, and whether a mirror step follows.\n *\n *  With a staging tree the install is the usual two-step: write\n *  `data/skills/<slug>/` and mirror the allowlist into `.claude/skills/<slug>/`.\n *  A root with NO staging tree has no bridge to mirror through, so the active\n *  skill dir IS the install — and installing into `data/skills/` there would be\n *  worse than useless: the mirror makes the collection discoverable, but its\n *  `.origin.json` and every non-allowlisted asset (notably `views/`) stay in a\n *  tree that reads and deletes now deliberately ignore. Update would not find\n *  the provenance, and delete would leave the install behind. */\nfunction importInstall(workspaceRoot: string): { skillsDir: string; mirrors: boolean } {\n  const staging = skillsStagingDir(workspaceRoot);\n  return staging === null ? { skillsDir: projectSkillsDir(workspaceRoot), mirrors: false } : { skillsDir: staging, mirrors: true };\n}\n\nconst installDir = (workspaceRoot: string, slug: string): string => path.join(importInstall(workspaceRoot).skillsDir, slug);\n\nasync function resolveTarget(workspaceRoot: string, registry: string, entry: RegistryEntry): Promise<TargetResolution> {\n  const { skillsDir, mirrors } = importInstall(workspaceRoot);\n  const existing = await findMatchingInstall(skillsDir, registry, entry);\n  if (existing) return { targetDir: path.join(skillsDir, existing), localSlug: existing, updated: true };\n  for (let attempt = 0; attempt < MAX_SLUG_ATTEMPTS; attempt += 1) {\n    const localSlug = renameCandidate(entry.slug, attempt);\n    const sourceAbsent = (await statType(path.join(skillsDir, localSlug))) === \"absent\";\n    // Without a mirror the two checks are the same directory, so the install\n    // dir being free is the whole condition.\n    const mirrorAbsent = !mirrors || (await statType(claudeSkillDir(workspaceRoot, localSlug))) === \"absent\";\n    if (sourceAbsent && mirrorAbsent) {\n      return { targetDir: path.join(skillsDir, localSlug), localSlug, updated: false };\n    }\n  }\n  return { conflict: `couldn't find an available slug for '${entry.slug}'` };\n}\n\ntype SchemaResolution = { schema: CollectionSchema } | { error: string };\n\nfunction validateAndNormalize(bundle: Map<string, string>, localSlug: string, workspaceRoot: string): SchemaResolution {\n  // SKILL.md is required: `mirrorToClaudeSkills` calls\n  // `mirrorSkillWrite({slug, relSegments: [SKILL_FILE]})` unconditionally\n  // after the data-side swap, which throws if SKILL.md is missing. Caught\n  // outside, that throw is logged but the data-side write still succeeds and\n  // the function returns `ok: true` for an unusable import. Reject up front\n  // so a missing SKILL.md surfaces as a clean 422 instead (CodeRabbit review\n  // on #1839).\n  if (bundle.get(SKILL_FILE) === undefined) return { error: \"bundle is missing SKILL.md\" };\n  const schemaText = bundle.get(SCHEMA_FILE);\n  if (schemaText === undefined) return { error: \"bundle is missing schema.json\" };\n  let parsedJson: unknown;\n  try {\n    parsedJson = JSON.parse(schemaText);\n  } catch {\n    return { error: \"schema.json is not valid JSON\" };\n  }\n  const parsed = CollectionSchemaZ.safeParse(parsedJson);\n  if (!parsed.success) return { error: `schema.json failed validation: ${parsed.error.issues[0]?.message ?? \"invalid\"}` };\n  // A `dataSource` collection can't be imported: its records are the rows of\n  // a machine-local data file the bundle doesn't (and can't) carry — and the\n  // R3 dataPath stamp below would collide with the exactly-one-of rule.\n  if (parsed.data.dataSource !== undefined) {\n    return { error: \"schema.json declares `dataSource` — external-data collections are machine-local and cannot be imported from a registry\" };\n  }\n  const schema: CollectionSchema = { ...parsed.data, dataPath: normalizedDataPath(localSlug) };\n  const acceptance = acceptParsedSchema(schema, { source: \"project\", workspaceRoot, slug: localSlug });\n  if (!acceptance.ok) return { error: `schema.json rejected: ${acceptance.reason}` };\n  return { schema };\n}\n\nasync function writeBundleFiles(targetDir: string, bundle: Map<string, string>, schema: CollectionSchema): Promise<void> {\n  for (const [rel, content] of bundle) {\n    if (rel.startsWith(SEED_PREFIX)) continue; // seed goes to dataPath, not the skill dir\n    const dest = path.join(targetDir, ...rel.split(\"/\"));\n    if (dest !== targetDir && !dest.startsWith(targetDir + path.sep)) continue; // belt-and-suspenders (paths pre-validated)\n    await mkdir(path.dirname(dest), { recursive: true });\n    await writeFile(dest, rel === SCHEMA_FILE ? `${JSON.stringify(schema, null, 2)}\\n` : content, \"utf-8\");\n  }\n}\n\nasync function materializeSeed(dataDir: string, bundle: Map<string, string>): Promise<{ written: number; skipped: boolean }> {\n  const seedEntries = [...bundle].filter(([rel]) => rel.startsWith(SEED_PREFIX));\n  if (seedEntries.length === 0) return { written: 0, skipped: false };\n  if (!(await isEmptyOrAbsentDir(dataDir))) return { written: 0, skipped: true };\n  await mkdir(dataDir, { recursive: true });\n  let written = 0;\n  for (const [rel, content] of seedEntries) {\n    const fileName = rel.slice(SEED_PREFIX.length);\n    if (fileName.includes(\"/\") || safeRecordId(fileName.replace(/\\.json$/, \"\")) === null) {\n      log.warn(\"collections-registry\", \"skipped unsafe seed record\", { rel });\n      continue;\n    }\n    await writeFile(path.join(dataDir, fileName), content, \"utf-8\");\n    written += 1;\n  }\n  return { written, skipped: false };\n}\n\n/** Compute the set of bundle-relative paths that should land in `.claude/skills/<slug>/`.\n *  Matches the bridge allowlist exactly — SKILL.md, schema.json,\n *  `templates/<safe>` — so anything else (seed, meta.json, views, README,\n *  assets) stays source-side. */\nfunction bridgeAllowlistFiles(bundle: Map<string, string>): Set<string> {\n  const wanted = new Set<string>([SKILL_FILE, SCHEMA_FILE]);\n  for (const rel of bundle.keys()) {\n    if (rel === SKILL_FILE || rel === SCHEMA_FILE) continue;\n    if (rel.startsWith(SEED_PREFIX)) continue;\n    if (!isSafeActionTemplatePath(rel)) continue;\n    wanted.add(rel);\n  }\n  return wanted;\n}\n\n/** Recursively list every file under `root`, returned as forward-slash paths\n *  relative to `root`. Empty list when `root` doesn't exist. Used to spot\n *  mirror files left over from a previous install so we can prune them after\n *  writing the new ones. */\nasync function listFilesRecursive(root: string, prefix = \"\"): Promise<string[]> {\n  const dir = prefix ? path.join(root, ...prefix.split(\"/\")) : root;\n  const entries: Dirent[] = await readdir(dir, { withFileTypes: true }).catch((): Dirent[] => []);\n  const out: string[] = [];\n  for (const entry of entries) {\n    const rel = prefix ? `${prefix}/${entry.name}` : entry.name;\n    if (entry.isFile()) out.push(rel);\n    else if (entry.isDirectory()) out.push(...(await listFilesRecursive(root, rel)));\n  }\n  return out;\n}\n\n// Mirror the just-written `data/skills/<slug>/` into `.claude/skills/<slug>/`\n// using the shared bridge package — exactly the set of files an\n// agent-authored skill would mirror, no more (SKILL.md, schema.json,\n// templates/<safe>). `.origin.json` is host bookkeeping and stays only on the\n// data side.\n//\n// **Write-then-prune ordering** (Codex review on #1839): write the new\n// bundle's allowlisted files FIRST (each is a per-file tmp+rename, atomic),\n// THEN prune mirror files that aren't in the new bundle. A transient mirror\n// failure during the writes leaves the previous mirror's files in place —\n// agent discovery keeps working with the prior state instead of finding an\n// empty `.claude/skills/<slug>/`. The prune step is best-effort: a failure\n// there leaves harmless stale leftovers but doesn't break the new install.\n// Compare with the old `mirrorSkillDelete`-first ordering, which could\n// silently leave an empty mirror if a subsequent write threw.\nasync function mirrorToClaudeSkills(workspaceRoot: string, localSlug: string, bundle: Map<string, string>): Promise<void> {\n  const wanted = bridgeAllowlistFiles(bundle);\n  // 1. Write the new set first (overwrites existing via tmp+rename).\n  for (const rel of wanted) {\n    mirrorSkillWrite(workspaceRoot, { slug: localSlug, relSegments: rel.split(\"/\") });\n  }\n  // 2. Prune files that exist in the mirror but aren't in the new bundle.\n  const mirrorRoot = claudeSkillDir(workspaceRoot, localSlug);\n  const existing = await listFilesRecursive(mirrorRoot);\n  for (const rel of existing) {\n    if (wanted.has(rel)) continue;\n    await rm(path.join(mirrorRoot, ...rel.split(\"/\")), { force: true }).catch(() => undefined);\n  }\n}\n\nexport async function writeImportedCollection(params: {\n  registry: string;\n  entry: RegistryEntry;\n  bundle: Map<string, string>;\n  workspaceRoot: string;\n  nowIso: string;\n}): Promise<ImportResult> {\n  const { registry, entry, bundle, workspaceRoot, nowIso } = params;\n  const target = await resolveTarget(workspaceRoot, registry, entry);\n  if (\"conflict\" in target) return { ok: false, status: STATUS_CONFLICT, error: target.conflict };\n\n  const { localSlug } = target;\n\n  // Pre-flight the data dir before schema validation: a non-directory at the dataPath\n  // (or an ancestor that's a file → ENOTDIR) would otherwise surface as a generic 500\n  // on mkdir. statType maps ENOTDIR/other to a deterministic 409 path-shape conflict.\n  const dataDir = path.join(workspaceRoot, ...normalizedDataPath(localSlug).split(\"/\"));\n  if ((await statType(dataDir)) === \"other\") {\n    return { ok: false, status: STATUS_CONFLICT, error: `data path for slug '${localSlug}' exists and is not a directory` };\n  }\n\n  const validated = validateAndNormalize(bundle, localSlug, workspaceRoot);\n  if (\"error\" in validated) return { ok: false, status: STATUS_UNPROCESSABLE, error: validated.error };\n\n  // Build the replacement fully in a hidden sibling staging dir under\n  // `data/skills/` (bundle + origin), so the prior install is untouched until\n  // everything is durably written. Leftover staging/backup dirs from a\n  // crashed import are cleaned first, keeping retries possible.\n  const skillsParent = path.dirname(target.targetDir);\n  await mkdir(skillsParent, { recursive: true }); // first-import case — data/skills/ may not exist\n  const staging = path.join(skillsParent, `.importing-${localSlug}`);\n  const backup = path.join(skillsParent, `.backup-${localSlug}`);\n  await rm(staging, { recursive: true, force: true });\n  await rm(backup, { recursive: true, force: true });\n  await mkdir(staging, { recursive: true });\n  await writeBundleFiles(staging, bundle, validated.schema);\n  const origin: ImportOrigin = { registry, author: entry.author, slug: entry.slug, version: entry.version, contentSha: entry.contentSha, importedAt: nowIso };\n  await writeFileAtomic(path.join(staging, ORIGIN_FILE), `${JSON.stringify(origin, null, 2)}\\n`);\n\n  // Swap with rollback: move the old install aside (rename), move the new in\n  // (rename), then discard the old. If the swap fails, restore the old so we\n  // never end up with no installed collection. Records live in dataPath (a\n  // separate dir) and are untouched.\n  if (target.updated) await rename(target.targetDir, backup);\n  try {\n    await rename(staging, target.targetDir);\n  } catch (err) {\n    if (target.updated) await rename(backup, target.targetDir).catch(() => undefined);\n    throw err;\n  }\n  await rm(backup, { recursive: true, force: true });\n\n  // Replicate the new `data/skills/<slug>/` set into `.claude/skills/<slug>/`\n  // via the shared bridge package — same allowlist + tmp+rename semantics the\n  // hook uses for agent-authored writes. Write-then-prune ordering inside\n  // mirrorToClaudeSkills means a transient failure here can't leave the mirror\n  // empty (Codex review on #1839); the worst case is a half-written mirror\n  // where the new install's SKILL.md/schema.json may not have updated, but the\n  // prior install remains accessible to the agent until the next mirror\n  // attempt. Logged-not-thrown matches the hook's posture for agent writes.\n  try {\n    // Skipped where the install already IS the active skill dir — there is\n    // nothing to mirror to, and `mirrorSkillWrite` would read a staging file\n    // that never exists.\n    if (importInstall(workspaceRoot).mirrors) await mirrorToClaudeSkills(workspaceRoot, localSlug, bundle);\n  } catch (err) {\n    log.warn(\"collections-registry\", \"mirror to .claude/skills/ failed (data/skills write succeeded; prior mirror left intact)\", {\n      localSlug,\n      error: errorMessage(err),\n    });\n  }\n\n  const seed = await materializeSeed(dataDir, bundle);\n  return { ok: true, localSlug, updated: target.updated, seedWritten: seed.written, seedSkipped: seed.skipped };\n}\n\nexport async function performImport(author: string, slug: string, workspaceRoot: string, registry: string | null = null): Promise<ImportResult> {\n  // The import's target workspace is also the registry scope — a multi-root\n  // host's per-project `collections-registries.json` must be the one consulted.\n  const merged = await fetchAllRegistries({ workspaceRoot });\n  let entry: RegistryEntry | undefined;\n  for (const reg of merged) {\n    if (registry !== null && reg.name !== registry) continue;\n    entry = reg.entries.find((candidate) => candidate.author === author && candidate.slug === slug);\n    if (entry) break;\n  }\n  if (!entry) return { ok: false, status: STATUS_NOT_FOUND, error: `unknown collection: ${author}/${slug}` };\n  const manifest = await fetchManifest(entry, { workspaceRoot });\n  if (!manifest.ok) return { ok: false, status: manifest.status, error: manifest.error };\n  const bundle = await fetchBundle(entry, manifest.files, { workspaceRoot });\n  if (!bundle.ok) return { ok: false, status: bundle.status, error: bundle.error };\n  try {\n    return await writeImportedCollection({\n      registry: entry.registryName,\n      entry,\n      bundle: bundle.files,\n      workspaceRoot,\n      nowIso: new Date().toISOString(),\n    });\n  } catch (err) {\n    log.warn(\"collections-registry\", \"import write failed\", { author, slug, registry: entry.registryName, error: errorMessage(err) });\n    return { ok: false, status: 500, error: `import failed: ${errorMessage(err)}` };\n  }\n}\n\n// Exported for downstream code that wants the path conventions without\n// importing skill-bridge directly.\nexport { claudeSkillDir, dataSkillDir, installDir, hasNonDirAncestor };\n","// Export a workspace collection into the curated registry's contribution layout\n// (collections/<author>/<slug>/ + meta.json + optional seed/) under\n// data/registry-export/, so the user can open a PR to the registry. The producer\n// side of the registry loop.\n//\n// writeCollectionExport takes explicit dirs + a workspace root so it is unit-testable\n// against temp dirs with no discovery/network; performExport (separate file) is the\n// thin glue that resolves the collection from the live workspace.\n\nimport { cp, mkdir, readdir, readFile, rm, stat, writeFile } from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport { log } from \"../../server/host.js\";\nimport { toPosixRelPath } from \"../../../files/relPath.js\";\n\nexport const EXPORT_BASE = \"data/registry-export\";\nconst BUNDLE_FILES = [\"SKILL.md\", \"schema.json\"] as const;\nconst OPTIONAL_FILES = [\"screenshot.png\"] as const;\nconst BUNDLE_DIRS = [\"views\", \"templates\"] as const;\nconst AUTHOR_RE = /^[A-Za-z0-9][A-Za-z0-9-]{0,38}$/;\nconst SLUG_RE = /^[a-z0-9][a-z0-9-]{0,62}$/;\nconst STATUS_BAD_REQUEST = 400;\n// Block obvious credentials from being published in seed data; PII is only warned.\nconst SECRET_PATTERNS = [\n  /AKIA[0-9A-Z]{16}/,\n  /gh[pousr]_[A-Za-z0-9]{20,}/,\n  /-----BEGIN [A-Z ]*PRIVATE KEY-----/,\n  /sk-[A-Za-z0-9]{20,}/,\n  /xox[baprs]-[A-Za-z0-9-]{10,}/,\n];\nconst hasSecret = (text: string): boolean => SECRET_PATTERNS.some((pattern) => pattern.test(text));\n// Bounded + non-overlapping (no ReDoS): local@label.tld with single quantifier runs.\nconst EMAIL_RE = /[\\w.%+-]{1,64}@[\\w-]{1,255}\\.[a-z]{2,24}/i;\n\nexport interface ExportMeta {\n  author: string;\n  slug: string;\n  version: string;\n  title: string;\n  description: string;\n  tags: string[];\n  license: string;\n}\n\nexport type ExportResult =\n  | { ok: true; outputPath: string; fileCount: number; seedCount: number; seedSkipped: number; warnings: string[] }\n  | { ok: false; status: number; error: string };\n\nasync function pathKind(target: string): Promise<\"dir\" | \"file\" | \"absent\"> {\n  try {\n    return (await stat(target)).isDirectory() ? \"dir\" : \"file\";\n  } catch {\n    return \"absent\";\n  }\n}\n\nasync function copyBundle(skillDir: string, outDir: string): Promise<number> {\n  let count = 0;\n  for (const file of [...BUNDLE_FILES, ...OPTIONAL_FILES]) {\n    const src = path.join(skillDir, file);\n    if ((await pathKind(src)) !== \"file\") continue;\n    await cp(src, path.join(outDir, file));\n    count += 1;\n  }\n  for (const dir of BUNDLE_DIRS) {\n    const src = path.join(skillDir, dir);\n    if ((await pathKind(src)) !== \"dir\") continue;\n    await cp(src, path.join(outDir, dir), { recursive: true });\n    count += (await readdir(src)).filter((name) => !name.startsWith(\".\")).length;\n  }\n  return count;\n}\n\nasync function exportSeed(dataDir: string, outDir: string): Promise<{ count: number; skipped: number; warnings: string[] }> {\n  let names: string[];\n  try {\n    // Dot-prefixed files are NOT records — the same rule every other reader of\n    // a data dir applies (`io.ts#listItems`, `ontology.ts`, the store watcher,\n    // `validate.ts`), and the bundle-dir count above. Sync state lives here too\n    // (`.calendar-sync.json`), and shipping it would put the user's calendar id\n    // in a published bundle and count it toward `dataConsent` (Codex review\n    // #2853).\n    names = (await readdir(dataDir)).filter((name) => name.endsWith(\".json\") && !name.startsWith(\".\"));\n  } catch {\n    return { count: 0, skipped: 0, warnings: [] };\n  }\n  if (names.length === 0) return { count: 0, skipped: 0, warnings: [] };\n  const seedDir = path.join(outDir, \"seed\", \"items\");\n  await mkdir(seedDir, { recursive: true });\n  const warnings: string[] = [];\n  let count = 0;\n  let skipped = 0;\n  for (const name of names) {\n    const base = path.basename(name);\n    const text = await readFile(path.join(dataDir, base), \"utf-8\");\n    if (hasSecret(text)) {\n      warnings.push(`skipped ${base}: contains a possible credential`);\n      skipped += 1;\n      continue;\n    }\n    if (EMAIL_RE.test(text)) warnings.push(`${base}: contains a possible email/PII (kept — your responsibility)`);\n    await writeFile(path.join(seedDir, base), text, \"utf-8\");\n    count += 1;\n  }\n  return { count, skipped, warnings };\n}\n\n// Resolve `segments` under `root` and return the absolute path only when it stays\n// inside `root` — a containment barrier for the user-derived author/slug and the\n// collection dirs, on top of the AUTHOR_RE/SLUG_RE format checks. `..` or an\n// absolute escape resolves outside `root` and yields null (rejected upstream).\nfunction resolveWithin(root: string, ...segments: string[]): string | null {\n  const resolvedRoot = path.resolve(root);\n  const target = path.resolve(resolvedRoot, ...segments);\n  return target === resolvedRoot || target.startsWith(resolvedRoot + path.sep) ? target : null;\n}\n\n// Required bundle files (SKILL.md, schema.json) must be present — exporting an\n// incomplete bundle would pass here but fail downstream registry curation.\n// Returns the first missing required file, or null when all are present.\nasync function findMissingRequired(skillDir: string): Promise<string | null> {\n  for (const file of BUNDLE_FILES) {\n    if ((await pathKind(path.join(skillDir, file))) !== \"file\") return file;\n  }\n  return null;\n}\n\nexport async function writeCollectionExport(params: {\n  workspaceRoot: string;\n  skillDir: string;\n  dataDir: string;\n  meta: ExportMeta;\n  includeSeed: boolean;\n}): Promise<ExportResult> {\n  const { workspaceRoot, skillDir, dataDir, meta, includeSeed } = params;\n  if (!AUTHOR_RE.test(meta.author)) return { ok: false, status: STATUS_BAD_REQUEST, error: `author '${meta.author}' is not a valid GitHub login` };\n  if (!SLUG_RE.test(meta.slug)) return { ok: false, status: STATUS_BAD_REQUEST, error: `slug '${meta.slug}' is invalid` };\n\n  const wsRoot = path.resolve(workspaceRoot);\n  const exportRoot = path.join(wsRoot, ...EXPORT_BASE.split(\"/\"));\n  const outDir = resolveWithin(exportRoot, meta.author, meta.slug);\n  const safeSkillDir = resolveWithin(wsRoot, skillDir);\n  const safeDataDir = resolveWithin(wsRoot, dataDir);\n  if (!outDir || !safeSkillDir || !safeDataDir) {\n    return { ok: false, status: STATUS_BAD_REQUEST, error: \"resolved path escapes the workspace\" };\n  }\n\n  const missing = await findMissingRequired(safeSkillDir);\n  if (missing) {\n    return { ok: false, status: STATUS_BAD_REQUEST, error: `required bundle file missing: ${missing}` };\n  }\n\n  await rm(outDir, { recursive: true, force: true });\n  await mkdir(outDir, { recursive: true });\n\n  const bundleCount = await copyBundle(safeSkillDir, outDir);\n  const seed = includeSeed ? await exportSeed(safeDataDir, outDir) : { count: 0, skipped: 0, warnings: [] };\n  const metaOut = { ...meta, ...(seed.count > 0 ? { dataConsent: true } : {}) };\n  await writeFile(path.join(outDir, \"meta.json\"), `${JSON.stringify(metaOut, null, 2)}\\n`, \"utf-8\");\n  log.info(\"collections-registry\", \"exported collection\", { slug: meta.slug, author: meta.author, seedCount: seed.count });\n  const outRel = toPosixRelPath(path.relative(wsRoot, outDir));\n  return { ok: true, outputPath: outRel, fileCount: bundleCount + 1, seedCount: seed.count, seedSkipped: seed.skipped, warnings: seed.warnings };\n}\n","// `description:` reader for a SKILL.md YAML frontmatter envelope.\n//\n// The host (MulmoClaude) parses SKILL.md frontmatter with js-yaml, but\n// @mulmoclaude/core deliberately carries no YAML dependency and export only needs\n// the single `description` scalar for the registry meta.json (best-effort — it\n// defaults to \"\" when absent). Rather than pull in a YAML parser we scan the\n// envelope for the first `description:` line and resolve the common YAML scalar\n// forms so exported descriptions match what the host produced:\n//   - double-quoted (\"…\")  → unescaped, trailing inline comment ignored\n//   - single-quoted ('…')  → '' → ', trailing inline comment ignored\n//   - plain (unquoted)     → trailing \" #comment\" stripped (YAML comment rule)\n// Block scalars (`description: |`) are NOT expanded — they yield \"\" (skill\n// descriptions are single-line in practice).\n\nconst FENCE = \"---\";\nconst KEY = \"description:\";\nconst BLOCK_SCALAR_INDICATORS = new Set([\"|\", \">\", \"|-\", \">-\", \"|+\", \">+\"]);\n\nconst isYamlSpace = (char: string | undefined): boolean => char === \" \" || char === \"\\t\";\n\n// After a closing quote, YAML allows only whitespace and an optional \"#\" comment.\n// Anything else (e.g. `\"foo\" bar`) is malformed — js-yaml would throw, so we\n// reject (→ null → \"\") rather than silently truncate.\nconst isOnlyTrailingComment = (rest: string): boolean => {\n  const trimmed = rest.trimStart();\n  return trimmed === \"\" || trimmed.startsWith(\"#\");\n};\n\n// Escapes a description realistically carries inside a double-quoted scalar;\n// any other `\\x` collapses to the literal `x`.\nconst DOUBLE_QUOTE_ESCAPES: Record<string, string> = { n: \"\\n\", t: \"\\t\" };\nconst unescapeDoubleQuote = (next: string): string => DOUBLE_QUOTE_ESCAPES[next] ?? next;\n\n// The text a two-character escape pair at `index` stands for, or null when the\n// pair isn't an escape — which makes `index` an ordinary character (possibly the\n// closing quote). Both YAML quoted forms differ only in this one rule.\ntype EscapeReader = (value: string, index: number) => string | null;\n\n// Walk a quoted scalar from just past its opening quote to the closing one.\n// Returns null for a malformed scalar (no closing quote, or trailing non-comment\n// text) so the caller degrades to \"\" — matching the host's js-yaml behavior.\nfunction scanQuotedScalar(value: string, quote: string, readEscape: EscapeReader): string | null {\n  const out: string[] = [];\n  // `charAt` (not `value[i]`) so the scanner reads a plain `string`: every\n  // index below is in range, and an out-of-range read would be \"\" either way.\n  for (let i = 1; i < value.length; i += 1) {\n    const escaped = readEscape(value, i);\n    if (escaped !== null) {\n      out.push(escaped);\n      i += 1;\n      continue;\n    }\n    const char = value.charAt(i);\n    if (char === quote) return isOnlyTrailingComment(value.slice(i + 1)) ? out.join(\"\") : null;\n    out.push(char);\n  }\n  return null; // unterminated\n}\n\n// A trailing backslash has nothing to escape, so it stays a literal backslash.\nconst readDoubleQuoteEscape: EscapeReader = (value, index) =>\n  value.charAt(index) === \"\\\\\" && index + 1 < value.length ? unescapeDoubleQuote(value.charAt(index + 1)) : null;\n\n// The only escape in a single-quoted scalar is a doubled quote ('').\nconst readSingleQuoteEscape: EscapeReader = (value, index) => (value.charAt(index) === \"'\" && value[index + 1] === \"'\" ? \"'\" : null);\n\nfunction parseDoubleQuoted(value: string): string | null {\n  return scanQuotedScalar(value, '\"', readDoubleQuoteEscape);\n}\n\nfunction parseSingleQuoted(value: string): string | null {\n  return scanQuotedScalar(value, \"'\", readSingleQuoteEscape);\n}\n\n// Plain scalar: a \"#\" preceded by whitespace (or at the start) begins a YAML\n// comment; \"#\" not preceded by whitespace (e.g. \"C#\") is literal.\nfunction stripPlainComment(value: string): string {\n  for (let i = 0; i < value.length; i += 1) {\n    if (value[i] === \"#\" && (i === 0 || isYamlSpace(value[i - 1]))) return value.slice(0, i);\n  }\n  return value;\n}\n\n/** Extract the frontmatter `description` from raw SKILL.md text. Returns \"\" when\n *  there's no `---` envelope, no `description:` key, or the value is a block\n *  scalar indicator. */\nexport function parseSkillDescription(raw: string): string {\n  const lines = raw.split(/\\r?\\n/);\n  if (lines[0]?.trim() !== FENCE) return \"\";\n  for (const line of lines.slice(1)) {\n    if (line.trim() === FENCE) return \"\"; // end of envelope, key not found\n    if (!line.startsWith(KEY)) continue;\n    return resolveScalar(line.slice(KEY.length).trim());\n  }\n  return \"\";\n}\n\n/** Resolve the raw text after `description:` to its scalar value. */\nfunction resolveScalar(value: string): string {\n  if (value === \"\" || BLOCK_SCALAR_INDICATORS.has(value)) return \"\";\n  if (value.startsWith('\"')) return parseDoubleQuoted(value) ?? \"\";\n  if (value.startsWith(\"'\")) return parseSingleQuoted(value) ?? \"\";\n  return stripPlainComment(value).trim();\n}\n","// Thin glue for the collection export: resolve the collection from the live workspace\n// (its skill dir + data dir + schema), derive meta from SKILL.md front-matter / any\n// existing meta.json, then hand off to the testable writeCollectionExport. Kept\n// separate so the file-writing core stays import-light + unit-testable.\n\nimport { readFile } from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport { loadCollection } from \"../../server/index.js\";\nimport { isRecord } from \"../guards.js\";\nimport { parseSkillDescription } from \"./skillDescription.js\";\nimport { writeCollectionExport, type ExportMeta, type ExportResult } from \"./exportCollection.js\";\n\nconst STATUS_NOT_FOUND = 404;\nconst STATUS_UNPROCESSABLE = 422;\n\nasync function readJsonObject(file: string): Promise<Record<string, unknown> | null> {\n  try {\n    const parsed: unknown = JSON.parse(await readFile(file, \"utf-8\"));\n    return isRecord(parsed) ? parsed : null;\n  } catch {\n    return null;\n  }\n}\n\nexport async function performExport(\n  slug: string,\n  opts: { author: string; license: string; includeSeed: boolean },\n  workspaceRoot: string,\n): Promise<ExportResult> {\n  const collection = await loadCollection(slug);\n  if (!collection) return { ok: false, status: STATUS_NOT_FOUND, error: `collection not found: ${slug}` };\n  // Mirrors the import-side refusal: a `dataSource` collection's records are\n  // a machine-local data file a bundle can't carry.\n  if (collection.schema.dataSource !== undefined) {\n    return { ok: false, status: STATUS_UNPROCESSABLE, error: `collection '${slug}' is backed by an external dataSource and cannot be exported to a registry` };\n  }\n  const skillMd = await readFile(path.join(collection.skillDir, \"SKILL.md\"), \"utf-8\").catch(() => \"\");\n  const existingMeta = await readJsonObject(path.join(collection.skillDir, \"meta.json\"));\n  const meta: ExportMeta = {\n    author: opts.author,\n    slug,\n    version: typeof existingMeta?.version === \"string\" ? existingMeta.version : \"1.0.0\",\n    title: collection.schema.title,\n    description: parseSkillDescription(skillMd),\n    tags: [],\n    license: opts.license,\n  };\n  return writeCollectionExport({ workspaceRoot, skillDir: collection.skillDir, dataDir: collection.dataDir, meta, includeSeed: opts.includeSeed });\n}\n","// @mulmoclaude/core/collection/registry/server — node-only collection registry\n// engine (Discover catalog fetch/cache, import writer, export writer). Shares the\n// `configureCollectionHost` binding with @mulmoclaude/core/collection/server, so a\n// host wires the workspace + logger + paths ONCE and both engines work. The\n// isomorphic contract types live on @mulmoclaude/core/collection/registry.\n\nimport { fetchAllRegistries } from \"./client.js\";\nimport type { RegistryScope } from \"./registriesConfig.js\";\nimport { performImport } from \"./importWriter.js\";\nimport type { RegistryListResponse, RegistryImportResponse } from \"../types.js\";\n\nexport {\n  CACHE_TTL_MS,\n  STALE_RETRY_BACKOFF_MS,\n  fetchAllRegistries,\n  fetchRegistryIndex,\n  findRegistry,\n  listRegistries,\n  resetRegistryCache,\n  type FetchIndexResult,\n  type IndexLoader,\n  type MergedRegistryResult,\n  type RegistryDescriptor,\n} from \"./client.js\";\nexport {\n  collectionFileUrl,\n  fetchCollectionFile,\n  parseJsonObject,\n  previewCollection,\n  rawBaseForEntry,\n  type FileResult,\n  type JsonObjectResult,\n  type PreviewResult,\n} from \"./collectionFiles.js\";\nexport {\n  fetchBundle,\n  fetchManifest,\n  isSafeBundlePath,\n  normalizedDataPath,\n  parseManifest,\n  withNormalizedDataPath,\n  type BundleFetch,\n  type ManifestFetch,\n  type ManifestResult,\n} from \"./importCollection.js\";\nexport { claudeSkillDir, dataSkillDir, performImport, writeImportedCollection, type ImportOrigin, type ImportResult } from \"./importWriter.js\";\nexport { EXPORT_BASE, writeCollectionExport, type ExportMeta, type ExportResult } from \"./exportCollection.js\";\nexport { performExport } from \"./performExport.js\";\nexport { parseSkillDescription } from \"./skillDescription.js\";\nexport { loadRegistriesConfig, parseRegistriesConfig, OFFICIAL_REGISTRY_NAME, type RegistryConfigEntry, type RegistryScope } from \"./registriesConfig.js\";\nexport type { RegistryEntry, RegistryIndex, ParseResult } from \"../registryIndex.js\";\nexport { parseRegistryIndex } from \"../registryIndex.js\";\nexport type { RegistrySummary, RegistryListResponse, RegistryImportResponse } from \"../types.js\";\n\n/** Build the merged Discover catalog response (`GET …collectionsRegistry.list`).\n *  Wraps `fetchAllRegistries` with the per-registry summary + stale-flag shaping\n *  every host needs, so a downstream host doesn't re-implement the mapping. */\nexport async function listRegistry(scope: RegistryScope = {}): Promise<RegistryListResponse> {\n  const merged = await fetchAllRegistries(scope);\n  return {\n    registries: merged.map((reg) => ({\n      name: reg.name,\n      status: reg.status,\n      generatedAt: reg.generatedAt,\n      error: reg.error,\n      entryCount: reg.entries.length,\n    })),\n    stale: merged.some((reg) => reg.status === \"stale\"),\n    collections: merged.flatMap((reg) => reg.entries),\n  };\n}\n\nexport type RegistryImportOutcome = { ok: true; response: RegistryImportResponse } | { ok: false; status: number; error: string };\n\n/** Import a registry collection and return the host-facing response shape\n *  (`POST …collectionsRegistry.import`). On failure carries the HTTP status so\n *  the host route can pass it straight through. */\nexport async function importRegistry(author: string, slug: string, workspaceRoot: string, registry: string | null = null): Promise<RegistryImportOutcome> {\n  const result = await performImport(author, slug, workspaceRoot, registry);\n  if (!result.ok) return { ok: false, status: result.status, error: result.error };\n  return {\n    ok: true,\n    response: { localSlug: result.localSlug, updated: result.updated, seedWritten: result.seedWritten, seedSkipped: result.seedSkipped },\n  };\n}\n"],"mappings":"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"}