@skaile/workspaces 0.45.0 → 0.47.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (136) hide show
  1. package/CHANGELOG.md +98 -0
  2. package/dist/{asset-feeds-AOZLZMDV.js → asset-feeds-DLRQWELS.js} +7 -7
  3. package/dist/{asset-feeds-AOZLZMDV.js.map → asset-feeds-DLRQWELS.js.map} +1 -1
  4. package/dist/asset-manager/index.js +7 -7
  5. package/dist/asset-manager/installer.js +6 -6
  6. package/dist/asset-manager/renderers.js +2 -2
  7. package/dist/asset-manager/src/index.d.ts.map +1 -1
  8. package/dist/{chunk-VPXV2Z5E.js → chunk-3VBQJZYL.js} +6 -6
  9. package/dist/chunk-3VBQJZYL.js.map +1 -0
  10. package/dist/{chunk-FYLIR4AV.js → chunk-4OCZBSBY.js} +5 -2
  11. package/dist/chunk-4OCZBSBY.js.map +1 -0
  12. package/dist/{chunk-CVWA4RIK.js → chunk-4VPRAG35.js} +5 -5
  13. package/dist/{chunk-CVWA4RIK.js.map → chunk-4VPRAG35.js.map} +1 -1
  14. package/dist/{chunk-RGPBEGP2.js → chunk-CU5Z7GH3.js} +6 -2
  15. package/dist/chunk-CU5Z7GH3.js.map +1 -0
  16. package/dist/{chunk-CBZEIFU4.js → chunk-DDR4OSSM.js} +3 -3
  17. package/dist/{chunk-CBZEIFU4.js.map → chunk-DDR4OSSM.js.map} +1 -1
  18. package/dist/{chunk-L6BKSTAX.js → chunk-DHU4LJZV.js} +16 -18
  19. package/dist/chunk-DHU4LJZV.js.map +1 -0
  20. package/dist/{chunk-PCXU2CVW.js → chunk-FAALG3QN.js} +4 -4
  21. package/dist/{chunk-PCXU2CVW.js.map → chunk-FAALG3QN.js.map} +1 -1
  22. package/dist/{chunk-BLGHFVXE.js → chunk-G3GODNHM.js} +66 -4
  23. package/dist/chunk-G3GODNHM.js.map +1 -0
  24. package/dist/{chunk-JUZGLINM.js → chunk-HETXFD2Q.js} +2 -2
  25. package/dist/{chunk-JUZGLINM.js.map → chunk-HETXFD2Q.js.map} +1 -1
  26. package/dist/{chunk-ETDXTGDF.js → chunk-HOEP5CJQ.js} +3 -3
  27. package/dist/{chunk-ETDXTGDF.js.map → chunk-HOEP5CJQ.js.map} +1 -1
  28. package/dist/{chunk-5FVJXQDP.js → chunk-JXHULIOA.js} +3 -3
  29. package/dist/{chunk-5FVJXQDP.js.map → chunk-JXHULIOA.js.map} +1 -1
  30. package/dist/{chunk-ZAEJ33Y6.js → chunk-LLOXWWB6.js} +5 -5
  31. package/dist/{chunk-ZAEJ33Y6.js.map → chunk-LLOXWWB6.js.map} +1 -1
  32. package/dist/{chunk-N2KV5RK3.js → chunk-ON5NSPB6.js} +8 -8
  33. package/dist/{chunk-N2KV5RK3.js.map → chunk-ON5NSPB6.js.map} +1 -1
  34. package/dist/{chunk-GM3BV6JK.js → chunk-P6HRQPXC.js} +2 -2
  35. package/dist/{chunk-GM3BV6JK.js.map → chunk-P6HRQPXC.js.map} +1 -1
  36. package/dist/{chunk-LHUCCPH4.js → chunk-THAJ4MOW.js} +5 -5
  37. package/dist/{chunk-LHUCCPH4.js.map → chunk-THAJ4MOW.js.map} +1 -1
  38. package/dist/{chunk-XUXVH3JK.js → chunk-WRBF34YE.js} +3 -3
  39. package/dist/{chunk-XUXVH3JK.js.map → chunk-WRBF34YE.js.map} +1 -1
  40. package/dist/{chunk-COSTF7QW.js → chunk-WTFJFW7F.js} +50 -12
  41. package/dist/chunk-WTFJFW7F.js.map +1 -0
  42. package/dist/{chunk-LMRO2QNF.js → chunk-XUUMKMMJ.js} +119 -6
  43. package/dist/chunk-XUUMKMMJ.js.map +1 -0
  44. package/dist/{chunk-XF2BBX6P.js → chunk-Z3ZRI2AE.js} +3 -3
  45. package/dist/{chunk-XF2BBX6P.js.map → chunk-Z3ZRI2AE.js.map} +1 -1
  46. package/dist/cli/index.js +128 -81
  47. package/dist/cli/index.js.map +1 -1
  48. package/dist/cli/src/commands/asset-cmd.d.ts.map +1 -1
  49. package/dist/cli/src/commands/catalog.d.ts +2 -1
  50. package/dist/cli/src/commands/catalog.d.ts.map +1 -1
  51. package/dist/cli/src/commands/npx.d.ts.map +1 -1
  52. package/dist/cli/src/commands/project.d.ts.map +1 -1
  53. package/dist/cli/src/commands/source.d.ts +17 -4
  54. package/dist/cli/src/commands/source.d.ts.map +1 -1
  55. package/dist/cli/src/commands/validate.d.ts.map +1 -1
  56. package/dist/cli/src/ensure-sources.d.ts.map +1 -1
  57. package/dist/connectors/config.js +4 -4
  58. package/dist/connectors/index.js +6 -6
  59. package/dist/connectors/rclone.js +1 -1
  60. package/dist/connectors/src/rclone-process-manager.d.ts.map +1 -1
  61. package/dist/core/index.js +3 -3
  62. package/dist/core/runtime-assets.js +2 -2
  63. package/dist/core/src/conformance.d.ts +33 -0
  64. package/dist/core/src/conformance.d.ts.map +1 -0
  65. package/dist/core/src/index.d.ts +2 -1
  66. package/dist/core/src/index.d.ts.map +1 -1
  67. package/dist/core/src/repo-manager.d.ts +24 -0
  68. package/dist/core/src/repo-manager.d.ts.map +1 -1
  69. package/dist/core/src/runtime-assets.d.ts.map +1 -1
  70. package/dist/core/src/workspace-config.d.ts.map +1 -1
  71. package/dist/core/workspace-config.js +1 -1
  72. package/dist/deploy/index.js +3 -3
  73. package/dist/discovery/index.js +2 -2
  74. package/dist/{ensure-sources-NSDMTAWN.js → ensure-sources-KLCGXVE6.js} +12 -13
  75. package/dist/ensure-sources-KLCGXVE6.js.map +1 -0
  76. package/dist/factory-assets/connectors/deploy.js +6 -6
  77. package/dist/factory-assets/connectors/devserver.js +6 -6
  78. package/dist/factory-assets/connectors/flow/adapter.js +6 -6
  79. package/dist/factory-assets/connectors/flow/engine.js +3 -3
  80. package/dist/factory-assets/connectors/flow/run-flow.js +7 -7
  81. package/dist/factory-assets/connectors/flow.js +6 -6
  82. package/dist/factory-assets/connectors/git/CONNECTOR.md +8 -0
  83. package/dist/factory-assets/connectors/git/driver.d.ts +55 -1
  84. package/dist/factory-assets/connectors/git/driver.d.ts.map +1 -1
  85. package/dist/factory-assets/connectors/git.js +6 -6
  86. package/dist/factory-assets/connectors/gmail.js +6 -6
  87. package/dist/factory-assets/connectors/googledrive.js +6 -6
  88. package/dist/factory-assets/connectors/local.js +6 -6
  89. package/dist/factory-assets/connectors/mattermost.js +6 -6
  90. package/dist/factory-assets/connectors/memory.js +6 -6
  91. package/dist/factory-assets/connectors/minio.js +6 -6
  92. package/dist/factory-assets/connectors/postgres.js +6 -6
  93. package/dist/factory-assets/connectors/s3.js +6 -6
  94. package/dist/factory-assets/connectors/sharepoint.js +6 -6
  95. package/dist/factory-assets/connectors/sqlite.js +6 -6
  96. package/dist/factory-assets/connectors/static-server.js +6 -6
  97. package/dist/factory-assets/connectors/tunnel.js +6 -6
  98. package/dist/factory-assets/connectors/webdav.js +6 -6
  99. package/dist/factory-assets/connectors/xstate-store.js +6 -6
  100. package/dist/factory-assets/connectors/xstate.js +6 -6
  101. package/dist/{flows-WELXQ7IG.js → flows-PNDUCOJR.js} +3 -3
  102. package/dist/{flows-WELXQ7IG.js.map → flows-PNDUCOJR.js.map} +1 -1
  103. package/dist/library/index.js +6 -6
  104. package/dist/library/install.js +3 -3
  105. package/dist/{open-library-362BZ6OW.js → open-library-COHFCT4N.js} +9 -9
  106. package/dist/{open-library-362BZ6OW.js.map → open-library-COHFCT4N.js.map} +1 -1
  107. package/dist/{paths-4SSFMX5Z.js → paths-2SYXGTZJ.js} +6 -6
  108. package/dist/{paths-4SSFMX5Z.js.map → paths-2SYXGTZJ.js.map} +1 -1
  109. package/dist/{plugin-store-2X2YXJVG.js → plugin-store-UNENLB56.js} +5 -5
  110. package/dist/{plugin-store-2X2YXJVG.js.map → plugin-store-UNENLB56.js.map} +1 -1
  111. package/dist/runner/index.js +8 -8
  112. package/dist/sdk/asset-manager.js +7 -7
  113. package/dist/sdk/core.js +3 -3
  114. package/dist/sdk/flow.js +3 -3
  115. package/dist/sdk/index.js +8 -8
  116. package/dist/sdk/runner.js +8 -8
  117. package/dist/{setup-VGZTFQ32.js → setup-AYH6SR4U.js} +5 -5
  118. package/dist/{setup-VGZTFQ32.js.map → setup-AYH6SR4U.js.map} +1 -1
  119. package/dist/{store-client-XFZFKY3W.js → store-client-U4FMAIWX.js} +6 -6
  120. package/dist/{store-client-XFZFKY3W.js.map → store-client-U4FMAIWX.js.map} +1 -1
  121. package/dist/tui/index.js +8 -8
  122. package/dist/types/manifests.js +1 -1
  123. package/dist/types/src/manifests/skill.d.ts +1 -0
  124. package/dist/types/src/manifests/skill.d.ts.map +1 -1
  125. package/dist/workspace-plugin/adapters/mcp.js +1 -1
  126. package/dist/workspace-plugin/adapters/omp.js +3 -3
  127. package/dist/workspace-plugin/index.js +1 -1
  128. package/package.json +1 -1
  129. package/dist/chunk-BLGHFVXE.js.map +0 -1
  130. package/dist/chunk-COSTF7QW.js.map +0 -1
  131. package/dist/chunk-FYLIR4AV.js.map +0 -1
  132. package/dist/chunk-L6BKSTAX.js.map +0 -1
  133. package/dist/chunk-LMRO2QNF.js.map +0 -1
  134. package/dist/chunk-RGPBEGP2.js.map +0 -1
  135. package/dist/chunk-VPXV2Z5E.js.map +0 -1
  136. package/dist/ensure-sources-NSDMTAWN.js.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../connectors/src/fs-utils.ts","../connectors/src/port-pool.ts","../connectors/src/watcher.ts","../connectors/src/rclone-process-manager.ts"],"names":["mkdir"],"mappings":"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","file":"chunk-FYLIR4AV.js","sourcesContent":["/**\n * Shared filesystem helpers for connector infrastructure.\n *\n * @docLink packages/connectors/api-reference#fs-utils\n */\n\nimport { chmod, mkdir } from \"node:fs/promises\";\nimport type { Logger } from \"@skaile/workspaces/types\";\n\n/**\n * mkdir(recursive) + chmod 0o770 in one call. The post-mkdir `chmod` is the\n * load-bearing piece: `mkdir(mode:)` is ANDed with the process umask\n * (typically 022 → effective mode 0o750), which strips the group-write bit\n * that `fusermount3` requires on the rclone mountpoint and rclone needs on\n * its vfs cache directory. Explicit `chmod` is umask-immune.\n *\n * EPERM on `chmod` is swallowed: when a foreign uid pre-created the\n * directory (a stray uid-1000 process inside the container or a host-side\n * platform process writing through the project bind-mount), the runner\n * cannot chmod it. The platform's agent container entrypoint runs as root\n * and heals the subtree on the next restart — see\n * `platform/docker/agent/entrypoint.sh` `_skaile_heal_ownership`. A debug\n * line is emitted when a logger is supplied so the rare-but-real heal\n * trigger is observable in session logs without adding noise on the happy\n * path.\n *\n * The chmod is *idempotent* (the syscall always fires, but a no-op when\n * the mode is already 0o770), not a no-op — kernel behaviour for chmod is\n * \"set\", not \"set-if-different\".\n *\n * @param dir Absolute or relative path to ensure exists at mode 0o770.\n * @param log Optional logger. When provided, EPERM-on-chmod emits a\n * `debug`-level entry under whatever taxonomy the caller's logger uses.\n */\nexport async function ensureDirMode(dir: string, log?: Logger): Promise<void> {\n await mkdir(dir, { recursive: true });\n try {\n await chmod(dir, 0o770);\n } catch (err) {\n log?.debug(\"chmod 0770 skipped (EPERM — entrypoint heal expected)\", {\n path: dir,\n error: err instanceof Error ? err.message : String(err),\n });\n }\n}\n","/**\n * PortPool — allocates ports from a [min, max] range, checks OS for collisions.\n */\n\nimport { createConnection } from \"node:net\";\n\n/**\n * Allocates TCP ports from a `[min, max]` range with OS-level collision detection.\n * Used by service connector adapters (devserver, static-server) to assign local ports.\n * @docLink packages/connectors/api-reference#port-pool\n */\nexport class PortPool {\n private readonly min: number;\n private readonly max: number;\n private readonly inUse = new Set<number>();\n\n constructor(range: [number, number]) {\n this.min = range[0];\n this.max = range[1];\n }\n\n /** Allocate the next free port from the range. Checks OS for collisions. */\n async allocate(): Promise<number> {\n for (let port = this.min; port <= this.max; port++) {\n if (this.inUse.has(port)) continue;\n if (!(await PortPool.isPortFree(port))) {\n this.inUse.add(port);\n continue;\n }\n this.inUse.add(port);\n return port;\n }\n throw new Error(`No free port in range ${this.min}-${this.max}`);\n }\n\n /** Mark a port as in-use (for explicit port args or registered instances). */\n reserve(port: number): void {\n this.inUse.add(port);\n }\n\n /** Return a port to the pool. */\n release(port: number): void {\n this.inUse.delete(port);\n }\n\n /** Check if a port is currently tracked as in-use. */\n isInUse(port: number): boolean {\n return this.inUse.has(port);\n }\n\n /** Quick TCP connect test — returns true if nothing is listening. */\n static isPortFree(port: number, host = \"127.0.0.1\"): Promise<boolean> {\n return new Promise((resolve) => {\n const socket = createConnection({ port, host });\n socket.once(\"connect\", () => {\n socket.destroy();\n resolve(false);\n });\n socket.once(\"error\", () => {\n socket.destroy();\n resolve(true);\n });\n socket.setTimeout(500, () => {\n socket.destroy();\n resolve(true);\n });\n });\n }\n}\n","/**\n * Shared filesystem watcher factory for mountable adapters.\n *\n * Uses chokidar for cross-platform, debounced file watching.\n *\n * Automatically reads .gitignore from the watched directory and merges\n * those patterns into chokidar's ignore list. This prevents scanning\n * large generated directories (node_modules, dist, .next, etc.) that\n * most projects already declare as ignored.\n */\n\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { join, relative } from \"node:path\";\nimport { createLogger } from \"@skaile/workspaces/core/logging\";\n// Static import so bun --compile bundles chokidar into the binary. A dynamic\n// `await import(\"chokidar\")` is not seen by the compiler's static analyzer\n// and fails at runtime inside the /$bunfs/ virtual filesystem.\nimport chokidar from \"chokidar\";\nimport type { ConnectorChangeEvent } from \"./connector-types.js\";\nimport type { WatchHandle, WatchOptions } from \"./shared-types.js\";\n\n/**\n * Convert a glob pattern to a matcher function.\n *\n * Chokidar 5 changed string matchers to exact equality (`===`) instead of\n * glob matching. We convert our patterns to functions so chokidar can still\n * filter correctly.\n */\nfunction globToMatcher(pattern: string): (path: string) => boolean {\n // Simple segment-name patterns: **/NAME/** or **/NAME\n // Match any path that contains /NAME/ or ends with /NAME\n const segmentMatch = pattern.match(/^\\*\\*\\/([^*/?]+)\\/\\*\\*$/);\n if (segmentMatch) {\n const name = segmentMatch[1];\n return (p: string) => p.includes(`/${name}/`) || p.endsWith(`/${name}`) || p === name;\n }\n\n // Dot-prefixed segment: **/.NAME or **/.NAME/**\n const dotSegment = pattern.match(/^\\*\\*\\/(\\.[\\w#]+)(?:\\/\\*\\*)?$/);\n if (dotSegment) {\n const name = dotSegment[1];\n return (p: string) => p.includes(`/${name}/`) || p.endsWith(`/${name}`) || p === name;\n }\n\n // Extension wildcard: **/*.EXT.* or **/*.EXT\n const extMatch = pattern.match(/^\\*\\*\\/\\*(\\.\\w+(?:\\.\\*)?)/);\n if (extMatch) {\n const suffix = extMatch[1];\n if (suffix.endsWith(\".*\")) {\n // e.g. **/*.tmp.* -> match any file with .tmp. in it\n const base = suffix.slice(0, -2);\n return (p: string) => p.includes(base);\n }\n return (p: string) => p.endsWith(suffix);\n }\n\n // Suffix wildcard: **/*SUFFIX (e.g. **/*~)\n const suffixMatch = pattern.match(/^\\*\\*\\/\\*(.+)$/);\n if (suffixMatch) {\n const sfx = suffixMatch[1];\n return (p: string) => p.endsWith(sfx);\n }\n\n // Fallback: convert simple globs to regex\n const escaped = pattern\n .replace(/[.+^${}()|[\\]\\\\]/g, \"\\\\$&\")\n .replace(/\\*\\*/g, \"{{GLOBSTAR}}\")\n .replace(/\\*/g, \"[^/]*\")\n .replace(/\\?/g, \"[^/]\")\n .replace(/\\{\\{GLOBSTAR\\}\\}/g, \".*\");\n const re = new RegExp(`^${escaped}$`);\n return (p: string) => re.test(p);\n}\n\nconst DEFAULT_IGNORED: Array<string | ((path: string) => boolean)> = [\n (p: string) => p.includes(\"/.git/\") || p.endsWith(\"/.git\"),\n (p: string) => p.includes(\"/node_modules/\") || p.endsWith(\"/node_modules\"),\n (p: string) => p.includes(\"/.connectors/\") || p.endsWith(\"/.connectors\"),\n // Atomic-write tempfiles (Bun.write creates `<name>.tmp.<pid>.<ts>` then renames).\n // These vanish between readdir and fs.watch, causing EINVAL that crashes the process.\n (p: string) => /\\.tmp\\.\\d/.test(p),\n // Editor swap/backup files that also race with save operations.\n (p: string) => p.endsWith(\".swp\"),\n (p: string) => p.endsWith(\".swx\"),\n (p: string) => p.includes(\"/.#\"),\n (p: string) => p.endsWith(\"~\"),\n];\n/**\n * Default chokidar `awaitWriteFinish` stability threshold (ms). Exported so the\n * rclone process manager can reuse the same write-stabilization concept when\n * gating a flush on a quiescent mount.\n */\nexport const DEFAULT_DEBOUNCE_MS = 150;\n\n/**\n * Parse a .gitignore file into glob patterns suitable for chokidar's `ignored` option.\n * Handles comments, blank lines, directory patterns, and root-relative patterns.\n * Negation patterns (!) are skipped - chokidar cannot un-ignore.\n */\nfunction parseGitignore(rootDir: string): Array<(path: string) => boolean> {\n const gitignorePath = join(rootDir, \".gitignore\");\n if (!existsSync(gitignorePath)) return [];\n\n try {\n const content = readFileSync(gitignorePath, \"utf-8\");\n const matchers: Array<(path: string) => boolean> = [];\n\n for (const raw of content.split(\"\\n\")) {\n const line = raw.trim();\n if (!line || line.startsWith(\"#\") || line.startsWith(\"!\")) continue;\n\n let pattern = line;\n\n // Strip leading / (root-relative -> convert to rootDir-relative)\n if (pattern.startsWith(\"/\")) {\n pattern = pattern.slice(1);\n } else if (!pattern.includes(\"/\")) {\n // Bare name like \"node_modules\" or \"*.log\" -> match anywhere\n pattern = `**/${pattern}`;\n }\n\n // Directory pattern (trailing /) -> ensure it matches contents too\n if (pattern.endsWith(\"/\")) {\n matchers.push(globToMatcher(`${pattern}**`));\n } else {\n matchers.push(globToMatcher(pattern));\n // Also match as directory (e.g. \"dist\" should match \"dist/\" and \"dist/**\")\n if (!pattern.includes(\"*\") && !pattern.includes(\".\")) {\n matchers.push(globToMatcher(`${pattern}/**`));\n }\n }\n }\n\n return matchers;\n } catch {\n return [];\n }\n}\n\ntype ChokidarAction = \"create\" | \"edit\" | \"delete\";\n\nconst CHOKIDAR_EVENT_MAP: Record<string, ChokidarAction> = {\n add: \"create\",\n change: \"edit\",\n unlink: \"delete\",\n addDir: \"create\",\n unlinkDir: \"delete\",\n};\n\n/**\n * Create a cross-platform filesystem watcher on `rootDir` using chokidar.\n * Auto-reads `.gitignore` from `rootDir` and merges those patterns into the ignore list.\n * @param rootDir - Absolute path to the directory to watch.\n * @param callback - Called with each `ConnectorChangeEvent` (create / edit / delete).\n * @param options - Debounce interval and additional ignore patterns.\n * @returns A `WatchHandle` — call `.close()` to stop watching.\n * @docLink packages/connectors/api-reference#create-fs-watcher\n */\nexport async function createFsWatcher(\n rootDir: string,\n callback: (event: ConnectorChangeEvent) => void,\n options?: WatchOptions,\n): Promise<WatchHandle> {\n const log = createLogger({ kind: \"connector\", subkind: \"watcher\", instance: rootDir });\n const gitignorePatterns = parseGitignore(rootDir);\n // Convert any remaining string patterns from options to matcher functions\n // (chokidar 5 treats strings as exact equality, not globs)\n const optionsIgnored = (options?.ignored ?? []).map((entry) =>\n typeof entry === \"string\" ? globToMatcher(entry) : entry,\n );\n const ignored = [...DEFAULT_IGNORED, ...gitignorePatterns, ...optionsIgnored];\n const debounceMs = options?.debounceMs ?? DEFAULT_DEBOUNCE_MS;\n\n const watcher = chokidar.watch(rootDir, {\n ignoreInitial: true,\n ignored,\n awaitWriteFinish: { stabilityThreshold: debounceMs, pollInterval: 50 },\n usePolling: false,\n });\n\n // Swallow transient watch errors (EINVAL/ENOENT when a file vanishes between\n // readdir and fs.watch). Without this handler, chokidar rethrows and the\n // agent process dies.\n watcher.on(\"error\", (err) => {\n const message = err instanceof Error ? err.message : String(err);\n log.warn(\"watcher error (non-fatal)\", { message });\n });\n\n for (const [chokidarEvent, action] of Object.entries(CHOKIDAR_EVENT_MAP)) {\n (watcher as { on(event: string, fn: (fullPath: string) => void): void }).on(\n chokidarEvent,\n (fullPath: string) => {\n const rel = relative(rootDir, fullPath);\n if (!rel || rel.startsWith(\"..\")) return;\n // Normalize to forward slashes\n const normalizedPath = rel.split(\"\\\\\").join(\"/\");\n callback({ path: normalizedPath, action, source: \"filesystem\" });\n },\n );\n }\n\n return {\n close: () => watcher.close(),\n };\n}\n","/**\n * RcloneProcessManager — supervises an rclone FUSE subprocess per mount.\n *\n * Responsibilities:\n * - Spawn rclone with a per-mount config + cache dir, wait for the FUSE\n * mountpoint to appear, then return a handle.\n * - Pipe rclone's JSON-formatted log lines into the parent driver's\n * {@link Logger} via a child source `${driverName}+rclone`.\n * - Coordinate graceful stop (flush → SIGTERM → fusermount fallback).\n * - Expose `flush` (POST /vfs/refresh + poll /vfs/stats), `statSize`\n * (operations/stat → authoritative remote size, backing the read-path\n * stale-tail gate) and `status` (process liveness + cache-dir size).\n *\n * Cross-link: see `workspaces/core/CLAUDE.md` § Logging for the\n * `createLogger` / `LogStore` contract, and\n * `_devlog/specs/2026-05-01-debug-logging-design.md` for the source taxonomy.\n */\n\nimport { type ChildProcess, spawn } from \"node:child_process\";\nimport { randomBytes } from \"node:crypto\";\nimport {\n cp,\n mkdir,\n readdir,\n readFile,\n rename,\n rm,\n stat,\n unlink,\n writeFile,\n} from \"node:fs/promises\";\nimport { tmpdir } from \"node:os\";\nimport path from \"node:path\";\nimport type { Readable } from \"node:stream\";\nimport type { Logger } from \"@skaile/workspaces/types\";\nimport { ensureDirMode } from \"./fs-utils.js\";\nimport { PortPool } from \"./port-pool.js\";\nimport { DEFAULT_DEBOUNCE_MS } from \"./watcher.js\";\n\n/** Module-level pool for rclone remote-control (rc) ports. */\nconst RCLONE_RC_PORTS = new PortPool([55000, 56000]);\n\n/** Default rclone `--vfs-write-back` delay; raised from 5s so a rapidly-rewritten file settles before upload (avoids mid-write \"sizes differ\" aborts). */\nexport const DEFAULT_VFS_WRITE_BACK = \"30s\";\n\n/** Consecutive failed upload retries for one object before a stuck-upload error is surfaced. */\nexport const DEFAULT_UPLOAD_STUCK_THRESHOLD = 3;\n\n/**\n * Stabilization gate defaults for {@link RcloneProcessManager.flush}. Before\n * forcing an upload we wait until the vfs cache dir has had no write for\n * `thresholdMs`, bounded by `timeoutMs` so close/hibernate never blocks\n * forever. `pollMs` reuses the watcher's write-stabilization debounce.\n */\nconst STABILIZE_THRESHOLD_MS = 1_500;\nconst STABILIZE_TIMEOUT_MS = 30_000;\nconst STABILIZE_POLL_MS = DEFAULT_DEBOUNCE_MS;\n\n/**\n * Spawn-time configuration for a single rclone FUSE mount.\n * @docLink packages/connectors/api-reference#rclone-spawn-config\n */\nexport interface RcloneSpawnConfig {\n /** Logical mount id; used as `instance` and as part of the rclone config filename. */\n mountId: string;\n /**\n * Driver name (e.g. \"sharepoint\", \"webdav\"); used to derive the rclone\n * subprocess child logger subkind: `${driverName}+rclone`.\n */\n driverName: string;\n /** Absolute path inside the container where rclone will FUSE-mount. Created if missing. */\n mountPoint: string;\n /** Absolute path inside the container for the vfs cache. Created if missing. */\n cacheDir: string;\n /** Full INI text for rclone.conf (one [remote] section, named `skaile-<mountId>`). */\n rcloneConfig: string;\n /** Remote spec, e.g. `skaile-foo:/Clients/KADK`. */\n remote: string;\n /** rclone --vfs-cache-mode value. */\n vfsCacheMode: \"minimal\" | \"writes\" | \"full\";\n /** Per-mount cache size cap. Default: '5G'. */\n cacheMaxSize?: string;\n /** Per-mount cache age cap. Default: '168h'. */\n cacheMaxAge?: string;\n /**\n * Skip rclone's post-transfer size + checksum verification by appending\n * `--ignore-size --ignore-checksum`. Default: false (verification on).\n *\n * Escape hatch for remotes that mutate uploaded bytes server-side (notably\n * SharePoint Online normalising LF→CRLF on text/html), which makes the\n * remote object a different size/hash than the local source. rclone reads\n * that as `corrupted on transfer`, deletes the upload, and retries forever,\n * so the file never durably lands. Enabling this trades integrity\n * verification for sync-ability and must only be set by drivers that have\n * confirmed the mutation is benign. Off-by-default; wired per-driver, never\n * globally.\n */\n ignoreSizeCheck?: boolean;\n /**\n * rclone `--vfs-write-back` delay (e.g. '30s', '1m'). Controls how long a\n * dirty file sits before rclone starts uploading it. Default:\n * {@link DEFAULT_VFS_WRITE_BACK}. Raise it when the agent rewrites files\n * faster than they upload, to avoid mid-write \"sizes differ\" aborts.\n */\n vfsWriteBack?: string;\n /**\n * Consecutive upload retries for one object before {@link onUploadStuck}\n * fires. Default: {@link DEFAULT_UPLOAD_STUCK_THRESHOLD}.\n */\n uploadStuckThreshold?: number;\n /**\n * Optional hook invoked once per object when its upload has failed\n * `uploadStuckThreshold` times in a row. spawn() always also logs an\n * error-level entry through the `${driverName}+rclone` child logger; this\n * hook lets callers surface the stranded file elsewhere (e.g. a sync event).\n */\n onUploadStuck?: (object: string, tries: number) => void;\n /**\n * Optional hook invoked when rclone reports an OAuth auth failure (notably\n * `invalid_client` / `couldn't fetch token`, the symptom of an expired\n * access token that rclone cannot self-refresh). Wired by the mount driver\n * to the reactive arm of its token-refresh controller. Fires per matching\n * log line; the controller dedupes via its in-flight guard + cooldown.\n */\n onAuthError?: () => void;\n /**\n * Parent driver Logger — already tagged\n * `{kind:\"mount\", subkind:<driver>, instance:<mountId>}` by ConnectorManager.\n * Used for manager-level events; rclone subprocess events go through the\n * derived `child({subkind: \\`${driverName}+rclone\\`})` logger.\n */\n log: Logger;\n}\n\n/**\n * Handle returned by `RcloneProcessManager.spawn()` once the FUSE mountpoint is confirmed.\n * @docLink packages/connectors/api-reference#rclone-handle\n */\nexport interface RcloneHandle {\n /** OS process id of the rclone subprocess. */\n pid: number;\n /** Confirmed FUSE mountpoint (echo of input). */\n mountPoint: string;\n /** Cache directory (echo of input). */\n cacheDir: string;\n /** The local rc API address rclone is bound to, e.g. '127.0.0.1:54321'. */\n rcAddr: string;\n}\n\ninterface InternalEntry {\n proc: ChildProcess;\n configPath: string;\n port: number;\n mountPoint: string;\n cacheDir: string;\n /** The full spawn config, retained so `reconfigure` can recycle the process. */\n spawnConfig: RcloneSpawnConfig;\n log: Logger;\n rcloneLog: Logger;\n /**\n * Last few stderr lines for diagnostic purposes (used in spawn-failure\n * messages).\n */\n recentStderr: string[];\n}\n\nconst HANDLES = new Map<number, InternalEntry>();\n\n/**\n * Manages rclone FUSE subprocesses for mount drivers. Stateless across instances —\n * the internal handle registry is module-scoped so a fresh `RcloneProcessManager`\n * can still find handles created by a previous instance.\n * @docLink packages/connectors/api-reference#rclone-process-manager\n */\nexport class RcloneProcessManager {\n /**\n * @param now Injectable clock (ms) used only to timestamp the quarantine dir\n * on a poisoned-cache reset, so the move-aside name is deterministic in tests.\n */\n constructor(private readonly now: () => number = Date.now) {}\n\n /**\n * Spawn an rclone FUSE mount with one-shot poisoned-cache recovery. Delegates\n * to {@link spawnOnce}; if that fails specifically because the persistent VFS\n * cache was poisoned (a prior container SIGKILLed mid-write left `vfs`/`vfsMeta`\n * referencing missing backing files), quarantine the cache and retry the mount\n * exactly once on a clean rebuild from the authoritative remote.\n *\n * The retry is single-shot and bounded: if the fresh-cache mount also fails the\n * cause is connectivity/token (not the cache), so the error propagates without\n * a second reset — never a reset/respawn loop. A non-poison failure, or a\n * poison failure with nothing to quarantine, propagates immediately.\n */\n async spawn(config: RcloneSpawnConfig): Promise<RcloneHandle> {\n try {\n return await this.spawnOnce(config);\n } catch (err) {\n if (!(err instanceof CachePoisonedMountError)) throw err;\n let quarantined: string | null;\n try {\n quarantined = await quarantineCacheDir(config.cacheDir, this.now());\n } catch (qErr) {\n // Quarantine itself failed (disk full, EPERM) — surface the ORIGINAL\n // mount error, not the quarantine error, so triage sees the real cause.\n config.log.warn(\"rclone vfs-cache quarantine failed — surfacing original mount error\", {\n cacheDir: config.cacheDir,\n error: qErr instanceof Error ? qErr.message : String(qErr),\n });\n throw err;\n }\n if (!quarantined) {\n // Nothing to quarantine — not actually a poisoned cache; rethrow.\n throw err;\n }\n config.log.warn(\n \"rclone mount failed on a poisoned vfs cache — quarantined it and retrying the mount once\",\n { cacheDir: config.cacheDir, quarantined },\n );\n // Single retry on the now-clean cache. If this also fails, propagate —\n // do NOT quarantine/retry again (the cause is no longer the cache).\n return await this.spawnOnce(config);\n }\n }\n\n /**\n * Spawn an rclone FUSE mount. Resolves once the mountpoint is confirmed\n * present in `/proc/self/mounts`. Throws on timeout, on early exit, or\n * if invariants are violated. A readiness-timeout accompanied by the\n * poisoned-cache log signature throws {@link CachePoisonedMountError} so the\n * public {@link spawn} can apply its quarantine-and-retry recovery.\n */\n protected async spawnOnce(config: RcloneSpawnConfig): Promise<RcloneHandle> {\n if (!path.isAbsolute(config.mountPoint)) {\n throw new Error(`mountPoint must be absolute: ${config.mountPoint}`);\n }\n if (!path.isAbsolute(config.cacheDir)) {\n throw new Error(`cacheDir must be absolute: ${config.cacheDir}`);\n }\n\n // Defence-in-depth: the per-connector driver already chmods these via\n // ensureDirMode, but direct callers that bypass the driver still need\n // mountPoint and cacheDir to be group-writable for fusermount3 / vfs.\n await ensureDirMode(config.mountPoint, config.log);\n await ensureDirMode(config.cacheDir, config.log);\n\n const configPath = path.join(\n tmpdir(),\n `rclone-${config.mountId}-${randomBytes(6).toString(\"hex\")}.conf`,\n );\n await writeFile(configPath, config.rcloneConfig, { mode: 0o600 });\n\n const port = await RCLONE_RC_PORTS.allocate();\n const rcAddr = `127.0.0.1:${port}`;\n const rcloneLog = config.log.child({ subkind: `${config.driverName}+rclone` });\n\n config.log.info(\"rclone spawn starting\", {\n mountPoint: config.mountPoint,\n remote: config.remote,\n vfsCacheMode: config.vfsCacheMode,\n });\n\n const args = _buildRcloneArgs(config, { configPath, rcAddr });\n\n const proc = spawn(\"rclone\", args, { stdio: [\"ignore\", \"pipe\", \"pipe\"] });\n\n // Per-process tracker for the upload-stuck observability gate. When an\n // object's upload retry count crosses the threshold we log once at error\n // level (the stream otherwise stays at INFO and the failure is silent).\n const routeCtx: RcloneLogRouteContext = {\n stuckThreshold: config.uploadStuckThreshold ?? DEFAULT_UPLOAD_STUCK_THRESHOLD,\n alertedObjects: new Set<string>(),\n itemNotFoundCounts: new Map<string, number>(),\n onUploadStuck: (object, tries) => {\n rcloneLog.error(\n \"rclone upload repeatedly failing — file may be stranded in this session's cache\",\n undefined,\n { object, tries, event: \"sync_status\", phase: \"error\" },\n );\n config.onUploadStuck?.(object, tries);\n },\n onAuthError: config.onAuthError,\n };\n\n const recentStderr: string[] = [];\n const stderrTail = (line: string) => {\n recentStderr.push(line);\n if (recentStderr.length > 20) recentStderr.shift();\n };\n\n // Set once if any rclone log line carries the poisoned-cache signature, so a\n // subsequent mount-readiness failure is classified as recoverable. Applied to\n // the RAW line so it matches whether rclone emits JSON or plaintext (the\n // signature is a substring of the JSON-encoded `msg` either way).\n let cachePoisonObserved = false;\n const noteCachePoison = (line: string) => {\n if (!cachePoisonObserved && _isCachePoisonLine(line)) cachePoisonObserved = true;\n };\n\n const stdoutHandler = (line: string) => {\n noteCachePoison(line);\n _routeRcloneLogLine(line, rcloneLog, routeCtx);\n };\n const stderrHandler = (line: string) => {\n stderrTail(line);\n noteCachePoison(line);\n _routeRcloneLogLine(line, rcloneLog, routeCtx);\n };\n\n if (proc.stdout) attachLineSplitter(proc.stdout, stdoutHandler);\n if (proc.stderr) attachLineSplitter(proc.stderr, stderrHandler);\n\n let earlyExitCode: number | null = null;\n let earlyExitSignal: NodeJS.Signals | null = null;\n const earlyExit = new Promise<void>((resolve) => {\n proc.once(\"exit\", (code, signal) => {\n earlyExitCode = code;\n earlyExitSignal = signal;\n resolve();\n });\n });\n\n const mountReady = waitFor(\n async () => {\n if (earlyExitCode !== null || earlyExitSignal !== null) return false;\n return await isMountpoint(config.mountPoint);\n },\n { timeoutMs: 15_000, intervalMs: 100 },\n );\n\n const ready = await Promise.race([mountReady, earlyExit.then(() => false)]);\n\n if (!ready) {\n try {\n if (proc.exitCode === null && proc.signalCode === null) {\n proc.kill(\"SIGKILL\");\n }\n } catch {\n // ignore\n }\n await unlink(configPath).catch(() => {});\n RCLONE_RC_PORTS.release(port);\n const tail =\n recentStderr.length > 0 ? `\\nstderr tail:\\n${recentStderr.slice(-5).join(\"\\n\")}` : \"\";\n const message = `rclone failed to mount ${config.remote} at ${config.mountPoint}${tail}`;\n // A poisoned cache is recoverable — signal spawn() to quarantine + retry.\n if (cachePoisonObserved) {\n throw new CachePoisonedMountError(message);\n }\n throw new Error(message);\n }\n\n const pid = proc.pid;\n if (pid === undefined) {\n // Should never happen if mountReady resolved true, but defend anyway.\n proc.kill(\"SIGKILL\");\n await unlink(configPath).catch(() => {});\n RCLONE_RC_PORTS.release(port);\n throw new Error(\"rclone process has no pid after successful mount\");\n }\n\n const entry: InternalEntry = {\n proc,\n configPath,\n port,\n mountPoint: config.mountPoint,\n cacheDir: config.cacheDir,\n spawnConfig: config,\n log: config.log,\n rcloneLog,\n recentStderr,\n };\n HANDLES.set(pid, entry);\n\n proc.on(\"exit\", (code) => {\n // If the entry is still in the registry, this was unplanned.\n if (HANDLES.has(pid)) {\n config.log.warn(\"rclone exited unexpectedly\", { code, pid });\n }\n });\n\n config.log.info(\"rclone mountpoint confirmed\", { pid });\n\n return { pid, mountPoint: config.mountPoint, cacheDir: config.cacheDir, rcAddr };\n }\n\n /**\n * Stop an rclone subprocess. Attempts a flush first, then SIGTERM, then\n * SIGKILL + fusermount3 if `graceMs` elapses without the mountpoint\n * disappearing.\n *\n * `graceMs` bounds both the flush stabilization gate and the SIGTERM→SIGKILL\n * window — it is *not* a single total wall-clock cap: the flush also waits on\n * rclone's `/vfs/stats` drain (its own 60s ceiling) between the two.\n */\n async stop(handle: RcloneHandle, opts?: { graceMs?: number }): Promise<void> {\n const graceMs = opts?.graceMs ?? 30_000;\n const entry = HANDLES.get(handle.pid);\n if (!entry) {\n return;\n }\n\n try {\n // Bound the stabilization gate by graceMs so stop() doesn't silently add\n // the full default stabilize timeout on top of the caller's budget.\n await this.flush(handle, { stabilizeTimeoutMs: graceMs });\n } catch (err) {\n entry.log.warn(\"rclone flush before stop failed\", {\n pid: handle.pid,\n error: err instanceof Error ? err.message : String(err),\n });\n }\n\n entry.log.info(\"rclone stop initiated\", { pid: handle.pid });\n\n // Remove FIRST so the exit handler doesn't fire the unplanned-exit warning.\n HANDLES.delete(handle.pid);\n\n try {\n entry.proc.kill(\"SIGTERM\");\n } catch {\n // ignore — process may already be gone\n }\n\n const unmounted = await waitFor(async () => !(await isMountpoint(entry.mountPoint)), {\n timeoutMs: graceMs,\n intervalMs: 200,\n });\n\n if (!unmounted) {\n try {\n entry.proc.kill(\"SIGKILL\");\n } catch {\n // ignore\n }\n await new Promise<void>((resolve) => {\n const fuse = spawn(\"fusermount3\", [\"-u\", entry.mountPoint], { stdio: \"ignore\" });\n fuse.once(\"exit\", () => resolve());\n fuse.once(\"error\", () => resolve());\n });\n entry.log.warn(\"rclone hard-killed\", { pid: handle.pid });\n }\n\n RCLONE_RC_PORTS.release(entry.port);\n await unlink(entry.configPath).catch(() => {});\n }\n\n /**\n * Apply a freshly-rendered rclone INI to a running mount by recycling the\n * process: flush + stop the current rclone, then re-spawn at the same\n * mountpoint/cacheDir with the new config. Returns the new handle.\n *\n * rclone holds the OAuth token in memory (baked into the config at spawn);\n * there is no rc command to swap it on a live `onedrive` backend, so a\n * recycle is the reliable way to apply a refreshed token. The vfs cache dir\n * is reused, so the remount revalidates rather than re-downloads. During the\n * brief unmount window the read-only mount-placeholder barrier underneath is\n * exposed (writes fail with EROFS, not EIO) — see ConnectorManager's\n * read-only-until-ready guarantee.\n */\n async reconfigure(handle: RcloneHandle, rcloneConfig: string): Promise<RcloneHandle> {\n const entry = HANDLES.get(handle.pid);\n if (!entry) {\n throw new Error(`rclone handle not found (pid=${handle.pid})`);\n }\n const nextConfig: RcloneSpawnConfig = { ...entry.spawnConfig, rcloneConfig };\n entry.log.info(\"rclone reconfigure — recycling process to apply refreshed credential\", {\n pid: handle.pid,\n });\n await this.stop(handle, { graceMs: 30_000 });\n return this.spawn(nextConfig);\n }\n\n /**\n * Force rclone to upload pending writes, then wait until the in-use\n * counter reaches zero.\n *\n * Before issuing the refresh it waits for the vfs cache dir to go quiescent\n * (no write for `stabilityThresholdMs`, bounded by `stabilizeTimeoutMs`) so a\n * close/hibernate-triggered flush doesn't snapshot a half-written file and\n * trigger rclone's mid-write \"sizes differ\" abort. Pass `stabilize: false`\n * to skip the gate.\n */\n async flush(\n handle: RcloneHandle,\n opts?: { stabilize?: boolean; stabilityThresholdMs?: number; stabilizeTimeoutMs?: number },\n ): Promise<void> {\n const entry = HANDLES.get(handle.pid);\n if (!entry) {\n throw new Error(`rclone handle not found (pid=${handle.pid})`);\n }\n\n if (opts?.stabilize !== false) {\n const thresholdMs = opts?.stabilityThresholdMs ?? STABILIZE_THRESHOLD_MS;\n const timeoutMs = opts?.stabilizeTimeoutMs ?? STABILIZE_TIMEOUT_MS;\n // Scan only the vfs content subtree (agent writes land here). The sibling\n // `vfsMeta/` tree is rclone housekeeping whose churn would never settle.\n const scanDir = await vfsContentDir(entry.cacheDir);\n const quiescent = await awaitQuiescent(scanDir, {\n thresholdMs,\n timeoutMs,\n pollMs: STABILIZE_POLL_MS,\n });\n if (!quiescent) {\n entry.log.warn(\"rclone cache did not stabilize before flush — proceeding anyway\", {\n pid: handle.pid,\n thresholdMs,\n timeoutMs,\n });\n }\n }\n\n const refreshRes = await fetch(`http://${handle.rcAddr}/vfs/refresh?recursive=true`, {\n method: \"POST\",\n });\n if (!refreshRes.ok) {\n const body = await refreshRes.text().catch(() => \"\");\n throw new Error(`rclone /vfs/refresh failed: ${refreshRes.status} ${body}`);\n }\n\n const ok = await waitFor(\n async () => {\n const r = await fetch(`http://${handle.rcAddr}/vfs/stats`, { method: \"GET\" });\n if (!r.ok) return false;\n const body = (await r.json()) as { inUse?: number; [k: string]: unknown };\n return body.inUse === 0;\n },\n { timeoutMs: 60_000, intervalMs: 500 },\n );\n if (!ok) {\n throw new Error(`rclone flush did not drain within 60s (pid=${handle.pid})`);\n }\n }\n\n /**\n * Authoritative remote byte size for a mount-relative path, via rclone's\n * `operations/stat` rc endpoint. Backs the mount read-path stale-tail gate:\n * `operations/stat` hits the backend object directly, so it returns the true\n * remote size even when the VFS cache is serving a non-truncated item (and\n * `statSync` on the FUSE mount reports the inflated length). Returns `null`\n * when the handle is unknown, the object is missing / a directory, or the\n * call fails — the caller then trusts the on-disk bytes.\n */\n async statSize(handle: RcloneHandle, relPath: string): Promise<number | null> {\n const entry = HANDLES.get(handle.pid);\n if (!entry) return null;\n return fetchAuthoritativeSize(handle.rcAddr, entry.spawnConfig.remote, relPath);\n }\n\n /** Liveness + cache-dir size. */\n async status(handle: RcloneHandle): Promise<{ alive: boolean; cacheBytes: number }> {\n const entry = HANDLES.get(handle.pid);\n if (!entry) {\n return { alive: false, cacheBytes: 0 };\n }\n const alive = entry.proc.exitCode === null && entry.proc.signalCode === null;\n const cacheBytes = await dirSize(entry.cacheDir);\n return { alive, cacheBytes };\n }\n}\n\ninterface RcloneJsonLine {\n level?: string;\n msg?: string;\n source?: string;\n time?: string;\n object?: string;\n error?: unknown;\n}\n\n/**\n * Per-process state threaded through {@link _routeRcloneLogLine} so it can\n * detect a sustained upload failure (the same object failing to upload K times\n * in a row) and surface it exactly once, instead of letting rclone retry\n * silently at INFO level forever.\n */\nexport interface RcloneLogRouteContext {\n /** Consecutive retries for one object before {@link onUploadStuck} fires. */\n stuckThreshold?: number;\n /** Objects already alerted on, to fire once and not on every later retry. */\n alertedObjects?: Set<string>;\n /** Per-object consecutive `itemNotFound` count; escalates at {@link stuckThreshold}. */\n itemNotFoundCounts?: Map<string, number>;\n /** Called the first time an object crosses {@link stuckThreshold}. */\n onUploadStuck?: (object: string, tries: number) => void;\n /** Called when a line matches an OAuth auth-failure pattern. */\n onAuthError?: () => void;\n}\n\n/** rclone's vfs write-back failure line: \"... failed to upload try #3, will retry ...\". */\nconst UPLOAD_FAIL_RE = /failed to upload.*?try #(\\d+)/i;\n/** rclone's vfs write-back success line, used to reset the per-object alert. */\nconst UPLOAD_OK_RE = /upload succeeded/i;\n/**\n * OAuth token-level failures rclone emits when the access token is expired and\n * it cannot self-refresh (the Skaile-managed-Entra `client_secret`-stripped\n * case). `invalid_client` / `couldn't fetch token` is the confirmed prod\n * symptom; the rest cover the equivalent MSAL/refresh-grant token failures.\n * Bare HTTP `401` is intentionally excluded — rclone retries many transient\n * 401s internally without needing a token refresh; only these token-level\n * failures mean rclone is stuck.\n */\nconst AUTH_FAIL_RE =\n /invalid_client|couldn'?t fetch token|invalid_grant|InvalidAuthenticationToken/i;\n/**\n * `itemNotFound` is the OneDrive/SharePoint Graph 404 on an upload target. It is\n * NOT necessarily permanent: a stale VFS dir-cache parent-id (a folder deleted\n * and recreated remotely) or OneDrive's new-folder indexing lag both surface as\n * itemNotFound yet clear once rclone re-lists the parent (a respawn rebuilds the\n * in-memory dir-cache from the remote). Escalating on the FIRST occurrence\n * misclassifies those transient 404s as \"remote gone\" and trips a premature\n * recycle/quarantine — confirmed on prod where the parent dir + driveId were\n * valid throughout. So treat it like any other upload failure: count consecutive\n * occurrences per object and surface only once it crosses the stuck threshold (a\n * genuinely-vanished target keeps failing and still escalates; quarantine-replay\n * is the safety net either way).\n */\nconst ITEM_NOT_FOUND_RE = /itemNotFound/i;\n\n/**\n * rclone's poisoned-VFS-cache signature. A container SIGKILLed mid-write leaves\n * the persistent `--vfs-cache-mode full` write-back cache (`vfs` + `vfsMeta`)\n * inconsistent — entries reference backing files that no longer exist. On the\n * next spawn rclone replays that backlog on every boot, fails to reload, and\n * never attaches the FUSE mountpoint (the readiness probe times out). The two\n * phrasings rclone emits are \"failed to reload item\" and \"failed to add virtual\n * dir entry\"; matching either flags the failure as cache-poisoning so spawn can\n * quarantine the cache and retry once on a clean rebuild from the remote.\n */\nconst CACHE_POISON_RE = /failed to reload item|failed to add virtual dir entry/i;\n\n/**\n * Thrown by {@link RcloneProcessManager.spawnOnce} when a mount-readiness\n * failure was accompanied by the {@link CACHE_POISON_RE} signature, so\n * {@link RcloneProcessManager.spawn} knows the failure is a recoverable\n * poisoned cache (quarantine + single retry) rather than a connectivity/token\n * fault. Its `message` is the full mount-failure detail (including the stderr\n * tail), so surfacing it directly when recovery declines loses no diagnostics.\n */\nexport class CachePoisonedMountError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"CachePoisonedMountError\";\n }\n}\n\n/**\n * @internal\n * True when an rclone log line carries the poisoned-VFS-cache signature\n * ({@link CACHE_POISON_RE}). Exported for tests; not part of the public API.\n */\nexport function _isCachePoisonLine(line: string): boolean {\n return CACHE_POISON_RE.test(line);\n}\n\n/**\n * Move a poisoned rclone VFS cache aside so the next spawn rebuilds a clean one\n * from the authoritative remote. Moves `<cacheDir>/vfs` + `<cacheDir>/vfsMeta`\n * (whichever exist) into `<cacheDir>/.corrupt-<ISO>` — a move-aside, never a\n * delete, so any (junk) un-uploaded bytes stay recoverable for forensics. The\n * quarantine dir is nested inside `cacheDir` (not a sibling) so it lives within\n * the per-session cache dir the platform removes wholesale on session close —\n * bounding its lifetime to the session — and rclone only reads its own\n * `vfs`/`vfsMeta` subdirs, so the dotted sibling is inert to the live mount.\n * (A bounded retain-N/reap-after-M GC of repeated resets within one long-lived\n * session is a follow-up; session-close cleanup covers the common case.)\n *\n * Returns the quarantine dir path when anything was moved, else `null` (nothing\n * to quarantine — the failure was not a poisoned cache). `nowMs` is injected for\n * deterministic test timestamps. Exported for tests; not part of the public API.\n */\nexport async function quarantineCacheDir(cacheDir: string, nowMs: number): Promise<string | null> {\n const stamp = new Date(nowMs).toISOString().replace(/[:.]/g, \"-\");\n const quarantineDir = path.join(cacheDir, `.corrupt-${stamp}`);\n // Create the destination parent BEFORE any rename so an ENOENT from rename\n // unambiguously means \"src is missing\" (not \"dst dir absent\"). An empty dir\n // (nothing moved) is cleaned up below.\n await mkdir(quarantineDir, { recursive: true });\n let moved = 0;\n for (const sub of [\"vfs\", \"vfsMeta\"] as const) {\n const src = path.join(cacheDir, sub);\n const dst = path.join(quarantineDir, sub);\n try {\n await rename(src, dst);\n } catch (err) {\n const code = (err as { code?: string } | null)?.code;\n if (code === \"ENOENT\") continue; // this cache sub doesn't exist — skip\n if (code === \"EXDEV\") {\n // Cross-device rename — fall back to copy + rm. Clean up a partial dst if\n // the copy fails, so a retry never sees a half-written quarantine (and\n // src stays put → move-aside semantics hold).\n try {\n await cp(src, dst, { recursive: true });\n } catch (cpErr) {\n await rm(dst, { recursive: true, force: true }).catch(() => undefined);\n throw cpErr;\n }\n await rm(src, { recursive: true, force: true });\n } else {\n throw err;\n }\n }\n moved += 1;\n }\n if (moved === 0) {\n // No cache subdir existed — drop the empty quarantine dir we made.\n await rm(quarantineDir, { recursive: true, force: true }).catch(() => undefined);\n return null;\n }\n return quarantineDir;\n}\n\n/**\n * @internal\n * Route a single rclone log line (JSON or raw) to the appropriate Logger\n * call. Exported for tests; not part of the public API. When `ctx` is\n * supplied, also tracks consecutive upload failures per object and invokes\n * `ctx.onUploadStuck` once the retry count for an object reaches the threshold.\n */\nexport function _routeRcloneLogLine(line: string, log: Logger, ctx?: RcloneLogRouteContext): void {\n const trimmed = line.trim();\n if (trimmed.length === 0) return;\n\n let parsed: RcloneJsonLine | null = null;\n try {\n const candidate = JSON.parse(trimmed);\n if (candidate && typeof candidate === \"object\") parsed = candidate as RcloneJsonLine;\n } catch {\n parsed = null;\n }\n\n if (!parsed) {\n if (ctx) {\n _trackUploadFailure(trimmed, undefined, ctx);\n if (AUTH_FAIL_RE.test(trimmed)) ctx.onAuthError?.();\n if (ITEM_NOT_FOUND_RE.test(trimmed)) _trackItemNotFound(undefined, trimmed, ctx);\n }\n log.info(trimmed);\n return;\n }\n\n const level = (parsed.level ?? \"INFO\").toUpperCase();\n const msg = parsed.msg ?? \"\";\n const data: Record<string, unknown> = {};\n if (parsed.object !== undefined) data.object = parsed.object;\n if (parsed.source !== undefined) data.source = parsed.source;\n\n if (ctx) {\n _trackUploadFailure(msg, parsed.object, ctx);\n const errText = typeof parsed.error === \"string\" ? parsed.error : \"\";\n if (AUTH_FAIL_RE.test(msg) || (errText && AUTH_FAIL_RE.test(errText))) ctx.onAuthError?.();\n if (ITEM_NOT_FOUND_RE.test(msg) || (errText && ITEM_NOT_FOUND_RE.test(errText))) {\n _trackItemNotFound(parsed.object, msg, ctx);\n }\n }\n\n switch (level) {\n case \"DEBUG\":\n log.debug(msg, data);\n break;\n case \"INFO\":\n case \"NOTICE\":\n log.info(msg, data);\n break;\n case \"WARNING\":\n log.warn(msg, data);\n break;\n case \"ERROR\":\n case \"CRITICAL\":\n case \"EMERGENCY\":\n case \"ALERT\":\n log.error(msg, parsed.error, data);\n break;\n default:\n log.info(msg, data);\n break;\n }\n}\n\n/**\n * @internal\n * Inspect one rclone message for an upload retry / success and update the\n * per-object alert state in `ctx`. Fires `onUploadStuck` once when an object's\n * retry count first reaches the threshold; a later success clears the alert so\n * a fresh failure run can re-trigger.\n */\nfunction _trackUploadFailure(\n msg: string,\n object: string | undefined,\n ctx: RcloneLogRouteContext,\n): void {\n const failMatch = UPLOAD_FAIL_RE.exec(msg);\n if (failMatch) {\n const tries = Number(failMatch[1]);\n const key = object ?? extractObjectFromMsg(msg) ?? \"(unknown)\";\n const threshold = ctx.stuckThreshold ?? DEFAULT_UPLOAD_STUCK_THRESHOLD;\n if (!ctx.alertedObjects) ctx.alertedObjects = new Set<string>();\n const alerted = ctx.alertedObjects;\n if (tries >= threshold && !alerted.has(key)) {\n alerted.add(key);\n ctx.onUploadStuck?.(key, tries);\n }\n return;\n }\n if (UPLOAD_OK_RE.test(msg)) {\n const key = object ?? extractObjectFromMsg(msg);\n if (key) {\n ctx.alertedObjects?.delete(key);\n ctx.itemNotFoundCounts?.delete(key);\n }\n }\n}\n\n/**\n * @internal\n * Track consecutive `itemNotFound` upload failures per object and surface via\n * `onUploadStuck` only once an object crosses the stuck threshold — the same gate\n * the retry-count path uses — rather than on the first occurrence, because\n * itemNotFound is often transient (see {@link ITEM_NOT_FOUND_RE}). A later upload\n * success clears the count (in {@link _trackUploadFailure}). Deduped against\n * `alertedObjects` so it fires at most once per stuck run, and shares that set\n * with the retry tracker so the two paths can't double-fire for one object.\n */\nfunction _trackItemNotFound(\n object: string | undefined,\n msg: string,\n ctx: RcloneLogRouteContext,\n): void {\n const key = object ?? extractObjectFromMsg(msg) ?? \"(unknown)\";\n if (!ctx.itemNotFoundCounts) ctx.itemNotFoundCounts = new Map<string, number>();\n if (!ctx.alertedObjects) ctx.alertedObjects = new Set<string>();\n const count = (ctx.itemNotFoundCounts.get(key) ?? 0) + 1;\n ctx.itemNotFoundCounts.set(key, count);\n const threshold = ctx.stuckThreshold ?? DEFAULT_UPLOAD_STUCK_THRESHOLD;\n if (count >= threshold && !ctx.alertedObjects.has(key)) {\n ctx.alertedObjects.add(key);\n ctx.onUploadStuck?.(key, count);\n }\n}\n\n/** Best-effort path extraction from a free-text rclone message. */\nfunction extractObjectFromMsg(msg: string): string | undefined {\n const m = /(?:^|\\s)([^\\s:]+\\/[^\\s:]+):/.exec(msg);\n return m?.[1];\n}\n\n/**\n * @internal\n * Build the `rclone mount` argv from a spawn config. Extracted from spawn() so\n * the flag wiring (notably `--vfs-write-back` and the conditional\n * `--ignore-size --ignore-checksum`) is unit-testable without actually\n * launching rclone. Exported for tests; not part of the public API.\n */\nexport function _buildRcloneArgs(\n config: RcloneSpawnConfig,\n io: { configPath: string; rcAddr: string },\n): string[] {\n const args = [\n \"mount\",\n config.remote,\n config.mountPoint,\n \"--config\",\n io.configPath,\n \"--cache-dir\",\n config.cacheDir,\n \"--vfs-cache-mode\",\n config.vfsCacheMode,\n \"--vfs-cache-max-size\",\n config.cacheMaxSize ?? \"5G\",\n \"--vfs-cache-max-age\",\n config.cacheMaxAge ?? \"168h\",\n \"--vfs-write-back\",\n config.vfsWriteBack ?? DEFAULT_VFS_WRITE_BACK,\n \"--vfs-cache-poll-interval\",\n \"60s\",\n \"--rc\",\n \"--rc-addr\",\n io.rcAddr,\n // loopback-only rc server — without no-auth, flush's POST /vfs/refresh 403s,\n // graceful stop fails, and the write-back cache is left dirty. Safe: nothing\n // external can reach 127.0.0.1:<port>.\n \"--rc-no-auth\",\n \"--log-level\",\n \"INFO\",\n \"--use-json-log\",\n \"--allow-other\",\n // The ro-tmpfs deferred-mount barrier is already mounted here; without this\n // rclone aborts with \"directory already mounted\". See mount-placeholder.ts.\n \"--allow-non-empty\",\n ];\n\n // Remotes that rewrite bytes on upload (SharePoint LF→CRLF) make the\n // post-transfer size/hash check fail and rclone rolls the upload back\n // forever. Both flags are needed: a byte change shifts size AND checksum.\n if (config.ignoreSizeCheck) {\n args.push(\"--ignore-size\", \"--ignore-checksum\");\n }\n\n return args;\n}\n\n/**\n * @internal\n * Split an rclone mount `remote` (`skaile-<id>:/base/path`) plus a\n * mount-relative path into the `{fs, remote}` pair rclone's `operations/stat`\n * rc command expects: `fs` is the backend root (`skaile-<id>:`) and `remote` is\n * the object path within it. Leading/trailing slashes are normalised away so\n * the join is stable regardless of how either side is slashed. Exported for\n * tests; not part of the public API.\n */\nexport function _operationsStatTarget(\n remote: string,\n relPath: string,\n): { fs: string; remote: string } {\n const colon = remote.indexOf(\":\");\n const fs = colon >= 0 ? remote.slice(0, colon + 1) : remote;\n const base = colon >= 0 ? remote.slice(colon + 1) : \"\";\n const joined = [base, relPath]\n .map((s) => s.replace(/^\\/+|\\/+$/g, \"\"))\n .filter((s) => s.length > 0)\n .join(\"/\");\n return { fs, remote: joined };\n}\n\n/**\n * Query rclone's `operations/stat` rc endpoint for the authoritative remote\n * size of `relPath` under `remote`. Returns the byte size, or `null` when the\n * object is missing, is a directory, the call fails, or the size is absent.\n *\n * Unlike a `statSync` on the FUSE mount, `operations/stat` resolves the object\n * against the backend directly, so it is not subject to the VFS cache's\n * non-truncated stale tail. Pass `fetchImpl` to test without a live rc server.\n */\nexport async function fetchAuthoritativeSize(\n rcAddr: string,\n remote: string,\n relPath: string,\n fetchImpl: typeof fetch = fetch,\n): Promise<number | null> {\n const target = _operationsStatTarget(remote, relPath);\n try {\n const res = await fetchImpl(`http://${rcAddr}/operations/stat`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify(target),\n });\n if (!res.ok) return null;\n const body = (await res.json()) as { item?: { Size?: number; IsDir?: boolean } | null };\n const item = body.item;\n if (!item || item.IsDir === true) return null;\n return typeof item.Size === \"number\" && item.Size >= 0 ? item.Size : null;\n } catch {\n return null;\n }\n}\n\n/**\n * Poll `dir` until its newest file mtime is at least `thresholdMs` in the past\n * (no write for that long), or `timeoutMs` elapses. Returns true if it went\n * quiescent, false on timeout. An empty/missing dir counts as quiescent.\n */\nexport async function awaitQuiescent(\n dir: string,\n opts: { thresholdMs: number; timeoutMs: number; pollMs: number },\n): Promise<boolean> {\n const deadline = Date.now() + opts.timeoutMs;\n for (;;) {\n const newest = await newestMtimeMs(dir);\n if (newest === null || Date.now() - newest >= opts.thresholdMs) return true;\n if (Date.now() >= deadline) return false;\n await sleep(opts.pollMs);\n }\n}\n\n/**\n * Resolve the rclone vfs content subtree (`<cacheDir>/vfs`) where cached file\n * data — and therefore agent writes — land, falling back to `cacheDir` itself\n * if that subtree doesn't exist yet. Keeps the stabilization gate off rclone's\n * `vfsMeta/` housekeeping tree.\n */\nasync function vfsContentDir(cacheDir: string): Promise<string> {\n const vfs = path.join(cacheDir, \"vfs\");\n try {\n return (await stat(vfs)).isDirectory() ? vfs : cacheDir;\n } catch {\n return cacheDir;\n }\n}\n\n/**\n * Recursively find the most recent file mtime (ms) under `dir`. Returns null if\n * the dir is missing or contains no files. Symlinks are skipped — rclone's\n * cache holds only regular files and dirs.\n */\nasync function newestMtimeMs(dir: string): Promise<number | null> {\n let newest: number | null = null;\n try {\n const entries = await readdir(dir, { withFileTypes: true });\n for (const e of entries) {\n const full = path.join(dir, String(e.name));\n if (e.isDirectory()) {\n const sub = await newestMtimeMs(full);\n if (sub !== null && (newest === null || sub > newest)) newest = sub;\n } else if (e.isFile()) {\n try {\n const s = await stat(full);\n if (newest === null || s.mtimeMs > newest) newest = s.mtimeMs;\n } catch {\n // ignore — file vanished between readdir and stat\n }\n }\n }\n } catch {\n return null;\n }\n return newest;\n}\n\n/**\n * @internal\n * Returns true if a FUSE mount is present at `mountPoint` in the given\n * /proc/self/mounts text. The fstype check (field 3, `fuse.*`) is essential:\n * the deferred-mount barrier leaves a `tmpfs` mounted at the same path, so a\n * path-only match would report the *barrier* as the confirmed mount and mask a\n * dead rclone process. Exported for tests; not part of the public API.\n */\nexport function _fuseMountPresent(procMountsText: string, mountPoint: string): boolean {\n const resolved = path.resolve(mountPoint);\n for (const raw of procMountsText.split(\"\\n\")) {\n if (raw.length === 0) continue;\n const fields = raw.split(/\\s+/);\n const mp = fields[1];\n const fstype = fields[2];\n if (!mp || !fstype) continue;\n // /proc/self/mounts encodes spaces as \\040; cheap decode.\n const decoded = mp.replace(/\\\\040/g, \" \");\n // User-space FUSE only (`fuse` or `fuse.<subtype>`); excludes the `fusectl`\n // kernel control fs. rclone mounts as `fuse.rclone`.\n if (decoded === resolved && (fstype === \"fuse\" || fstype.startsWith(\"fuse.\"))) return true;\n }\n return false;\n}\n\n/** Returns true if a FUSE mount (rclone) is live at `mountPoint`. */\nasync function isMountpoint(mountPoint: string): Promise<boolean> {\n try {\n const text = await readFile(\"/proc/self/mounts\", \"utf8\");\n return _fuseMountPresent(text, mountPoint);\n } catch {\n return false;\n }\n}\n\n/**\n * Poll `check` every `intervalMs` until it returns true or `timeoutMs`\n * elapses. Returns true on success, false on timeout.\n */\nasync function waitFor(\n check: () => Promise<boolean>,\n opts: { timeoutMs: number; intervalMs: number },\n): Promise<boolean> {\n const deadline = Date.now() + opts.timeoutMs;\n while (Date.now() < deadline) {\n if (await check()) return true;\n await sleep(opts.intervalMs);\n }\n return await check();\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => {\n setTimeout(resolve, ms);\n });\n}\n\n/** Wire a Readable to a per-line callback, buffering partial chunks. */\nfunction attachLineSplitter(stream: Readable, onLine: (line: string) => void): void {\n let buffer = \"\";\n stream.setEncoding(\"utf8\");\n stream.on(\"data\", (chunk: string) => {\n buffer += chunk;\n let idx = buffer.indexOf(\"\\n\");\n while (idx >= 0) {\n const line = buffer.slice(0, idx);\n buffer = buffer.slice(idx + 1);\n if (line.length > 0) onLine(line);\n idx = buffer.indexOf(\"\\n\");\n }\n });\n stream.on(\"end\", () => {\n if (buffer.length > 0) {\n onLine(buffer);\n buffer = \"\";\n }\n });\n}\n\n/** Recursively sum file sizes under `dir`. Returns 0 if dir does not exist. */\nasync function dirSize(dir: string): Promise<number> {\n let total = 0;\n try {\n const entries = await readdir(dir, { withFileTypes: true });\n for (const e of entries) {\n const full = path.join(dir, String(e.name));\n if (e.isDirectory()) {\n total += await dirSize(full);\n } else if (e.isFile()) {\n try {\n const s = await stat(full);\n total += s.size;\n } catch {\n // ignore\n }\n }\n }\n } catch {\n return 0;\n }\n return total;\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../asset-manager/src/index.ts"],"names":["parseYaml","stringifyYaml"],"mappings":"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","file":"chunk-L6BKSTAX.js","sourcesContent":["/**\n * @skaile/asset-manager — programmatic AI asset management API.\n *\n * Manages project-local repositories, dependency resolution, deployment,\n * lock files, patches, and contribution workflows.\n *\n * Usage:\n * import { AssetManager } from \"@skaile/workspaces/asset-manager\"\n * const am = new AssetManager({ projectDir: \"/path/to/project\" })\n * await am.install()\n */\n\nimport { spawnSync } from \"node:child_process\";\nimport {\n existsSync,\n lstatSync,\n readdirSync,\n readFileSync,\n rmSync,\n unlinkSync,\n writeFileSync,\n} from \"node:fs\";\nimport { dirname, join, resolve, sep } from \"node:path\";\nimport type {\n AiComponent,\n CatalogEntry,\n DriverTarget,\n LockFile,\n OverrideEntry,\n ProvenanceCandidate,\n SkWorkspaceConfig,\n SourceClone,\n SourceDeclaration,\n SourceEntry,\n StoreEntry,\n StoreFetcher,\n} from \"@skaile/workspaces/core\";\nimport {\n buildLockFile,\n buildProvenanceIndex,\n checkRepoStatus,\n applyPatch as coreApplyPatch,\n deployedBase,\n deployedDir,\n ensureRepo,\n extractForPatch,\n factoryAssetRoots,\n generatePatch,\n getGlobalCacheDir,\n getRepoCommit,\n isDeployed,\n migrateLegacyDir,\n parseAssetRef,\n readLinks,\n readLock,\n resolveAll,\n resolveAsset,\n resolveRuntimeAssets,\n resolveSkWorkspaceConfig,\n savePatch,\n scanRepo,\n SKAILE_YAML_DEFAULT,\n verifyLock,\n writeLock,\n} from \"@skaile/workspaces/core\";\nimport type { ResolveResult } from \"@skaile/workspaces/core\";\nimport type { AssetFetcher } from \"@skaile/workspaces/library\";\nimport type { InstallManifest } from \"@skaile/workspaces/types\";\nimport { parse as parseYaml, stringify as stringifyYaml } from \"yaml\";\nimport { commitChanges } from \"./contrib.js\";\nimport type { HistoryEntry } from \"./history.js\";\nimport { appendHistory, clearHistory, getRecentHistory } from \"./history.js\";\nimport type { DeployOptions } from \"./installer.js\";\nimport { createScaffold, deployAll, removeAsset } from \"./installer.js\";\n\n/** Derive a cache slug from a source git URL (`<host>/<owner>/<repo>` → `<repo>`). */\nfunction sourceSlug(url: string): string {\n return (\n url\n .replace(/\\.git$/, \"\")\n .split(/[/:]/)\n .pop() ?? \"source\"\n );\n}\n\n/**\n * Normalize a git remote URL to a comparable identity so the same repo declared\n * in different syntaxes (`https://…`, `git@host:…`, trailing `/`, `.git` suffix,\n * case) compares equal. Used to dedupe the implicit factory source against an\n * explicit user declaration.\n */\nfunction normalizeRepoUrl(url: string): string {\n return url\n .trim()\n .replace(/^git@([^:]+):/, \"https://$1/\") // git@host:org/repo → https://host/org/repo\n .replace(/^[a-z]+:\\/\\//i, \"\") // drop scheme\n .replace(/\\.git$/i, \"\")\n .replace(/\\/+$/, \"\")\n .toLowerCase();\n}\n\n/** Primary manifest filename for each asset kind (the deploy entry point). */\nconst MD_BY_KIND: Record<string, string> = {\n skill: \"SKILL.md\",\n agent: \"AGENT.md\",\n bundle: \"BUNDLE.md\",\n \"mcp-server\": \"MCP.md\",\n connector: \"CONNECTOR.md\",\n prompt: \"PROMPT.md\",\n contract: \"CONTRACT.md\",\n};\n\n/**\n * Pick a candidate's primary manifest file from its `files[]`. Fixed-name kinds\n * (skill/agent/contract/…) match their `MD_BY_KIND` basename; `prompt` and\n * `flow` use their `<name>.prompt.md` / `<name>.flow.{yaml,json}` suffixes\n * (these have no fixed basename, so an exact-name match alone would miss them).\n */\nfunction matchManifestPath(kind: string, paths: readonly string[]): string | undefined {\n const exact = MD_BY_KIND[kind];\n if (exact) {\n const hit = paths.find((p) => p.endsWith(exact));\n if (hit) return hit;\n }\n if (kind === \"prompt\") return paths.find((p) => p.endsWith(\".prompt.md\"));\n if (kind === \"flow\") {\n return paths.find((p) => p.endsWith(\".flow.yaml\") || p.endsWith(\".flow.json\"));\n }\n return undefined;\n}\n\n/**\n * Asset kinds that are never deployed to a driver target as files — bundles\n * resolve to their members, mcp-servers are wired at session startup, and the\n * mixin kinds are resolved at session creation. Store bytes are not staged for\n * these (mirrors the skip set in `deployAll`).\n */\nexport const NON_DEPLOYABLE_KINDS = new Set([\n \"bundle\",\n \"mcp-server\",\n \"persona\",\n \"ruleset\",\n \"knowledge\",\n]);\n\n/**\n * Longest common leading directory prefix across `paths` (slash-joined, no\n * trailing slash). Mirrors the prefix-strip `installFromManifest` flat mode\n * applies, so a staged asset's manifest can be located deterministically.\n */\nfunction commonDirPrefix(paths: readonly string[]): string {\n if (paths.length === 0) return \"\";\n const dirs = paths.map((p) => p.split(\"/\").slice(0, -1));\n let common = dirs[0]!;\n for (let i = 1; i < dirs.length && common.length > 0; i++) {\n const segs = dirs[i]!;\n let n = 0;\n while (n < common.length && n < segs.length && common[n] === segs[n]) n++;\n common = common.slice(0, n);\n }\n return common.join(\"/\");\n}\n\n/**\n * Index lock entries by their `<kind>:<name>` suffix for deployed-asset lookup.\n * Only entries whose canonical key fully parses (kind, name, publisher, version)\n * are included.\n */\nfunction indexLockByKindName(\n lock: LockFile | null,\n): Map<string, { publisher: string; version: string; url: string }> {\n const lockByKindName = new Map<string, { publisher: string; version: string; url: string }>();\n for (const [key] of Object.entries(lock?.assets ?? {})) {\n const parsed = parseCanonicalLockKey(key);\n if (parsed.kind && parsed.name && parsed.publisher && parsed.version) {\n lockByKindName.set(`${parsed.kind}:${parsed.name}`, {\n publisher: parsed.publisher,\n version: parsed.version,\n url: lock!.assets[key]!.source.url,\n });\n }\n }\n return lockByKindName;\n}\n\n/** Derive an asset's sync status from its repository's live status. */\nfunction computeSyncStatus(repoStatus: RepoStatusInfo | undefined): string {\n if (!repoStatus) return \"unknown\";\n if (repoStatus.kind === \"local\") return \"local\";\n if (repoStatus.error) return \"error\";\n if (repoStatus.upToDate) return \"synced\";\n return \"outdated\";\n}\n\n/**\n * Group overview entries by domain, sort domains alphabetically, and sort\n * entries within each domain by kind then name.\n */\nfunction groupAndSortByDomain(entries: OverviewEntry[]): Map<string, OverviewEntry[]> {\n const byDomain = new Map<string, OverviewEntry[]>();\n for (const e of entries) {\n if (!byDomain.has(e.domain)) byDomain.set(e.domain, []);\n byDomain.get(e.domain)!.push(e);\n }\n\n const sorted = new Map<string, OverviewEntry[]>();\n for (const key of [...byDomain.keys()].sort()) {\n sorted.set(\n key,\n byDomain\n .get(key)!\n .sort((a, b) =>\n a.kind !== b.kind ? a.kind.localeCompare(b.kind) : a.name.localeCompare(b.name),\n ),\n );\n }\n return sorted;\n}\n\n/**\n * Parse a canonical lock key (`<kind>:@<publisher>/<name>#<version>`) into its\n * parts. The lock key is now a canonical asset ref, so this delegates to the one\n * ref parser; `AssetRef.pin` is exposed as `version` so the callers' destructuring\n * is unchanged. Stays total — callers rely on `{}`-then-`continue`, but\n * `parseAssetRef` throws, so a malformed key is caught and returned as `{}`.\n *\n * @internal Exported for unit tests; not part of the stable public surface.\n */\nexport function parseCanonicalLockKey(key: string): {\n publisher?: string;\n kind?: string;\n name?: string;\n version?: string;\n} {\n try {\n const ref = parseAssetRef(key);\n return {\n publisher: ref.publisher,\n kind: ref.kind,\n name: ref.name,\n version: ref.pin,\n };\n } catch {\n return {};\n }\n}\n\n/**\n * Reconciliation state of a declared dependency relative to the lock + disk.\n * `invalid` flags a `dependencies:` entry that isn't a parseable canonical ref —\n * surfaced (not silently dropped) so a `skaile.yaml` typo is visible.\n */\nexport type DeclaredState = \"declared\" | \"installed\" | \"drift\" | \"invalid\";\n\n/**\n * A top-level dependency declared in `skaile.yaml`, annotated with its\n * reconciliation {@link DeclaredState}. Transitive (lock-only) deps are never\n * included — {@link AssetManager.listDeclared} walks the declared set only.\n */\nexport interface DeclaredAsset {\n /** The canonical declared ref exactly as written in `skaile.yaml`. */\n ref: string;\n kind: string;\n name: string;\n state: DeclaredState;\n}\n\n/**\n * Thrown by {@link AssetManager.listDeclared} when the project has no\n * `skaile.yaml`. The CLI maps this to a `skaile init` hint.\n */\nexport class MissingManifestError extends Error {\n constructor(readonly projectDir: string) {\n super(`No skaile.yaml in ${projectDir}.`);\n this.name = \"MissingManifestError\";\n }\n}\n\nexport type { HistoryEntry } from \"./history.js\";\nexport {\n appendHistory,\n clearHistory,\n getRecentHistory,\n loadHistory,\n} from \"./history.js\";\n// Re-export sub-modules\nexport type { DeployOptions } from \"./installer.js\";\nexport { createScaffold, deployAll, removeAsset } from \"./installer.js\";\nexport type { Log } from \"./renderers.js\";\nexport { renderAgentToFramework } from \"./renderers.js\";\n// Contrib helpers (commitChanges et al.) are still used internally by the\n// patch-submit flow but are no longer part of the public API surface — the\n// `skaile repo contrib *` command tree was removed on 2026-05-12.\n\n// ── Types ────────────────────────────────────────────────────────────────────\n\n/**\n * Metadata about a repository declared in `skaile.yaml`.\n *\n * @docLink packages/asset-manager/concepts#asset-manager\n */\nexport interface RepoInfo {\n /** Repository name as declared in `skaile.yaml`. */\n name: string;\n /** How the repo is sourced: cloned from a URL, mounted from a local path, or symlinked via `skaile repo link`. */\n kind: \"local\" | \"remote\" | \"linked\";\n /** Remote URL (present when `kind === \"remote\"`). */\n url?: string;\n /** Filesystem path (present when `kind === \"local\"` or `kind === \"linked\"`). */\n path?: string;\n /** Git branch configured for this repository. */\n branch: string;\n /** Whether the repository has been cloned/resolved locally. */\n cloned: boolean;\n}\n\n/**\n * Live sync status for a repository.\n *\n * @docLink packages/asset-manager/concepts#asset-manager\n */\nexport interface RepoStatusInfo {\n /** Repository name as declared in `skaile.yaml`. */\n name: string;\n /** How the repo is sourced. */\n kind: \"local\" | \"remote\" | \"linked\";\n /** Number of commits the local clone is behind the remote. */\n behind: number;\n /** `true` when the local clone matches the remote HEAD. */\n upToDate: boolean;\n /** Error message when status check failed. */\n error?: string;\n}\n\n/**\n * Result of a full `skaile install` or `skaile add` run.\n *\n * @docLink packages/asset-manager/concepts#asset-manager\n */\nexport interface InstallResult {\n /** Asset refs (`kind:name`) successfully deployed in this run. */\n deployed: string[];\n /** Asset refs (`kind:name`) removed because they are no longer in the resolved set. */\n removed: string[];\n /** Asset refs that could not be resolved in any configured repository. */\n missing: string[];\n /** Whether `skaile.lock.yaml` was written or updated. */\n lockWritten: boolean;\n /**\n * npm packages installed as a side effect of resolving runtime asset peer\n * deps (connectors / mounts declared in skaile.yaml). Empty when nothing\n * needed installing or when the runtime-deps step was skipped.\n */\n npmInstalled?: string[];\n /**\n * npm packages that the runtime-deps step tried but failed to install.\n * Non-fatal — listed for telemetry and CLI reporting.\n */\n npmFailed?: string[];\n}\n\n/**\n * An installed asset whose source repository is behind the remote.\n *\n * @docLink packages/asset-manager/concepts#asset-manager\n */\nexport interface OutdatedEntry {\n /** Asset kind (`skill`, `agent`, `prompt`, `flow`, `contract`). */\n kind: string;\n /** Asset name as registered in the catalog. */\n name: string;\n /** Repository that provides this asset. */\n publisher: string;\n /** Version string recorded in the lock file at install time. */\n currentVersion: string;\n /** Number of commits the local repository is behind the remote. */\n behind: number;\n}\n\n/**\n * A node in the resolved dependency tree (returned by `AssetManager.tree()`).\n *\n * @docLink packages/asset-manager/concepts#asset-manager\n */\nexport interface DependencyNode {\n /** Asset ref (`kind:name`) or `\"project\"` for the root node. */\n ref: string;\n /** Transitive dependencies resolved by this node. */\n children: DependencyNode[];\n}\n\n/**\n * A missing dependency detected by `AssetManager.doctor()`.\n *\n * @docLink packages/asset-manager/concepts#asset-manager\n */\nexport interface DepIssue {\n /** Kind of the asset that has the unsatisfied requirement. */\n assetKind: string;\n /** Name of the asset that has the unsatisfied requirement. */\n assetName: string;\n /** Kind of the missing dependency. */\n depKind: string;\n /** Name of the missing dependency. */\n depName: string;\n /** `true` when the missing dependency exists in a configured repository but has not been installed. */\n inRepos: boolean;\n}\n\n/**\n * A single deployed asset shown in the workspace overview.\n *\n * @docLink packages/asset-manager/concepts#asset-manager\n */\nexport interface OverviewEntry {\n /** Asset kind (`skill`, `agent`, `prompt`, `flow`, `contract`). */\n kind: string;\n /** Asset name. */\n name: string;\n /** Domain the asset belongs to (from the lock file; `\"unknown\"` when unresolvable). */\n domain: string;\n /** Repository that provides this asset. */\n publisher: string;\n /** Version string from the lock file. */\n version: string;\n /**\n * Sync status relative to the source repository.\n * - `\"synced\"` — local clone matches remote HEAD\n * - `\"outdated\"` — local clone is behind the remote\n * - `\"local\"` — sourced from a local path, no remote to compare\n * - `\"error\"` — status check failed\n * - `\"unknown\"` — repository not found or lock entry missing\n */\n syncStatus: string;\n}\n\n/**\n * Aggregated workspace overview returned by `AssetManager.overview()`.\n *\n * @docLink packages/asset-manager/concepts#asset-manager\n */\nexport interface OverviewResult {\n /** Entries grouped by domain, sorted alphabetically. Each group is sorted by kind then name. */\n byDomain: Map<string, OverviewEntry[]>;\n /** Total number of deployed assets. */\n total: number;\n /** Sync status for each configured repository. */\n repos: RepoStatusInfo[];\n}\n\n// ── AssetManager ─────────────────────────────────────────────────────────────\n\n/**\n * Options for constructing an {@link AssetManager}.\n *\n * @docLink packages/asset-manager/concepts#asset-manager\n */\nexport interface AssetManagerOptions {\n /** Absolute or relative path to the workspace root (must contain `skaile.yaml`). */\n projectDir: string;\n /**\n * Agent framework to target for asset deployment.\n * Determines which framework directories (``.claude/``, ``.omp/``, etc.) are used.\n * Defaults to `\"claude-code\"`.\n */\n driverTarget?: DriverTarget;\n /**\n * When `true`, assets are installed into the global Skaile cache rather than the\n * project workspace. Skips `skaile.yaml` dependency updates.\n */\n global?: boolean;\n /**\n * Catalog read-protocol fetcher used to resolve store-published assets. When\n * omitted, one is built per call from the configured stores\n * (`RemoteCatalogSource`). Injected mainly by tests to stay network-free.\n */\n storeFetcher?: StoreFetcher;\n /**\n * Byte fetcher used to fetch a store asset's files at its pinned commit before\n * deploy. When omitted, the production GitHub fetcher is used. Injected by\n * tests to stay network-free.\n */\n assetFetcher?: AssetFetcher;\n /**\n * Overrides the global `catalog.url` used as a store fallback when the project\n * declares no `stores:`. Pass `\"\"` to disable the fallback entirely. When\n * omitted, the URL is read from `~/.skaile/config.yaml` (`resolveConfig`).\n */\n catalogUrl?: string;\n}\n\n/** Canonical git URL identity for the bundled factory source. Never fetched —\n * the bytes live inside the package (`factory-assets/`); the URL is only the\n * match key the provenance walker and `candidateToCatalogEntry` key off. */\nconst FACTORY_SOURCE_URL = \"https://github.com/skaile-ai/ai-assets\";\n\n/**\n * Locate the built-in first-party skills/bundles shipped inside the package.\n *\n * Resolves through the shared {@link factoryAssetRoots} helper — the\n * `SKAILE_FACTORY_ASSETS_DIR` override layer (when set) ahead of the bundled\n * tree (in-repo source during dev, `dist/factory-assets/` after install), so a\n * container's override is honoured here identically to `serve`. Returns the\n * highest-precedence root that carries a `skaile.manifest.yaml` (the publication\n * manifest that names the source's publisher), or `null` when none qualifies —\n * the factory source is then simply not injected rather than erroring.\n */\nfunction resolveFactoryAssetsDir(): string | null {\n for (const dir of factoryAssetRoots()) {\n if (existsSync(join(dir, \"skaile.manifest.yaml\"))) return dir;\n }\n return null;\n}\n\n/** Read the declared `publisher` from a source's root `skaile.manifest.yaml`. */\nfunction readDeclaredPublisher(sourceDir: string): string | undefined {\n try {\n const raw = parseYaml(readFileSync(join(sourceDir, \"skaile.manifest.yaml\"), \"utf8\")) as {\n publisher?: unknown;\n } | null;\n return raw && typeof raw.publisher === \"string\" && raw.publisher.length > 0\n ? raw.publisher\n : undefined;\n } catch {\n return undefined;\n }\n}\n\n/**\n * The bundled factory source `{ dir, publisher }`, or `null` when no usable\n * bundle is present. Resolved once per process — the package location and the\n * bundled `skaile.manifest.yaml` are immutable for the process lifetime, so the\n * `require.resolve` + `existsSync` probes + YAML parse run a single time rather\n * than on every `loadConfig()` call. `undefined` = not yet computed.\n */\nlet factorySourceCache: { dir: string; publisher: string } | null | undefined;\n\nfunction resolveFactorySource(): { dir: string; publisher: string } | null {\n if (factorySourceCache !== undefined) return factorySourceCache;\n const dir = resolveFactoryAssetsDir();\n const publisher = dir ? readDeclaredPublisher(dir) : undefined;\n factorySourceCache = dir && publisher ? { dir, publisher } : null;\n return factorySourceCache;\n}\n\n/**\n * Programmatic API for managing AI assets in a Skaile workspace.\n *\n * `AssetManager` wraps repository management, catalog search, asset installation,\n * lock-file tracking, patch workflows, and workspace diagnostics. The CLI delegates\n * all `skaile catalog`, `skaile repo`, `skaile install`, `skaile add`, and\n * `skaile init` commands to this class.\n *\n * @example\n * ```typescript\n * import { AssetManager } from \"@skaile/workspaces/asset-manager\";\n *\n * const am = new AssetManager({ projectDir: \"/my-project\" });\n *\n * // Install all dependencies declared in skaile.yaml\n * const result = await am.install();\n * console.log(`Deployed: ${result.deployed.join(\", \")}`);\n *\n * // Add a single skill (resolves transitive deps, updates skaile.yaml)\n * const deployed = am.add(\"skill:my-skill\");\n *\n * // Search the catalog\n * const skills = am.search(\"code review\", \"skill\");\n * ```\n *\n * @docLink packages/asset-manager/concepts#asset-manager\n */\nexport class AssetManager {\n /** Resolved absolute path to the workspace root. */\n readonly projectDir: string;\n /** Agent framework driver target used for all deploy operations. */\n readonly driverTarget: DriverTarget;\n /** Whether this instance operates in global-install mode. */\n readonly global: boolean;\n /** Injected catalog fetcher (tests / custom); falls back to a built one. */\n private readonly injectedStoreFetcher?: StoreFetcher;\n /** Injected byte fetcher for store staging; falls back to GitHub. */\n private readonly injectedAssetFetcher?: AssetFetcher;\n /** Injected global catalog URL override for the no-project-store fallback. */\n private readonly catalogUrlOverride?: string;\n\n constructor(opts: AssetManagerOptions) {\n this.projectDir = resolve(opts.projectDir);\n this.driverTarget = opts.driverTarget ?? (\"claude-code\" as DriverTarget);\n this.global = opts.global ?? false;\n this.injectedStoreFetcher = opts.storeFetcher;\n this.injectedAssetFetcher = opts.assetFetcher;\n this.catalogUrlOverride = opts.catalogUrl;\n }\n\n private get storeCacheDir(): string {\n return migrateLegacyDir(\n join(this.projectDir, \".skaile\", \"cache\", \"store\"),\n join(this.projectDir, \".skaile\", \"store-cache\"),\n );\n }\n\n private get reposDir(): string {\n return migrateLegacyDir(\n join(this.projectDir, \".skaile\", \"cache\", \"sources\"),\n join(this.projectDir, \".skaile\", \"repos\"),\n );\n }\n\n /**\n * Project-scoped cache dirs rooted at `.skaile/cache/` (`store`, `sources`)\n * relative to `projectDir`. Reading is a side effect: it triggers lazy\n * migration of the legacy `.skaile/{store-cache,repos}` dirs.\n */\n get projectCacheDirs(): { store: string; sources: string } {\n return { store: this.storeCacheDir, sources: this.reposDir };\n }\n\n private get lockPath(): string {\n return join(this.projectDir, \"skaile.lock.yaml\");\n }\n\n private get patchDir(): string {\n return join(this.projectDir, \".skaile\", \"patches\");\n }\n\n private get deployOpts(): DeployOptions {\n return { driverTarget: this.driverTarget, global: this.global, cwd: this.projectDir };\n }\n\n private loadConfig(): {\n repositories: Record<string, SourceDeclaration>;\n sources: SourceEntry[];\n stores: StoreEntry[];\n dependencies: string[];\n overrides: OverrideEntry[];\n patches: Record<string, string>;\n config: SkWorkspaceConfig;\n } {\n // resolveSkWorkspaceConfig runs the canonical normalizer and throws on\n // legacy keys (`repositories:` / `ai_resources:`) — propagate to the caller.\n const config = resolveSkWorkspaceConfig(this.projectDir);\n\n const sources = config.sources ?? [];\n const stores = config.stores ?? [];\n const dependencies = config.dependencies ?? [];\n const overrides = config.overrides ?? [];\n const patches = config.patches ?? {};\n\n // Source clones live in the global clone cache (cache/sources); the slug is\n // the cache key for ensureRepo. getGlobalCacheDir() migrates legacy roots.\n const sourcesDir = getGlobalCacheDir();\n const repositories: Record<string, SourceDeclaration> = {};\n for (const s of sources) {\n const slug = sourceSlug(s.url);\n if (repositories[slug]) continue;\n repositories[slug] = { path: join(sourcesDir, slug), url: s.url };\n }\n\n // Implicit built-in source: the first-party assets shipped inside the\n // package (`dist/factory-assets/`). Always available, zero config — keyed by\n // its declared publisher so refs (`kind:@<publisher>/name`) and `info`\n // resolve cleanly. Skipped when the user already declares the same source\n // explicitly (avoids duplicate catalog entries) or when no bundle is present.\n const factory = resolveFactorySource();\n const factoryUrl = normalizeRepoUrl(FACTORY_SOURCE_URL);\n const alreadyDeclared = Object.values(repositories).some(\n (d) => d.url !== undefined && normalizeRepoUrl(d.url) === factoryUrl,\n );\n if (factory && !alreadyDeclared && !repositories[factory.publisher]) {\n repositories[factory.publisher] = {\n path: factory.dir,\n url: FACTORY_SOURCE_URL,\n factory: true,\n };\n }\n\n return { repositories, sources, stores, dependencies, overrides, patches, config };\n }\n\n /** Build provenance-index clones from the resolved source declarations. */\n private buildClones(repositories: Record<string, SourceDeclaration>): SourceClone[] {\n const clones: SourceClone[] = [];\n for (const [slug, decl] of Object.entries(repositories)) {\n const localPath = this.resolveRepoDir(decl, slug);\n if (!localPath || !existsSync(localPath)) continue;\n const commit = getRepoCommit(localPath) ?? \"0\".repeat(40);\n clones.push({\n localPath,\n sourceUrl: decl.url ?? localPath,\n commit,\n tag: decl.branch,\n });\n }\n return clones;\n }\n\n /**\n * Bridge a resolved {@link ProvenanceCandidate} to a {@link CatalogEntry} for\n * the deploy pipeline. `source` is the absolute path to the asset's primary\n * manifest (or its directory) inside the clone; `publisher` is set to the\n * clone slug so `deployAll`'s repositories lookup resolves local-vs-remote.\n */\n private candidateToCatalogEntry(\n c: ProvenanceCandidate,\n repositories: Record<string, SourceDeclaration>,\n ): CatalogEntry | null {\n // Find the clone slug whose declaration URL matches the candidate's source.\n let slug: string | undefined;\n let cloneDir: string | undefined;\n for (const [s, decl] of Object.entries(repositories)) {\n if (decl.url === c.sourceUrl) {\n slug = s;\n cloneDir = this.resolveRepoDir(decl, s) ?? undefined;\n break;\n }\n }\n if (!cloneDir) {\n // Unknown source — deployable store assets are routed via staged bytes\n // before reaching here, so this branch now only hits non-deployable store\n // kinds (e.g. mcp-server), which deployAll skips. Fall back to first clone.\n const first = Object.entries(repositories)[0];\n if (first) {\n slug = first[0];\n cloneDir = this.resolveRepoDir(first[1], first[0]) ?? undefined;\n }\n }\n if (!cloneDir || !slug) return null;\n\n const mdName = MD_BY_KIND[c.kind];\n const mdRel = c.files.find((f) => (mdName ? f.path.endsWith(mdName) : false))?.path;\n const source = mdRel ? join(cloneDir, mdRel) : cloneDir;\n\n const entry: CatalogEntry = {\n name: c.name,\n kind: c.kind as CatalogEntry[\"kind\"],\n description: c.description ?? \"\",\n source,\n publisher: slug,\n version: c.version,\n requires: [],\n // Manifest-declared deps are authoritative for the candidate's deps.\n dependencies: c.deps ?? [],\n metadata: c.metadata,\n };\n if (c.category != null) entry.category = c.category;\n if (c.keywords && c.keywords.length > 0) entry.keywords = c.keywords;\n if (c.license != null) entry.license = c.license;\n if (c.homepage != null) entry.homepage = c.homepage;\n return entry;\n }\n\n // ── Store fetch-then-deploy ────────────────────────────────────────────\n\n /** A candidate's stable identity key (`<publisher>/<kind>:<name>@<version>`). */\n private candidateKey(c: ProvenanceCandidate): string {\n return `${c.publisher}/${c.kind}:${c.name}@${c.version}`;\n }\n\n /**\n * Resolve `deps`, falling back to the global `catalog.url` store when the\n * project declares no store and the first pass leaves something missing.\n *\n * The first pass uses the project stores only, so locally-resolvable refs\n * never trigger a network probe. The fallback retry is best-effort: any error\n * (offline, store down) keeps the first pass's result rather than regressing.\n */\n private async resolveWithStores(\n deps: string[],\n opts: {\n provenanceIndex: ReturnType<typeof buildProvenanceIndex>;\n overrides: OverrideEntry[];\n stores: StoreEntry[];\n },\n ): Promise<ResolveResult> {\n const first = await resolveAll(deps, {\n provenanceIndex: opts.provenanceIndex,\n overrides: opts.overrides,\n stores: opts.stores,\n storeFetcher: this.storeFetcherFor(opts.stores),\n projectDir: this.projectDir,\n });\n if (first.missing.length === 0) return first;\n\n const fallback = await this.globalStoreFallback(opts.stores);\n if (fallback.length === 0) return first;\n\n const stores = [...opts.stores, ...fallback];\n try {\n const retry = await resolveAll(deps, {\n provenanceIndex: opts.provenanceIndex,\n overrides: opts.overrides,\n stores,\n storeFetcher: this.storeFetcherFor(stores),\n projectDir: this.projectDir,\n });\n // Monotone: same provenanceIndex + overrides, only more stores added —\n // resolution can gain deps but never lose one, so fewer-missing wins.\n return retry.missing.length < first.missing.length ? retry : first;\n } catch {\n return first;\n }\n }\n\n /** The catalog fetcher to use: an injected one, else built from `stores`. */\n private storeFetcherFor(stores: StoreEntry[]): StoreFetcher | undefined {\n return this.injectedStoreFetcher ?? this.buildStoreFetcher(stores);\n }\n\n /**\n * The global `catalog.url` as a single-store fallback, or `[]` when no\n * project store should be synthesized — `local` sentinel, already-declared,\n * or no URL. Honours an explicit `catalogUrl` injection (`\"\"` disables it).\n */\n private async globalStoreFallback(projectStores: StoreEntry[]): Promise<StoreEntry[]> {\n let url = this.catalogUrlOverride;\n if (url === undefined) {\n try {\n const { resolveConfig } = await import(\"@skaile/workspaces/library\");\n url = resolveConfig({ projectDir: this.projectDir }).catalog.url;\n } catch {\n return [];\n }\n }\n if (!url || url.trim().toLowerCase() === \"local\") return [];\n if (projectStores.some((s) => normalizeRepoUrl(s.url) === normalizeRepoUrl(url!))) return [];\n return [{ url }];\n }\n\n /**\n * Build deployable catalog entries from resolved candidates. Store-resolved\n * candidates (no local clone bytes) are fetched + SHA-verified into the\n * project store-cache first, then their entry points at the staged bytes so\n * the existing copy-deploy path works. Source-backed candidates keep the\n * clone-relative entry.\n */\n private async buildCatalogEntries(\n resolved: ProvenanceCandidate[],\n repositories: Record<string, SourceDeclaration>,\n ): Promise<CatalogEntry[]> {\n const staged = await this.stageStoreAssets(resolved, repositories);\n const entries: CatalogEntry[] = [];\n for (const c of resolved) {\n const stagedPath = staged.get(this.candidateKey(c));\n const entry = stagedPath\n ? this.stagedCandidateToEntry(c, stagedPath)\n : this.candidateToCatalogEntry(c, repositories);\n if (entry) entries.push(entry);\n }\n return entries;\n }\n\n /**\n * Fetch + SHA-verify the bytes of every store-resolved deployable candidate\n * into `.skaile/cache/store/`, reusing the same verified-fetch path the\n * pointer-only `library.install` uses (`installFromManifest` flat mode).\n *\n * @returns Map of candidate key → staged primary-manifest path.\n */\n private async stageStoreAssets(\n resolved: ProvenanceCandidate[],\n repositories: Record<string, SourceDeclaration>,\n ): Promise<Map<string, string>> {\n const staged = new Map<string, string>();\n let installFromManifest:\n | typeof import(\"@skaile/workspaces/library\").installFromManifest\n | undefined;\n\n for (const c of resolved) {\n if (NON_DEPLOYABLE_KINDS.has(c.kind)) continue;\n if (!c.files || c.files.length === 0 || !c.sourceUrl || !c.commit) continue;\n if (this.candidateHasLocalBytes(c, repositories)) continue;\n\n if (!installFromManifest) {\n ({ installFromManifest } = await import(\"@skaile/workspaces/library\"));\n }\n const targetDir = join(this.storeCacheDir, c.publisher, c.kind, c.name, c.version);\n // Per-file paths in c.files are attacker-controlled but validated by\n // installFromManifest before any fetch/write (rejects abs / `..`); this\n // outer guard only asserts the staging dir stays inside the cache root.\n const cacheRoot = resolve(this.storeCacheDir);\n if (!resolve(targetDir).startsWith(cacheRoot + sep)) {\n throw new Error(`unsafe store-cache path for ${this.candidateKey(c)}`);\n }\n const manifest: InstallManifest = {\n ref: `${c.kind}:@${c.publisher}/${c.name}#${c.version}`,\n source: { url: c.sourceUrl, commitSha: c.commit },\n files: c.files,\n sha256: c.sha256,\n kind: c.kind,\n // tier = catalog storage hint (S3/CDN); flat-mode verified fetch pulls\n // from source.url@commit and ignores it, so \"\" is inert.\n tier: \"\",\n };\n const { installPath } = await installFromManifest({\n manifest,\n libraryRoot: this.storeCacheDir,\n targetDir,\n fetcher: this.injectedAssetFetcher,\n });\n staged.set(this.candidateKey(c), join(installPath, this.stagedManifestRel(c)));\n }\n return staged;\n }\n\n /** Repo-relative path of a candidate's primary manifest (un-stripped). */\n private primaryManifestRel(c: ProvenanceCandidate): string | undefined {\n const paths = (c.files ?? []).map((f) => f.path);\n // Last resort: a kind with no manifest convention falls back to the first\n // file so deploy still has a concrete source rather than crashing.\n return matchManifestPath(c.kind, paths) ?? paths[0];\n }\n\n /**\n * The primary-manifest path relative to a staged asset dir. Takes the kind's\n * manifest (e.g. `SKILL.md`), then strips the same common-dir prefix\n * `installFromManifest` flat mode removed on write.\n */\n private stagedManifestRel(c: ProvenanceCandidate): string {\n const paths = (c.files ?? []).map((f) => f.path);\n const mdRel = this.primaryManifestRel(c) ?? \"\";\n const root = commonDirPrefix(paths);\n return root && mdRel.startsWith(`${root}/`) ? mdRel.slice(root.length + 1) : mdRel;\n }\n\n /**\n * `true` when a candidate's primary manifest is present on a local source\n * clone — its `sourceUrl` matches a registered source AND the manifest file\n * exists on disk at the expected path. A URL match alone is not enough: a\n * store can pin a different commit (or a subtree not bundled) of a repo that\n * is also a registered source, in which case the bytes must be fetched from\n * the store rather than read from the clone. (Only the primary manifest is\n * probed — a partially-cloned source is deployed as-is, matching the existing\n * clone-deploy path.)\n */\n private candidateHasLocalBytes(\n c: ProvenanceCandidate,\n repositories: Record<string, SourceDeclaration>,\n ): boolean {\n if (!c.sourceUrl) return false;\n const rel = this.primaryManifestRel(c);\n for (const [slug, decl] of Object.entries(repositories)) {\n if (decl.url === undefined || decl.url !== c.sourceUrl) continue;\n const dir = this.resolveRepoDir(decl, slug);\n if (!dir) continue;\n if (existsSync(rel ? join(dir, rel) : dir)) return true;\n }\n return false;\n }\n\n /** Build a copy-deploy catalog entry pointing at staged store bytes. */\n private stagedCandidateToEntry(c: ProvenanceCandidate, stagedManifestPath: string): CatalogEntry {\n const entry: CatalogEntry = {\n name: c.name,\n kind: c.kind as CatalogEntry[\"kind\"],\n description: c.description ?? \"\",\n source: stagedManifestPath,\n // Real publisher (never a clone slug) → deployAsset copies rather than\n // symlinking the ephemeral store-cache dir.\n publisher: c.publisher,\n version: c.version,\n requires: [],\n dependencies: c.deps ?? [],\n metadata: c.metadata,\n };\n if (c.category != null) entry.category = c.category;\n if (c.keywords && c.keywords.length > 0) entry.keywords = c.keywords;\n if (c.license != null) entry.license = c.license;\n if (c.homepage != null) entry.homepage = c.homepage;\n return entry;\n }\n\n // ── Install / resolve ──────────────────────────────────────────────────\n\n /**\n * Install all dependencies declared in `skaile.yaml`.\n *\n * Steps: clone/pull repositories → resolve transitive dependencies → reconcile\n * (remove stale assets) → deploy new assets → write `skaile.lock.yaml` → record history.\n *\n * @param opts - Optional installation options.\n * @param opts.locked - When `true`, restore the exact versions recorded in the existing\n * lock file instead of resolving from source. Throws if no lock file is found.\n * @returns {@link InstallResult} summarising what was deployed, what was missing, and any collisions.\n */\n async install(opts?: { locked?: boolean }): Promise<InstallResult> {\n const { repositories, sources, stores, dependencies, overrides, patches } = this.loadConfig();\n\n if (opts?.locked) {\n return this.installLocked(repositories, patches);\n }\n\n // 1. Ensure all source clones are present/up to date.\n const cloneError = this.ensureSourceClones(repositories, sources);\n if (cloneError) return cloneError;\n\n // 2. Build the provenance index from the clones and resolve.\n const provenanceIndex = buildProvenanceIndex(this.buildClones(repositories), {\n projectDir: this.projectDir,\n });\n const { resolved, missing, overridesApplied } = await this.resolveWithStores(dependencies, {\n provenanceIndex,\n overrides,\n stores,\n });\n\n // 3. Reconcile: remove stale assets (in old lock but not in new resolved set).\n const removed = this.reconcileRemovedAssets(resolved);\n\n // 4. Map candidates to catalog entries (fetching store bytes) and deploy.\n const entries = await this.buildCatalogEntries(resolved, repositories);\n const deployed = deployAll(entries, repositories, patches, this.deployOpts);\n\n // 5. Write the v2 lock file.\n writeLock(this.lockPath, buildLockFile(resolved, overridesApplied));\n\n // 6. Record history.\n this.recordInstallHistory(deployed, removed);\n\n // 7. Install npm peer deps for any mount/connector declared in skaile.yaml.\n const { npmInstalled, npmFailed } = await this.installRuntimeAssetDeps();\n\n return { deployed, removed, missing, lockWritten: true, npmInstalled, npmFailed };\n }\n\n /**\n * Ensure all source clones are present/up to date. Returns an early\n * {@link InstallResult} describing the failed source on the first error, or\n * `null` when every clone succeeds.\n */\n private ensureSourceClones(\n repositories: Record<string, SourceDeclaration>,\n sources: SourceEntry[],\n ): InstallResult | null {\n const pinBySlug = new Map(sources.map((s) => [sourceSlug(s.url), s.pin]));\n for (const [name, decl] of Object.entries(repositories)) {\n try {\n ensureRepo(decl, name, this.reposDir, {\n projectDir: this.projectDir,\n pin: pinBySlug.get(name),\n });\n } catch (err) {\n return {\n deployed: [],\n removed: [],\n missing: [`source:${name} (${err instanceof Error ? err.message : String(err)})`],\n lockWritten: false,\n };\n }\n }\n return null;\n }\n\n /**\n * Remove stale assets — those recorded in the old lock but absent from the\n * newly resolved set. Returns the list of removed refs.\n */\n private reconcileRemovedAssets(resolved: ProvenanceCandidate[]): string[] {\n const oldLock = this.tryReadLock();\n const resolvedRefs = new Set(\n resolved.map((c) => `${c.publisher}/${c.kind}:${c.name}@${c.version}`),\n );\n const removed: string[] = [];\n if (oldLock) {\n for (const ref of Object.keys(oldLock.assets)) {\n if (!resolvedRefs.has(ref)) {\n const { kind, name } = parseCanonicalLockKey(ref);\n if (kind && name) {\n removeAsset(kind, name, this.deployOpts);\n removed.push(ref);\n }\n }\n }\n }\n return removed;\n }\n\n /** Append `add`/`remove` history entries for a completed install reconcile. */\n private recordInstallHistory(deployed: string[], removed: string[]): void {\n for (const ref of deployed) {\n appendHistory(this.projectDir, {\n ref,\n action: \"add\",\n timestamp: new Date().toISOString(),\n context: this.global ? \"global\" : \"project\",\n });\n }\n for (const ref of removed) {\n appendHistory(this.projectDir, {\n ref,\n action: \"remove\",\n timestamp: new Date().toISOString(),\n context: this.global ? \"global\" : \"project\",\n });\n }\n }\n\n /** Read the lock, returning null on a legacy v1 lock instead of throwing. */\n private tryReadLock(): LockFile | null {\n try {\n return readLock(this.lockPath);\n } catch {\n return null;\n }\n }\n\n /** Build a store fetcher from the configured stores, or undefined when none. */\n private buildStoreFetcher(stores: StoreEntry[]): StoreFetcher | undefined {\n if (stores.length === 0) return undefined;\n return {\n getInstallManifest: async (storeUrl, ref) => {\n const { RemoteCatalogSource, CatalogHttpError } = await import(\n \"@skaile/workspaces/library\"\n );\n const src = new RemoteCatalogSource({ baseUrl: storeUrl });\n try {\n const m = await src.getInstallManifest(ref);\n return {\n sourceUrl: m.source.url,\n commit: m.source.commitSha,\n sha256: m.sha256,\n files: m.files,\n };\n } catch (err) {\n if (err instanceof CatalogHttpError && err.status === 404) return null;\n throw err;\n }\n },\n getCanonicalDigest: async (storeUrl, ref) => {\n const { RemoteCatalogSource } = await import(\"@skaile/workspaces/library\");\n const src = new RemoteCatalogSource({ baseUrl: storeUrl });\n return src.getCanonicalDigest(ref);\n },\n };\n }\n\n /**\n * Resolve runtime assets and install any missing npm peer deps.\n *\n * - Required deps: installed via `bun add --optional`. Failure is recorded\n * in `npmFailed` but does not throw — install() proceeds so users get a\n * useful error message rather than a hung command.\n * - Optional deps: not installed automatically (would force every consumer\n * to pull every connector's deps). Future: add a flag to opt in.\n */\n private async installRuntimeAssetDeps(): Promise<{\n npmInstalled: string[];\n npmFailed: string[];\n }> {\n const npmInstalled: string[] = [];\n const npmFailed: string[] = [];\n let runtimeAssets: Awaited<ReturnType<typeof resolveRuntimeAssets>> | null = null;\n try {\n runtimeAssets = await resolveRuntimeAssets(this.projectDir);\n } catch {\n // Non-fatal — projects with no skaile.yaml or unresolvable factory-assets\n // simply have no runtime deps to install.\n return { npmInstalled, npmFailed };\n }\n\n const required = runtimeAssets.requiredNpmDeps.required;\n if (required.length === 0) return { npmInstalled, npmFailed };\n\n const { findMissingPackages, installNpmPackages } = await import(\n \"@skaile/workspaces/connectors\"\n );\n const missing = findMissingPackages(required, this.projectDir);\n if (missing.length === 0) return { npmInstalled, npmFailed };\n\n const result = await installNpmPackages(missing, this.projectDir);\n if (result.success) {\n npmInstalled.push(...missing);\n } else {\n npmFailed.push(...missing);\n }\n return { npmInstalled, npmFailed };\n }\n\n private installLocked(\n repositories: Record<string, SourceDeclaration>,\n patches: Record<string, string>,\n ): InstallResult {\n const lock = this.tryReadLock();\n if (!lock) {\n throw new Error(\"No lock file found. Run `skaile install` first.\");\n }\n\n // Ensure every contributing source clone exists at its pinned commit. Sources\n // are keyed by URL slug; the lock's `sources[]` carries the URL + commit.\n const declBySlug = new Map(Object.entries(repositories));\n for (const src of lock.sources) {\n const slug = sourceSlug(src.url);\n const decl = declBySlug.get(slug) ?? { url: src.url };\n ensureRepo(decl, slug, this.reposDir, { projectDir: this.projectDir, pin: src.commit });\n }\n\n // Resolve a source URL to its on-disk clone for verification.\n const resolveCloneDir = (sourceUrl: string): string | null => {\n const slug = sourceSlug(sourceUrl);\n const decl = declBySlug.get(slug) ?? { url: sourceUrl };\n return this.resolveRepoDir(decl, slug);\n };\n\n // Verify integrity against the v2 lock.\n const verification = verifyLock(lock, resolveCloneDir);\n if (!verification.ok) {\n const issues = [\n ...verification.drifted.map((r) => `drifted: ${r}`),\n ...verification.missing.map((r) => `missing: ${r}`),\n ];\n throw new Error(`Lock file verification failed:\\n ${issues.join(\"\\n \")}`);\n }\n\n // Rebuild catalog entries from the lock and deploy.\n const resolved: CatalogEntry[] = [];\n for (const [ref, entry] of Object.entries(lock.assets)) {\n const { publisher, kind, name } = parseCanonicalLockKey(ref);\n if (!publisher || !kind || !name) continue;\n const slug = sourceSlug(entry.source.url);\n const cloneDir = resolveCloneDir(entry.source.url) ?? join(this.reposDir, slug);\n const mdRel =\n entry.files.find((f) => /\\.(md|yaml)$/i.test(f.path))?.path ?? entry.files[0]?.path ?? \"\";\n resolved.push({\n name,\n kind: kind as CatalogEntry[\"kind\"],\n description: \"\",\n source: mdRel ? join(cloneDir, mdRel) : cloneDir,\n publisher: slug,\n version: entry.source.commit,\n requires: [],\n dependencies: [],\n });\n // Ensure the repositories map has an entry for deployAll's local/remote check.\n if (!repositories[slug]) repositories[slug] = { url: entry.source.url, path: cloneDir };\n }\n\n const deployed = deployAll(resolved, repositories, patches, this.deployOpts);\n return { deployed, removed: [], missing: [], lockWritten: false };\n }\n\n /**\n * Add a single asset (and its transitive dependencies) to the workspace.\n *\n * Resolves `ref`, deploys the asset and all requirements, then records the ref\n * in `skaile.yaml` `dependencies` so subsequent `skaile install` runs re-deploy it.\n *\n * @param ref - Asset ref in `kind:name` or `repo/kind:name` form (e.g. `skill:my-skill`).\n * @returns Array of asset refs that were deployed in this call.\n * @throws When the asset cannot be found in any configured repository.\n */\n async add(ref: string): Promise<string[]> {\n const { repositories, stores, overrides, patches } = this.loadConfig();\n const parsed = parseAssetRef(ref);\n\n // Ensure clones.\n for (const [name, decl] of Object.entries(repositories)) {\n try {\n ensureRepo(decl, name, this.reposDir, { projectDir: this.projectDir });\n } catch {}\n }\n\n const provenanceIndex = buildProvenanceIndex(this.buildClones(repositories), {\n projectDir: this.projectDir,\n });\n const { resolved, missing } = await this.resolveWithStores([ref], {\n provenanceIndex,\n overrides,\n stores,\n });\n if (resolved.length === 0) {\n throw new Error(\n `Asset not found: ${ref}${missing.length ? ` (missing: ${missing.join(\", \")})` : \"\"}`,\n );\n }\n\n const entries = await this.buildCatalogEntries(resolved, repositories);\n const deployed = deployAll(entries, repositories, patches, this.deployOpts);\n\n // Add to skaile.yaml dependencies (canonical ref string).\n this.addDependencyToConfig(ref);\n\n for (const d of deployed) {\n appendHistory(this.projectDir, {\n ref: d,\n action: \"add\",\n timestamp: new Date().toISOString(),\n context: this.global ? \"global\" : \"project\",\n });\n }\n\n return deployed;\n }\n\n /**\n * Remove a deployed asset and unregister it from `skaile.yaml`.\n *\n * @param ref - Asset ref in `kind:name` form (e.g. `skill:my-skill`).\n * @returns `true` if the asset was found and removed, `false` if it was not deployed.\n */\n remove(ref: string): boolean {\n const parsed = parseAssetRef(ref);\n const ok = removeAsset(parsed.kind, parsed.name, this.deployOpts);\n if (ok) {\n const depRef = `${parsed.kind}:${parsed.name}`;\n this.removeDependencyFromConfig(depRef);\n\n appendHistory(this.projectDir, {\n ref: depRef,\n action: \"remove\",\n timestamp: new Date().toISOString(),\n context: this.global ? \"global\" : \"project\",\n });\n }\n return ok;\n }\n\n // ── Query ──────────────────────────────────────────────────────────────\n\n /**\n * Search the catalog across all configured repositories.\n *\n * @param query - Substring to match against entry names and descriptions (case-insensitive).\n * Omit to return all entries.\n * @param kind - Filter by asset kind (`\"skill\"`, `\"agent\"`, `\"prompt\"`, `\"flow\"`, `\"contract\"`).\n * Omit to return all kinds.\n * @returns Array of matching {@link CatalogEntry} objects from all accessible repositories.\n */\n search(query?: string, kind?: string): CatalogEntry[] {\n const { repositories } = this.loadConfig();\n let all: CatalogEntry[] = [];\n\n for (const [name, decl] of Object.entries(repositories)) {\n const repoDir = this.resolveRepoDir(decl, name);\n if (!repoDir) continue;\n all = [...all, ...scanRepo(repoDir, name)];\n }\n\n if (kind) all = all.filter((e) => e.kind === kind);\n if (query) {\n const q = query.toLowerCase();\n all = all.filter(\n (e) => e.name.toLowerCase().includes(q) || e.description.toLowerCase().includes(q),\n );\n }\n return all;\n }\n\n /**\n * Look up a single asset's full catalog entry.\n *\n * @param ref - Asset ref in `kind:name` or `repo/kind:name` form.\n * @returns The matching {@link CatalogEntry}, or `null` when not found.\n */\n info(ref: string): CatalogEntry | null {\n const { repositories } = this.loadConfig();\n const parsed = parseAssetRef(ref);\n\n for (const [name, decl] of Object.entries(repositories)) {\n const repoDir = this.resolveRepoDir(decl, name);\n if (!repoDir) continue;\n // Match on the entry's scanned (manifest) publisher, not the repo map key\n // (= URL slug). The two are unrelated identities under canonical schema.\n const entries = scanRepo(repoDir, name);\n const match = entries.find(\n (e) =>\n e.kind === parsed.kind &&\n e.name === parsed.name &&\n (!parsed.publisher || e.publisher === parsed.publisher),\n );\n if (match) return match;\n }\n return null;\n }\n\n /**\n * List all assets currently deployed in the workspace (or global cache).\n *\n * Scans the framework deploy directories rather than the lock file, so it\n * also returns assets that were installed manually or outside of `skaile install`.\n *\n * @param kind - Filter by asset kind. Omit to return all kinds.\n * @returns Shallow {@link CatalogEntry} objects (description and version will be empty).\n */\n listDeployed(kind?: string): CatalogEntry[] {\n // Bundles are dependency groups, not deployed as files — exclude from scan\n const kinds = (\n kind ? [kind] : [\"skill\", \"agent\", \"prompt\", \"flow\", \"contract\"]\n ) as AiComponent[];\n const result: CatalogEntry[] = [];\n const seen = new Set<string>();\n for (const k of kinds) {\n try {\n const base = deployedBase(k, this.driverTarget, this.global, this.projectDir);\n if (!existsSync(base)) continue;\n for (const item of readdirSync(base, { withFileTypes: true })) {\n // Directories and symlinks use the directory name directly (skills, omp agents, etc.)\n // Files use the stem without extension (claude-code agents → .md, codex agents → .toml,\n // prompts → .prompt.md, flows → .flow.yaml/.flow.json)\n let name: string;\n if (item.isDirectory() || item.isSymbolicLink()) {\n name = item.name;\n } else if (item.isFile()) {\n name = item.name\n .replace(/\\.prompt\\.md$/, \"\")\n .replace(/\\.flow\\.(yaml|json)$/, \"\")\n .replace(/\\.bundle\\.yaml$/, \"\")\n .replace(/\\.(md|toml|yaml|json)$/, \"\");\n } else {\n continue;\n }\n const key = `${k}:${name}`;\n if (seen.has(key)) continue;\n seen.add(key);\n result.push({\n name,\n kind: k as any,\n description: \"\",\n source: join(base, item.name),\n version: \"\",\n requires: [],\n dependencies: [],\n });\n }\n } catch {}\n }\n return result;\n }\n\n /**\n * List the **declared** top-level dependencies from `skaile.yaml`, each tagged\n * with a reconciliation {@link DeclaredState}:\n *\n * - `declared` — in `skaile.yaml`, not yet resolved into the lock.\n * - `installed` — declared + locked, and (for deployable kinds) materialized on\n * disk. Non-deployable kinds ({@link NON_DEPLOYABLE_KINDS}) count as installed\n * once locked — they are wired at session start, never written to the target dir.\n * - `drift` — declared + locked but the deployed files are missing on disk.\n * - `invalid` — the `dependencies:` entry isn't a parseable canonical ref. Only\n * surfaced in the unfiltered listing (a `kind` filter can't classify it).\n *\n * Transitive (lock-only) deps are excluded by construction — only the declared\n * set is walked, so a lock entry with no matching `dependencies:` ref never shows.\n *\n * @param kind - Filter by asset kind. Omit to return all kinds.\n * @returns One {@link DeclaredAsset} per declared dep (after the optional kind filter).\n * @throws {MissingManifestError} when the project has no `skaile.yaml`.\n * @throws {Error} with a `migrate-skaile-manifest` hint on legacy `repositories:` / `ai_resources:` keys.\n */\n listDeclared(kind?: string): DeclaredAsset[] {\n if (!existsSync(join(this.projectDir, SKAILE_YAML_DEFAULT))) {\n throw new MissingManifestError(this.projectDir);\n }\n // resolveSkWorkspaceConfig runs the canonical normalizer (throws on legacy\n // keys) — used directly rather than loadConfig() to avoid the latter's\n // repositories-map build + getGlobalCacheDir() migration side effects on a read.\n const dependencies = resolveSkWorkspaceConfig(this.projectDir).dependencies ?? [];\n const lock = this.tryReadLock();\n const lockKeys = lock ? Object.keys(lock.assets).map(parseCanonicalLockKey) : [];\n\n const out: DeclaredAsset[] = [];\n for (const ref of dependencies) {\n let parsed: ReturnType<typeof parseAssetRef>;\n try {\n parsed = parseAssetRef(ref);\n } catch {\n // An unparseable ref has no kind to match a filter against; surface it\n // as `invalid` in the unfiltered listing rather than dropping it silently.\n if (!kind) out.push({ ref, kind: \"\", name: ref, state: \"invalid\" });\n continue;\n }\n if (kind && parsed.kind !== kind) continue;\n\n // A declared ref need not carry a publisher; match on kind+name and, when\n // present, the publisher — the lock key is always fully canonical.\n const locked = lockKeys.some(\n (k) =>\n k.kind === parsed.kind &&\n k.name === parsed.name &&\n (!parsed.publisher || k.publisher === parsed.publisher),\n );\n\n let state: DeclaredState;\n if (!locked) {\n state = \"declared\";\n } else if (NON_DEPLOYABLE_KINDS.has(parsed.kind)) {\n state = \"installed\";\n } else {\n const onDisk = isDeployed(\n parsed.kind as AiComponent,\n parsed.name,\n this.driverTarget,\n this.global,\n this.projectDir,\n );\n state = onDisk ? \"installed\" : \"drift\";\n }\n out.push({ ref, kind: parsed.kind, name: parsed.name, state });\n }\n return out;\n }\n\n /**\n * Build an aggregated workspace overview with domain grouping and sync status.\n *\n * Combines deployed assets, lock file metadata, and live repository status\n * into a single structured result. Used by `skaile status`.\n *\n * @returns {@link OverviewResult} with entries grouped by domain and per-repo sync status.\n */\n overview(): OverviewResult {\n const { repositories } = this.loadConfig();\n const lock = this.tryReadLock();\n const deployed = this.listDeployed();\n\n const repoStatuses = this.buildRepoStatuses(repositories);\n const lockByKindName = indexLockByKindName(lock);\n\n // Build entries with publisher + sync info. Domain grouping is by publisher\n // now that the lock no longer records a project-local domain.\n const entries: OverviewEntry[] = [];\n for (const d of deployed) {\n const lockEntry = lockByKindName.get(`${d.kind}:${d.name}`);\n const publisher = lockEntry?.publisher ?? \"\";\n const version = lockEntry?.version ?? \"\";\n const slug = lockEntry ? sourceSlug(lockEntry.url) : \"\";\n const syncStatus = slug ? computeSyncStatus(repoStatuses.get(slug)) : \"unknown\";\n const domain = publisher || \"unknown\";\n entries.push({ kind: d.kind, name: d.name, domain, publisher, version, syncStatus });\n }\n\n return {\n byDomain: groupAndSortByDomain(entries),\n total: entries.length,\n repos: [...repoStatuses.values()],\n };\n }\n\n /** Collect live sync status for every configured repository, keyed by name. */\n private buildRepoStatuses(\n repositories: Record<string, SourceDeclaration>,\n ): Map<string, RepoStatusInfo> {\n const repoStatuses = new Map<string, RepoStatusInfo>();\n for (const [name, decl] of Object.entries(repositories)) {\n const status = checkRepoStatus(decl, name, this.reposDir);\n repoStatuses.set(name, {\n name,\n kind: status.kind,\n behind: status.behind,\n upToDate: status.upToDate,\n error: status.error,\n });\n }\n return repoStatuses;\n }\n\n /**\n * Build the resolved dependency tree from the lock file.\n *\n * @returns Root {@link DependencyNode} with `ref === \"project\"` whose children\n * are the directly-declared dependencies, each with their own transitive subtrees.\n * Returns a single node with `ref === \"(no lock file)\"` when no lock exists.\n */\n tree(): DependencyNode {\n const lock = this.tryReadLock();\n if (!lock) return { ref: \"(no lock file)\", children: [] };\n\n // v2 lock no longer records per-asset parent provenance — every locked asset\n // is shown as a direct child of the project (flat tree).\n return {\n ref: \"project\",\n children: Object.keys(lock.assets).map((ref) => ({ ref, children: [] })),\n };\n }\n\n /**\n * Explain why an asset is installed by tracing its dependency chain in the lock file.\n *\n * @param ref - Asset ref in `kind:name` form.\n * @returns Chain of refs from the asset back to `\"direct (skaile.yaml)\"`, or `[]` when\n * the asset is not in the lock file.\n */\n why(ref: string): string[] {\n const lock = this.tryReadLock();\n if (!lock) return [];\n if (!lock.assets[ref]) return []; // not in lock file\n // v2 lock no longer records a dep chain — every locked asset is reported as\n // directly declared. (Transitive provenance reconstruction is out of scope.)\n return [ref, \"direct (skaile.yaml)\"];\n }\n\n /**\n * List installed assets whose source repository is behind the remote.\n *\n * Only remote repositories (not local paths) are checked for staleness.\n *\n * @returns Array of {@link OutdatedEntry} objects, one per asset in a repository\n * that has commits not yet pulled locally.\n */\n outdated(): OutdatedEntry[] {\n const { repositories } = this.loadConfig();\n const lock = this.tryReadLock();\n if (!lock) return [];\n\n const result: OutdatedEntry[] = [];\n for (const src of lock.sources) {\n const slug = sourceSlug(src.url);\n const decl = repositories[slug];\n if (!decl || decl.path) continue; // skip unknown / local sources\n const status = checkRepoStatus(decl, slug, this.reposDir);\n if (status.behind <= 0) continue;\n for (const [ref, entry] of Object.entries(lock.assets)) {\n if (entry.source.url !== src.url) continue;\n const { publisher, kind, name, version } = parseCanonicalLockKey(ref);\n if (!kind || !name) continue;\n result.push({\n kind,\n name,\n publisher: publisher ?? slug,\n currentVersion: version ?? \"\",\n behind: status.behind,\n });\n }\n }\n return result;\n }\n\n /**\n * Produce a unified diff between the deployed asset and its catalog source.\n *\n * Useful for detecting manual edits to deployed files or verifying that a patch\n * was applied correctly.\n *\n * @param ref - Asset ref in `kind:name` form.\n * @returns Unified diff string, or `null` when there are no differences or the\n * asset is not deployed/resolvable.\n */\n diff(ref: string): string | null {\n const parsed = parseAssetRef(ref);\n const entry = this.info(ref);\n if (!entry) return null;\n\n const deployedPath = join(\n deployedBase(parsed.kind as AiComponent, this.driverTarget, this.global, this.projectDir),\n parsed.name,\n );\n if (!existsSync(deployedPath) || !existsSync(entry.source)) return null;\n\n const r = spawnSync(\"diff\", [\"-ruN\", entry.source, deployedPath], { encoding: \"utf8\" });\n return r.status === 1 ? r.stdout : null;\n }\n\n // ── Lock ───────────────────────────────────────────────────────────────\n\n /**\n * Resolve all declared dependencies and write (or overwrite) `skaile.lock.yaml`.\n *\n * Performs repository sync and full dependency resolution without deploying assets.\n * Use this to regenerate the lock file after manually editing `skaile.yaml`.\n *\n * @returns The written {@link LockFile} data.\n */\n async lock(): Promise<LockFile> {\n const { repositories, stores, dependencies, overrides } = this.loadConfig();\n\n for (const [name, decl] of Object.entries(repositories)) {\n try {\n ensureRepo(decl, name, this.reposDir, { projectDir: this.projectDir });\n } catch {}\n }\n\n const provenanceIndex = buildProvenanceIndex(this.buildClones(repositories), {\n projectDir: this.projectDir,\n });\n const { resolved, overridesApplied } = await this.resolveWithStores(dependencies, {\n provenanceIndex,\n overrides,\n stores,\n });\n const lockData = buildLockFile(resolved, overridesApplied);\n writeLock(this.lockPath, lockData);\n return lockData;\n }\n\n // ── Patch workflow ─────────────────────────────────────────────────────\n\n /**\n * Extract a deployed asset into a patch working directory for editing.\n *\n * Copies the deployed asset to `.skaile/patches/<kind>-<name>/` so changes\n * can be made there and then committed as a patch file via `patchCommit`.\n *\n * @param ref - Asset ref in `kind:name` form.\n * @returns Absolute path to the patch working directory.\n * @throws When the asset cannot be found in the catalog.\n */\n patch(ref: string): string {\n const entry = this.info(ref);\n if (!entry) throw new Error(`Asset not found: ${ref}`);\n return extractForPatch(entry, this.patchDir);\n }\n\n /**\n * Generate a `.patch` file from changes made in the patch working directory.\n *\n * Diffs the patch working directory against the original catalog source and\n * writes the result to `.skaile/patches/<kind>-<name>.patch`.\n *\n * @param ref - Asset ref in `kind:name` form.\n * @returns Absolute path to the generated `.patch` file.\n * @throws When the patch working directory does not exist or no differences are found.\n */\n patchCommit(ref: string): string {\n const parsed = parseAssetRef(ref);\n const entry = this.info(ref);\n if (!entry) throw new Error(`Asset not found: ${ref}`);\n\n const patchedDir = join(this.patchDir, `${parsed.kind}-${parsed.name}`);\n if (!existsSync(patchedDir)) {\n throw new Error(`No patch working dir found. Run \\`skaile patch ${ref}\\` first.`);\n }\n\n const originalDir = dirname(entry.source);\n const content = generatePatch(originalDir, patchedDir);\n if (!content) throw new Error(\"No differences found.\");\n\n const patchFile = join(this.patchDir, `${parsed.kind}-${parsed.name}.patch`);\n savePatch(patchFile, content);\n return patchFile;\n }\n\n /**\n * Apply the committed patch file to the repository clone and open a contribution branch.\n *\n * Applies `.skaile/patches/<kind>-<name>.patch` to the repository clone, creates a\n * `patch/<kind>-<name>` branch, and stages a commit — ready to push via `contribPush`.\n *\n * @param ref - Asset ref in `kind:name` form.\n * @throws When the asset is not found, has no repository, or the patch file is missing.\n */\n patchSubmit(ref: string): void {\n const parsed = parseAssetRef(ref);\n const entry = this.info(ref);\n if (!entry?.publisher) throw new Error(`Asset not found or no publisher: ${ref}`);\n\n const { repositories } = this.loadConfig();\n const decl = repositories[entry.publisher];\n if (!decl?.url) throw new Error(\"Can only submit patches for remote sources.\");\n\n // Resolve through the same helper search/info use so patch + read agree on the clone dir.\n const repoDir = this.resolveRepoDir(decl, entry.publisher);\n if (!repoDir) throw new Error(`Repository clone not found for ${entry.publisher}.`);\n const branchName = `patch/${parsed.kind}-${parsed.name}`;\n\n // Apply patch to repo clone\n const patchFile = join(this.patchDir, `${parsed.kind}-${parsed.name}.patch`);\n if (!existsSync(patchFile)) throw new Error(\"No patch file. Run `skaile patch-commit` first.\");\n\n coreApplyPatch(repoDir, patchFile);\n commitChanges(repoDir, `fix: improve ${parsed.kind} ${parsed.name}`, branchName);\n }\n\n /**\n * Delete the patch working directory and patch file for an asset.\n *\n * @param ref - Asset ref in `kind:name` form.\n */\n patchRemove(ref: string): void {\n const parsed = parseAssetRef(ref);\n const patchFile = join(this.patchDir, `${parsed.kind}-${parsed.name}.patch`);\n const patchedDir = join(this.patchDir, `${parsed.kind}-${parsed.name}`);\n try {\n rmSync(patchFile);\n } catch {}\n try {\n rmSync(patchedDir, { recursive: true });\n } catch {}\n }\n\n // ── Doctor ─────────────────────────────────────────────────────────────\n\n /**\n * Scan deployed assets for unsatisfied transitive dependencies.\n *\n * For each deployed asset, checks that all entries in its `requires` list are\n * also deployed. Returns a list of issues with a flag indicating whether the\n * missing dependency can be resolved from a configured repository.\n *\n * @returns Array of {@link DepIssue} objects. An empty array means the workspace is healthy.\n */\n doctor(): DepIssue[] {\n const { repositories } = this.loadConfig();\n const deployed = this.listDeployed();\n const issues: DepIssue[] = [];\n\n for (const entry of deployed) {\n const full = this.info(`${entry.kind}:${entry.name}`);\n if (!full) continue;\n for (const req of full.requires) {\n if (\n !isDeployed(\n req.kind as AiComponent,\n req.name,\n this.driverTarget,\n this.global,\n this.projectDir,\n )\n ) {\n const inRepos =\n resolveAsset({ kind: req.kind, name: req.name }, repositories, this.reposDir) !== null;\n issues.push({\n assetKind: entry.kind,\n assetName: entry.name,\n depKind: req.kind,\n depName: req.name,\n inRepos,\n });\n }\n }\n }\n return issues;\n }\n\n // ── Scaffold ───────────────────────────────────────────────────────────\n\n /**\n * Create a minimal asset scaffold directory (delegates to {@link createScaffold}).\n *\n * @param name - Asset name (also used as the directory name).\n * @param kind - Asset kind: `skill` | `agent` | `bundle` | `flow` | `prompt` | `contract`.\n * @param destDir - Parent directory to create the asset in.\n * @returns `{ ok: true, path }` on success, `{ ok: false, path: errorMessage }` if the\n * directory already exists.\n */\n create(name: string, kind: string, destDir: string): { ok: boolean; path: string } {\n return createScaffold(name, kind, destDir);\n }\n\n // ── Contrib (REMOVED 2026-05-12) ───────────────────────────────────────\n //\n // The `contribChanges / contribDiff / contribCommit / contribPush /\n // contribCompare` methods were retired alongside `skaile repo contrib *`.\n // The refinement push-back workflow is being re-introduced in Phase 4 as\n // `skaile publish` + `skaile preset push` against the Library Source model.\n\n // ── History ────────────────────────────────────────────────────────────\n\n /**\n * Return recent asset action history entries, newest first.\n *\n * @param limit - Maximum number of entries to return. Defaults to `20`.\n * @returns Array of {@link HistoryEntry} objects in reverse-chronological order.\n */\n history(limit = 20): HistoryEntry[] {\n return getRecentHistory(this.projectDir, limit);\n }\n\n /**\n * Erase all asset action history for this workspace.\n */\n clearHistory(): void {\n clearHistory(this.projectDir);\n }\n\n // ── Clean ───────────────────────────────────────────────────────────────\n\n /**\n * Remove deployed assets tracked by the lock file and report unmanaged ones.\n *\n * With `opts.all`, also deletes `.skaile/history.yaml`, `.skaile/patches/`,\n * `.skaile/cache/sources/`, and `skaile.lock.yaml` — effectively resetting the\n * workspace to a pre-install state.\n *\n * @param opts - Optional cleanup options.\n * @param opts.all - When `true`, remove all Skaile-managed state in addition to deployed assets.\n * @returns Object with `removed` (successfully cleaned refs), `skipped` (with reasons),\n * and `unmanaged` (deployed assets not in the lock file).\n */\n clean(opts?: { all?: boolean }): {\n removed: string[];\n skipped: Array<{ ref: string; reason: string }>;\n unmanaged: string[];\n } {\n const lock = this.tryReadLock();\n const skipped: Array<{ ref: string; reason: string }> = [];\n\n const removed = this.cleanLockedDeployedAssets(lock);\n const unmanaged = this.collectUnmanagedAssets(lock);\n\n if (opts?.all) this.removeAllManagedState();\n\n return { removed, skipped, unmanaged };\n }\n\n /**\n * Remove the deployed dir of every asset tracked by the lock; missing dirs\n * still count as removed. Returns the list of cleaned refs.\n */\n private cleanLockedDeployedAssets(lock: LockFile | null): string[] {\n const removed: string[] = [];\n if (!lock) return removed;\n for (const ref of Object.keys(lock.assets)) {\n const { kind, name } = parseCanonicalLockKey(ref);\n if (!kind || !name) continue;\n const dest = deployedDir(\n kind as AiComponent,\n name,\n this.driverTarget,\n this.global,\n this.projectDir,\n );\n\n try {\n const stat = lstatSync(dest);\n if (stat.isSymbolicLink()) unlinkSync(dest);\n else rmSync(dest, { recursive: true, force: true });\n removed.push(ref);\n } catch {\n // Already gone — count as removed\n removed.push(ref);\n }\n }\n return removed;\n }\n\n /**\n * Report deployed assets not tracked by the lock file. Deployed assets are\n * keyed by <kind>:<name>; lock canonical refs are mapped to that shape.\n */\n private collectUnmanagedAssets(lock: LockFile | null): string[] {\n const lockRefs = lock\n ? new Set(\n Object.keys(lock.assets).map((r) => {\n const p = parseCanonicalLockKey(r);\n return p.kind && p.name ? `${p.kind}:${p.name}` : r;\n }),\n )\n : new Set<string>();\n const unmanaged: string[] = [];\n const allDeployed = this.listDeployed();\n for (const d of allDeployed) {\n const ref = `${d.kind}:${d.name}`;\n if (!lockRefs.has(ref)) {\n unmanaged.push(ref);\n }\n }\n return unmanaged;\n }\n\n /** Delete all Skaile-managed state: history file, patches/, cache/sources/, lock. */\n private removeAllManagedState(): void {\n // Delete history file\n const historyFile = join(this.projectDir, \".skaile\", \"history.yaml\");\n try {\n unlinkSync(historyFile);\n } catch {}\n\n // Remove patches dir\n try {\n rmSync(this.patchDir, { recursive: true, force: true });\n } catch {}\n\n // Remove repos dir\n try {\n rmSync(this.reposDir, { recursive: true, force: true });\n } catch {}\n\n // Remove lock file\n try {\n unlinkSync(this.lockPath);\n } catch {}\n }\n\n // ── Helpers ────────────────────────────────────────────────────────────\n\n /** Add a dependency ref to skaile.yaml if not already present. */\n private addDependencyToConfig(ref: string): void {\n if (this.global) return; // global installs don't modify skaile.yaml\n const configPath = join(this.projectDir, \"skaile.yaml\");\n if (!existsSync(configPath)) return;\n const raw = parseYaml(readFileSync(configPath, \"utf8\")) ?? {};\n if (!raw.dependencies) raw.dependencies = [];\n if (!raw.dependencies.includes(ref)) {\n raw.dependencies.push(ref);\n writeFileSync(configPath, stringifyYaml(raw, { lineWidth: 120 }));\n }\n }\n\n /** Remove a dependency ref from skaile.yaml. */\n private removeDependencyFromConfig(ref: string): void {\n if (this.global) return;\n const configPath = join(this.projectDir, \"skaile.yaml\");\n if (!existsSync(configPath)) return;\n const raw = parseYaml(readFileSync(configPath, \"utf8\")) ?? {};\n if (!raw.dependencies) return;\n const idx = raw.dependencies.indexOf(ref);\n if (idx !== -1) {\n raw.dependencies.splice(idx, 1);\n writeFileSync(configPath, stringifyYaml(raw, { lineWidth: 120 }));\n }\n }\n\n private resolveRepoDir(decl: SourceDeclaration, name: string): string | null {\n // Check links first\n const links = readLinks(this.projectDir);\n if (links[name]) {\n return existsSync(links[name]) ? links[name] : null;\n }\n\n if (decl.path) {\n const resolved = resolve(this.projectDir, decl.path);\n return existsSync(resolved) ? resolved : null;\n }\n\n // Check project-local symlink, then global cache\n const dest = join(this.reposDir, name);\n if (existsSync(dest)) return dest;\n\n const globalDest = join(getGlobalCacheDir(), name);\n if (existsSync(join(globalDest, \".git\"))) return globalDest;\n\n return null;\n }\n}\n\n// ── Agent install (renders GitAgent packages to framework-native files) ──\n\nexport { installAgent } from \"./install-agent.js\";\n\n// ── Renderers ─────────────────────────────────────────────────────────────\n\nexport type { AgentRenderer, AgentRenderInput, AgentRenderResult } from \"./renderers.js\";\nexport {\n AGENT_RENDERERS,\n claudeCodeRenderer,\n codexRenderer,\n driverTargetSupportsAgents,\n ompRenderer,\n} from \"./renderers.js\";\n\n// ── Fragments ─────────────────────────────────────────────────────────────\n\nexport type {\n AbilityRef,\n ConnectorRef,\n ContractRef,\n FragmentContext,\n FragmentId,\n} from \"./fragments.js\";\nexport { BUILT_IN_FRAGMENTS, loadPromptExtensions, resolveFragments } from \"./fragments.js\";\n"]}