@ai-agent-forge/agent-forge 0.86.7 → 0.88.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 (717) hide show
  1. package/CHANGELOG.md +45 -0
  2. package/README.md +10 -11
  3. package/dist/artifacts/artifact-store.d.ts.map +1 -1
  4. package/dist/artifacts/artifact-store.js +9 -5
  5. package/dist/artifacts/artifact-store.js.map +1 -1
  6. package/dist/bundle/.build-manifest.json +430 -413
  7. package/dist/bundle/chunks/{chunk-A7GUOX2H.js → chunk-6ZKDNZHA.js} +5 -1
  8. package/dist/bundle/chunks/chunk-HLJEVRWP.js +13 -0
  9. package/dist/bundle/chunks/chunk-YGHQME4V.js +1456 -0
  10. package/dist/bundle/chunks/image-resize-worker.js +12 -1
  11. package/dist/bundle/chunks/{virtual-modules-3IZ4MYSQ.js → virtual-modules-KZ5DRH7Q.js} +1 -1
  12. package/dist/bundle/cli.js +1 -1
  13. package/dist/bundle/client.js +1 -1
  14. package/dist/bundle/index.js +2 -2
  15. package/dist/bundle/rpc-entry.js +1 -1
  16. package/dist/cli/args.d.ts.map +1 -1
  17. package/dist/cli/args.js +231 -185
  18. package/dist/cli/args.js.map +1 -1
  19. package/dist/cli/auth-check.d.ts.map +1 -1
  20. package/dist/cli/auth-check.js +17 -4
  21. package/dist/cli/auth-check.js.map +1 -1
  22. package/dist/cli/auth-command.d.ts.map +1 -1
  23. package/dist/cli/auth-command.js +15 -9
  24. package/dist/cli/auth-command.js.map +1 -1
  25. package/dist/cli/credential-print.d.ts.map +1 -1
  26. package/dist/cli/credential-print.js +14 -7
  27. package/dist/cli/credential-print.js.map +1 -1
  28. package/dist/cli/experimental/command.d.ts.map +1 -1
  29. package/dist/cli/experimental/command.js +6 -5
  30. package/dist/cli/experimental/command.js.map +1 -1
  31. package/dist/cli/list-models.d.ts.map +1 -1
  32. package/dist/cli/list-models.js +9 -8
  33. package/dist/cli/list-models.js.map +1 -1
  34. package/dist/cli/plugin-manager-controller.d.ts.map +1 -1
  35. package/dist/cli/plugin-manager-controller.js +2 -1
  36. package/dist/cli/plugin-manager-controller.js.map +1 -1
  37. package/dist/cli/serve.d.ts.map +1 -1
  38. package/dist/cli/serve.js +8 -5
  39. package/dist/cli/serve.js.map +1 -1
  40. package/dist/client/remote-session.d.ts.map +1 -1
  41. package/dist/client/remote-session.js +16 -9
  42. package/dist/client/remote-session.js.map +1 -1
  43. package/dist/config.d.ts.map +1 -1
  44. package/dist/config.js +5 -3
  45. package/dist/config.js.map +1 -1
  46. package/dist/core/agent-capability-contract.d.ts +0 -7
  47. package/dist/core/agent-capability-contract.d.ts.map +1 -1
  48. package/dist/core/agent-capability-contract.js +72 -68
  49. package/dist/core/agent-capability-contract.js.map +1 -1
  50. package/dist/core/agent-session-bash.d.ts.map +1 -1
  51. package/dist/core/agent-session-bash.js +5 -4
  52. package/dist/core/agent-session-bash.js.map +1 -1
  53. package/dist/core/agent-session-compaction.d.ts +6 -10
  54. package/dist/core/agent-session-compaction.d.ts.map +1 -1
  55. package/dist/core/agent-session-compaction.js +35 -133
  56. package/dist/core/agent-session-compaction.js.map +1 -1
  57. package/dist/core/agent-session-context.d.ts.map +1 -1
  58. package/dist/core/agent-session-context.js +18 -13
  59. package/dist/core/agent-session-context.js.map +1 -1
  60. package/dist/core/agent-session-internal.d.ts +0 -6
  61. package/dist/core/agent-session-internal.d.ts.map +1 -1
  62. package/dist/core/agent-session-internal.js.map +1 -1
  63. package/dist/core/agent-session-model.d.ts.map +1 -1
  64. package/dist/core/agent-session-model.js +2 -1
  65. package/dist/core/agent-session-model.js.map +1 -1
  66. package/dist/core/agent-session-retry.d.ts.map +1 -1
  67. package/dist/core/agent-session-retry.js +3 -3
  68. package/dist/core/agent-session-retry.js.map +1 -1
  69. package/dist/core/agent-session-runtime.d.ts.map +1 -1
  70. package/dist/core/agent-session-runtime.js +7 -6
  71. package/dist/core/agent-session-runtime.js.map +1 -1
  72. package/dist/core/agent-session-services.d.ts +1 -1
  73. package/dist/core/agent-session-services.d.ts.map +1 -1
  74. package/dist/core/agent-session-services.js.map +1 -1
  75. package/dist/core/agent-session-tools.d.ts.map +1 -1
  76. package/dist/core/agent-session-tools.js +3 -2
  77. package/dist/core/agent-session-tools.js.map +1 -1
  78. package/dist/core/agent-session.d.ts +40 -22
  79. package/dist/core/agent-session.d.ts.map +1 -1
  80. package/dist/core/agent-session.js +147 -67
  81. package/dist/core/agent-session.js.map +1 -1
  82. package/dist/core/auth-guidance.d.ts.map +1 -1
  83. package/dist/core/auth-guidance.js +11 -5
  84. package/dist/core/auth-guidance.js.map +1 -1
  85. package/dist/core/auth-storage.d.ts.map +1 -1
  86. package/dist/core/auth-storage.js +9 -6
  87. package/dist/core/auth-storage.js.map +1 -1
  88. package/dist/core/compaction/compaction.d.ts.map +1 -1
  89. package/dist/core/compaction/compaction.js +2 -1
  90. package/dist/core/compaction/compaction.js.map +1 -1
  91. package/dist/core/embedded-sdk.d.ts.map +1 -1
  92. package/dist/core/embedded-sdk.js +10 -6
  93. package/dist/core/embedded-sdk.js.map +1 -1
  94. package/dist/core/export-html/index.d.ts.map +1 -1
  95. package/dist/core/export-html/index.js +9 -4
  96. package/dist/core/export-html/index.js.map +1 -1
  97. package/dist/core/extensions/agent-composition.d.ts.map +1 -1
  98. package/dist/core/extensions/agent-composition.js +26 -19
  99. package/dist/core/extensions/agent-composition.js.map +1 -1
  100. package/dist/core/extensions/bootstrap-agent-loop.d.ts.map +1 -1
  101. package/dist/core/extensions/bootstrap-agent-loop.js +3 -2
  102. package/dist/core/extensions/bootstrap-agent-loop.js.map +1 -1
  103. package/dist/core/extensions/bootstrap-compaction-policy.d.ts.map +1 -1
  104. package/dist/core/extensions/bootstrap-compaction-policy.js +0 -34
  105. package/dist/core/extensions/bootstrap-compaction-policy.js.map +1 -1
  106. package/dist/core/extensions/bootstrap-lifecycle.d.ts.map +1 -1
  107. package/dist/core/extensions/bootstrap-lifecycle.js +20 -17
  108. package/dist/core/extensions/bootstrap-lifecycle.js.map +1 -1
  109. package/dist/core/extensions/bootstrap-overflow-policy.d.ts.map +1 -1
  110. package/dist/core/extensions/bootstrap-overflow-policy.js +2 -1
  111. package/dist/core/extensions/bootstrap-overflow-policy.js.map +1 -1
  112. package/dist/core/extensions/bootstrap-retry-policy.d.ts.map +1 -1
  113. package/dist/core/extensions/bootstrap-retry-policy.js +4 -3
  114. package/dist/core/extensions/bootstrap-retry-policy.js.map +1 -1
  115. package/dist/core/extensions/bootstrap-skills.d.ts.map +1 -1
  116. package/dist/core/extensions/bootstrap-skills.js +7 -6
  117. package/dist/core/extensions/bootstrap-skills.js.map +1 -1
  118. package/dist/core/extensions/bootstrap-tools.d.ts.map +1 -1
  119. package/dist/core/extensions/bootstrap-tools.js +2 -1
  120. package/dist/core/extensions/bootstrap-tools.js.map +1 -1
  121. package/dist/core/extensions/capability-plugin.d.ts.map +1 -1
  122. package/dist/core/extensions/capability-plugin.js +37 -13
  123. package/dist/core/extensions/capability-plugin.js.map +1 -1
  124. package/dist/core/extensions/capability-runtime-events.d.ts.map +1 -1
  125. package/dist/core/extensions/capability-runtime-events.js +17 -13
  126. package/dist/core/extensions/capability-runtime-events.js.map +1 -1
  127. package/dist/core/extensions/capability-runtime-guards.d.ts.map +1 -1
  128. package/dist/core/extensions/capability-runtime-guards.js +16 -15
  129. package/dist/core/extensions/capability-runtime-guards.js.map +1 -1
  130. package/dist/core/extensions/capability-runtime-manifest.d.ts.map +1 -1
  131. package/dist/core/extensions/capability-runtime-manifest.js +52 -30
  132. package/dist/core/extensions/capability-runtime-manifest.js.map +1 -1
  133. package/dist/core/extensions/capability-runtime-validation.d.ts.map +1 -1
  134. package/dist/core/extensions/capability-runtime-validation.js +66 -65
  135. package/dist/core/extensions/capability-runtime-validation.js.map +1 -1
  136. package/dist/core/extensions/capability-runtime.d.ts.map +1 -1
  137. package/dist/core/extensions/capability-runtime.js +147 -127
  138. package/dist/core/extensions/capability-runtime.js.map +1 -1
  139. package/dist/core/extensions/compaction-memory-failure-mode.d.ts.map +1 -1
  140. package/dist/core/extensions/compaction-memory-failure-mode.js +3 -2
  141. package/dist/core/extensions/compaction-memory-failure-mode.js.map +1 -1
  142. package/dist/core/extensions/context-strategy-binding.d.ts.map +1 -1
  143. package/dist/core/extensions/context-strategy-binding.js +7 -4
  144. package/dist/core/extensions/context-strategy-binding.js.map +1 -1
  145. package/dist/core/extensions/lifecycle-catalog.d.ts.map +1 -1
  146. package/dist/core/extensions/lifecycle-catalog.js +290 -279
  147. package/dist/core/extensions/lifecycle-catalog.js.map +1 -1
  148. package/dist/core/extensions/lifecycle-delivery-queue.d.ts.map +1 -1
  149. package/dist/core/extensions/lifecycle-delivery-queue.js +3 -2
  150. package/dist/core/extensions/lifecycle-delivery-queue.js.map +1 -1
  151. package/dist/core/extensions/provider-failover.d.ts +7 -3
  152. package/dist/core/extensions/provider-failover.d.ts.map +1 -1
  153. package/dist/core/extensions/provider-failover.js +9 -8
  154. package/dist/core/extensions/provider-failover.js.map +1 -1
  155. package/dist/core/facade/coding-agent-facade.d.ts +6 -6
  156. package/dist/core/facade/coding-agent-facade.d.ts.map +1 -1
  157. package/dist/core/facade/coding-agent-facade.js +2 -3
  158. package/dist/core/facade/coding-agent-facade.js.map +1 -1
  159. package/dist/core/http-dispatcher.d.ts.map +1 -1
  160. package/dist/core/http-dispatcher.js +2 -1
  161. package/dist/core/http-dispatcher.js.map +1 -1
  162. package/dist/core/i18n/index.d.ts +14 -0
  163. package/dist/core/i18n/index.d.ts.map +1 -0
  164. package/dist/core/i18n/index.js +67 -0
  165. package/dist/core/i18n/index.js.map +1 -0
  166. package/dist/core/i18n/locales/en/example.d.ts +7 -0
  167. package/dist/core/i18n/locales/en/example.d.ts.map +1 -0
  168. package/dist/core/i18n/locales/en/example.js +7 -0
  169. package/dist/core/i18n/locales/en/example.js.map +1 -0
  170. package/dist/core/i18n/locales/zh-cn/cli.d.ts +8 -0
  171. package/dist/core/i18n/locales/zh-cn/cli.d.ts.map +1 -0
  172. package/dist/core/i18n/locales/zh-cn/cli.js +229 -0
  173. package/dist/core/i18n/locales/zh-cn/cli.js.map +1 -0
  174. package/dist/core/i18n/locales/zh-cn/common.d.ts +6 -0
  175. package/dist/core/i18n/locales/zh-cn/common.d.ts.map +1 -0
  176. package/dist/core/i18n/locales/zh-cn/common.js +6 -0
  177. package/dist/core/i18n/locales/zh-cn/common.js.map +1 -0
  178. package/dist/core/i18n/locales/zh-cn/core-contract-core.d.ts +13 -0
  179. package/dist/core/i18n/locales/zh-cn/core-contract-core.d.ts.map +1 -0
  180. package/dist/core/i18n/locales/zh-cn/core-contract-core.js +173 -0
  181. package/dist/core/i18n/locales/zh-cn/core-contract-core.js.map +1 -0
  182. package/dist/core/i18n/locales/zh-cn/core-contract-extensions.d.ts +12 -0
  183. package/dist/core/i18n/locales/zh-cn/core-contract-extensions.d.ts.map +1 -0
  184. package/dist/core/i18n/locales/zh-cn/core-contract-extensions.js +582 -0
  185. package/dist/core/i18n/locales/zh-cn/core-contract-extensions.js.map +1 -0
  186. package/dist/core/i18n/locales/zh-cn/core-contract-final.d.ts +9 -0
  187. package/dist/core/i18n/locales/zh-cn/core-contract-final.d.ts.map +1 -0
  188. package/dist/core/i18n/locales/zh-cn/core-contract-final.js +55 -0
  189. package/dist/core/i18n/locales/zh-cn/core-contract-final.js.map +1 -0
  190. package/dist/core/i18n/locales/zh-cn/core-contract-plugins.d.ts +11 -0
  191. package/dist/core/i18n/locales/zh-cn/core-contract-plugins.d.ts.map +1 -0
  192. package/dist/core/i18n/locales/zh-cn/core-contract-plugins.js +455 -0
  193. package/dist/core/i18n/locales/zh-cn/core-contract-plugins.js.map +1 -0
  194. package/dist/core/i18n/locales/zh-cn/core-errors.d.ts +9 -0
  195. package/dist/core/i18n/locales/zh-cn/core-errors.d.ts.map +1 -0
  196. package/dist/core/i18n/locales/zh-cn/core-errors.js +191 -0
  197. package/dist/core/i18n/locales/zh-cn/core-errors.js.map +1 -0
  198. package/dist/core/i18n/locales/zh-cn/example.d.ts +7 -0
  199. package/dist/core/i18n/locales/zh-cn/example.d.ts.map +1 -0
  200. package/dist/core/i18n/locales/zh-cn/example.js +10 -0
  201. package/dist/core/i18n/locales/zh-cn/example.js.map +1 -0
  202. package/dist/core/i18n/locales/zh-cn/index.d.ts +2 -0
  203. package/dist/core/i18n/locales/zh-cn/index.d.ts.map +1 -0
  204. package/dist/core/i18n/locales/zh-cn/index.js +41 -0
  205. package/dist/core/i18n/locales/zh-cn/index.js.map +1 -0
  206. package/dist/core/i18n/locales/zh-cn/interactive-mode.d.ts +10 -0
  207. package/dist/core/i18n/locales/zh-cn/interactive-mode.d.ts.map +1 -0
  208. package/dist/core/i18n/locales/zh-cn/interactive-mode.js +267 -0
  209. package/dist/core/i18n/locales/zh-cn/interactive-mode.js.map +1 -0
  210. package/dist/core/i18n/locales/zh-cn/keybindings.d.ts +11 -0
  211. package/dist/core/i18n/locales/zh-cn/keybindings.d.ts.map +1 -0
  212. package/dist/core/i18n/locales/zh-cn/keybindings.js +67 -0
  213. package/dist/core/i18n/locales/zh-cn/keybindings.js.map +1 -0
  214. package/dist/core/i18n/locales/zh-cn/slash-commands.d.ts +7 -0
  215. package/dist/core/i18n/locales/zh-cn/slash-commands.d.ts.map +1 -0
  216. package/dist/core/i18n/locales/zh-cn/slash-commands.js +39 -0
  217. package/dist/core/i18n/locales/zh-cn/slash-commands.js.map +1 -0
  218. package/dist/core/i18n/locales/zh-cn/tui-builtin.d.ts +10 -0
  219. package/dist/core/i18n/locales/zh-cn/tui-builtin.d.ts.map +1 -0
  220. package/dist/core/i18n/locales/zh-cn/tui-builtin.js +15 -0
  221. package/dist/core/i18n/locales/zh-cn/tui-builtin.js.map +1 -0
  222. package/dist/core/i18n/locales/zh-cn/tui-components-misc.d.ts +13 -0
  223. package/dist/core/i18n/locales/zh-cn/tui-components-misc.d.ts.map +1 -0
  224. package/dist/core/i18n/locales/zh-cn/tui-components-misc.js +102 -0
  225. package/dist/core/i18n/locales/zh-cn/tui-components-misc.js.map +1 -0
  226. package/dist/core/i18n/locales/zh-cn/tui-components-selectors.d.ts +12 -0
  227. package/dist/core/i18n/locales/zh-cn/tui-components-selectors.d.ts.map +1 -0
  228. package/dist/core/i18n/locales/zh-cn/tui-components-selectors.js +286 -0
  229. package/dist/core/i18n/locales/zh-cn/tui-components-selectors.js.map +1 -0
  230. package/dist/core/i18n/locales/zh-cn/tui-interactive-misc.d.ts +9 -0
  231. package/dist/core/i18n/locales/zh-cn/tui-interactive-misc.d.ts.map +1 -0
  232. package/dist/core/i18n/locales/zh-cn/tui-interactive-misc.js +79 -0
  233. package/dist/core/i18n/locales/zh-cn/tui-interactive-misc.js.map +1 -0
  234. package/dist/core/i18n/locales/zh-cn/tui-self-owned.d.ts +8 -0
  235. package/dist/core/i18n/locales/zh-cn/tui-self-owned.d.ts.map +1 -0
  236. package/dist/core/i18n/locales/zh-cn/tui-self-owned.js +72 -0
  237. package/dist/core/i18n/locales/zh-cn/tui-self-owned.js.map +1 -0
  238. package/dist/core/keybindings.d.ts +15 -0
  239. package/dist/core/keybindings.d.ts.map +1 -1
  240. package/dist/core/keybindings.js +18 -0
  241. package/dist/core/keybindings.js.map +1 -1
  242. package/dist/core/logger.d.ts.map +1 -1
  243. package/dist/core/logger.js +5 -1
  244. package/dist/core/logger.js.map +1 -1
  245. package/dist/core/model-config.d.ts +0 -1
  246. package/dist/core/model-config.d.ts.map +1 -1
  247. package/dist/core/model-config.js +9 -1
  248. package/dist/core/model-config.js.map +1 -1
  249. package/dist/core/model-registry.d.ts.map +1 -1
  250. package/dist/core/model-registry.js +2 -1
  251. package/dist/core/model-registry.js.map +1 -1
  252. package/dist/core/model-runtime.d.ts.map +1 -1
  253. package/dist/core/model-runtime.js +11 -7
  254. package/dist/core/model-runtime.js.map +1 -1
  255. package/dist/core/package-install-host.d.ts.map +1 -1
  256. package/dist/core/package-install-host.js +4 -3
  257. package/dist/core/package-install-host.js.map +1 -1
  258. package/dist/core/package-manager.d.ts.map +1 -1
  259. package/dist/core/package-manager.js +15 -10
  260. package/dist/core/package-manager.js.map +1 -1
  261. package/dist/core/package-resource-collection.d.ts.map +1 -1
  262. package/dist/core/package-resource-collection.js +2 -1
  263. package/dist/core/package-resource-collection.js.map +1 -1
  264. package/dist/core/package-source.d.ts.map +1 -1
  265. package/dist/core/package-source.js +3 -2
  266. package/dist/core/package-source.js.map +1 -1
  267. package/dist/core/provider-composer.d.ts +2 -2
  268. package/dist/core/provider-composer.d.ts.map +1 -1
  269. package/dist/core/provider-composer.js +29 -21
  270. package/dist/core/provider-composer.js.map +1 -1
  271. package/dist/core/remote-catalog-provider.d.ts.map +1 -1
  272. package/dist/core/remote-catalog-provider.js +6 -2
  273. package/dist/core/remote-catalog-provider.js.map +1 -1
  274. package/dist/core/resolve-config-value.d.ts.map +1 -1
  275. package/dist/core/resolve-config-value.js +15 -5
  276. package/dist/core/resolve-config-value.js.map +1 -1
  277. package/dist/core/sdk.d.ts +27 -5
  278. package/dist/core/sdk.d.ts.map +1 -1
  279. package/dist/core/sdk.js +80 -55
  280. package/dist/core/sdk.js.map +1 -1
  281. package/dist/core/session-cwd.d.ts.map +1 -1
  282. package/dist/core/session-cwd.js +5 -2
  283. package/dist/core/session-cwd.js.map +1 -1
  284. package/dist/core/session-export.d.ts.map +1 -1
  285. package/dist/core/session-export.js +2 -1
  286. package/dist/core/session-export.js.map +1 -1
  287. package/dist/core/session-manager.d.ts.map +1 -1
  288. package/dist/core/session-manager.js +39 -29
  289. package/dist/core/session-manager.js.map +1 -1
  290. package/dist/core/session-storage.d.ts.map +1 -1
  291. package/dist/core/session-storage.js +3 -3
  292. package/dist/core/session-storage.js.map +1 -1
  293. package/dist/core/settings-manager.d.ts +20 -20
  294. package/dist/core/settings-manager.d.ts.map +1 -1
  295. package/dist/core/settings-manager.js +47 -59
  296. package/dist/core/settings-manager.js.map +1 -1
  297. package/dist/core/slash-commands.d.ts.map +1 -1
  298. package/dist/core/slash-commands.js +53 -32
  299. package/dist/core/slash-commands.js.map +1 -1
  300. package/dist/core/system-prompt.d.ts.map +1 -1
  301. package/dist/core/system-prompt.js +25 -2
  302. package/dist/core/system-prompt.js.map +1 -1
  303. package/dist/core/tools/bash.d.ts.map +1 -1
  304. package/dist/core/tools/bash.js +11 -7
  305. package/dist/core/tools/bash.js.map +1 -1
  306. package/dist/core/tools/edit-diff.d.ts.map +1 -1
  307. package/dist/core/tools/edit-diff.js +9 -4
  308. package/dist/core/tools/edit-diff.js.map +1 -1
  309. package/dist/core/tools/edit.d.ts.map +1 -1
  310. package/dist/core/tools/edit.js +4 -3
  311. package/dist/core/tools/edit.js.map +1 -1
  312. package/dist/core/tools/index.d.ts.map +1 -1
  313. package/dist/core/tools/index.js +3 -2
  314. package/dist/core/tools/index.js.map +1 -1
  315. package/dist/core/tools/output-accumulator.d.ts.map +1 -1
  316. package/dist/core/tools/output-accumulator.js +2 -1
  317. package/dist/core/tools/output-accumulator.js.map +1 -1
  318. package/dist/core/tools/read.d.ts.map +1 -1
  319. package/dist/core/tools/read.js +6 -2
  320. package/dist/core/tools/read.js.map +1 -1
  321. package/dist/core/tools/write.d.ts.map +1 -1
  322. package/dist/core/tools/write.js +2 -1
  323. package/dist/core/tools/write.js.map +1 -1
  324. package/dist/durable/durable-service.d.ts.map +1 -1
  325. package/dist/durable/durable-service.js +25 -18
  326. package/dist/durable/durable-service.js.map +1 -1
  327. package/dist/host/checkpoint-commit.d.ts.map +1 -1
  328. package/dist/host/checkpoint-commit.js +2 -1
  329. package/dist/host/checkpoint-commit.js.map +1 -1
  330. package/dist/host/manual-compaction.d.ts.map +1 -1
  331. package/dist/host/manual-compaction.js +2 -1
  332. package/dist/host/manual-compaction.js.map +1 -1
  333. package/dist/host/output-projection.d.ts +0 -13
  334. package/dist/host/output-projection.d.ts.map +1 -1
  335. package/dist/host/output-projection.js +16 -2
  336. package/dist/host/output-projection.js.map +1 -1
  337. package/dist/host/summary-retry.d.ts.map +1 -1
  338. package/dist/host/summary-retry.js +3 -2
  339. package/dist/host/summary-retry.js.map +1 -1
  340. package/dist/main.d.ts.map +1 -1
  341. package/dist/main.js +97 -60
  342. package/dist/main.js.map +1 -1
  343. package/dist/modes/interactive/components/agents-view.d.ts.map +1 -1
  344. package/dist/modes/interactive/components/agents-view.js +18 -15
  345. package/dist/modes/interactive/components/agents-view.js.map +1 -1
  346. package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  347. package/dist/modes/interactive/components/assistant-message.js +6 -5
  348. package/dist/modes/interactive/components/assistant-message.js.map +1 -1
  349. package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -1
  350. package/dist/modes/interactive/components/bash-execution.js +12 -7
  351. package/dist/modes/interactive/components/bash-execution.js.map +1 -1
  352. package/dist/modes/interactive/components/bordered-loader.d.ts.map +1 -1
  353. package/dist/modes/interactive/components/bordered-loader.js +2 -1
  354. package/dist/modes/interactive/components/bordered-loader.js.map +1 -1
  355. package/dist/modes/interactive/components/branch-summary-message.d.ts.map +1 -1
  356. package/dist/modes/interactive/components/branch-summary-message.js +6 -5
  357. package/dist/modes/interactive/components/branch-summary-message.js.map +1 -1
  358. package/dist/modes/interactive/components/compaction-summary-message.d.ts.map +1 -1
  359. package/dist/modes/interactive/components/compaction-summary-message.js +9 -5
  360. package/dist/modes/interactive/components/compaction-summary-message.js.map +1 -1
  361. package/dist/modes/interactive/components/config-selector.d.ts.map +1 -1
  362. package/dist/modes/interactive/components/config-selector.js +18 -15
  363. package/dist/modes/interactive/components/config-selector.js.map +1 -1
  364. package/dist/modes/interactive/components/custom-entry.d.ts.map +1 -1
  365. package/dist/modes/interactive/components/custom-entry.js +2 -1
  366. package/dist/modes/interactive/components/custom-entry.js.map +1 -1
  367. package/dist/modes/interactive/components/dialog-editor.d.ts.map +1 -1
  368. package/dist/modes/interactive/components/dialog-editor.js +5 -4
  369. package/dist/modes/interactive/components/dialog-editor.js.map +1 -1
  370. package/dist/modes/interactive/components/dialog-input.d.ts.map +1 -1
  371. package/dist/modes/interactive/components/dialog-input.js +2 -1
  372. package/dist/modes/interactive/components/dialog-input.js.map +1 -1
  373. package/dist/modes/interactive/components/dialog-selector.d.ts.map +1 -1
  374. package/dist/modes/interactive/components/dialog-selector.js +4 -3
  375. package/dist/modes/interactive/components/dialog-selector.js.map +1 -1
  376. package/dist/modes/interactive/components/first-time-setup.d.ts.map +1 -1
  377. package/dist/modes/interactive/components/first-time-setup.js +11 -10
  378. package/dist/modes/interactive/components/first-time-setup.js.map +1 -1
  379. package/dist/modes/interactive/components/footer.d.ts +0 -2
  380. package/dist/modes/interactive/components/footer.d.ts.map +1 -1
  381. package/dist/modes/interactive/components/footer.js +8 -10
  382. package/dist/modes/interactive/components/footer.js.map +1 -1
  383. package/dist/modes/interactive/components/index.d.ts +1 -0
  384. package/dist/modes/interactive/components/index.d.ts.map +1 -1
  385. package/dist/modes/interactive/components/index.js +1 -0
  386. package/dist/modes/interactive/components/index.js.map +1 -1
  387. package/dist/modes/interactive/components/keybinding-hints.d.ts.map +1 -1
  388. package/dist/modes/interactive/components/keybinding-hints.js +3 -2
  389. package/dist/modes/interactive/components/keybinding-hints.js.map +1 -1
  390. package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
  391. package/dist/modes/interactive/components/login-dialog.js +12 -11
  392. package/dist/modes/interactive/components/login-dialog.js.map +1 -1
  393. package/dist/modes/interactive/components/mermaid.d.ts.map +1 -1
  394. package/dist/modes/interactive/components/mermaid.js +6 -2
  395. package/dist/modes/interactive/components/mermaid.js.map +1 -1
  396. package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
  397. package/dist/modes/interactive/components/model-selector.js +28 -16
  398. package/dist/modes/interactive/components/model-selector.js.map +1 -1
  399. package/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -1
  400. package/dist/modes/interactive/components/oauth-selector.js +10 -9
  401. package/dist/modes/interactive/components/oauth-selector.js.map +1 -1
  402. package/dist/modes/interactive/components/plugin-manager-entry.d.ts.map +1 -1
  403. package/dist/modes/interactive/components/plugin-manager-entry.js +22 -13
  404. package/dist/modes/interactive/components/plugin-manager-entry.js.map +1 -1
  405. package/dist/modes/interactive/components/plugin-selection-entry.d.ts.map +1 -1
  406. package/dist/modes/interactive/components/plugin-selection-entry.js +27 -12
  407. package/dist/modes/interactive/components/plugin-selection-entry.js.map +1 -1
  408. package/dist/modes/interactive/components/queue-manager-selector.d.ts +60 -0
  409. package/dist/modes/interactive/components/queue-manager-selector.d.ts.map +1 -0
  410. package/dist/modes/interactive/components/queue-manager-selector.js +166 -0
  411. package/dist/modes/interactive/components/queue-manager-selector.js.map +1 -0
  412. package/dist/modes/interactive/components/scoped-models-selector.d.ts.map +1 -1
  413. package/dist/modes/interactive/components/scoped-models-selector.js +16 -14
  414. package/dist/modes/interactive/components/scoped-models-selector.js.map +1 -1
  415. package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
  416. package/dist/modes/interactive/components/session-selector.js +43 -31
  417. package/dist/modes/interactive/components/session-selector.js.map +1 -1
  418. package/dist/modes/interactive/components/settings-selector.d.ts +4 -6
  419. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  420. package/dist/modes/interactive/components/settings-selector.js +115 -120
  421. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  422. package/dist/modes/interactive/components/settings-submenu.d.ts.map +1 -1
  423. package/dist/modes/interactive/components/settings-submenu.js +5 -4
  424. package/dist/modes/interactive/components/settings-submenu.js.map +1 -1
  425. package/dist/modes/interactive/components/show-images-selector.d.ts.map +1 -1
  426. package/dist/modes/interactive/components/show-images-selector.js +3 -2
  427. package/dist/modes/interactive/components/show-images-selector.js.map +1 -1
  428. package/dist/modes/interactive/components/skill-invocation-message.d.ts.map +1 -1
  429. package/dist/modes/interactive/components/skill-invocation-message.js +4 -3
  430. package/dist/modes/interactive/components/skill-invocation-message.js.map +1 -1
  431. package/dist/modes/interactive/components/status-indicator.d.ts.map +1 -1
  432. package/dist/modes/interactive/components/status-indicator.js +14 -5
  433. package/dist/modes/interactive/components/status-indicator.js.map +1 -1
  434. package/dist/modes/interactive/components/theme-selector.d.ts.map +1 -1
  435. package/dist/modes/interactive/components/theme-selector.js +2 -1
  436. package/dist/modes/interactive/components/theme-selector.js.map +1 -1
  437. package/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -1
  438. package/dist/modes/interactive/components/thinking-selector.js +11 -4
  439. package/dist/modes/interactive/components/thinking-selector.js.map +1 -1
  440. package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  441. package/dist/modes/interactive/components/tool-execution.js +8 -3
  442. package/dist/modes/interactive/components/tool-execution.js.map +1 -1
  443. package/dist/modes/interactive/components/tree-list.d.ts.map +1 -1
  444. package/dist/modes/interactive/components/tree-list.js +7 -6
  445. package/dist/modes/interactive/components/tree-list.js.map +1 -1
  446. package/dist/modes/interactive/components/tree-render.d.ts.map +1 -1
  447. package/dist/modes/interactive/components/tree-render.js +28 -23
  448. package/dist/modes/interactive/components/tree-render.js.map +1 -1
  449. package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -1
  450. package/dist/modes/interactive/components/tree-selector.js +9 -7
  451. package/dist/modes/interactive/components/tree-selector.js.map +1 -1
  452. package/dist/modes/interactive/components/user-message-selector.d.ts.map +1 -1
  453. package/dist/modes/interactive/components/user-message-selector.js +5 -4
  454. package/dist/modes/interactive/components/user-message-selector.js.map +1 -1
  455. package/dist/modes/interactive/components/workflow-view.d.ts.map +1 -1
  456. package/dist/modes/interactive/components/workflow-view.js +36 -21
  457. package/dist/modes/interactive/components/workflow-view.js.map +1 -1
  458. package/dist/modes/interactive/external-editor.d.ts.map +1 -1
  459. package/dist/modes/interactive/external-editor.js +2 -1
  460. package/dist/modes/interactive/external-editor.js.map +1 -1
  461. package/dist/modes/interactive/interactive-auth.d.ts.map +1 -1
  462. package/dist/modes/interactive/interactive-auth.js +71 -40
  463. package/dist/modes/interactive/interactive-auth.js.map +1 -1
  464. package/dist/modes/interactive/interactive-commands.d.ts +1 -0
  465. package/dist/modes/interactive/interactive-commands.d.ts.map +1 -1
  466. package/dist/modes/interactive/interactive-commands.js +3 -0
  467. package/dist/modes/interactive/interactive-commands.js.map +1 -1
  468. package/dist/modes/interactive/interactive-dialog-ui.d.ts.map +1 -1
  469. package/dist/modes/interactive/interactive-dialog-ui.js +5 -5
  470. package/dist/modes/interactive/interactive-dialog-ui.js.map +1 -1
  471. package/dist/modes/interactive/interactive-format.d.ts.map +1 -1
  472. package/dist/modes/interactive/interactive-format.js +34 -18
  473. package/dist/modes/interactive/interactive-format.js.map +1 -1
  474. package/dist/modes/interactive/interactive-helpers.d.ts.map +1 -1
  475. package/dist/modes/interactive/interactive-helpers.js +7 -2
  476. package/dist/modes/interactive/interactive-helpers.js.map +1 -1
  477. package/dist/modes/interactive/interactive-mode.d.ts +4 -2
  478. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  479. package/dist/modes/interactive/interactive-mode.js +350 -279
  480. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  481. package/dist/modes/interactive/interactive-selectors.d.ts +9 -0
  482. package/dist/modes/interactive/interactive-selectors.d.ts.map +1 -1
  483. package/dist/modes/interactive/interactive-selectors.js +79 -25
  484. package/dist/modes/interactive/interactive-selectors.js.map +1 -1
  485. package/dist/modes/interactive/theme/theme-controller.d.ts.map +1 -1
  486. package/dist/modes/interactive/theme/theme-controller.js +5 -1
  487. package/dist/modes/interactive/theme/theme-controller.js.map +1 -1
  488. package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  489. package/dist/modes/interactive/theme/theme.js +26 -23
  490. package/dist/modes/interactive/theme/theme.js.map +1 -1
  491. package/dist/modes/json-event.d.ts.map +1 -1
  492. package/dist/modes/json-event.js +3 -2
  493. package/dist/modes/json-event.js.map +1 -1
  494. package/dist/modes/print-mode.d.ts.map +1 -1
  495. package/dist/modes/print-mode.js +3 -2
  496. package/dist/modes/print-mode.js.map +1 -1
  497. package/dist/modes/rpc/rpc-client.d.ts +0 -8
  498. package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  499. package/dist/modes/rpc/rpc-client.js +3 -14
  500. package/dist/modes/rpc/rpc-client.js.map +1 -1
  501. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  502. package/dist/modes/rpc/rpc-mode.js +0 -9
  503. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  504. package/dist/modes/rpc/rpc-types.d.ts +0 -19
  505. package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  506. package/dist/modes/rpc/rpc-types.js.map +1 -1
  507. package/dist/package-manager-cli.d.ts.map +1 -1
  508. package/dist/package-manager-cli.js +28 -13
  509. package/dist/package-manager-cli.js.map +1 -1
  510. package/dist/plugins/ecosystem/catalog.d.ts.map +1 -1
  511. package/dist/plugins/ecosystem/catalog.js +3 -2
  512. package/dist/plugins/ecosystem/catalog.js.map +1 -1
  513. package/dist/plugins/ecosystem/cli.d.ts.map +1 -1
  514. package/dist/plugins/ecosystem/cli.js +2 -1
  515. package/dist/plugins/ecosystem/cli.js.map +1 -1
  516. package/dist/plugins/ecosystem/default-plugin-market.d.ts.map +1 -1
  517. package/dist/plugins/ecosystem/default-plugin-market.js +3 -2
  518. package/dist/plugins/ecosystem/default-plugin-market.js.map +1 -1
  519. package/dist/plugins/ecosystem/distribution.d.ts.map +1 -1
  520. package/dist/plugins/ecosystem/distribution.js +2 -1
  521. package/dist/plugins/ecosystem/distribution.js.map +1 -1
  522. package/dist/plugins/ecosystem/installer.d.ts.map +1 -1
  523. package/dist/plugins/ecosystem/installer.js +3 -2
  524. package/dist/plugins/ecosystem/installer.js.map +1 -1
  525. package/dist/plugins/ecosystem/node-disk-registry-source.d.ts.map +1 -1
  526. package/dist/plugins/ecosystem/node-disk-registry-source.js +20 -17
  527. package/dist/plugins/ecosystem/node-disk-registry-source.js.map +1 -1
  528. package/dist/plugins/ecosystem/node-distribution-host.d.ts.map +1 -1
  529. package/dist/plugins/ecosystem/node-distribution-host.js +35 -34
  530. package/dist/plugins/ecosystem/node-distribution-host.js.map +1 -1
  531. package/dist/plugins/ecosystem/node-npm-registry-source.d.ts.map +1 -1
  532. package/dist/plugins/ecosystem/node-npm-registry-source.js +35 -34
  533. package/dist/plugins/ecosystem/node-npm-registry-source.js.map +1 -1
  534. package/dist/plugins/ecosystem/node-package-install-host.d.ts.map +1 -1
  535. package/dist/plugins/ecosystem/node-package-install-host.js +9 -8
  536. package/dist/plugins/ecosystem/node-package-install-host.js.map +1 -1
  537. package/dist/plugins/ecosystem/node-package-install-persistence.d.ts.map +1 -1
  538. package/dist/plugins/ecosystem/node-package-install-persistence.js +4 -3
  539. package/dist/plugins/ecosystem/node-package-install-persistence.js.map +1 -1
  540. package/dist/plugins/ecosystem/node-plugin-bootstrap.d.ts +9 -2
  541. package/dist/plugins/ecosystem/node-plugin-bootstrap.d.ts.map +1 -1
  542. package/dist/plugins/ecosystem/node-plugin-bootstrap.js +44 -5
  543. package/dist/plugins/ecosystem/node-plugin-bootstrap.js.map +1 -1
  544. package/dist/plugins/ecosystem/node-plugin-trust-root.d.ts.map +1 -1
  545. package/dist/plugins/ecosystem/node-plugin-trust-root.js +10 -9
  546. package/dist/plugins/ecosystem/node-plugin-trust-root.js.map +1 -1
  547. package/dist/plugins/ecosystem/node-registry-source.d.ts.map +1 -1
  548. package/dist/plugins/ecosystem/node-registry-source.js +31 -30
  549. package/dist/plugins/ecosystem/node-registry-source.js.map +1 -1
  550. package/dist/plugins/ecosystem/node-release-package-source.d.ts.map +1 -1
  551. package/dist/plugins/ecosystem/node-release-package-source.js +30 -29
  552. package/dist/plugins/ecosystem/node-release-package-source.js.map +1 -1
  553. package/dist/plugins/ecosystem/node-tar-writer.d.ts.map +1 -1
  554. package/dist/plugins/ecosystem/node-tar-writer.js +11 -10
  555. package/dist/plugins/ecosystem/node-tar-writer.js.map +1 -1
  556. package/dist/plugins/ecosystem/node-url-package-source.d.ts.map +1 -1
  557. package/dist/plugins/ecosystem/node-url-package-source.js +21 -20
  558. package/dist/plugins/ecosystem/node-url-package-source.js.map +1 -1
  559. package/dist/plugins/ecosystem/plugin-acquisition.d.ts.map +1 -1
  560. package/dist/plugins/ecosystem/plugin-acquisition.js +3 -2
  561. package/dist/plugins/ecosystem/plugin-acquisition.js.map +1 -1
  562. package/dist/plugins/ecosystem/plugin-bootstrap.d.ts +9 -1
  563. package/dist/plugins/ecosystem/plugin-bootstrap.d.ts.map +1 -1
  564. package/dist/plugins/ecosystem/plugin-bootstrap.js +5 -0
  565. package/dist/plugins/ecosystem/plugin-bootstrap.js.map +1 -1
  566. package/dist/plugins/ecosystem/registry-cli-adapter.d.ts.map +1 -1
  567. package/dist/plugins/ecosystem/registry-cli-adapter.js +2 -1
  568. package/dist/plugins/ecosystem/registry-cli-adapter.js.map +1 -1
  569. package/dist/plugins/ecosystem/registry.d.ts.map +1 -1
  570. package/dist/plugins/ecosystem/registry.js +35 -32
  571. package/dist/plugins/ecosystem/registry.js.map +1 -1
  572. package/dist/plugins/ecosystem/resolver.d.ts.map +1 -1
  573. package/dist/plugins/ecosystem/resolver.js +3 -2
  574. package/dist/plugins/ecosystem/resolver.js.map +1 -1
  575. package/dist/plugins/ecosystem/selection-store.d.ts.map +1 -1
  576. package/dist/plugins/ecosystem/selection-store.js +11 -10
  577. package/dist/plugins/ecosystem/selection-store.js.map +1 -1
  578. package/dist/plugins/ecosystem/selection.d.ts.map +1 -1
  579. package/dist/plugins/ecosystem/selection.js +8 -7
  580. package/dist/plugins/ecosystem/selection.js.map +1 -1
  581. package/dist/plugins/ecosystem/state.d.ts.map +1 -1
  582. package/dist/plugins/ecosystem/state.js +24 -23
  583. package/dist/plugins/ecosystem/state.js.map +1 -1
  584. package/dist/plugins/ecosystem/updates.d.ts.map +1 -1
  585. package/dist/plugins/ecosystem/updates.js +5 -4
  586. package/dist/plugins/ecosystem/updates.js.map +1 -1
  587. package/dist/plugins/mcp-http.d.ts +0 -17
  588. package/dist/plugins/mcp-http.d.ts.map +1 -1
  589. package/dist/plugins/mcp-http.js +30 -7
  590. package/dist/plugins/mcp-http.js.map +1 -1
  591. package/dist/plugins/plugin-supervisor.d.ts.map +1 -1
  592. package/dist/plugins/plugin-supervisor.js +19 -1
  593. package/dist/plugins/plugin-supervisor.js.map +1 -1
  594. package/dist/profile/first-roles.d.ts.map +1 -1
  595. package/dist/profile/first-roles.js +10 -1
  596. package/dist/profile/first-roles.js.map +1 -1
  597. package/dist/profile/goal-plugin.d.ts.map +1 -1
  598. package/dist/profile/goal-plugin.js +24 -5
  599. package/dist/profile/goal-plugin.js.map +1 -1
  600. package/dist/profile/identity.d.ts.map +1 -1
  601. package/dist/profile/identity.js +7 -6
  602. package/dist/profile/identity.js.map +1 -1
  603. package/dist/profile/lock.d.ts.map +1 -1
  604. package/dist/profile/lock.js +15 -1
  605. package/dist/profile/lock.js.map +1 -1
  606. package/dist/profile/plan-plugin.d.ts.map +1 -1
  607. package/dist/profile/plan-plugin.js +26 -13
  608. package/dist/profile/plan-plugin.js.map +1 -1
  609. package/dist/profile/plugin-profiles.d.ts.map +1 -1
  610. package/dist/profile/plugin-profiles.js +2 -1
  611. package/dist/profile/plugin-profiles.js.map +1 -1
  612. package/dist/profile/policy-manifest.d.ts.map +1 -1
  613. package/dist/profile/policy-manifest.js +5 -4
  614. package/dist/profile/policy-manifest.js.map +1 -1
  615. package/dist/profile/profile-registry.d.ts +0 -12
  616. package/dist/profile/profile-registry.d.ts.map +1 -1
  617. package/dist/profile/profile-registry.js +14 -1
  618. package/dist/profile/profile-registry.js.map +1 -1
  619. package/dist/profile/role-catalog.d.ts +0 -1
  620. package/dist/profile/role-catalog.d.ts.map +1 -1
  621. package/dist/profile/role-catalog.js +17 -15
  622. package/dist/profile/role-catalog.js.map +1 -1
  623. package/dist/profile/role-orchestrator.d.ts.map +1 -1
  624. package/dist/profile/role-orchestrator.js +8 -7
  625. package/dist/profile/role-orchestrator.js.map +1 -1
  626. package/dist/profile/role-runner.d.ts.map +1 -1
  627. package/dist/profile/role-runner.js +3 -2
  628. package/dist/profile/role-runner.js.map +1 -1
  629. package/dist/profile/root-facade.d.ts.map +1 -1
  630. package/dist/profile/root-facade.js +2 -1
  631. package/dist/profile/root-facade.js.map +1 -1
  632. package/dist/profile/skill-discovery-wiring.d.ts.map +1 -1
  633. package/dist/profile/skill-discovery-wiring.js +7 -2
  634. package/dist/profile/skill-discovery-wiring.js.map +1 -1
  635. package/dist/profile/state-store.d.ts.map +1 -1
  636. package/dist/profile/state-store.js +13 -9
  637. package/dist/profile/state-store.js.map +1 -1
  638. package/dist/profile/todo-plugin.d.ts.map +1 -1
  639. package/dist/profile/todo-plugin.js +9 -4
  640. package/dist/profile/todo-plugin.js.map +1 -1
  641. package/dist/profiles/builtin-suites.d.ts +13 -6
  642. package/dist/profiles/builtin-suites.d.ts.map +1 -1
  643. package/dist/profiles/builtin-suites.js +15 -6
  644. package/dist/profiles/builtin-suites.js.map +1 -1
  645. package/dist/profiles/suite-loader.d.ts +25 -1
  646. package/dist/profiles/suite-loader.d.ts.map +1 -1
  647. package/dist/profiles/suite-loader.js +34 -9
  648. package/dist/profiles/suite-loader.js.map +1 -1
  649. package/dist/remote/server-entry.d.ts.map +1 -1
  650. package/dist/remote/server-entry.js +3 -2
  651. package/dist/remote/server-entry.js.map +1 -1
  652. package/dist/remote/session-source.d.ts.map +1 -1
  653. package/dist/remote/session-source.js +8 -4
  654. package/dist/remote/session-source.js.map +1 -1
  655. package/dist/share/session-share.d.ts.map +1 -1
  656. package/dist/share/session-share.js +14 -2
  657. package/dist/share/session-share.js.map +1 -1
  658. package/dist/testing/plugin-testkit.d.ts.map +1 -1
  659. package/dist/testing/plugin-testkit.js +4 -3
  660. package/dist/testing/plugin-testkit.js.map +1 -1
  661. package/dist/testing/runtime-delivery-queue.d.ts.map +1 -1
  662. package/dist/testing/runtime-delivery-queue.js +2 -1
  663. package/dist/testing/runtime-delivery-queue.js.map +1 -1
  664. package/dist/testing/session-plugin-testkit.d.ts.map +1 -1
  665. package/dist/testing/session-plugin-testkit.js +10 -7
  666. package/dist/testing/session-plugin-testkit.js.map +1 -1
  667. package/dist/utils/ansi.d.ts.map +1 -1
  668. package/dist/utils/ansi.js +2 -1
  669. package/dist/utils/ansi.js.map +1 -1
  670. package/dist/utils/clipboard.d.ts.map +1 -1
  671. package/dist/utils/clipboard.js +7 -6
  672. package/dist/utils/clipboard.js.map +1 -1
  673. package/dist/utils/image-resize-worker.d.ts.map +1 -1
  674. package/dist/utils/image-resize-worker.js +3 -2
  675. package/dist/utils/image-resize-worker.js.map +1 -1
  676. package/dist/utils/photon.d.ts +2 -2
  677. package/dist/utils/photon.d.ts.map +1 -1
  678. package/dist/utils/photon.js +2 -2
  679. package/dist/utils/photon.js.map +1 -1
  680. package/dist/utils/shell.d.ts.map +1 -1
  681. package/dist/utils/shell.js +9 -8
  682. package/dist/utils/shell.js.map +1 -1
  683. package/dist/utils/tools-manager.d.ts.map +1 -1
  684. package/dist/utils/tools-manager.js +23 -13
  685. package/dist/utils/tools-manager.js.map +1 -1
  686. package/dist/utils/version-check.d.ts.map +1 -1
  687. package/dist/utils/version-check.js +5 -1
  688. package/dist/utils/version-check.js.map +1 -1
  689. package/docs/compaction.md +1 -3
  690. package/docs/docs.json +4 -0
  691. package/docs/index.md +1 -0
  692. package/docs/keybindings.md +3 -0
  693. package/docs/mcp.md +103 -0
  694. package/docs/models.md +14 -22
  695. package/docs/providers.md +0 -1
  696. package/docs/quickstart.md +1 -1
  697. package/docs/rpc.md +1 -26
  698. package/docs/sdk.md +4 -6
  699. package/docs/settings.md +10 -12
  700. package/docs/skills.md +1 -9
  701. package/docs/terminal-setup.md +2 -3
  702. package/docs/usage.md +7 -6
  703. package/examples/extensions/with-deps/package-lock.json +2 -2
  704. package/examples/extensions/with-deps/package.json +1 -1
  705. package/examples/extensions/with-deps/plugin.json +1 -1
  706. package/examples/sdk/10-settings.ts +2 -4
  707. package/examples/sdk/12-full-control.ts +1 -2
  708. package/package.json +1 -3
  709. package/dist/bundle/chunks/chunk-EALJ5DDX.js +0 -1452
  710. package/dist/core/extensions/microcompact.d.ts +0 -80
  711. package/dist/core/extensions/microcompact.d.ts.map +0 -1
  712. package/dist/core/extensions/microcompact.js +0 -134
  713. package/dist/core/extensions/microcompact.js.map +0 -1
  714. package/dist/server/create-harness.d.ts +0 -26
  715. package/dist/server/create-harness.d.ts.map +0 -1
  716. package/dist/server/create-harness.js +0 -106
  717. package/dist/server/create-harness.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"plan-plugin.js","sourceRoot":"","sources":["../../src/profile/plan-plugin.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Plan plugin (2.3c) — Plan semantics bound to a branch/revision over the\n * 2.3a transition store.\n *\n * Status graph: null → draft → active → completed, and draft/active →\n * discarded. A plan is created with its step list and bound to a code branch;\n * while active, `linkRevision` records plan progress against concrete\n * revisions, and `complete` requires evidence plus the final revision. The\n * plugin holds NO shadow state: status, revision, steps, branch, and the\n * latest linked revision are all derived from the transition history, so\n * recovery is exactly a store replay.\n */\nimport type { JsonValue } from \"@agent-forge/ai\";\nimport type { TransitionEvidenceRefV1, TransitionStoreV1 } from \"./state-store.ts\";\n\nexport type PlanStatusV1 = \"draft\" | \"active\" | \"completed\" | \"discarded\";\n\nexport interface PlanStepV1 {\n\treadonly stepId: string;\n\treadonly title: string;\n}\n\nexport interface PlanV1 {\n\treadonly planId: string;\n\treadonly owner: string;\n\treadonly title: string;\n\treadonly branch: string;\n\treadonly steps: readonly PlanStepV1[];\n\treadonly status: PlanStatusV1;\n\t/** The latest revision explicitly linked while active (undefined before the first link). */\n\treadonly revision?: number;\n\treadonly evidence: readonly TransitionEvidenceRefV1[];\n\treadonly revisionNo: number;\n}\n\nexport interface PlanPluginV1 {\n\tcreatePlan(input: {\n\t\treadonly planId: string;\n\t\treadonly owner: string;\n\t\treadonly title: string;\n\t\treadonly branch: string;\n\t\treadonly steps: readonly PlanStepV1[];\n\t}): PlanV1;\n\tactivate(planId: string, owner: string, options?: { readonly operationId?: string }): PlanV1;\n\t/** Records plan progress against a concrete revision of the bound branch. */\n\tlinkRevision(planId: string, owner: string, revision: number, options?: { readonly operationId?: string }): PlanV1;\n\tcomplete(\n\t\tplanId: string,\n\t\towner: string,\n\t\tevidence: readonly TransitionEvidenceRefV1[],\n\t\toptions?: { readonly atRevision?: number; readonly operationId?: string },\n\t): PlanV1;\n\tdiscard(planId: string, owner: string): PlanV1;\n\tget(planId: string, owner: string): PlanV1 | undefined;\n}\n\ninterface PlanPayloadV1 {\n\treadonly title: string;\n\treadonly branch: string;\n\treadonly steps: readonly PlanStepV1[];\n\treadonly linkedRevision?: number;\n}\n\nfunction planPayloadOf(record: { readonly payload?: unknown }): Partial<PlanPayloadV1> | undefined {\n\tconst payload = record.payload;\n\tif (payload !== null && typeof payload === \"object\" && !Array.isArray(payload)) {\n\t\treturn payload as Partial<PlanPayloadV1>;\n\t}\n\treturn undefined;\n}\n\nexport function createPlanPlugin(options: { readonly transitions: TransitionStoreV1 }): PlanPluginV1 {\n\tconst transitions = options.transitions;\n\n\tconst planHistory = (planId: string, owner: string) =>\n\t\ttransitions.history(planId).filter((record) => record.domain === \"plan\" && record.owner === owner);\n\n\tconst current = (planId: string, owner: string): { status: PlanStatusV1; revisionNo: number } | undefined => {\n\t\tconst state = transitions.currentStatus(\"plan\", planId);\n\t\tif (state === undefined || planHistory(planId, owner).length === 0) return undefined;\n\t\treturn { status: state.status as PlanStatusV1, revisionNo: state.revision };\n\t};\n\n\tconst planGet = (planId: string, owner: string): PlanV1 | undefined => {\n\t\tconst state = current(planId, owner);\n\t\tif (!state) return undefined;\n\t\tconst history = planHistory(planId, owner);\n\t\t// v8 ignore next -- 因果校验保证每条 plan 历史都以 fromStatus=null 的创建记录开始\n\t\tconst createPayload = planPayloadOf(history.find((record) => record.fromStatus === null) ?? {});\n\t\tconst lastLinked = [...history]\n\t\t\t.reverse()\n\t\t\t.map((record) => planPayloadOf(record)?.linkedRevision)\n\t\t\t.find((revision): revision is number => typeof revision === \"number\");\n\t\tconst lastEvidence = [...history].reverse().find((record) => record.evidence.length > 0)?.evidence ?? [];\n\t\treturn {\n\t\t\tplanId,\n\t\t\towner,\n\t\t\ttitle: createPayload?.title ?? planId,\n\t\t\tbranch: createPayload?.branch ?? \"\",\n\t\t\tsteps: createPayload?.steps ?? [],\n\t\t\tstatus: state.status,\n\t\t\t...(lastLinked === undefined ? {} : { revision: lastLinked }),\n\t\t\tevidence: lastEvidence,\n\t\t\trevisionNo: state.revisionNo,\n\t\t};\n\t};\n\n\t/** A retried transition with an already-applied operationId returns the existing state instead of conflicting. */\n\tconst replayedPlan = (\n\t\tplanId: string,\n\t\towner: string,\n\t\ttoStatus: PlanStatusV1,\n\t\toperationId?: string,\n\t): PlanV1 | undefined => {\n\t\tif (!operationId) return undefined;\n\t\tconst applied = planHistory(planId, owner).some(\n\t\t\t(record) => record.toStatus === toStatus && record.operationId === operationId,\n\t\t);\n\t\treturn applied ? planGet(planId, owner) : undefined;\n\t};\n\n\tconst transitionPlan = (\n\t\tplanId: string,\n\t\towner: string,\n\t\tfromStatus: PlanStatusV1 | null,\n\t\ttoStatus: PlanStatusV1,\n\t\tplanOptions: {\n\t\t\treadonly evidence?: readonly TransitionEvidenceRefV1[];\n\t\t\treadonly payload?: PlanPayloadV1;\n\t\t\treadonly operationId?: string;\n\t\t},\n\t): PlanV1 => {\n\t\ttransitions.transition({\n\t\t\tdomain: \"plan\",\n\t\t\tentityId: planId,\n\t\t\towner,\n\t\t\tfromStatus,\n\t\t\ttoStatus,\n\t\t\toperationId: planOptions.operationId ?? `${toStatus}:${planId}`,\n\t\t\tevidence: planOptions.evidence,\n\t\t\tpayload: planOptions.payload as JsonValue | undefined,\n\t\t});\n\t\treturn planGet(planId, owner)!;\n\t};\n\n\treturn {\n\t\tcreatePlan({ planId, owner, title, branch, steps }) {\n\t\t\tif (title.trim().length === 0) throw new Error(\"Plan title must be a non-empty string\");\n\t\t\tif (branch.trim().length === 0) throw new Error(\"Plan branch must be a non-empty string\");\n\t\t\tif (steps.length === 0) throw new Error(\"Plan requires at least one step\");\n\t\t\tconst stepIds = new Set<string>();\n\t\t\tfor (const step of steps) {\n\t\t\t\tif (typeof step.stepId !== \"string\" || step.stepId.trim().length === 0) {\n\t\t\t\t\tthrow new Error(\"Plan stepId must be a non-empty string\");\n\t\t\t\t}\n\t\t\t\tif (typeof step.title !== \"string\" || step.title.trim().length === 0) {\n\t\t\t\t\tthrow new Error(\"Plan step title must be a non-empty string\");\n\t\t\t\t}\n\t\t\t\tif (stepIds.has(step.stepId)) throw new Error(`Duplicate plan stepId: ${step.stepId}`);\n\t\t\t\tstepIds.add(step.stepId);\n\t\t\t}\n\t\t\treturn transitionPlan(planId, owner, null, \"draft\", {\n\t\t\t\tpayload: { title, branch, steps: [...steps] },\n\t\t\t\toperationId: `create:${planId}`,\n\t\t\t});\n\t\t},\n\t\tactivate(planId, owner, activateOptions) {\n\t\t\tconst replayed = replayedPlan(planId, owner, \"active\", activateOptions?.operationId);\n\t\t\tif (replayed) return replayed;\n\t\t\tconst plan = planGet(planId, owner);\n\t\t\tif (plan?.status !== \"draft\") {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Plan ${planId} must be in draft status to activate (current: ${plan?.status ?? \"missing\"})`,\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn transitionPlan(planId, owner, \"draft\", \"active\", { operationId: activateOptions?.operationId });\n\t\t},\n\t\tlinkRevision(planId, owner, revision, linkOptions) {\n\t\t\tconst replayed = replayedPlan(planId, owner, \"active\", linkOptions?.operationId);\n\t\t\tif (replayed) return replayed;\n\t\t\tconst plan = planGet(planId, owner);\n\t\t\tif (plan?.status !== \"active\") {\n\t\t\t\tthrow new Error(`Plan ${planId} must be active to link a revision (current: ${plan?.status ?? \"missing\"})`);\n\t\t\t}\n\t\t\tif (!Number.isSafeInteger(revision) || revision < 1) {\n\t\t\t\tthrow new Error(`Plan revision must be a positive safe integer, got ${revision}`);\n\t\t\t}\n\t\t\treturn transitionPlan(planId, owner, \"active\", \"active\", {\n\t\t\t\tpayload: { title: plan.title, branch: plan.branch, steps: plan.steps, linkedRevision: revision },\n\t\t\t\toperationId: linkOptions?.operationId ?? `link:${planId}:${revision}`,\n\t\t\t});\n\t\t},\n\t\tcomplete(planId, owner, evidence, completeOptions) {\n\t\t\tconst replayed = replayedPlan(planId, owner, \"completed\", completeOptions?.operationId);\n\t\t\tif (replayed) return replayed;\n\t\t\tconst plan = planGet(planId, owner);\n\t\t\tif (plan?.status !== \"active\") {\n\t\t\t\tthrow new Error(`Plan ${planId} must be active to complete (current: ${plan?.status ?? \"missing\"})`);\n\t\t\t}\n\t\t\tif (evidence.length === 0) throw new Error(\"Completing a plan requires at least one evidence reference\");\n\t\t\tconst target = completeOptions?.atRevision ?? plan.revision;\n\t\t\tif (typeof target !== \"number\") {\n\t\t\t\tthrow new Error(`Plan ${planId} requires atRevision or a linked revision to complete`);\n\t\t\t}\n\t\t\treturn transitionPlan(planId, owner, \"active\", \"completed\", {\n\t\t\t\tevidence,\n\t\t\t\tpayload: { title: plan.title, branch: plan.branch, steps: plan.steps, linkedRevision: target },\n\t\t\t\toperationId: completeOptions?.operationId,\n\t\t\t});\n\t\t},\n\t\tdiscard(planId, owner) {\n\t\t\tconst plan = planGet(planId, owner);\n\t\t\tif (!plan || plan.status === \"completed\" || plan.status === \"discarded\") {\n\t\t\t\tthrow new Error(`Plan ${planId} cannot be discarded from status ${plan?.status ?? \"missing\"}`);\n\t\t\t}\n\t\t\treturn transitionPlan(planId, owner, plan.status, \"discarded\", {});\n\t\t},\n\t\tget(planId, owner) {\n\t\t\treturn planGet(planId, owner);\n\t\t},\n\t};\n}\n"]}
1
+ {"version":3,"file":"plan-plugin.js","sourceRoot":"","sources":["../../src/profile/plan-plugin.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,CAAC,EAAE,MAAM,uBAAuB,CAAC;AAmD1C,SAAS,aAAa,CAAC,MAAsC,EAAsC;IAClG,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC;IAC/B,IAAI,OAAO,KAAK,IAAI,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QAChF,OAAO,OAAiC,CAAC;IAC1C,CAAC;IACD,OAAO,SAAS,CAAC;AAAA,CACjB;AAED,MAAM,UAAU,gBAAgB,CAAC,OAAoD,EAAgB;IACpG,MAAM,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC;IAExC,MAAM,WAAW,GAAG,CAAC,MAAc,EAAE,KAAa,EAAE,EAAE,CACrD,WAAW,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,KAAK,MAAM,IAAI,MAAM,CAAC,KAAK,KAAK,KAAK,CAAC,CAAC;IAEpG,MAAM,OAAO,GAAG,CAAC,MAAc,EAAE,KAAa,EAA4D,EAAE,CAAC;QAC5G,MAAM,KAAK,GAAG,WAAW,CAAC,aAAa,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACxD,IAAI,KAAK,KAAK,SAAS,IAAI,WAAW,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,SAAS,CAAC;QACrF,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,MAAsB,EAAE,UAAU,EAAE,KAAK,CAAC,QAAQ,EAAE,CAAC;IAAA,CAC5E,CAAC;IAEF,MAAM,OAAO,GAAG,CAAC,MAAc,EAAE,KAAa,EAAsB,EAAE,CAAC;QACtE,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QACrC,IAAI,CAAC,KAAK;YAAE,OAAO,SAAS,CAAC;QAC7B,MAAM,OAAO,GAAG,WAAW,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QAC3C,qGAA+D;QAC/D,MAAM,aAAa,GAAG,aAAa,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,UAAU,KAAK,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;QAChG,MAAM,UAAU,GAAG,CAAC,GAAG,OAAO,CAAC;aAC7B,OAAO,EAAE;aACT,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,aAAa,CAAC,MAAM,CAAC,EAAE,cAAc,CAAC;aACtD,IAAI,CAAC,CAAC,QAAQ,EAAsB,EAAE,CAAC,OAAO,QAAQ,KAAK,QAAQ,CAAC,CAAC;QACvE,MAAM,YAAY,GAAG,CAAC,GAAG,OAAO,CAAC,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,EAAE,QAAQ,IAAI,EAAE,CAAC;QACzG,OAAO;YACN,MAAM;YACN,KAAK;YACL,KAAK,EAAE,aAAa,EAAE,KAAK,IAAI,MAAM;YACrC,MAAM,EAAE,aAAa,EAAE,MAAM,IAAI,EAAE;YACnC,KAAK,EAAE,aAAa,EAAE,KAAK,IAAI,EAAE;YACjC,MAAM,EAAE,KAAK,CAAC,MAAM;YACpB,GAAG,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,UAAU,EAAE,CAAC;YAC7D,QAAQ,EAAE,YAAY;YACtB,UAAU,EAAE,KAAK,CAAC,UAAU;SAC5B,CAAC;IAAA,CACF,CAAC;IAEF,kHAAkH;IAClH,MAAM,YAAY,GAAG,CACpB,MAAc,EACd,KAAa,EACb,QAAsB,EACtB,WAAoB,EACC,EAAE,CAAC;QACxB,IAAI,CAAC,WAAW;YAAE,OAAO,SAAS,CAAC;QACnC,MAAM,OAAO,GAAG,WAAW,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,IAAI,CAC9C,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,QAAQ,KAAK,QAAQ,IAAI,MAAM,CAAC,WAAW,KAAK,WAAW,CAC9E,CAAC;QACF,OAAO,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAAA,CACpD,CAAC;IAEF,MAAM,cAAc,GAAG,CACtB,MAAc,EACd,KAAa,EACb,UAA+B,EAC/B,QAAsB,EACtB,WAIC,EACQ,EAAE,CAAC;QACZ,WAAW,CAAC,UAAU,CAAC;YACtB,MAAM,EAAE,MAAM;YACd,QAAQ,EAAE,MAAM;YAChB,KAAK;YACL,UAAU;YACV,QAAQ;YACR,WAAW,EAAE,WAAW,CAAC,WAAW,IAAI,GAAG,QAAQ,IAAI,MAAM,EAAE;YAC/D,QAAQ,EAAE,WAAW,CAAC,QAAQ;YAC9B,OAAO,EAAE,WAAW,CAAC,OAAgC;SACrD,CAAC,CAAC;QACH,OAAO,OAAO,CAAC,MAAM,EAAE,KAAK,CAAE,CAAC;IAAA,CAC/B,CAAC;IAEF,OAAO;QACN,UAAU,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE;YACnD,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC;gBAAE,MAAM,IAAI,KAAK,CAAC,CAAC,CAAC,uCAAuC,CAAC,CAAC,CAAC;YAC3F,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC;gBAAE,MAAM,IAAI,KAAK,CAAC,CAAC,CAAC,wCAAwC,CAAC,CAAC,CAAC;YAC7F,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;gBAAE,MAAM,IAAI,KAAK,CAAC,CAAC,CAAC,iCAAiC,CAAC,CAAC,CAAC;YAC9E,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAC;YAClC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;gBAC1B,IAAI,OAAO,IAAI,CAAC,MAAM,KAAK,QAAQ,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;oBACxE,MAAM,IAAI,KAAK,CAAC,CAAC,CAAC,wCAAwC,CAAC,CAAC,CAAC;gBAC9D,CAAC;gBACD,IAAI,OAAO,IAAI,CAAC,KAAK,KAAK,QAAQ,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;oBACtE,MAAM,IAAI,KAAK,CAAC,CAAC,CAAC,4CAA4C,CAAC,CAAC,CAAC;gBAClE,CAAC;gBACD,IAAI,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC;oBAC3B,MAAM,IAAI,KAAK,CAAC,CAAC,CAAC,iCAAiC,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;gBAChF,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YAC1B,CAAC;YACD,OAAO,cAAc,CAAC,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE;gBACnD,OAAO,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,GAAG,KAAK,CAAC,EAAE;gBAC7C,WAAW,EAAE,UAAU,MAAM,EAAE;aAC/B,CAAC,CAAC;QAAA,CACH;QACD,QAAQ,CAAC,MAAM,EAAE,KAAK,EAAE,eAAe,EAAE;YACxC,MAAM,QAAQ,GAAG,YAAY,CAAC,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,eAAe,EAAE,WAAW,CAAC,CAAC;YACrF,IAAI,QAAQ;gBAAE,OAAO,QAAQ,CAAC;YAC9B,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;YACpC,IAAI,IAAI,EAAE,MAAM,KAAK,OAAO,EAAE,CAAC;gBAC9B,MAAM,IAAI,KAAK,CACd,CAAC,CAAC,uEAAuE,EAAE;oBAC1E,MAAM;oBACN,MAAM,EAAE,IAAI,EAAE,MAAM,IAAI,SAAS;iBACjC,CAAC,CACF,CAAC;YACH,CAAC;YACD,OAAO,cAAc,CAAC,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,EAAE,WAAW,EAAE,eAAe,EAAE,WAAW,EAAE,CAAC,CAAC;QAAA,CACvG;QACD,YAAY,CAAC,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE;YAClD,MAAM,QAAQ,GAAG,YAAY,CAAC,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,WAAW,CAAC,CAAC;YACjF,IAAI,QAAQ;gBAAE,OAAO,QAAQ,CAAC;YAC9B,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;YACpC,IAAI,IAAI,EAAE,MAAM,KAAK,QAAQ,EAAE,CAAC;gBAC/B,MAAM,IAAI,KAAK,CACd,CAAC,CAAC,qEAAqE,EAAE;oBACxE,MAAM;oBACN,MAAM,EAAE,IAAI,EAAE,MAAM,IAAI,SAAS;iBACjC,CAAC,CACF,CAAC;YACH,CAAC;YACD,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,QAAQ,CAAC,IAAI,QAAQ,GAAG,CAAC,EAAE,CAAC;gBACrD,MAAM,IAAI,KAAK,CAAC,CAAC,CAAC,+DAA+D,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC;YACnG,CAAC;YACD,OAAO,cAAc,CAAC,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE;gBACxD,OAAO,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,cAAc,EAAE,QAAQ,EAAE;gBAChG,WAAW,EAAE,WAAW,EAAE,WAAW,IAAI,QAAQ,MAAM,IAAI,QAAQ,EAAE;aACrE,CAAC,CAAC;QAAA,CACH;QACD,QAAQ,CAAC,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,eAAe,EAAE;YAClD,MAAM,QAAQ,GAAG,YAAY,CAAC,MAAM,EAAE,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,WAAW,CAAC,CAAC;YACxF,IAAI,QAAQ;gBAAE,OAAO,QAAQ,CAAC;YAC9B,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;YACpC,IAAI,IAAI,EAAE,MAAM,KAAK,QAAQ,EAAE,CAAC;gBAC/B,MAAM,IAAI,KAAK,CACd,CAAC,CAAC,8DAA8D,EAAE;oBACjE,MAAM;oBACN,MAAM,EAAE,IAAI,EAAE,MAAM,IAAI,SAAS;iBACjC,CAAC,CACF,CAAC;YACH,CAAC;YACD,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;gBAAE,MAAM,IAAI,KAAK,CAAC,CAAC,CAAC,4DAA4D,CAAC,CAAC,CAAC;YAC5G,MAAM,MAAM,GAAG,eAAe,EAAE,UAAU,IAAI,IAAI,CAAC,QAAQ,CAAC;YAC5D,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;gBAChC,MAAM,IAAI,KAAK,CAAC,CAAC,CAAC,oEAAoE,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC;YACtG,CAAC;YACD,OAAO,cAAc,CAAC,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE;gBAC3D,QAAQ;gBACR,OAAO,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,cAAc,EAAE,MAAM,EAAE;gBAC9F,WAAW,EAAE,eAAe,EAAE,WAAW;aACzC,CAAC,CAAC;QAAA,CACH;QACD,OAAO,CAAC,MAAM,EAAE,KAAK,EAAE;YACtB,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;YACpC,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,KAAK,WAAW,IAAI,IAAI,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;gBACzE,MAAM,IAAI,KAAK,CACd,CAAC,CAAC,wDAAwD,EAAE;oBAC3D,MAAM;oBACN,MAAM,EAAE,IAAI,EAAE,MAAM,IAAI,SAAS;iBACjC,CAAC,CACF,CAAC;YACH,CAAC;YACD,OAAO,cAAc,CAAC,MAAM,EAAE,KAAK,EAAE,IAAI,CAAC,MAAM,EAAE,WAAW,EAAE,EAAE,CAAC,CAAC;QAAA,CACnE;QACD,GAAG,CAAC,MAAM,EAAE,KAAK,EAAE;YAClB,OAAO,OAAO,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QAAA,CAC9B;KACD,CAAC;AAAA,CACF","sourcesContent":["/**\n * Plan plugin (2.3c) — Plan semantics bound to a branch/revision over the\n * 2.3a transition store.\n *\n * Status graph: null → draft → active → completed, and draft/active →\n * discarded. A plan is created with its step list and bound to a code branch;\n * while active, `linkRevision` records plan progress against concrete\n * revisions, and `complete` requires evidence plus the final revision. The\n * plugin holds NO shadow state: status, revision, steps, branch, and the\n * latest linked revision are all derived from the transition history, so\n * recovery is exactly a store replay.\n */\nimport type { JsonValue } from \"@agent-forge/ai\";\nimport { t } from \"../core/i18n/index.ts\";\nimport type { TransitionEvidenceRefV1, TransitionStoreV1 } from \"./state-store.ts\";\n\nexport type PlanStatusV1 = \"draft\" | \"active\" | \"completed\" | \"discarded\";\n\nexport interface PlanStepV1 {\n\treadonly stepId: string;\n\treadonly title: string;\n}\n\nexport interface PlanV1 {\n\treadonly planId: string;\n\treadonly owner: string;\n\treadonly title: string;\n\treadonly branch: string;\n\treadonly steps: readonly PlanStepV1[];\n\treadonly status: PlanStatusV1;\n\t/** The latest revision explicitly linked while active (undefined before the first link). */\n\treadonly revision?: number;\n\treadonly evidence: readonly TransitionEvidenceRefV1[];\n\treadonly revisionNo: number;\n}\n\nexport interface PlanPluginV1 {\n\tcreatePlan(input: {\n\t\treadonly planId: string;\n\t\treadonly owner: string;\n\t\treadonly title: string;\n\t\treadonly branch: string;\n\t\treadonly steps: readonly PlanStepV1[];\n\t}): PlanV1;\n\tactivate(planId: string, owner: string, options?: { readonly operationId?: string }): PlanV1;\n\t/** Records plan progress against a concrete revision of the bound branch. */\n\tlinkRevision(planId: string, owner: string, revision: number, options?: { readonly operationId?: string }): PlanV1;\n\tcomplete(\n\t\tplanId: string,\n\t\towner: string,\n\t\tevidence: readonly TransitionEvidenceRefV1[],\n\t\toptions?: { readonly atRevision?: number; readonly operationId?: string },\n\t): PlanV1;\n\tdiscard(planId: string, owner: string): PlanV1;\n\tget(planId: string, owner: string): PlanV1 | undefined;\n}\n\ninterface PlanPayloadV1 {\n\treadonly title: string;\n\treadonly branch: string;\n\treadonly steps: readonly PlanStepV1[];\n\treadonly linkedRevision?: number;\n}\n\nfunction planPayloadOf(record: { readonly payload?: unknown }): Partial<PlanPayloadV1> | undefined {\n\tconst payload = record.payload;\n\tif (payload !== null && typeof payload === \"object\" && !Array.isArray(payload)) {\n\t\treturn payload as Partial<PlanPayloadV1>;\n\t}\n\treturn undefined;\n}\n\nexport function createPlanPlugin(options: { readonly transitions: TransitionStoreV1 }): PlanPluginV1 {\n\tconst transitions = options.transitions;\n\n\tconst planHistory = (planId: string, owner: string) =>\n\t\ttransitions.history(planId).filter((record) => record.domain === \"plan\" && record.owner === owner);\n\n\tconst current = (planId: string, owner: string): { status: PlanStatusV1; revisionNo: number } | undefined => {\n\t\tconst state = transitions.currentStatus(\"plan\", planId);\n\t\tif (state === undefined || planHistory(planId, owner).length === 0) return undefined;\n\t\treturn { status: state.status as PlanStatusV1, revisionNo: state.revision };\n\t};\n\n\tconst planGet = (planId: string, owner: string): PlanV1 | undefined => {\n\t\tconst state = current(planId, owner);\n\t\tif (!state) return undefined;\n\t\tconst history = planHistory(planId, owner);\n\t\t// v8 ignore next -- 因果校验保证每条 plan 历史都以 fromStatus=null 的创建记录开始\n\t\tconst createPayload = planPayloadOf(history.find((record) => record.fromStatus === null) ?? {});\n\t\tconst lastLinked = [...history]\n\t\t\t.reverse()\n\t\t\t.map((record) => planPayloadOf(record)?.linkedRevision)\n\t\t\t.find((revision): revision is number => typeof revision === \"number\");\n\t\tconst lastEvidence = [...history].reverse().find((record) => record.evidence.length > 0)?.evidence ?? [];\n\t\treturn {\n\t\t\tplanId,\n\t\t\towner,\n\t\t\ttitle: createPayload?.title ?? planId,\n\t\t\tbranch: createPayload?.branch ?? \"\",\n\t\t\tsteps: createPayload?.steps ?? [],\n\t\t\tstatus: state.status,\n\t\t\t...(lastLinked === undefined ? {} : { revision: lastLinked }),\n\t\t\tevidence: lastEvidence,\n\t\t\trevisionNo: state.revisionNo,\n\t\t};\n\t};\n\n\t/** A retried transition with an already-applied operationId returns the existing state instead of conflicting. */\n\tconst replayedPlan = (\n\t\tplanId: string,\n\t\towner: string,\n\t\ttoStatus: PlanStatusV1,\n\t\toperationId?: string,\n\t): PlanV1 | undefined => {\n\t\tif (!operationId) return undefined;\n\t\tconst applied = planHistory(planId, owner).some(\n\t\t\t(record) => record.toStatus === toStatus && record.operationId === operationId,\n\t\t);\n\t\treturn applied ? planGet(planId, owner) : undefined;\n\t};\n\n\tconst transitionPlan = (\n\t\tplanId: string,\n\t\towner: string,\n\t\tfromStatus: PlanStatusV1 | null,\n\t\ttoStatus: PlanStatusV1,\n\t\tplanOptions: {\n\t\t\treadonly evidence?: readonly TransitionEvidenceRefV1[];\n\t\t\treadonly payload?: PlanPayloadV1;\n\t\t\treadonly operationId?: string;\n\t\t},\n\t): PlanV1 => {\n\t\ttransitions.transition({\n\t\t\tdomain: \"plan\",\n\t\t\tentityId: planId,\n\t\t\towner,\n\t\t\tfromStatus,\n\t\t\ttoStatus,\n\t\t\toperationId: planOptions.operationId ?? `${toStatus}:${planId}`,\n\t\t\tevidence: planOptions.evidence,\n\t\t\tpayload: planOptions.payload as JsonValue | undefined,\n\t\t});\n\t\treturn planGet(planId, owner)!;\n\t};\n\n\treturn {\n\t\tcreatePlan({ planId, owner, title, branch, steps }) {\n\t\t\tif (title.trim().length === 0) throw new Error(t(\"Plan title must be a non-empty string\"));\n\t\t\tif (branch.trim().length === 0) throw new Error(t(\"Plan branch must be a non-empty string\"));\n\t\t\tif (steps.length === 0) throw new Error(t(\"Plan requires at least one step\"));\n\t\t\tconst stepIds = new Set<string>();\n\t\t\tfor (const step of steps) {\n\t\t\t\tif (typeof step.stepId !== \"string\" || step.stepId.trim().length === 0) {\n\t\t\t\t\tthrow new Error(t(\"Plan stepId must be a non-empty string\"));\n\t\t\t\t}\n\t\t\t\tif (typeof step.title !== \"string\" || step.title.trim().length === 0) {\n\t\t\t\t\tthrow new Error(t(\"Plan step title must be a non-empty string\"));\n\t\t\t\t}\n\t\t\t\tif (stepIds.has(step.stepId))\n\t\t\t\t\tthrow new Error(t(\"Duplicate plan stepId: {stepId}\", { stepId: step.stepId }));\n\t\t\t\tstepIds.add(step.stepId);\n\t\t\t}\n\t\t\treturn transitionPlan(planId, owner, null, \"draft\", {\n\t\t\t\tpayload: { title, branch, steps: [...steps] },\n\t\t\t\toperationId: `create:${planId}`,\n\t\t\t});\n\t\t},\n\t\tactivate(planId, owner, activateOptions) {\n\t\t\tconst replayed = replayedPlan(planId, owner, \"active\", activateOptions?.operationId);\n\t\t\tif (replayed) return replayed;\n\t\t\tconst plan = planGet(planId, owner);\n\t\t\tif (plan?.status !== \"draft\") {\n\t\t\t\tthrow new Error(\n\t\t\t\t\tt(\"Plan {planId} must be in draft status to activate (current: {status})\", {\n\t\t\t\t\t\tplanId,\n\t\t\t\t\t\tstatus: plan?.status ?? \"missing\",\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn transitionPlan(planId, owner, \"draft\", \"active\", { operationId: activateOptions?.operationId });\n\t\t},\n\t\tlinkRevision(planId, owner, revision, linkOptions) {\n\t\t\tconst replayed = replayedPlan(planId, owner, \"active\", linkOptions?.operationId);\n\t\t\tif (replayed) return replayed;\n\t\t\tconst plan = planGet(planId, owner);\n\t\t\tif (plan?.status !== \"active\") {\n\t\t\t\tthrow new Error(\n\t\t\t\t\tt(\"Plan {planId} must be active to link a revision (current: {status})\", {\n\t\t\t\t\t\tplanId,\n\t\t\t\t\t\tstatus: plan?.status ?? \"missing\",\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (!Number.isSafeInteger(revision) || revision < 1) {\n\t\t\t\tthrow new Error(t(\"Plan revision must be a positive safe integer, got {revision}\", { revision }));\n\t\t\t}\n\t\t\treturn transitionPlan(planId, owner, \"active\", \"active\", {\n\t\t\t\tpayload: { title: plan.title, branch: plan.branch, steps: plan.steps, linkedRevision: revision },\n\t\t\t\toperationId: linkOptions?.operationId ?? `link:${planId}:${revision}`,\n\t\t\t});\n\t\t},\n\t\tcomplete(planId, owner, evidence, completeOptions) {\n\t\t\tconst replayed = replayedPlan(planId, owner, \"completed\", completeOptions?.operationId);\n\t\t\tif (replayed) return replayed;\n\t\t\tconst plan = planGet(planId, owner);\n\t\t\tif (plan?.status !== \"active\") {\n\t\t\t\tthrow new Error(\n\t\t\t\t\tt(\"Plan {planId} must be active to complete (current: {status})\", {\n\t\t\t\t\t\tplanId,\n\t\t\t\t\t\tstatus: plan?.status ?? \"missing\",\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (evidence.length === 0) throw new Error(t(\"Completing a plan requires at least one evidence reference\"));\n\t\t\tconst target = completeOptions?.atRevision ?? plan.revision;\n\t\t\tif (typeof target !== \"number\") {\n\t\t\t\tthrow new Error(t(\"Plan {planId} requires atRevision or a linked revision to complete\", { planId }));\n\t\t\t}\n\t\t\treturn transitionPlan(planId, owner, \"active\", \"completed\", {\n\t\t\t\tevidence,\n\t\t\t\tpayload: { title: plan.title, branch: plan.branch, steps: plan.steps, linkedRevision: target },\n\t\t\t\toperationId: completeOptions?.operationId,\n\t\t\t});\n\t\t},\n\t\tdiscard(planId, owner) {\n\t\t\tconst plan = planGet(planId, owner);\n\t\t\tif (!plan || plan.status === \"completed\" || plan.status === \"discarded\") {\n\t\t\t\tthrow new Error(\n\t\t\t\t\tt(\"Plan {planId} cannot be discarded from status {status}\", {\n\t\t\t\t\t\tplanId,\n\t\t\t\t\t\tstatus: plan?.status ?? \"missing\",\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn transitionPlan(planId, owner, plan.status, \"discarded\", {});\n\t\t},\n\t\tget(planId, owner) {\n\t\t\treturn planGet(planId, owner);\n\t\t},\n\t};\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"plugin-profiles.d.ts","sourceRoot":"","sources":["../../src/profile/plugin-profiles.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACX,WAAW,EACX,gBAAgB,EAEhB,mBAAmB,EACnB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAmB,KAAK,uBAAuB,EAAE,KAAK,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAEjH,MAAM,MAAM,wBAAwB,GACjC,aAAa,GACb,YAAY,GACZ,iBAAiB,GACjB,iBAAiB,GACjB,iBAAiB,GACjB,kBAAkB,GAClB,cAAc,GACd,aAAa,GACb,iBAAiB,GACjB,uBAAuB,GACvB,kBAAkB,GAClB,gBAAgB,CAAC;AAEpB,MAAM,WAAW,sBAAsB;IACtC,QAAQ,CAAC,EAAE,EAAE,wBAAwB,CAAC;IACtC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE,CAAC;CACtC;AAED;;;;;;;;GAQG;AACH,MAAM,MAAM,gCAAgC,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC,CAAC;AAE1F,MAAM,MAAM,gCAAgC,GACzC;IAAE,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;IAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GAC5D;IAAE,QAAQ,CAAC,MAAM,EAAE,qBAAqB,CAAC;IAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GACtE;IACA,QAAQ,CAAC,MAAM,EAAE,mBAAmB,CAAC;IACrC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,gBAAgB,EAAE,SAAS,MAAM,EAAE,CAAC;IAC7C,QAAQ,CAAC,kBAAkB,EAAE,SAAS,MAAM,EAAE,CAAC;CAC9C,GACD;IACA,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;IAC5B,QAAQ,CAAC,OAAO,EAAE,sBAAsB,CAAC;IACzC,QAAQ,CAAC,UAAU,EAAE,mBAAmB,CAAC;IACzC,QAAQ,CAAC,QAAQ,CAAC,EAAE,uBAAuB,CAAC;CAC3C,CAAC;AAuCL,wBAAgB,2BAA2B,IAAI,SAAS,sBAAsB,EAAE,CAE/E;AAED,sFAAsF;AACtF,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,IAAI,wBAAwB,CAE3F;AAED,gFAAgF;AAChF,wBAAgB,4BAA4B,IAAI,SAAS,gBAAgB,EAAE,CAO1E;AAED;;;;;GAKG;AACH,wBAAgB,+BAA+B,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,oBAAoB,EAAE,CAOlG;AAED,wBAAgB,6BAA6B,CAAC,KAAK,EAAE;IACpD,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAC3B,iEAAiE;IACjE,QAAQ,CAAC,iBAAiB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/C,QAAQ,CAAC,iBAAiB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/C,QAAQ,CAAC,eAAe,CAAC,EAAE,SAAS,oBAAoB,EAAE,CAAC;IAC3D,yEAAyE;IACzE,QAAQ,CAAC,iBAAiB,CAAC,EAAE,gCAAgC,CAAC;CAC9D,GAAG,gCAAgC,CA2FnC","sourcesContent":["import { VERSION } from \"../config.ts\";\nimport { comparePluginVersionsV1 } from \"../plugins/ecosystem/catalog.ts\";\nimport { resolvePluginProfileV1 } from \"../plugins/ecosystem/resolver.ts\";\nimport type {\n\tHostFactsV1,\n\tPluginManifestV1,\n\tPluginResolutionV1,\n\tProfileResolutionV1,\n} from \"../plugins/ecosystem/types.ts\";\nimport { assembleProfile, type ProfileAssemblyResultV1, type VerifiedToolPluginV1 } from \"./profile-assembly.ts\";\n\nexport type BuiltinPluginProfileIdV1 =\n\t| \"coding-core\"\n\t| \"desktop-qa\"\n\t| \"desktop-observe\"\n\t| \"desktop-control\"\n\t| \"lsp-diagnostics\"\n\t| \"image-generation\"\n\t| \"process-exec\"\n\t| \"test-runner\"\n\t| \"workspace-files\"\n\t| \"workspace-files-write\"\n\t| \"formatter-linter\"\n\t| \"git-repository\";\n\nexport interface BuiltinPluginProfileV1 {\n\treadonly id: BuiltinPluginProfileIdV1;\n\treadonly version: string;\n\treadonly pluginIds: readonly string[];\n}\n\n/**\n * Host-owned manifest replacements for installed, verified package versions.\n *\n * Builtin manifests remain the default. A host may explicitly provide one\n * replacement per builtin plugin ID when a staged/verified/active install is\n * selected for a new Profile. The resolver never discovers files or chooses a\n * version implicitly; the replacement is part of the resulting Profile\n * identity and must still pass normal compatibility and verification checks.\n */\nexport type BuiltinPluginManifestOverridesV1 = Readonly<Record<string, PluginManifestV1>>;\n\nexport type BuiltinPluginProfileResolutionV1 =\n\t| { readonly status: \"not_found\"; readonly profileId: string }\n\t| { readonly status: \"host_facts_required\"; readonly profileId: string }\n\t| {\n\t\t\treadonly status: \"invalid_selection\";\n\t\t\treadonly profileId: string;\n\t\t\treadonly unknownPluginIds: readonly string[];\n\t\t\treadonly duplicatePluginIds: readonly string[];\n\t }\n\t| {\n\t\t\treadonly status: \"resolved\";\n\t\t\treadonly profile: BuiltinPluginProfileV1;\n\t\t\treadonly resolution: ProfileResolutionV1;\n\t\t\treadonly assembly?: ProfileAssemblyResultV1;\n\t };\n\n// D-075 S3: every first-party category-A plugin now ships as an independent\n// package under `plugins/` with the `agent-forge.plugin.<name>` id domain\n// (design §4.1). No embedded manifests remain; profiles resolve through the\n// install store (host-provided `manifestOverrides` from active bindings).\nconst manifests: Readonly<Record<string, PluginManifestV1>> = Object.freeze({});\n\nconst profiles: readonly BuiltinPluginProfileV1[] = Object.freeze([\n\t{ id: \"coding-core\", version: \"1\", pluginIds: [] },\n\t{\n\t\tid: \"desktop-qa\",\n\t\tversion: \"1\",\n\t\tpluginIds: [\"agent-forge.plugin.desktop-windows-observe\", \"agent-forge.plugin.desktop-windows-input\"],\n\t},\n\t{ id: \"desktop-observe\", version: \"1\", pluginIds: [\"agent-forge.plugin.desktop-windows-observe\"] },\n\t{\n\t\tid: \"desktop-control\",\n\t\tversion: \"1\",\n\t\tpluginIds: [\"agent-forge.plugin.desktop-windows-observe\", \"agent-forge.plugin.desktop-windows-input\"],\n\t},\n\t{ id: \"lsp-diagnostics\", version: \"1\", pluginIds: [\"agent-forge.plugin.lsp-diagnostics\"] },\n\t{ id: \"image-generation\", version: \"1\", pluginIds: [\"agent-forge.plugin.image-generation\"] },\n\t{ id: \"process-exec\", version: \"1\", pluginIds: [\"agent-forge.plugin.process-exec\"] },\n\t{ id: \"test-runner\", version: \"1\", pluginIds: [\"agent-forge.plugin.test-runner\"] },\n\t{ id: \"workspace-files\", version: \"1\", pluginIds: [\"agent-forge.plugin.workspace-files\"] },\n\t{ id: \"workspace-files-write\", version: \"1\", pluginIds: [\"agent-forge.plugin.workspace-files-write\"] },\n\t{\n\t\t// D-075 S2: the plugin code ships as the independent package\n\t\t// `agent-forge.plugin.formatter-linter` (design §4.1 id domain); this\n\t\t// Profile stays the stable user entry (`--plugin-profile formatter-linter`)\n\t\t// and resolves through the install store, not an embedded manifest.\n\t\tid: \"formatter-linter\",\n\t\tversion: \"1\",\n\t\tpluginIds: [\"agent-forge.plugin.formatter-linter\"],\n\t},\n\t{ id: \"git-repository\", version: \"1\", pluginIds: [\"agent-forge.plugin.git-repository\"] },\n]);\n\nexport function listBuiltinPluginProfilesV1(): readonly BuiltinPluginProfileV1[] {\n\treturn profiles;\n}\n\n/** True when the id names a builtin plugin profile (the CLI selection vocabulary). */\nexport function isBuiltinPluginProfileIdV1(value: string): value is BuiltinPluginProfileIdV1 {\n\treturn profiles.some((profile) => profile.id === value);\n}\n\n/** Return the first-party manifest projection for catalog and selection UIs. */\nexport function listBuiltinPluginManifestsV1(): readonly PluginManifestV1[] {\n\treturn Object.freeze(\n\t\tObject.values(manifests).sort((left, right) => {\n\t\t\tconst idOrder = `${left.id}@${left.pluginVersion}`.localeCompare(`${right.id}@${right.pluginVersion}`);\n\t\t\treturn idOrder === 0 ? comparePluginVersionsV1(left.pluginVersion, right.pluginVersion) : idOrder;\n\t\t}),\n\t);\n}\n\n/**\n * First-party plugins of an explicitly selected Profile are trusted by\n * default: builtins ship with the product and the user chose the Profile\n * explicitly. Installed third-party versions are still verified through the\n * active-binding resolver; host-injected verifiedPlugins always win.\n */\nexport function defaultBuiltinVerifiedPluginsV1(profileId: string): readonly VerifiedToolPluginV1[] {\n\tconst profile = profiles.find((candidate) => candidate.id === profileId);\n\tif (profile === undefined) return [];\n\treturn profile.pluginIds.flatMap((pluginId) => {\n\t\tconst manifest = manifests[pluginId];\n\t\treturn manifest === undefined ? [] : [{ pluginId: manifest.id, version: manifest.pluginVersion }];\n\t});\n}\n\nexport function resolveBuiltinPluginProfileV1(input: {\n\treadonly profileId: string;\n\treadonly host: HostFactsV1;\n\t/** Optional subset of the selected builtin Profile's plugins. */\n\treadonly selectedPluginIds?: readonly string[];\n\treadonly disabledPluginIds?: readonly string[];\n\treadonly verifiedPlugins?: readonly VerifiedToolPluginV1[];\n\t/** Explicit host-selected active manifests; never inferred from disk. */\n\treadonly manifestOverrides?: BuiltinPluginManifestOverridesV1;\n}): BuiltinPluginProfileResolutionV1 {\n\tconst profile = profiles.find((candidate) => candidate.id === input.profileId);\n\tif (profile === undefined) return { status: \"not_found\", profileId: input.profileId };\n\tconst requestedPluginIds = input.selectedPluginIds;\n\tconst requestedDisabledPluginIds = input.disabledPluginIds;\n\tif (requestedPluginIds !== undefined || requestedDisabledPluginIds !== undefined) {\n\t\tconst availablePluginIds = new Set(profile.pluginIds);\n\t\tconst duplicatePluginIds: string[] = [];\n\t\tconst unknownPluginIds: string[] = [];\n\t\tfor (const requestedIds of [requestedPluginIds ?? [], requestedDisabledPluginIds ?? []]) {\n\t\t\tconst seen = new Set<string>();\n\t\t\tfor (const pluginId of requestedIds) {\n\t\t\t\tif (!availablePluginIds.has(pluginId) && !unknownPluginIds.includes(pluginId))\n\t\t\t\t\tunknownPluginIds.push(pluginId);\n\t\t\t\tif (seen.has(pluginId) && !duplicatePluginIds.includes(pluginId)) duplicatePluginIds.push(pluginId);\n\t\t\t\tseen.add(pluginId);\n\t\t\t}\n\t\t}\n\t\tif (unknownPluginIds.length > 0 || duplicatePluginIds.length > 0) {\n\t\t\treturn {\n\t\t\t\tstatus: \"invalid_selection\",\n\t\t\t\tprofileId: input.profileId,\n\t\t\t\tunknownPluginIds: Object.freeze([...new Set(unknownPluginIds)]),\n\t\t\t\tduplicatePluginIds: Object.freeze(duplicatePluginIds),\n\t\t\t};\n\t\t}\n\t}\n\tconst selected =\n\t\trequestedPluginIds === undefined\n\t\t\t? profile.pluginIds\n\t\t\t: profile.pluginIds.filter((pluginId) => requestedPluginIds.includes(pluginId));\n\tconst selectedProfile =\n\t\trequestedPluginIds === undefined\n\t\t\t? profile\n\t\t\t: Object.freeze({ ...profile, pluginIds: Object.freeze([...selected]) });\n\tconst disabled = new Set(input.disabledPluginIds ?? []);\n\t// D-075 S2: a Profile plugin without a builtin manifest and without a\n\t// host-installed override is a structured miss, not a startup failure. The\n\t// plugin is omitted from the resolved manifest and runtime bindings; the\n\t// remaining Profile plugins resolve normally (soft degradation).\n\tconst manifestByPluginId = new Map(\n\t\tselectedProfile.pluginIds.map((pluginId) => [pluginId, manifestFor(pluginId, input.manifestOverrides)] as const),\n\t);\n\tconst missingPluginIds = selectedProfile.pluginIds.filter(\n\t\t(pluginId) => manifestByPluginId.get(pluginId) === undefined,\n\t);\n\tconst resolution = resolvePluginProfileV1({\n\t\tprofileId: selectedProfile.id,\n\t\tprofileVersion: selectedProfile.version,\n\t\tplugins: selectedProfile.pluginIds.flatMap((pluginId) => {\n\t\t\tconst manifest = manifestByPluginId.get(pluginId);\n\t\t\treturn manifest === undefined\n\t\t\t\t? []\n\t\t\t\t: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tmanifest,\n\t\t\t\t\t\t\t// A user-disabled plugin must not block the remaining profile. It is\n\t\t\t\t\t\t\t// still represented in the resolution diagnostics, but is omitted from\n\t\t\t\t\t\t\t// the active resolved manifest and runtime bindings.\n\t\t\t\t\t\t\trequired: !disabled.has(pluginId),\n\t\t\t\t\t\t\tdisabled: disabled.has(pluginId),\n\t\t\t\t\t\t},\n\t\t\t\t\t];\n\t\t}),\n\t\thost: input.host,\n\t\t// The host's own version enforces each manifest's minHostVersion floor\n\t\t// at the single builtin profile resolution funnel used by production\n\t\t// loading paths.\n\t\thostVersion: VERSION,\n\t});\n\tconst merged = mergeMissingPluginResolutionsV1(resolution, missingPluginIds, disabled);\n\tif (merged.status !== \"ready\") return { status: \"resolved\", profile: selectedProfile, resolution: merged };\n\tconst resolvedPlugins = merged.resolvedManifest.plugins.map((plugin) => ({\n\t\tpluginId: plugin.pluginId,\n\t\tpluginVersion: plugin.pluginVersion,\n\t\tcapabilityRefs: plugin.capabilityRefs,\n\t\t...(plugin.selectedAdapter === undefined ? {} : { selectedAdapter: plugin.selectedAdapter }),\n\t}));\n\tconst verifiedPlugins = input.verifiedPlugins ?? [];\n\tconst assembly = assembleProfile({\n\t\tprofileId: selectedProfile.id,\n\t\tprofileVersion: selectedProfile.version,\n\t\tresolvedPlugins,\n\t\tverifiedPlugins,\n\t});\n\treturn {\n\t\tstatus: \"resolved\",\n\t\tprofile: selectedProfile,\n\t\tresolution: merged,\n\t\tassembly,\n\t};\n}\n\nfunction manifestFor(\n\tpluginId: string,\n\toverrides: BuiltinPluginManifestOverridesV1 | undefined,\n): PluginManifestV1 | undefined {\n\tconst manifest = overrides?.[pluginId] ?? manifests[pluginId];\n\t// A mismatched override stays a hard host error: the host selected it\n\t// explicitly, so silence would hide an identity bug. A plain absent\n\t// manifest (no builtin, no installed override) is the structured miss.\n\tif (manifest !== undefined && manifest.id !== pluginId)\n\t\tthrow new Error(`builtin manifest override does not match plugin ${pluginId}`);\n\treturn manifest;\n}\n\n/**\n * Merge structured `manifest_missing` resolutions for Profile plugins that\n * have no builtin manifest and no installed override into the resolver\n * result. Missing plugins never block the Profile (soft degradation): the\n * remaining diagnostics and the resolved manifest stay exactly what the\n * resolver produced, and the merged plugin list keeps the resolver's\n * deterministic id sort.\n */\nfunction mergeMissingPluginResolutionsV1(\n\tresolution: ProfileResolutionV1,\n\tmissingPluginIds: readonly string[],\n\tdisabled: ReadonlySet<string>,\n): ProfileResolutionV1 {\n\tif (missingPluginIds.length === 0) return resolution;\n\tconst missing: PluginResolutionV1[] = missingPluginIds.map((pluginId) => ({\n\t\tpluginId,\n\t\tpluginVersion: \"\",\n\t\trequired: !disabled.has(pluginId),\n\t\tstatus: \"manifest-missing\",\n\t\tdiagnostics: [\n\t\t\t{\n\t\t\t\tcode: \"manifest_missing\",\n\t\t\t\tmessage: `Plugin ${pluginId} has no builtin manifest and no installed active override; the plugin is omitted from this profile (install it with agent-forge plugin install)`,\n\t\t\t},\n\t\t],\n\t}));\n\tconst plugins = [...resolution.plugins, ...missing].sort((left, right) =>\n\t\tleft.pluginId.localeCompare(right.pluginId),\n\t);\n\treturn Object.freeze({\n\t\t...resolution,\n\t\tplugins: Object.freeze(plugins),\n\t\tdiagnostics: Object.freeze(plugins.flatMap((plugin) => plugin.diagnostics)),\n\t});\n}\n"]}
1
+ {"version":3,"file":"plugin-profiles.d.ts","sourceRoot":"","sources":["../../src/profile/plugin-profiles.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACX,WAAW,EACX,gBAAgB,EAEhB,mBAAmB,EACnB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAmB,KAAK,uBAAuB,EAAE,KAAK,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAEjH,MAAM,MAAM,wBAAwB,GACjC,aAAa,GACb,YAAY,GACZ,iBAAiB,GACjB,iBAAiB,GACjB,iBAAiB,GACjB,kBAAkB,GAClB,cAAc,GACd,aAAa,GACb,iBAAiB,GACjB,uBAAuB,GACvB,kBAAkB,GAClB,gBAAgB,CAAC;AAEpB,MAAM,WAAW,sBAAsB;IACtC,QAAQ,CAAC,EAAE,EAAE,wBAAwB,CAAC;IACtC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE,CAAC;CACtC;AAED;;;;;;;;GAQG;AACH,MAAM,MAAM,gCAAgC,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC,CAAC;AAE1F,MAAM,MAAM,gCAAgC,GACzC;IAAE,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;IAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GAC5D;IAAE,QAAQ,CAAC,MAAM,EAAE,qBAAqB,CAAC;IAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GACtE;IACA,QAAQ,CAAC,MAAM,EAAE,mBAAmB,CAAC;IACrC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,gBAAgB,EAAE,SAAS,MAAM,EAAE,CAAC;IAC7C,QAAQ,CAAC,kBAAkB,EAAE,SAAS,MAAM,EAAE,CAAC;CAC9C,GACD;IACA,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;IAC5B,QAAQ,CAAC,OAAO,EAAE,sBAAsB,CAAC;IACzC,QAAQ,CAAC,UAAU,EAAE,mBAAmB,CAAC;IACzC,QAAQ,CAAC,QAAQ,CAAC,EAAE,uBAAuB,CAAC;CAC3C,CAAC;AAuCL,wBAAgB,2BAA2B,IAAI,SAAS,sBAAsB,EAAE,CAE/E;AAED,sFAAsF;AACtF,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,IAAI,wBAAwB,CAE3F;AAED,gFAAgF;AAChF,wBAAgB,4BAA4B,IAAI,SAAS,gBAAgB,EAAE,CAO1E;AAED;;;;;GAKG;AACH,wBAAgB,+BAA+B,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,oBAAoB,EAAE,CAOlG;AAED,wBAAgB,6BAA6B,CAAC,KAAK,EAAE;IACpD,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAC3B,iEAAiE;IACjE,QAAQ,CAAC,iBAAiB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/C,QAAQ,CAAC,iBAAiB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/C,QAAQ,CAAC,eAAe,CAAC,EAAE,SAAS,oBAAoB,EAAE,CAAC;IAC3D,yEAAyE;IACzE,QAAQ,CAAC,iBAAiB,CAAC,EAAE,gCAAgC,CAAC;CAC9D,GAAG,gCAAgC,CA2FnC","sourcesContent":["import { VERSION } from \"../config.ts\";\nimport { t } from \"../core/i18n/index.ts\";\nimport { comparePluginVersionsV1 } from \"../plugins/ecosystem/catalog.ts\";\nimport { resolvePluginProfileV1 } from \"../plugins/ecosystem/resolver.ts\";\nimport type {\n\tHostFactsV1,\n\tPluginManifestV1,\n\tPluginResolutionV1,\n\tProfileResolutionV1,\n} from \"../plugins/ecosystem/types.ts\";\nimport { assembleProfile, type ProfileAssemblyResultV1, type VerifiedToolPluginV1 } from \"./profile-assembly.ts\";\n\nexport type BuiltinPluginProfileIdV1 =\n\t| \"coding-core\"\n\t| \"desktop-qa\"\n\t| \"desktop-observe\"\n\t| \"desktop-control\"\n\t| \"lsp-diagnostics\"\n\t| \"image-generation\"\n\t| \"process-exec\"\n\t| \"test-runner\"\n\t| \"workspace-files\"\n\t| \"workspace-files-write\"\n\t| \"formatter-linter\"\n\t| \"git-repository\";\n\nexport interface BuiltinPluginProfileV1 {\n\treadonly id: BuiltinPluginProfileIdV1;\n\treadonly version: string;\n\treadonly pluginIds: readonly string[];\n}\n\n/**\n * Host-owned manifest replacements for installed, verified package versions.\n *\n * Builtin manifests remain the default. A host may explicitly provide one\n * replacement per builtin plugin ID when a staged/verified/active install is\n * selected for a new Profile. The resolver never discovers files or chooses a\n * version implicitly; the replacement is part of the resulting Profile\n * identity and must still pass normal compatibility and verification checks.\n */\nexport type BuiltinPluginManifestOverridesV1 = Readonly<Record<string, PluginManifestV1>>;\n\nexport type BuiltinPluginProfileResolutionV1 =\n\t| { readonly status: \"not_found\"; readonly profileId: string }\n\t| { readonly status: \"host_facts_required\"; readonly profileId: string }\n\t| {\n\t\t\treadonly status: \"invalid_selection\";\n\t\t\treadonly profileId: string;\n\t\t\treadonly unknownPluginIds: readonly string[];\n\t\t\treadonly duplicatePluginIds: readonly string[];\n\t }\n\t| {\n\t\t\treadonly status: \"resolved\";\n\t\t\treadonly profile: BuiltinPluginProfileV1;\n\t\t\treadonly resolution: ProfileResolutionV1;\n\t\t\treadonly assembly?: ProfileAssemblyResultV1;\n\t };\n\n// D-075 S3: every first-party category-A plugin now ships as an independent\n// package under `plugins/` with the `agent-forge.plugin.<name>` id domain\n// (design §4.1). No embedded manifests remain; profiles resolve through the\n// install store (host-provided `manifestOverrides` from active bindings).\nconst manifests: Readonly<Record<string, PluginManifestV1>> = Object.freeze({});\n\nconst profiles: readonly BuiltinPluginProfileV1[] = Object.freeze([\n\t{ id: \"coding-core\", version: \"1\", pluginIds: [] },\n\t{\n\t\tid: \"desktop-qa\",\n\t\tversion: \"1\",\n\t\tpluginIds: [\"agent-forge.plugin.desktop-windows-observe\", \"agent-forge.plugin.desktop-windows-input\"],\n\t},\n\t{ id: \"desktop-observe\", version: \"1\", pluginIds: [\"agent-forge.plugin.desktop-windows-observe\"] },\n\t{\n\t\tid: \"desktop-control\",\n\t\tversion: \"1\",\n\t\tpluginIds: [\"agent-forge.plugin.desktop-windows-observe\", \"agent-forge.plugin.desktop-windows-input\"],\n\t},\n\t{ id: \"lsp-diagnostics\", version: \"1\", pluginIds: [\"agent-forge.plugin.lsp-diagnostics\"] },\n\t{ id: \"image-generation\", version: \"1\", pluginIds: [\"agent-forge.plugin.image-generation\"] },\n\t{ id: \"process-exec\", version: \"1\", pluginIds: [\"agent-forge.plugin.process-exec\"] },\n\t{ id: \"test-runner\", version: \"1\", pluginIds: [\"agent-forge.plugin.test-runner\"] },\n\t{ id: \"workspace-files\", version: \"1\", pluginIds: [\"agent-forge.plugin.workspace-files\"] },\n\t{ id: \"workspace-files-write\", version: \"1\", pluginIds: [\"agent-forge.plugin.workspace-files-write\"] },\n\t{\n\t\t// D-075 S2: the plugin code ships as the independent package\n\t\t// `agent-forge.plugin.formatter-linter` (design §4.1 id domain); this\n\t\t// Profile stays the stable user entry (`--plugin-profile formatter-linter`)\n\t\t// and resolves through the install store, not an embedded manifest.\n\t\tid: \"formatter-linter\",\n\t\tversion: \"1\",\n\t\tpluginIds: [\"agent-forge.plugin.formatter-linter\"],\n\t},\n\t{ id: \"git-repository\", version: \"1\", pluginIds: [\"agent-forge.plugin.git-repository\"] },\n]);\n\nexport function listBuiltinPluginProfilesV1(): readonly BuiltinPluginProfileV1[] {\n\treturn profiles;\n}\n\n/** True when the id names a builtin plugin profile (the CLI selection vocabulary). */\nexport function isBuiltinPluginProfileIdV1(value: string): value is BuiltinPluginProfileIdV1 {\n\treturn profiles.some((profile) => profile.id === value);\n}\n\n/** Return the first-party manifest projection for catalog and selection UIs. */\nexport function listBuiltinPluginManifestsV1(): readonly PluginManifestV1[] {\n\treturn Object.freeze(\n\t\tObject.values(manifests).sort((left, right) => {\n\t\t\tconst idOrder = `${left.id}@${left.pluginVersion}`.localeCompare(`${right.id}@${right.pluginVersion}`);\n\t\t\treturn idOrder === 0 ? comparePluginVersionsV1(left.pluginVersion, right.pluginVersion) : idOrder;\n\t\t}),\n\t);\n}\n\n/**\n * First-party plugins of an explicitly selected Profile are trusted by\n * default: builtins ship with the product and the user chose the Profile\n * explicitly. Installed third-party versions are still verified through the\n * active-binding resolver; host-injected verifiedPlugins always win.\n */\nexport function defaultBuiltinVerifiedPluginsV1(profileId: string): readonly VerifiedToolPluginV1[] {\n\tconst profile = profiles.find((candidate) => candidate.id === profileId);\n\tif (profile === undefined) return [];\n\treturn profile.pluginIds.flatMap((pluginId) => {\n\t\tconst manifest = manifests[pluginId];\n\t\treturn manifest === undefined ? [] : [{ pluginId: manifest.id, version: manifest.pluginVersion }];\n\t});\n}\n\nexport function resolveBuiltinPluginProfileV1(input: {\n\treadonly profileId: string;\n\treadonly host: HostFactsV1;\n\t/** Optional subset of the selected builtin Profile's plugins. */\n\treadonly selectedPluginIds?: readonly string[];\n\treadonly disabledPluginIds?: readonly string[];\n\treadonly verifiedPlugins?: readonly VerifiedToolPluginV1[];\n\t/** Explicit host-selected active manifests; never inferred from disk. */\n\treadonly manifestOverrides?: BuiltinPluginManifestOverridesV1;\n}): BuiltinPluginProfileResolutionV1 {\n\tconst profile = profiles.find((candidate) => candidate.id === input.profileId);\n\tif (profile === undefined) return { status: \"not_found\", profileId: input.profileId };\n\tconst requestedPluginIds = input.selectedPluginIds;\n\tconst requestedDisabledPluginIds = input.disabledPluginIds;\n\tif (requestedPluginIds !== undefined || requestedDisabledPluginIds !== undefined) {\n\t\tconst availablePluginIds = new Set(profile.pluginIds);\n\t\tconst duplicatePluginIds: string[] = [];\n\t\tconst unknownPluginIds: string[] = [];\n\t\tfor (const requestedIds of [requestedPluginIds ?? [], requestedDisabledPluginIds ?? []]) {\n\t\t\tconst seen = new Set<string>();\n\t\t\tfor (const pluginId of requestedIds) {\n\t\t\t\tif (!availablePluginIds.has(pluginId) && !unknownPluginIds.includes(pluginId))\n\t\t\t\t\tunknownPluginIds.push(pluginId);\n\t\t\t\tif (seen.has(pluginId) && !duplicatePluginIds.includes(pluginId)) duplicatePluginIds.push(pluginId);\n\t\t\t\tseen.add(pluginId);\n\t\t\t}\n\t\t}\n\t\tif (unknownPluginIds.length > 0 || duplicatePluginIds.length > 0) {\n\t\t\treturn {\n\t\t\t\tstatus: \"invalid_selection\",\n\t\t\t\tprofileId: input.profileId,\n\t\t\t\tunknownPluginIds: Object.freeze([...new Set(unknownPluginIds)]),\n\t\t\t\tduplicatePluginIds: Object.freeze(duplicatePluginIds),\n\t\t\t};\n\t\t}\n\t}\n\tconst selected =\n\t\trequestedPluginIds === undefined\n\t\t\t? profile.pluginIds\n\t\t\t: profile.pluginIds.filter((pluginId) => requestedPluginIds.includes(pluginId));\n\tconst selectedProfile =\n\t\trequestedPluginIds === undefined\n\t\t\t? profile\n\t\t\t: Object.freeze({ ...profile, pluginIds: Object.freeze([...selected]) });\n\tconst disabled = new Set(input.disabledPluginIds ?? []);\n\t// D-075 S2: a Profile plugin without a builtin manifest and without a\n\t// host-installed override is a structured miss, not a startup failure. The\n\t// plugin is omitted from the resolved manifest and runtime bindings; the\n\t// remaining Profile plugins resolve normally (soft degradation).\n\tconst manifestByPluginId = new Map(\n\t\tselectedProfile.pluginIds.map((pluginId) => [pluginId, manifestFor(pluginId, input.manifestOverrides)] as const),\n\t);\n\tconst missingPluginIds = selectedProfile.pluginIds.filter(\n\t\t(pluginId) => manifestByPluginId.get(pluginId) === undefined,\n\t);\n\tconst resolution = resolvePluginProfileV1({\n\t\tprofileId: selectedProfile.id,\n\t\tprofileVersion: selectedProfile.version,\n\t\tplugins: selectedProfile.pluginIds.flatMap((pluginId) => {\n\t\t\tconst manifest = manifestByPluginId.get(pluginId);\n\t\t\treturn manifest === undefined\n\t\t\t\t? []\n\t\t\t\t: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tmanifest,\n\t\t\t\t\t\t\t// A user-disabled plugin must not block the remaining profile. It is\n\t\t\t\t\t\t\t// still represented in the resolution diagnostics, but is omitted from\n\t\t\t\t\t\t\t// the active resolved manifest and runtime bindings.\n\t\t\t\t\t\t\trequired: !disabled.has(pluginId),\n\t\t\t\t\t\t\tdisabled: disabled.has(pluginId),\n\t\t\t\t\t\t},\n\t\t\t\t\t];\n\t\t}),\n\t\thost: input.host,\n\t\t// The host's own version enforces each manifest's minHostVersion floor\n\t\t// at the single builtin profile resolution funnel used by production\n\t\t// loading paths.\n\t\thostVersion: VERSION,\n\t});\n\tconst merged = mergeMissingPluginResolutionsV1(resolution, missingPluginIds, disabled);\n\tif (merged.status !== \"ready\") return { status: \"resolved\", profile: selectedProfile, resolution: merged };\n\tconst resolvedPlugins = merged.resolvedManifest.plugins.map((plugin) => ({\n\t\tpluginId: plugin.pluginId,\n\t\tpluginVersion: plugin.pluginVersion,\n\t\tcapabilityRefs: plugin.capabilityRefs,\n\t\t...(plugin.selectedAdapter === undefined ? {} : { selectedAdapter: plugin.selectedAdapter }),\n\t}));\n\tconst verifiedPlugins = input.verifiedPlugins ?? [];\n\tconst assembly = assembleProfile({\n\t\tprofileId: selectedProfile.id,\n\t\tprofileVersion: selectedProfile.version,\n\t\tresolvedPlugins,\n\t\tverifiedPlugins,\n\t});\n\treturn {\n\t\tstatus: \"resolved\",\n\t\tprofile: selectedProfile,\n\t\tresolution: merged,\n\t\tassembly,\n\t};\n}\n\nfunction manifestFor(\n\tpluginId: string,\n\toverrides: BuiltinPluginManifestOverridesV1 | undefined,\n): PluginManifestV1 | undefined {\n\tconst manifest = overrides?.[pluginId] ?? manifests[pluginId];\n\t// A mismatched override stays a hard host error: the host selected it\n\t// explicitly, so silence would hide an identity bug. A plain absent\n\t// manifest (no builtin, no installed override) is the structured miss.\n\tif (manifest !== undefined && manifest.id !== pluginId)\n\t\tthrow new Error(t(\"builtin manifest override does not match plugin {pluginId}\", { pluginId }));\n\treturn manifest;\n}\n\n/**\n * Merge structured `manifest_missing` resolutions for Profile plugins that\n * have no builtin manifest and no installed override into the resolver\n * result. Missing plugins never block the Profile (soft degradation): the\n * remaining diagnostics and the resolved manifest stay exactly what the\n * resolver produced, and the merged plugin list keeps the resolver's\n * deterministic id sort.\n */\nfunction mergeMissingPluginResolutionsV1(\n\tresolution: ProfileResolutionV1,\n\tmissingPluginIds: readonly string[],\n\tdisabled: ReadonlySet<string>,\n): ProfileResolutionV1 {\n\tif (missingPluginIds.length === 0) return resolution;\n\tconst missing: PluginResolutionV1[] = missingPluginIds.map((pluginId) => ({\n\t\tpluginId,\n\t\tpluginVersion: \"\",\n\t\trequired: !disabled.has(pluginId),\n\t\tstatus: \"manifest-missing\",\n\t\tdiagnostics: [\n\t\t\t{\n\t\t\t\tcode: \"manifest_missing\",\n\t\t\t\tmessage: `Plugin ${pluginId} has no builtin manifest and no installed active override; the plugin is omitted from this profile (install it with agent-forge plugin install)`,\n\t\t\t},\n\t\t],\n\t}));\n\tconst plugins = [...resolution.plugins, ...missing].sort((left, right) =>\n\t\tleft.pluginId.localeCompare(right.pluginId),\n\t);\n\treturn Object.freeze({\n\t\t...resolution,\n\t\tplugins: Object.freeze(plugins),\n\t\tdiagnostics: Object.freeze(plugins.flatMap((plugin) => plugin.diagnostics)),\n\t});\n}\n"]}
@@ -1,4 +1,5 @@
1
1
  import { VERSION } from "../config.js";
2
+ import { t } from "../core/i18n/index.js";
2
3
  import { comparePluginVersionsV1 } from "../plugins/ecosystem/catalog.js";
3
4
  import { resolvePluginProfileV1 } from "../plugins/ecosystem/resolver.js";
4
5
  import { assembleProfile } from "./profile-assembly.js";
@@ -161,7 +162,7 @@ function manifestFor(pluginId, overrides) {
161
162
  // explicitly, so silence would hide an identity bug. A plain absent
162
163
  // manifest (no builtin, no installed override) is the structured miss.
163
164
  if (manifest !== undefined && manifest.id !== pluginId)
164
- throw new Error(`builtin manifest override does not match plugin ${pluginId}`);
165
+ throw new Error(t("builtin manifest override does not match plugin {pluginId}", { pluginId }));
165
166
  return manifest;
166
167
  }
167
168
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"plugin-profiles.js","sourceRoot":"","sources":["../../src/profile/plugin-profiles.ts"],"names":[],"mappings":"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","sourcesContent":["import { VERSION } from \"../config.ts\";\nimport { comparePluginVersionsV1 } from \"../plugins/ecosystem/catalog.ts\";\nimport { resolvePluginProfileV1 } from \"../plugins/ecosystem/resolver.ts\";\nimport type {\n\tHostFactsV1,\n\tPluginManifestV1,\n\tPluginResolutionV1,\n\tProfileResolutionV1,\n} from \"../plugins/ecosystem/types.ts\";\nimport { assembleProfile, type ProfileAssemblyResultV1, type VerifiedToolPluginV1 } from \"./profile-assembly.ts\";\n\nexport type BuiltinPluginProfileIdV1 =\n\t| \"coding-core\"\n\t| \"desktop-qa\"\n\t| \"desktop-observe\"\n\t| \"desktop-control\"\n\t| \"lsp-diagnostics\"\n\t| \"image-generation\"\n\t| \"process-exec\"\n\t| \"test-runner\"\n\t| \"workspace-files\"\n\t| \"workspace-files-write\"\n\t| \"formatter-linter\"\n\t| \"git-repository\";\n\nexport interface BuiltinPluginProfileV1 {\n\treadonly id: BuiltinPluginProfileIdV1;\n\treadonly version: string;\n\treadonly pluginIds: readonly string[];\n}\n\n/**\n * Host-owned manifest replacements for installed, verified package versions.\n *\n * Builtin manifests remain the default. A host may explicitly provide one\n * replacement per builtin plugin ID when a staged/verified/active install is\n * selected for a new Profile. The resolver never discovers files or chooses a\n * version implicitly; the replacement is part of the resulting Profile\n * identity and must still pass normal compatibility and verification checks.\n */\nexport type BuiltinPluginManifestOverridesV1 = Readonly<Record<string, PluginManifestV1>>;\n\nexport type BuiltinPluginProfileResolutionV1 =\n\t| { readonly status: \"not_found\"; readonly profileId: string }\n\t| { readonly status: \"host_facts_required\"; readonly profileId: string }\n\t| {\n\t\t\treadonly status: \"invalid_selection\";\n\t\t\treadonly profileId: string;\n\t\t\treadonly unknownPluginIds: readonly string[];\n\t\t\treadonly duplicatePluginIds: readonly string[];\n\t }\n\t| {\n\t\t\treadonly status: \"resolved\";\n\t\t\treadonly profile: BuiltinPluginProfileV1;\n\t\t\treadonly resolution: ProfileResolutionV1;\n\t\t\treadonly assembly?: ProfileAssemblyResultV1;\n\t };\n\n// D-075 S3: every first-party category-A plugin now ships as an independent\n// package under `plugins/` with the `agent-forge.plugin.<name>` id domain\n// (design §4.1). No embedded manifests remain; profiles resolve through the\n// install store (host-provided `manifestOverrides` from active bindings).\nconst manifests: Readonly<Record<string, PluginManifestV1>> = Object.freeze({});\n\nconst profiles: readonly BuiltinPluginProfileV1[] = Object.freeze([\n\t{ id: \"coding-core\", version: \"1\", pluginIds: [] },\n\t{\n\t\tid: \"desktop-qa\",\n\t\tversion: \"1\",\n\t\tpluginIds: [\"agent-forge.plugin.desktop-windows-observe\", \"agent-forge.plugin.desktop-windows-input\"],\n\t},\n\t{ id: \"desktop-observe\", version: \"1\", pluginIds: [\"agent-forge.plugin.desktop-windows-observe\"] },\n\t{\n\t\tid: \"desktop-control\",\n\t\tversion: \"1\",\n\t\tpluginIds: [\"agent-forge.plugin.desktop-windows-observe\", \"agent-forge.plugin.desktop-windows-input\"],\n\t},\n\t{ id: \"lsp-diagnostics\", version: \"1\", pluginIds: [\"agent-forge.plugin.lsp-diagnostics\"] },\n\t{ id: \"image-generation\", version: \"1\", pluginIds: [\"agent-forge.plugin.image-generation\"] },\n\t{ id: \"process-exec\", version: \"1\", pluginIds: [\"agent-forge.plugin.process-exec\"] },\n\t{ id: \"test-runner\", version: \"1\", pluginIds: [\"agent-forge.plugin.test-runner\"] },\n\t{ id: \"workspace-files\", version: \"1\", pluginIds: [\"agent-forge.plugin.workspace-files\"] },\n\t{ id: \"workspace-files-write\", version: \"1\", pluginIds: [\"agent-forge.plugin.workspace-files-write\"] },\n\t{\n\t\t// D-075 S2: the plugin code ships as the independent package\n\t\t// `agent-forge.plugin.formatter-linter` (design §4.1 id domain); this\n\t\t// Profile stays the stable user entry (`--plugin-profile formatter-linter`)\n\t\t// and resolves through the install store, not an embedded manifest.\n\t\tid: \"formatter-linter\",\n\t\tversion: \"1\",\n\t\tpluginIds: [\"agent-forge.plugin.formatter-linter\"],\n\t},\n\t{ id: \"git-repository\", version: \"1\", pluginIds: [\"agent-forge.plugin.git-repository\"] },\n]);\n\nexport function listBuiltinPluginProfilesV1(): readonly BuiltinPluginProfileV1[] {\n\treturn profiles;\n}\n\n/** True when the id names a builtin plugin profile (the CLI selection vocabulary). */\nexport function isBuiltinPluginProfileIdV1(value: string): value is BuiltinPluginProfileIdV1 {\n\treturn profiles.some((profile) => profile.id === value);\n}\n\n/** Return the first-party manifest projection for catalog and selection UIs. */\nexport function listBuiltinPluginManifestsV1(): readonly PluginManifestV1[] {\n\treturn Object.freeze(\n\t\tObject.values(manifests).sort((left, right) => {\n\t\t\tconst idOrder = `${left.id}@${left.pluginVersion}`.localeCompare(`${right.id}@${right.pluginVersion}`);\n\t\t\treturn idOrder === 0 ? comparePluginVersionsV1(left.pluginVersion, right.pluginVersion) : idOrder;\n\t\t}),\n\t);\n}\n\n/**\n * First-party plugins of an explicitly selected Profile are trusted by\n * default: builtins ship with the product and the user chose the Profile\n * explicitly. Installed third-party versions are still verified through the\n * active-binding resolver; host-injected verifiedPlugins always win.\n */\nexport function defaultBuiltinVerifiedPluginsV1(profileId: string): readonly VerifiedToolPluginV1[] {\n\tconst profile = profiles.find((candidate) => candidate.id === profileId);\n\tif (profile === undefined) return [];\n\treturn profile.pluginIds.flatMap((pluginId) => {\n\t\tconst manifest = manifests[pluginId];\n\t\treturn manifest === undefined ? [] : [{ pluginId: manifest.id, version: manifest.pluginVersion }];\n\t});\n}\n\nexport function resolveBuiltinPluginProfileV1(input: {\n\treadonly profileId: string;\n\treadonly host: HostFactsV1;\n\t/** Optional subset of the selected builtin Profile's plugins. */\n\treadonly selectedPluginIds?: readonly string[];\n\treadonly disabledPluginIds?: readonly string[];\n\treadonly verifiedPlugins?: readonly VerifiedToolPluginV1[];\n\t/** Explicit host-selected active manifests; never inferred from disk. */\n\treadonly manifestOverrides?: BuiltinPluginManifestOverridesV1;\n}): BuiltinPluginProfileResolutionV1 {\n\tconst profile = profiles.find((candidate) => candidate.id === input.profileId);\n\tif (profile === undefined) return { status: \"not_found\", profileId: input.profileId };\n\tconst requestedPluginIds = input.selectedPluginIds;\n\tconst requestedDisabledPluginIds = input.disabledPluginIds;\n\tif (requestedPluginIds !== undefined || requestedDisabledPluginIds !== undefined) {\n\t\tconst availablePluginIds = new Set(profile.pluginIds);\n\t\tconst duplicatePluginIds: string[] = [];\n\t\tconst unknownPluginIds: string[] = [];\n\t\tfor (const requestedIds of [requestedPluginIds ?? [], requestedDisabledPluginIds ?? []]) {\n\t\t\tconst seen = new Set<string>();\n\t\t\tfor (const pluginId of requestedIds) {\n\t\t\t\tif (!availablePluginIds.has(pluginId) && !unknownPluginIds.includes(pluginId))\n\t\t\t\t\tunknownPluginIds.push(pluginId);\n\t\t\t\tif (seen.has(pluginId) && !duplicatePluginIds.includes(pluginId)) duplicatePluginIds.push(pluginId);\n\t\t\t\tseen.add(pluginId);\n\t\t\t}\n\t\t}\n\t\tif (unknownPluginIds.length > 0 || duplicatePluginIds.length > 0) {\n\t\t\treturn {\n\t\t\t\tstatus: \"invalid_selection\",\n\t\t\t\tprofileId: input.profileId,\n\t\t\t\tunknownPluginIds: Object.freeze([...new Set(unknownPluginIds)]),\n\t\t\t\tduplicatePluginIds: Object.freeze(duplicatePluginIds),\n\t\t\t};\n\t\t}\n\t}\n\tconst selected =\n\t\trequestedPluginIds === undefined\n\t\t\t? profile.pluginIds\n\t\t\t: profile.pluginIds.filter((pluginId) => requestedPluginIds.includes(pluginId));\n\tconst selectedProfile =\n\t\trequestedPluginIds === undefined\n\t\t\t? profile\n\t\t\t: Object.freeze({ ...profile, pluginIds: Object.freeze([...selected]) });\n\tconst disabled = new Set(input.disabledPluginIds ?? []);\n\t// D-075 S2: a Profile plugin without a builtin manifest and without a\n\t// host-installed override is a structured miss, not a startup failure. The\n\t// plugin is omitted from the resolved manifest and runtime bindings; the\n\t// remaining Profile plugins resolve normally (soft degradation).\n\tconst manifestByPluginId = new Map(\n\t\tselectedProfile.pluginIds.map((pluginId) => [pluginId, manifestFor(pluginId, input.manifestOverrides)] as const),\n\t);\n\tconst missingPluginIds = selectedProfile.pluginIds.filter(\n\t\t(pluginId) => manifestByPluginId.get(pluginId) === undefined,\n\t);\n\tconst resolution = resolvePluginProfileV1({\n\t\tprofileId: selectedProfile.id,\n\t\tprofileVersion: selectedProfile.version,\n\t\tplugins: selectedProfile.pluginIds.flatMap((pluginId) => {\n\t\t\tconst manifest = manifestByPluginId.get(pluginId);\n\t\t\treturn manifest === undefined\n\t\t\t\t? []\n\t\t\t\t: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tmanifest,\n\t\t\t\t\t\t\t// A user-disabled plugin must not block the remaining profile. It is\n\t\t\t\t\t\t\t// still represented in the resolution diagnostics, but is omitted from\n\t\t\t\t\t\t\t// the active resolved manifest and runtime bindings.\n\t\t\t\t\t\t\trequired: !disabled.has(pluginId),\n\t\t\t\t\t\t\tdisabled: disabled.has(pluginId),\n\t\t\t\t\t\t},\n\t\t\t\t\t];\n\t\t}),\n\t\thost: input.host,\n\t\t// The host's own version enforces each manifest's minHostVersion floor\n\t\t// at the single builtin profile resolution funnel used by production\n\t\t// loading paths.\n\t\thostVersion: VERSION,\n\t});\n\tconst merged = mergeMissingPluginResolutionsV1(resolution, missingPluginIds, disabled);\n\tif (merged.status !== \"ready\") return { status: \"resolved\", profile: selectedProfile, resolution: merged };\n\tconst resolvedPlugins = merged.resolvedManifest.plugins.map((plugin) => ({\n\t\tpluginId: plugin.pluginId,\n\t\tpluginVersion: plugin.pluginVersion,\n\t\tcapabilityRefs: plugin.capabilityRefs,\n\t\t...(plugin.selectedAdapter === undefined ? {} : { selectedAdapter: plugin.selectedAdapter }),\n\t}));\n\tconst verifiedPlugins = input.verifiedPlugins ?? [];\n\tconst assembly = assembleProfile({\n\t\tprofileId: selectedProfile.id,\n\t\tprofileVersion: selectedProfile.version,\n\t\tresolvedPlugins,\n\t\tverifiedPlugins,\n\t});\n\treturn {\n\t\tstatus: \"resolved\",\n\t\tprofile: selectedProfile,\n\t\tresolution: merged,\n\t\tassembly,\n\t};\n}\n\nfunction manifestFor(\n\tpluginId: string,\n\toverrides: BuiltinPluginManifestOverridesV1 | undefined,\n): PluginManifestV1 | undefined {\n\tconst manifest = overrides?.[pluginId] ?? manifests[pluginId];\n\t// A mismatched override stays a hard host error: the host selected it\n\t// explicitly, so silence would hide an identity bug. A plain absent\n\t// manifest (no builtin, no installed override) is the structured miss.\n\tif (manifest !== undefined && manifest.id !== pluginId)\n\t\tthrow new Error(`builtin manifest override does not match plugin ${pluginId}`);\n\treturn manifest;\n}\n\n/**\n * Merge structured `manifest_missing` resolutions for Profile plugins that\n * have no builtin manifest and no installed override into the resolver\n * result. Missing plugins never block the Profile (soft degradation): the\n * remaining diagnostics and the resolved manifest stay exactly what the\n * resolver produced, and the merged plugin list keeps the resolver's\n * deterministic id sort.\n */\nfunction mergeMissingPluginResolutionsV1(\n\tresolution: ProfileResolutionV1,\n\tmissingPluginIds: readonly string[],\n\tdisabled: ReadonlySet<string>,\n): ProfileResolutionV1 {\n\tif (missingPluginIds.length === 0) return resolution;\n\tconst missing: PluginResolutionV1[] = missingPluginIds.map((pluginId) => ({\n\t\tpluginId,\n\t\tpluginVersion: \"\",\n\t\trequired: !disabled.has(pluginId),\n\t\tstatus: \"manifest-missing\",\n\t\tdiagnostics: [\n\t\t\t{\n\t\t\t\tcode: \"manifest_missing\",\n\t\t\t\tmessage: `Plugin ${pluginId} has no builtin manifest and no installed active override; the plugin is omitted from this profile (install it with agent-forge plugin install)`,\n\t\t\t},\n\t\t],\n\t}));\n\tconst plugins = [...resolution.plugins, ...missing].sort((left, right) =>\n\t\tleft.pluginId.localeCompare(right.pluginId),\n\t);\n\treturn Object.freeze({\n\t\t...resolution,\n\t\tplugins: Object.freeze(plugins),\n\t\tdiagnostics: Object.freeze(plugins.flatMap((plugin) => plugin.diagnostics)),\n\t});\n}\n"]}
1
+ {"version":3,"file":"plugin-profiles.js","sourceRoot":"","sources":["../../src/profile/plugin-profiles.ts"],"names":[],"mappings":"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","sourcesContent":["import { VERSION } from \"../config.ts\";\nimport { t } from \"../core/i18n/index.ts\";\nimport { comparePluginVersionsV1 } from \"../plugins/ecosystem/catalog.ts\";\nimport { resolvePluginProfileV1 } from \"../plugins/ecosystem/resolver.ts\";\nimport type {\n\tHostFactsV1,\n\tPluginManifestV1,\n\tPluginResolutionV1,\n\tProfileResolutionV1,\n} from \"../plugins/ecosystem/types.ts\";\nimport { assembleProfile, type ProfileAssemblyResultV1, type VerifiedToolPluginV1 } from \"./profile-assembly.ts\";\n\nexport type BuiltinPluginProfileIdV1 =\n\t| \"coding-core\"\n\t| \"desktop-qa\"\n\t| \"desktop-observe\"\n\t| \"desktop-control\"\n\t| \"lsp-diagnostics\"\n\t| \"image-generation\"\n\t| \"process-exec\"\n\t| \"test-runner\"\n\t| \"workspace-files\"\n\t| \"workspace-files-write\"\n\t| \"formatter-linter\"\n\t| \"git-repository\";\n\nexport interface BuiltinPluginProfileV1 {\n\treadonly id: BuiltinPluginProfileIdV1;\n\treadonly version: string;\n\treadonly pluginIds: readonly string[];\n}\n\n/**\n * Host-owned manifest replacements for installed, verified package versions.\n *\n * Builtin manifests remain the default. A host may explicitly provide one\n * replacement per builtin plugin ID when a staged/verified/active install is\n * selected for a new Profile. The resolver never discovers files or chooses a\n * version implicitly; the replacement is part of the resulting Profile\n * identity and must still pass normal compatibility and verification checks.\n */\nexport type BuiltinPluginManifestOverridesV1 = Readonly<Record<string, PluginManifestV1>>;\n\nexport type BuiltinPluginProfileResolutionV1 =\n\t| { readonly status: \"not_found\"; readonly profileId: string }\n\t| { readonly status: \"host_facts_required\"; readonly profileId: string }\n\t| {\n\t\t\treadonly status: \"invalid_selection\";\n\t\t\treadonly profileId: string;\n\t\t\treadonly unknownPluginIds: readonly string[];\n\t\t\treadonly duplicatePluginIds: readonly string[];\n\t }\n\t| {\n\t\t\treadonly status: \"resolved\";\n\t\t\treadonly profile: BuiltinPluginProfileV1;\n\t\t\treadonly resolution: ProfileResolutionV1;\n\t\t\treadonly assembly?: ProfileAssemblyResultV1;\n\t };\n\n// D-075 S3: every first-party category-A plugin now ships as an independent\n// package under `plugins/` with the `agent-forge.plugin.<name>` id domain\n// (design §4.1). No embedded manifests remain; profiles resolve through the\n// install store (host-provided `manifestOverrides` from active bindings).\nconst manifests: Readonly<Record<string, PluginManifestV1>> = Object.freeze({});\n\nconst profiles: readonly BuiltinPluginProfileV1[] = Object.freeze([\n\t{ id: \"coding-core\", version: \"1\", pluginIds: [] },\n\t{\n\t\tid: \"desktop-qa\",\n\t\tversion: \"1\",\n\t\tpluginIds: [\"agent-forge.plugin.desktop-windows-observe\", \"agent-forge.plugin.desktop-windows-input\"],\n\t},\n\t{ id: \"desktop-observe\", version: \"1\", pluginIds: [\"agent-forge.plugin.desktop-windows-observe\"] },\n\t{\n\t\tid: \"desktop-control\",\n\t\tversion: \"1\",\n\t\tpluginIds: [\"agent-forge.plugin.desktop-windows-observe\", \"agent-forge.plugin.desktop-windows-input\"],\n\t},\n\t{ id: \"lsp-diagnostics\", version: \"1\", pluginIds: [\"agent-forge.plugin.lsp-diagnostics\"] },\n\t{ id: \"image-generation\", version: \"1\", pluginIds: [\"agent-forge.plugin.image-generation\"] },\n\t{ id: \"process-exec\", version: \"1\", pluginIds: [\"agent-forge.plugin.process-exec\"] },\n\t{ id: \"test-runner\", version: \"1\", pluginIds: [\"agent-forge.plugin.test-runner\"] },\n\t{ id: \"workspace-files\", version: \"1\", pluginIds: [\"agent-forge.plugin.workspace-files\"] },\n\t{ id: \"workspace-files-write\", version: \"1\", pluginIds: [\"agent-forge.plugin.workspace-files-write\"] },\n\t{\n\t\t// D-075 S2: the plugin code ships as the independent package\n\t\t// `agent-forge.plugin.formatter-linter` (design §4.1 id domain); this\n\t\t// Profile stays the stable user entry (`--plugin-profile formatter-linter`)\n\t\t// and resolves through the install store, not an embedded manifest.\n\t\tid: \"formatter-linter\",\n\t\tversion: \"1\",\n\t\tpluginIds: [\"agent-forge.plugin.formatter-linter\"],\n\t},\n\t{ id: \"git-repository\", version: \"1\", pluginIds: [\"agent-forge.plugin.git-repository\"] },\n]);\n\nexport function listBuiltinPluginProfilesV1(): readonly BuiltinPluginProfileV1[] {\n\treturn profiles;\n}\n\n/** True when the id names a builtin plugin profile (the CLI selection vocabulary). */\nexport function isBuiltinPluginProfileIdV1(value: string): value is BuiltinPluginProfileIdV1 {\n\treturn profiles.some((profile) => profile.id === value);\n}\n\n/** Return the first-party manifest projection for catalog and selection UIs. */\nexport function listBuiltinPluginManifestsV1(): readonly PluginManifestV1[] {\n\treturn Object.freeze(\n\t\tObject.values(manifests).sort((left, right) => {\n\t\t\tconst idOrder = `${left.id}@${left.pluginVersion}`.localeCompare(`${right.id}@${right.pluginVersion}`);\n\t\t\treturn idOrder === 0 ? comparePluginVersionsV1(left.pluginVersion, right.pluginVersion) : idOrder;\n\t\t}),\n\t);\n}\n\n/**\n * First-party plugins of an explicitly selected Profile are trusted by\n * default: builtins ship with the product and the user chose the Profile\n * explicitly. Installed third-party versions are still verified through the\n * active-binding resolver; host-injected verifiedPlugins always win.\n */\nexport function defaultBuiltinVerifiedPluginsV1(profileId: string): readonly VerifiedToolPluginV1[] {\n\tconst profile = profiles.find((candidate) => candidate.id === profileId);\n\tif (profile === undefined) return [];\n\treturn profile.pluginIds.flatMap((pluginId) => {\n\t\tconst manifest = manifests[pluginId];\n\t\treturn manifest === undefined ? [] : [{ pluginId: manifest.id, version: manifest.pluginVersion }];\n\t});\n}\n\nexport function resolveBuiltinPluginProfileV1(input: {\n\treadonly profileId: string;\n\treadonly host: HostFactsV1;\n\t/** Optional subset of the selected builtin Profile's plugins. */\n\treadonly selectedPluginIds?: readonly string[];\n\treadonly disabledPluginIds?: readonly string[];\n\treadonly verifiedPlugins?: readonly VerifiedToolPluginV1[];\n\t/** Explicit host-selected active manifests; never inferred from disk. */\n\treadonly manifestOverrides?: BuiltinPluginManifestOverridesV1;\n}): BuiltinPluginProfileResolutionV1 {\n\tconst profile = profiles.find((candidate) => candidate.id === input.profileId);\n\tif (profile === undefined) return { status: \"not_found\", profileId: input.profileId };\n\tconst requestedPluginIds = input.selectedPluginIds;\n\tconst requestedDisabledPluginIds = input.disabledPluginIds;\n\tif (requestedPluginIds !== undefined || requestedDisabledPluginIds !== undefined) {\n\t\tconst availablePluginIds = new Set(profile.pluginIds);\n\t\tconst duplicatePluginIds: string[] = [];\n\t\tconst unknownPluginIds: string[] = [];\n\t\tfor (const requestedIds of [requestedPluginIds ?? [], requestedDisabledPluginIds ?? []]) {\n\t\t\tconst seen = new Set<string>();\n\t\t\tfor (const pluginId of requestedIds) {\n\t\t\t\tif (!availablePluginIds.has(pluginId) && !unknownPluginIds.includes(pluginId))\n\t\t\t\t\tunknownPluginIds.push(pluginId);\n\t\t\t\tif (seen.has(pluginId) && !duplicatePluginIds.includes(pluginId)) duplicatePluginIds.push(pluginId);\n\t\t\t\tseen.add(pluginId);\n\t\t\t}\n\t\t}\n\t\tif (unknownPluginIds.length > 0 || duplicatePluginIds.length > 0) {\n\t\t\treturn {\n\t\t\t\tstatus: \"invalid_selection\",\n\t\t\t\tprofileId: input.profileId,\n\t\t\t\tunknownPluginIds: Object.freeze([...new Set(unknownPluginIds)]),\n\t\t\t\tduplicatePluginIds: Object.freeze(duplicatePluginIds),\n\t\t\t};\n\t\t}\n\t}\n\tconst selected =\n\t\trequestedPluginIds === undefined\n\t\t\t? profile.pluginIds\n\t\t\t: profile.pluginIds.filter((pluginId) => requestedPluginIds.includes(pluginId));\n\tconst selectedProfile =\n\t\trequestedPluginIds === undefined\n\t\t\t? profile\n\t\t\t: Object.freeze({ ...profile, pluginIds: Object.freeze([...selected]) });\n\tconst disabled = new Set(input.disabledPluginIds ?? []);\n\t// D-075 S2: a Profile plugin without a builtin manifest and without a\n\t// host-installed override is a structured miss, not a startup failure. The\n\t// plugin is omitted from the resolved manifest and runtime bindings; the\n\t// remaining Profile plugins resolve normally (soft degradation).\n\tconst manifestByPluginId = new Map(\n\t\tselectedProfile.pluginIds.map((pluginId) => [pluginId, manifestFor(pluginId, input.manifestOverrides)] as const),\n\t);\n\tconst missingPluginIds = selectedProfile.pluginIds.filter(\n\t\t(pluginId) => manifestByPluginId.get(pluginId) === undefined,\n\t);\n\tconst resolution = resolvePluginProfileV1({\n\t\tprofileId: selectedProfile.id,\n\t\tprofileVersion: selectedProfile.version,\n\t\tplugins: selectedProfile.pluginIds.flatMap((pluginId) => {\n\t\t\tconst manifest = manifestByPluginId.get(pluginId);\n\t\t\treturn manifest === undefined\n\t\t\t\t? []\n\t\t\t\t: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tmanifest,\n\t\t\t\t\t\t\t// A user-disabled plugin must not block the remaining profile. It is\n\t\t\t\t\t\t\t// still represented in the resolution diagnostics, but is omitted from\n\t\t\t\t\t\t\t// the active resolved manifest and runtime bindings.\n\t\t\t\t\t\t\trequired: !disabled.has(pluginId),\n\t\t\t\t\t\t\tdisabled: disabled.has(pluginId),\n\t\t\t\t\t\t},\n\t\t\t\t\t];\n\t\t}),\n\t\thost: input.host,\n\t\t// The host's own version enforces each manifest's minHostVersion floor\n\t\t// at the single builtin profile resolution funnel used by production\n\t\t// loading paths.\n\t\thostVersion: VERSION,\n\t});\n\tconst merged = mergeMissingPluginResolutionsV1(resolution, missingPluginIds, disabled);\n\tif (merged.status !== \"ready\") return { status: \"resolved\", profile: selectedProfile, resolution: merged };\n\tconst resolvedPlugins = merged.resolvedManifest.plugins.map((plugin) => ({\n\t\tpluginId: plugin.pluginId,\n\t\tpluginVersion: plugin.pluginVersion,\n\t\tcapabilityRefs: plugin.capabilityRefs,\n\t\t...(plugin.selectedAdapter === undefined ? {} : { selectedAdapter: plugin.selectedAdapter }),\n\t}));\n\tconst verifiedPlugins = input.verifiedPlugins ?? [];\n\tconst assembly = assembleProfile({\n\t\tprofileId: selectedProfile.id,\n\t\tprofileVersion: selectedProfile.version,\n\t\tresolvedPlugins,\n\t\tverifiedPlugins,\n\t});\n\treturn {\n\t\tstatus: \"resolved\",\n\t\tprofile: selectedProfile,\n\t\tresolution: merged,\n\t\tassembly,\n\t};\n}\n\nfunction manifestFor(\n\tpluginId: string,\n\toverrides: BuiltinPluginManifestOverridesV1 | undefined,\n): PluginManifestV1 | undefined {\n\tconst manifest = overrides?.[pluginId] ?? manifests[pluginId];\n\t// A mismatched override stays a hard host error: the host selected it\n\t// explicitly, so silence would hide an identity bug. A plain absent\n\t// manifest (no builtin, no installed override) is the structured miss.\n\tif (manifest !== undefined && manifest.id !== pluginId)\n\t\tthrow new Error(t(\"builtin manifest override does not match plugin {pluginId}\", { pluginId }));\n\treturn manifest;\n}\n\n/**\n * Merge structured `manifest_missing` resolutions for Profile plugins that\n * have no builtin manifest and no installed override into the resolver\n * result. Missing plugins never block the Profile (soft degradation): the\n * remaining diagnostics and the resolved manifest stay exactly what the\n * resolver produced, and the merged plugin list keeps the resolver's\n * deterministic id sort.\n */\nfunction mergeMissingPluginResolutionsV1(\n\tresolution: ProfileResolutionV1,\n\tmissingPluginIds: readonly string[],\n\tdisabled: ReadonlySet<string>,\n): ProfileResolutionV1 {\n\tif (missingPluginIds.length === 0) return resolution;\n\tconst missing: PluginResolutionV1[] = missingPluginIds.map((pluginId) => ({\n\t\tpluginId,\n\t\tpluginVersion: \"\",\n\t\trequired: !disabled.has(pluginId),\n\t\tstatus: \"manifest-missing\",\n\t\tdiagnostics: [\n\t\t\t{\n\t\t\t\tcode: \"manifest_missing\",\n\t\t\t\tmessage: `Plugin ${pluginId} has no builtin manifest and no installed active override; the plugin is omitted from this profile (install it with agent-forge plugin install)`,\n\t\t\t},\n\t\t],\n\t}));\n\tconst plugins = [...resolution.plugins, ...missing].sort((left, right) =>\n\t\tleft.pluginId.localeCompare(right.pluginId),\n\t);\n\treturn Object.freeze({\n\t\t...resolution,\n\t\tplugins: Object.freeze(plugins),\n\t\tdiagnostics: Object.freeze(plugins.flatMap((plugin) => plugin.diagnostics)),\n\t});\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"policy-manifest.d.ts","sourceRoot":"","sources":["../../src/profile/policy-manifest.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAGjD,MAAM,MAAM,YAAY,GAAG,cAAc,GAAG,YAAY,GAAG,qBAAqB,CAAC;AAEjF,MAAM,WAAW,mBAAmB;IACnC,QAAQ,CAAC,UAAU,EAAE,YAAY,CAAC;IAClC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,2EAAyE;IACzE,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,CAAC;CAC9B;AAED,MAAM,WAAW,gBAAgB;IAChC,QAAQ,CAAC,eAAe,EAAE,CAAC,CAAC;IAC5B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,YAAY,EAAE,SAAS,mBAAmB,EAAE,CAAC;IACtD,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;CAChC;AAED,MAAM,WAAW,oBAAoB;IACpC,QAAQ,CAAC,UAAU,EAAE,YAAY,CAAC;IAClC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,UAAU,GAAG,mBAAmB,CAAC;IAClD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,uBAAuB;IACvC,aAAa,CAAC,KAAK,EAAE;QACpB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;QAC3B,QAAQ,CAAC,YAAY,EAAE,SAAS,mBAAmB,EAAE,CAAC;KACtD,GAAG,gBAAgB,CAAC;IACrB,0FAA0F;IAC1F,oBAAoB,CACnB,QAAQ,EAAE,gBAAgB,EAC1B,KAAK,EAAE;QACN,QAAQ,CAAC,UAAU,EAAE,YAAY,CAAC;QAClC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;QAC1B,QAAQ,CAAC,QAAQ,EAAE,mBAAmB,GAAG,IAAI,CAAC;QAC9C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;KACxB,GACC;QAAE,QAAQ,CAAC,QAAQ,EAAE,gBAAgB,CAAC;QAAC,QAAQ,CAAC,MAAM,EAAE,oBAAoB,CAAA;KAAE,CAAC;CAClF;AAcD,wBAAgB,2BAA2B,IAAI,uBAAuB,CA4CrE","sourcesContent":["/**\n * Default policy manifest (2.7e) — an explicit, declarative manifest of the\n * confirmation / permission / dangerous-operation policies a profile wants,\n * with an external selection path.\n *\n * The manifest is PURE DECLARATION: the kernel ships no policy enforcement —\n * an enforcement plugin (or none at all) attaches externally. Every entry\n * states its `enabled` flag explicitly; selecting an external policy\n * replaces or nulls (disables) a declaration and produces a NEW frozen\n * manifest plus a change record — the previous manifest stays untouched.\n * Digests reuse the key-order-stable serialization so declarations are\n * replayable.\n */\nimport type { JsonValue } from \"@agent-forge/ai\";\nimport { stableJsonDigest } from \"./identity.ts\";\n\nexport type PolicyKindV1 = \"confirmation\" | \"permission\" | \"dangerous_operation\";\n\nexport interface PolicyDeclarationV1 {\n\treadonly policyKind: PolicyKindV1;\n\treadonly policyId: string;\n\treadonly description: string;\n\t/** Stated explicitly — a policy the profile does not want is `false`. */\n\treadonly enabled: boolean;\n\treadonly defaults?: JsonValue;\n}\n\nexport interface PolicyManifestV1 {\n\treadonly manifestVersion: 1;\n\treadonly profileId: string;\n\treadonly declarations: readonly PolicyDeclarationV1[];\n\treadonly manifestDigest: string;\n}\n\nexport interface PolicyChangeRecordV1 {\n\treadonly policyKind: PolicyKindV1;\n\treadonly policyId: string;\n\treadonly action: \"disabled\" | \"external_selected\";\n\treadonly reason: string;\n}\n\nexport interface PolicyManifestBuilderV1 {\n\tbuildManifest(input: {\n\t\treadonly profileId: string;\n\t\treadonly declarations: readonly PolicyDeclarationV1[];\n\t}): PolicyManifestV1;\n\t/** The external selection path: swap in an external declaration or disable one (null). */\n\tselectExternalPolicy(\n\t\tmanifest: PolicyManifestV1,\n\t\tinput: {\n\t\t\treadonly policyKind: PolicyKindV1;\n\t\t\treadonly policyId: string;\n\t\t\treadonly external: PolicyDeclarationV1 | null;\n\t\t\treadonly reason: string;\n\t\t},\n\t): { readonly manifest: PolicyManifestV1; readonly change: PolicyChangeRecordV1 };\n}\n\nfunction assertDeclaration(value: PolicyDeclarationV1): void {\n\tif (![\"confirmation\", \"permission\", \"dangerous_operation\"].includes(value.policyKind)) {\n\t\tthrow new Error(`Policy manifest policyKind is invalid: ${String(value.policyKind)}`);\n\t}\n\tif (typeof value.policyId !== \"string\" || value.policyId.trim().length === 0) {\n\t\tthrow new Error(\"Policy manifest policyId must be a non-empty string\");\n\t}\n\tif (typeof value.enabled !== \"boolean\") {\n\t\tthrow new Error(`Policy manifest ${value.policyId}: enabled must be stated explicitly`);\n\t}\n}\n\nexport function createPolicyManifestBuilder(): PolicyManifestBuilderV1 {\n\tconst buildManifest = (input: {\n\t\treadonly profileId: string;\n\t\treadonly declarations: readonly PolicyDeclarationV1[];\n\t}): PolicyManifestV1 => {\n\t\tif (input.profileId.trim().length === 0) throw new Error(\"Policy manifest profileId must be a non-empty string\");\n\t\tfor (const declaration of input.declarations) assertDeclaration(declaration);\n\t\tconst declarations = Object.freeze(input.declarations.map((declaration) => Object.freeze({ ...declaration })));\n\t\treturn Object.freeze({\n\t\t\tmanifestVersion: 1 as const,\n\t\t\tprofileId: input.profileId,\n\t\t\tdeclarations,\n\t\t\tmanifestDigest: stableJsonDigest(declarations as unknown as JsonValue),\n\t\t});\n\t};\n\n\treturn {\n\t\tbuildManifest,\n\t\tselectExternalPolicy(manifest, input) {\n\t\t\tassertDeclaration(\n\t\t\t\tinput.external ?? {\n\t\t\t\t\tpolicyKind: input.policyKind,\n\t\t\t\t\tpolicyId: input.policyId,\n\t\t\t\t\tdescription: \"\",\n\t\t\t\t\tenabled: false,\n\t\t\t\t},\n\t\t\t);\n\t\t\tconst kept = manifest.declarations.filter(\n\t\t\t\t(declaration) => !(declaration.policyKind === input.policyKind && declaration.policyId === input.policyId),\n\t\t\t);\n\t\t\tconst existed = kept.length !== manifest.declarations.length;\n\t\t\tconst declarations = input.external === null ? kept : [...kept, input.external];\n\t\t\tconst next = buildManifest({ profileId: manifest.profileId, declarations });\n\t\t\treturn {\n\t\t\t\tmanifest: next,\n\t\t\t\tchange: {\n\t\t\t\t\tpolicyKind: input.policyKind,\n\t\t\t\t\tpolicyId: input.policyId,\n\t\t\t\t\taction: input.external === null ? \"disabled\" : existed ? \"external_selected\" : \"external_selected\",\n\t\t\t\t\treason: input.reason,\n\t\t\t\t},\n\t\t\t};\n\t\t},\n\t};\n}\n"]}
1
+ {"version":3,"file":"policy-manifest.d.ts","sourceRoot":"","sources":["../../src/profile/policy-manifest.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAIjD,MAAM,MAAM,YAAY,GAAG,cAAc,GAAG,YAAY,GAAG,qBAAqB,CAAC;AAEjF,MAAM,WAAW,mBAAmB;IACnC,QAAQ,CAAC,UAAU,EAAE,YAAY,CAAC;IAClC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,2EAAyE;IACzE,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,CAAC;CAC9B;AAED,MAAM,WAAW,gBAAgB;IAChC,QAAQ,CAAC,eAAe,EAAE,CAAC,CAAC;IAC5B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,YAAY,EAAE,SAAS,mBAAmB,EAAE,CAAC;IACtD,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;CAChC;AAED,MAAM,WAAW,oBAAoB;IACpC,QAAQ,CAAC,UAAU,EAAE,YAAY,CAAC;IAClC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,UAAU,GAAG,mBAAmB,CAAC;IAClD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,uBAAuB;IACvC,aAAa,CAAC,KAAK,EAAE;QACpB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;QAC3B,QAAQ,CAAC,YAAY,EAAE,SAAS,mBAAmB,EAAE,CAAC;KACtD,GAAG,gBAAgB,CAAC;IACrB,0FAA0F;IAC1F,oBAAoB,CACnB,QAAQ,EAAE,gBAAgB,EAC1B,KAAK,EAAE;QACN,QAAQ,CAAC,UAAU,EAAE,YAAY,CAAC;QAClC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;QAC1B,QAAQ,CAAC,QAAQ,EAAE,mBAAmB,GAAG,IAAI,CAAC;QAC9C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;KACxB,GACC;QAAE,QAAQ,CAAC,QAAQ,EAAE,gBAAgB,CAAC;QAAC,QAAQ,CAAC,MAAM,EAAE,oBAAoB,CAAA;KAAE,CAAC;CAClF;AAgBD,wBAAgB,2BAA2B,IAAI,uBAAuB,CA6CrE","sourcesContent":["/**\n * Default policy manifest (2.7e) — an explicit, declarative manifest of the\n * confirmation / permission / dangerous-operation policies a profile wants,\n * with an external selection path.\n *\n * The manifest is PURE DECLARATION: the kernel ships no policy enforcement —\n * an enforcement plugin (or none at all) attaches externally. Every entry\n * states its `enabled` flag explicitly; selecting an external policy\n * replaces or nulls (disables) a declaration and produces a NEW frozen\n * manifest plus a change record — the previous manifest stays untouched.\n * Digests reuse the key-order-stable serialization so declarations are\n * replayable.\n */\nimport type { JsonValue } from \"@agent-forge/ai\";\nimport { t } from \"../core/i18n/index.ts\";\nimport { stableJsonDigest } from \"./identity.ts\";\n\nexport type PolicyKindV1 = \"confirmation\" | \"permission\" | \"dangerous_operation\";\n\nexport interface PolicyDeclarationV1 {\n\treadonly policyKind: PolicyKindV1;\n\treadonly policyId: string;\n\treadonly description: string;\n\t/** Stated explicitly — a policy the profile does not want is `false`. */\n\treadonly enabled: boolean;\n\treadonly defaults?: JsonValue;\n}\n\nexport interface PolicyManifestV1 {\n\treadonly manifestVersion: 1;\n\treadonly profileId: string;\n\treadonly declarations: readonly PolicyDeclarationV1[];\n\treadonly manifestDigest: string;\n}\n\nexport interface PolicyChangeRecordV1 {\n\treadonly policyKind: PolicyKindV1;\n\treadonly policyId: string;\n\treadonly action: \"disabled\" | \"external_selected\";\n\treadonly reason: string;\n}\n\nexport interface PolicyManifestBuilderV1 {\n\tbuildManifest(input: {\n\t\treadonly profileId: string;\n\t\treadonly declarations: readonly PolicyDeclarationV1[];\n\t}): PolicyManifestV1;\n\t/** The external selection path: swap in an external declaration or disable one (null). */\n\tselectExternalPolicy(\n\t\tmanifest: PolicyManifestV1,\n\t\tinput: {\n\t\t\treadonly policyKind: PolicyKindV1;\n\t\t\treadonly policyId: string;\n\t\t\treadonly external: PolicyDeclarationV1 | null;\n\t\t\treadonly reason: string;\n\t\t},\n\t): { readonly manifest: PolicyManifestV1; readonly change: PolicyChangeRecordV1 };\n}\n\nfunction assertDeclaration(value: PolicyDeclarationV1): void {\n\tif (![\"confirmation\", \"permission\", \"dangerous_operation\"].includes(value.policyKind)) {\n\t\tthrow new Error(\n\t\t\tt(\"Policy manifest policyKind is invalid: {policyKind}\", { policyKind: String(value.policyKind) }),\n\t\t);\n\t}\n\tif (typeof value.policyId !== \"string\" || value.policyId.trim().length === 0) {\n\t\tthrow new Error(t(\"Policy manifest policyId must be a non-empty string\"));\n\t}\n\tif (typeof value.enabled !== \"boolean\") {\n\t\tthrow new Error(t(\"Policy manifest {policyId}: enabled must be stated explicitly\", { policyId: value.policyId }));\n\t}\n}\n\nexport function createPolicyManifestBuilder(): PolicyManifestBuilderV1 {\n\tconst buildManifest = (input: {\n\t\treadonly profileId: string;\n\t\treadonly declarations: readonly PolicyDeclarationV1[];\n\t}): PolicyManifestV1 => {\n\t\tif (input.profileId.trim().length === 0)\n\t\t\tthrow new Error(t(\"Policy manifest profileId must be a non-empty string\"));\n\t\tfor (const declaration of input.declarations) assertDeclaration(declaration);\n\t\tconst declarations = Object.freeze(input.declarations.map((declaration) => Object.freeze({ ...declaration })));\n\t\treturn Object.freeze({\n\t\t\tmanifestVersion: 1 as const,\n\t\t\tprofileId: input.profileId,\n\t\t\tdeclarations,\n\t\t\tmanifestDigest: stableJsonDigest(declarations as unknown as JsonValue),\n\t\t});\n\t};\n\n\treturn {\n\t\tbuildManifest,\n\t\tselectExternalPolicy(manifest, input) {\n\t\t\tassertDeclaration(\n\t\t\t\tinput.external ?? {\n\t\t\t\t\tpolicyKind: input.policyKind,\n\t\t\t\t\tpolicyId: input.policyId,\n\t\t\t\t\tdescription: \"\",\n\t\t\t\t\tenabled: false,\n\t\t\t\t},\n\t\t\t);\n\t\t\tconst kept = manifest.declarations.filter(\n\t\t\t\t(declaration) => !(declaration.policyKind === input.policyKind && declaration.policyId === input.policyId),\n\t\t\t);\n\t\t\tconst existed = kept.length !== manifest.declarations.length;\n\t\t\tconst declarations = input.external === null ? kept : [...kept, input.external];\n\t\t\tconst next = buildManifest({ profileId: manifest.profileId, declarations });\n\t\t\treturn {\n\t\t\t\tmanifest: next,\n\t\t\t\tchange: {\n\t\t\t\t\tpolicyKind: input.policyKind,\n\t\t\t\t\tpolicyId: input.policyId,\n\t\t\t\t\taction: input.external === null ? \"disabled\" : existed ? \"external_selected\" : \"external_selected\",\n\t\t\t\t\treason: input.reason,\n\t\t\t\t},\n\t\t\t};\n\t\t},\n\t};\n}\n"]}
@@ -1,19 +1,20 @@
1
+ import { t } from "../core/i18n/index.js";
1
2
  import { stableJsonDigest } from "./identity.js";
2
3
  function assertDeclaration(value) {
3
4
  if (!["confirmation", "permission", "dangerous_operation"].includes(value.policyKind)) {
4
- throw new Error(`Policy manifest policyKind is invalid: ${String(value.policyKind)}`);
5
+ throw new Error(t("Policy manifest policyKind is invalid: {policyKind}", { policyKind: String(value.policyKind) }));
5
6
  }
6
7
  if (typeof value.policyId !== "string" || value.policyId.trim().length === 0) {
7
- throw new Error("Policy manifest policyId must be a non-empty string");
8
+ throw new Error(t("Policy manifest policyId must be a non-empty string"));
8
9
  }
9
10
  if (typeof value.enabled !== "boolean") {
10
- throw new Error(`Policy manifest ${value.policyId}: enabled must be stated explicitly`);
11
+ throw new Error(t("Policy manifest {policyId}: enabled must be stated explicitly", { policyId: value.policyId }));
11
12
  }
12
13
  }
13
14
  export function createPolicyManifestBuilder() {
14
15
  const buildManifest = (input) => {
15
16
  if (input.profileId.trim().length === 0)
16
- throw new Error("Policy manifest profileId must be a non-empty string");
17
+ throw new Error(t("Policy manifest profileId must be a non-empty string"));
17
18
  for (const declaration of input.declarations)
18
19
  assertDeclaration(declaration);
19
20
  const declarations = Object.freeze(input.declarations.map((declaration) => Object.freeze({ ...declaration })));
@@ -1 +1 @@
1
- {"version":3,"file":"policy-manifest.js","sourceRoot":"","sources":["../../src/profile/policy-manifest.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Default policy manifest (2.7e) — an explicit, declarative manifest of the\n * confirmation / permission / dangerous-operation policies a profile wants,\n * with an external selection path.\n *\n * The manifest is PURE DECLARATION: the kernel ships no policy enforcement —\n * an enforcement plugin (or none at all) attaches externally. Every entry\n * states its `enabled` flag explicitly; selecting an external policy\n * replaces or nulls (disables) a declaration and produces a NEW frozen\n * manifest plus a change record — the previous manifest stays untouched.\n * Digests reuse the key-order-stable serialization so declarations are\n * replayable.\n */\nimport type { JsonValue } from \"@agent-forge/ai\";\nimport { stableJsonDigest } from \"./identity.ts\";\n\nexport type PolicyKindV1 = \"confirmation\" | \"permission\" | \"dangerous_operation\";\n\nexport interface PolicyDeclarationV1 {\n\treadonly policyKind: PolicyKindV1;\n\treadonly policyId: string;\n\treadonly description: string;\n\t/** Stated explicitly — a policy the profile does not want is `false`. */\n\treadonly enabled: boolean;\n\treadonly defaults?: JsonValue;\n}\n\nexport interface PolicyManifestV1 {\n\treadonly manifestVersion: 1;\n\treadonly profileId: string;\n\treadonly declarations: readonly PolicyDeclarationV1[];\n\treadonly manifestDigest: string;\n}\n\nexport interface PolicyChangeRecordV1 {\n\treadonly policyKind: PolicyKindV1;\n\treadonly policyId: string;\n\treadonly action: \"disabled\" | \"external_selected\";\n\treadonly reason: string;\n}\n\nexport interface PolicyManifestBuilderV1 {\n\tbuildManifest(input: {\n\t\treadonly profileId: string;\n\t\treadonly declarations: readonly PolicyDeclarationV1[];\n\t}): PolicyManifestV1;\n\t/** The external selection path: swap in an external declaration or disable one (null). */\n\tselectExternalPolicy(\n\t\tmanifest: PolicyManifestV1,\n\t\tinput: {\n\t\t\treadonly policyKind: PolicyKindV1;\n\t\t\treadonly policyId: string;\n\t\t\treadonly external: PolicyDeclarationV1 | null;\n\t\t\treadonly reason: string;\n\t\t},\n\t): { readonly manifest: PolicyManifestV1; readonly change: PolicyChangeRecordV1 };\n}\n\nfunction assertDeclaration(value: PolicyDeclarationV1): void {\n\tif (![\"confirmation\", \"permission\", \"dangerous_operation\"].includes(value.policyKind)) {\n\t\tthrow new Error(`Policy manifest policyKind is invalid: ${String(value.policyKind)}`);\n\t}\n\tif (typeof value.policyId !== \"string\" || value.policyId.trim().length === 0) {\n\t\tthrow new Error(\"Policy manifest policyId must be a non-empty string\");\n\t}\n\tif (typeof value.enabled !== \"boolean\") {\n\t\tthrow new Error(`Policy manifest ${value.policyId}: enabled must be stated explicitly`);\n\t}\n}\n\nexport function createPolicyManifestBuilder(): PolicyManifestBuilderV1 {\n\tconst buildManifest = (input: {\n\t\treadonly profileId: string;\n\t\treadonly declarations: readonly PolicyDeclarationV1[];\n\t}): PolicyManifestV1 => {\n\t\tif (input.profileId.trim().length === 0) throw new Error(\"Policy manifest profileId must be a non-empty string\");\n\t\tfor (const declaration of input.declarations) assertDeclaration(declaration);\n\t\tconst declarations = Object.freeze(input.declarations.map((declaration) => Object.freeze({ ...declaration })));\n\t\treturn Object.freeze({\n\t\t\tmanifestVersion: 1 as const,\n\t\t\tprofileId: input.profileId,\n\t\t\tdeclarations,\n\t\t\tmanifestDigest: stableJsonDigest(declarations as unknown as JsonValue),\n\t\t});\n\t};\n\n\treturn {\n\t\tbuildManifest,\n\t\tselectExternalPolicy(manifest, input) {\n\t\t\tassertDeclaration(\n\t\t\t\tinput.external ?? {\n\t\t\t\t\tpolicyKind: input.policyKind,\n\t\t\t\t\tpolicyId: input.policyId,\n\t\t\t\t\tdescription: \"\",\n\t\t\t\t\tenabled: false,\n\t\t\t\t},\n\t\t\t);\n\t\t\tconst kept = manifest.declarations.filter(\n\t\t\t\t(declaration) => !(declaration.policyKind === input.policyKind && declaration.policyId === input.policyId),\n\t\t\t);\n\t\t\tconst existed = kept.length !== manifest.declarations.length;\n\t\t\tconst declarations = input.external === null ? kept : [...kept, input.external];\n\t\t\tconst next = buildManifest({ profileId: manifest.profileId, declarations });\n\t\t\treturn {\n\t\t\t\tmanifest: next,\n\t\t\t\tchange: {\n\t\t\t\t\tpolicyKind: input.policyKind,\n\t\t\t\t\tpolicyId: input.policyId,\n\t\t\t\t\taction: input.external === null ? \"disabled\" : existed ? \"external_selected\" : \"external_selected\",\n\t\t\t\t\treason: input.reason,\n\t\t\t\t},\n\t\t\t};\n\t\t},\n\t};\n}\n"]}
1
+ {"version":3,"file":"policy-manifest.js","sourceRoot":"","sources":["../../src/profile/policy-manifest.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Default policy manifest (2.7e) — an explicit, declarative manifest of the\n * confirmation / permission / dangerous-operation policies a profile wants,\n * with an external selection path.\n *\n * The manifest is PURE DECLARATION: the kernel ships no policy enforcement —\n * an enforcement plugin (or none at all) attaches externally. Every entry\n * states its `enabled` flag explicitly; selecting an external policy\n * replaces or nulls (disables) a declaration and produces a NEW frozen\n * manifest plus a change record — the previous manifest stays untouched.\n * Digests reuse the key-order-stable serialization so declarations are\n * replayable.\n */\nimport type { JsonValue } from \"@agent-forge/ai\";\nimport { t } from \"../core/i18n/index.ts\";\nimport { stableJsonDigest } from \"./identity.ts\";\n\nexport type PolicyKindV1 = \"confirmation\" | \"permission\" | \"dangerous_operation\";\n\nexport interface PolicyDeclarationV1 {\n\treadonly policyKind: PolicyKindV1;\n\treadonly policyId: string;\n\treadonly description: string;\n\t/** Stated explicitly — a policy the profile does not want is `false`. */\n\treadonly enabled: boolean;\n\treadonly defaults?: JsonValue;\n}\n\nexport interface PolicyManifestV1 {\n\treadonly manifestVersion: 1;\n\treadonly profileId: string;\n\treadonly declarations: readonly PolicyDeclarationV1[];\n\treadonly manifestDigest: string;\n}\n\nexport interface PolicyChangeRecordV1 {\n\treadonly policyKind: PolicyKindV1;\n\treadonly policyId: string;\n\treadonly action: \"disabled\" | \"external_selected\";\n\treadonly reason: string;\n}\n\nexport interface PolicyManifestBuilderV1 {\n\tbuildManifest(input: {\n\t\treadonly profileId: string;\n\t\treadonly declarations: readonly PolicyDeclarationV1[];\n\t}): PolicyManifestV1;\n\t/** The external selection path: swap in an external declaration or disable one (null). */\n\tselectExternalPolicy(\n\t\tmanifest: PolicyManifestV1,\n\t\tinput: {\n\t\t\treadonly policyKind: PolicyKindV1;\n\t\t\treadonly policyId: string;\n\t\t\treadonly external: PolicyDeclarationV1 | null;\n\t\t\treadonly reason: string;\n\t\t},\n\t): { readonly manifest: PolicyManifestV1; readonly change: PolicyChangeRecordV1 };\n}\n\nfunction assertDeclaration(value: PolicyDeclarationV1): void {\n\tif (![\"confirmation\", \"permission\", \"dangerous_operation\"].includes(value.policyKind)) {\n\t\tthrow new Error(\n\t\t\tt(\"Policy manifest policyKind is invalid: {policyKind}\", { policyKind: String(value.policyKind) }),\n\t\t);\n\t}\n\tif (typeof value.policyId !== \"string\" || value.policyId.trim().length === 0) {\n\t\tthrow new Error(t(\"Policy manifest policyId must be a non-empty string\"));\n\t}\n\tif (typeof value.enabled !== \"boolean\") {\n\t\tthrow new Error(t(\"Policy manifest {policyId}: enabled must be stated explicitly\", { policyId: value.policyId }));\n\t}\n}\n\nexport function createPolicyManifestBuilder(): PolicyManifestBuilderV1 {\n\tconst buildManifest = (input: {\n\t\treadonly profileId: string;\n\t\treadonly declarations: readonly PolicyDeclarationV1[];\n\t}): PolicyManifestV1 => {\n\t\tif (input.profileId.trim().length === 0)\n\t\t\tthrow new Error(t(\"Policy manifest profileId must be a non-empty string\"));\n\t\tfor (const declaration of input.declarations) assertDeclaration(declaration);\n\t\tconst declarations = Object.freeze(input.declarations.map((declaration) => Object.freeze({ ...declaration })));\n\t\treturn Object.freeze({\n\t\t\tmanifestVersion: 1 as const,\n\t\t\tprofileId: input.profileId,\n\t\t\tdeclarations,\n\t\t\tmanifestDigest: stableJsonDigest(declarations as unknown as JsonValue),\n\t\t});\n\t};\n\n\treturn {\n\t\tbuildManifest,\n\t\tselectExternalPolicy(manifest, input) {\n\t\t\tassertDeclaration(\n\t\t\t\tinput.external ?? {\n\t\t\t\t\tpolicyKind: input.policyKind,\n\t\t\t\t\tpolicyId: input.policyId,\n\t\t\t\t\tdescription: \"\",\n\t\t\t\t\tenabled: false,\n\t\t\t\t},\n\t\t\t);\n\t\t\tconst kept = manifest.declarations.filter(\n\t\t\t\t(declaration) => !(declaration.policyKind === input.policyKind && declaration.policyId === input.policyId),\n\t\t\t);\n\t\t\tconst existed = kept.length !== manifest.declarations.length;\n\t\t\tconst declarations = input.external === null ? kept : [...kept, input.external];\n\t\t\tconst next = buildManifest({ profileId: manifest.profileId, declarations });\n\t\t\treturn {\n\t\t\t\tmanifest: next,\n\t\t\t\tchange: {\n\t\t\t\t\tpolicyKind: input.policyKind,\n\t\t\t\t\tpolicyId: input.policyId,\n\t\t\t\t\taction: input.external === null ? \"disabled\" : existed ? \"external_selected\" : \"external_selected\",\n\t\t\t\t\treason: input.reason,\n\t\t\t\t},\n\t\t\t};\n\t\t},\n\t};\n}\n"]}
@@ -1,15 +1,3 @@
1
- /**
2
- * Profile registry (2.7a) — multi-source discovery, upgrades, and
3
- * compatibility for profile manifests on top of the minimal 2.0a identity.
4
- *
5
- * Sources register profiles with a priority (lower number wins). Resolution
6
- * is deterministic and replayable: filter candidates by the requested
7
- * version range, pick the highest version, break same-version ties by
8
- * source priority (the losing source is reported as superseded), and mark
9
- * deprecated winners explicitly (visible, digest still supplied — callers
10
- * decide whether to proceed). Builds on the minimal 2.0a identity/lock
11
- * without extending them.
12
- */
13
1
  export interface RegistryProfileEntryV1 {
14
2
  readonly profileId: string;
15
3
  readonly profileVersion: string;
@@ -1 +1 @@
1
- {"version":3,"file":"profile-registry.d.ts","sourceRoot":"","sources":["../../src/profile/profile-registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,sBAAsB;IACtC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,gBAAgB;IAChC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,oDAAoD;IACpD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,QAAQ,EAAE,SAAS,sBAAsB,EAAE,CAAC;CACrD;AAED,MAAM,WAAW,qBAAqB;IACrC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,MAAM,mBAAmB,GAC5B;IACA,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;IAC5B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,UAAU,EAAE,SAAS;QAAE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CAC9F,GACD;IACA,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC;IAC9B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACvB,GACD;IAAE,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;IAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC;AAEhE,MAAM,WAAW,iBAAiB;IACjC,cAAc,CAAC,MAAM,EAAE,gBAAgB,GAAG,IAAI,CAAC;IAC/C,OAAO,CAAC,KAAK,EAAE;QAAE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,qBAAqB,CAAA;KAAE,GAAG,mBAAmB,CAAC;CACnH;AAcD,wBAAgB,qBAAqB,IAAI,iBAAiB,CAmEzD","sourcesContent":["/**\n * Profile registry (2.7a) — multi-source discovery, upgrades, and\n * compatibility for profile manifests on top of the minimal 2.0a identity.\n *\n * Sources register profiles with a priority (lower number wins). Resolution\n * is deterministic and replayable: filter candidates by the requested\n * version range, pick the highest version, break same-version ties by\n * source priority (the losing source is reported as superseded), and mark\n * deprecated winners explicitly (visible, digest still supplied — callers\n * decide whether to proceed). Builds on the minimal 2.0a identity/lock\n * without extending them.\n */\nexport interface RegistryProfileEntryV1 {\n\treadonly profileId: string;\n\treadonly profileVersion: string;\n\treadonly manifestDigest: string;\n\treadonly deprecated?: string;\n}\n\nexport interface RegistrySourceV1 {\n\treadonly sourceId: string;\n\t/** Lower priority number wins same-version ties. */\n\treadonly priority: number;\n\treadonly profiles: readonly RegistryProfileEntryV1[];\n}\n\nexport interface ProfileVersionRangeV1 {\n\treadonly min?: string;\n\treadonly max?: string;\n}\n\nexport type ProfileResolutionV1 =\n\t| {\n\t\t\treadonly status: \"resolved\";\n\t\t\treadonly profileId: string;\n\t\t\treadonly profileVersion: string;\n\t\t\treadonly manifestDigest: string;\n\t\t\treadonly sourceId: string;\n\t\t\treadonly superseded: readonly { readonly sourceId: string; readonly profileVersion: string }[];\n\t }\n\t| {\n\t\t\treadonly status: \"deprecated\";\n\t\t\treadonly profileId: string;\n\t\t\treadonly profileVersion: string;\n\t\t\treadonly manifestDigest: string;\n\t\t\treadonly sourceId: string;\n\t\t\treadonly reason: string;\n\t }\n\t| { readonly status: \"not_found\"; readonly profileId: string };\n\nexport interface ProfileRegistryV1 {\n\tregisterSource(source: RegistrySourceV1): void;\n\tresolve(input: { readonly profileId: string; readonly versionRange?: ProfileVersionRangeV1 }): ProfileResolutionV1;\n}\n\n/** Segment-wise numeric semver comparison (\"1.2\" < \"1.10\" < \"2.0\"). */\nfunction compareVersions(a: string, b: string): number {\n\tconst pa = a.split(\".\").map((part) => Number.parseInt(part, 10) || 0);\n\tconst pb = b.split(\".\").map((part) => Number.parseInt(part, 10) || 0);\n\tconst length = Math.max(pa.length, pb.length);\n\tfor (let index = 0; index < length; index += 1) {\n\t\tconst diff = (pa[index] ?? 0) - (pb[index] ?? 0);\n\t\tif (diff !== 0) return diff;\n\t}\n\treturn 0;\n}\n\nexport function createProfileRegistry(): ProfileRegistryV1 {\n\tconst sources: RegistrySourceV1[] = [];\n\n\treturn {\n\t\tregisterSource(source) {\n\t\t\tif (sources.some((existing) => existing.sourceId === source.sourceId)) {\n\t\t\t\tthrow new Error(`Registry source already registered: ${source.sourceId}`);\n\t\t\t}\n\t\t\tsources.push(source);\n\t\t},\n\t\tresolve({ profileId, versionRange }) {\n\t\t\tconst candidates = sources\n\t\t\t\t.flatMap((source) =>\n\t\t\t\t\tsource.profiles\n\t\t\t\t\t\t.filter((profile) => profile.profileId === profileId)\n\t\t\t\t\t\t.map((profile) => ({ source, profile })),\n\t\t\t\t)\n\t\t\t\t.filter(({ profile }) => {\n\t\t\t\t\tif (versionRange?.min !== undefined && compareVersions(profile.profileVersion, versionRange.min) < 0) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t\tif (versionRange?.max !== undefined && compareVersions(profile.profileVersion, versionRange.max) > 0) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t\treturn true;\n\t\t\t\t})\n\t\t\t\t.sort((a, b) => {\n\t\t\t\t\tconst versionDiff = compareVersions(b.profile.profileVersion, a.profile.profileVersion);\n\t\t\t\t\tif (versionDiff !== 0) return versionDiff;\n\t\t\t\t\treturn a.source.priority - b.source.priority;\n\t\t\t\t});\n\n\t\t\tif (candidates.length === 0) {\n\t\t\t\treturn { status: \"not_found\", profileId };\n\t\t\t}\n\n\t\t\tconst winner = candidates[0]!;\n\t\t\tif (winner.profile.deprecated !== undefined) {\n\t\t\t\treturn {\n\t\t\t\t\tstatus: \"deprecated\",\n\t\t\t\t\tprofileId,\n\t\t\t\t\tprofileVersion: winner.profile.profileVersion,\n\t\t\t\t\tmanifestDigest: winner.profile.manifestDigest,\n\t\t\t\t\tsourceId: winner.source.sourceId,\n\t\t\t\t\treason: winner.profile.deprecated,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tconst superseded = candidates\n\t\t\t\t.slice(1)\n\t\t\t\t.filter(\n\t\t\t\t\t(candidate) => compareVersions(candidate.profile.profileVersion, winner.profile.profileVersion) === 0,\n\t\t\t\t)\n\t\t\t\t.map((candidate) => ({\n\t\t\t\t\tsourceId: candidate.source.sourceId,\n\t\t\t\t\tprofileVersion: candidate.profile.profileVersion,\n\t\t\t\t}));\n\t\t\treturn {\n\t\t\t\tstatus: \"resolved\",\n\t\t\t\tprofileId,\n\t\t\t\tprofileVersion: winner.profile.profileVersion,\n\t\t\t\tmanifestDigest: winner.profile.manifestDigest,\n\t\t\t\tsourceId: winner.source.sourceId,\n\t\t\t\tsuperseded,\n\t\t\t};\n\t\t},\n\t};\n}\n"]}
1
+ {"version":3,"file":"profile-registry.d.ts","sourceRoot":"","sources":["../../src/profile/profile-registry.ts"],"names":[],"mappings":"AAcA,MAAM,WAAW,sBAAsB;IACtC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,gBAAgB;IAChC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,oDAAoD;IACpD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,QAAQ,EAAE,SAAS,sBAAsB,EAAE,CAAC;CACrD;AAED,MAAM,WAAW,qBAAqB;IACrC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,MAAM,mBAAmB,GAC5B;IACA,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;IAC5B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,UAAU,EAAE,SAAS;QAAE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CAC9F,GACD;IACA,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC;IAC9B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACvB,GACD;IAAE,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;IAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC;AAEhE,MAAM,WAAW,iBAAiB;IACjC,cAAc,CAAC,MAAM,EAAE,gBAAgB,GAAG,IAAI,CAAC;IAC/C,OAAO,CAAC,KAAK,EAAE;QAAE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,qBAAqB,CAAA;KAAE,GAAG,mBAAmB,CAAC;CACnH;AAcD,wBAAgB,qBAAqB,IAAI,iBAAiB,CAmEzD","sourcesContent":["/**\n * Profile registry (2.7a) — multi-source discovery, upgrades, and\n * compatibility for profile manifests on top of the minimal 2.0a identity.\n *\n * Sources register profiles with a priority (lower number wins). Resolution\n * is deterministic and replayable: filter candidates by the requested\n * version range, pick the highest version, break same-version ties by\n * source priority (the losing source is reported as superseded), and mark\n * deprecated winners explicitly (visible, digest still supplied — callers\n * decide whether to proceed). Builds on the minimal 2.0a identity/lock\n * without extending them.\n */\nimport { t } from \"../core/i18n/index.ts\";\n\nexport interface RegistryProfileEntryV1 {\n\treadonly profileId: string;\n\treadonly profileVersion: string;\n\treadonly manifestDigest: string;\n\treadonly deprecated?: string;\n}\n\nexport interface RegistrySourceV1 {\n\treadonly sourceId: string;\n\t/** Lower priority number wins same-version ties. */\n\treadonly priority: number;\n\treadonly profiles: readonly RegistryProfileEntryV1[];\n}\n\nexport interface ProfileVersionRangeV1 {\n\treadonly min?: string;\n\treadonly max?: string;\n}\n\nexport type ProfileResolutionV1 =\n\t| {\n\t\t\treadonly status: \"resolved\";\n\t\t\treadonly profileId: string;\n\t\t\treadonly profileVersion: string;\n\t\t\treadonly manifestDigest: string;\n\t\t\treadonly sourceId: string;\n\t\t\treadonly superseded: readonly { readonly sourceId: string; readonly profileVersion: string }[];\n\t }\n\t| {\n\t\t\treadonly status: \"deprecated\";\n\t\t\treadonly profileId: string;\n\t\t\treadonly profileVersion: string;\n\t\t\treadonly manifestDigest: string;\n\t\t\treadonly sourceId: string;\n\t\t\treadonly reason: string;\n\t }\n\t| { readonly status: \"not_found\"; readonly profileId: string };\n\nexport interface ProfileRegistryV1 {\n\tregisterSource(source: RegistrySourceV1): void;\n\tresolve(input: { readonly profileId: string; readonly versionRange?: ProfileVersionRangeV1 }): ProfileResolutionV1;\n}\n\n/** Segment-wise numeric semver comparison (\"1.2\" < \"1.10\" < \"2.0\"). */\nfunction compareVersions(a: string, b: string): number {\n\tconst pa = a.split(\".\").map((part) => Number.parseInt(part, 10) || 0);\n\tconst pb = b.split(\".\").map((part) => Number.parseInt(part, 10) || 0);\n\tconst length = Math.max(pa.length, pb.length);\n\tfor (let index = 0; index < length; index += 1) {\n\t\tconst diff = (pa[index] ?? 0) - (pb[index] ?? 0);\n\t\tif (diff !== 0) return diff;\n\t}\n\treturn 0;\n}\n\nexport function createProfileRegistry(): ProfileRegistryV1 {\n\tconst sources: RegistrySourceV1[] = [];\n\n\treturn {\n\t\tregisterSource(source) {\n\t\t\tif (sources.some((existing) => existing.sourceId === source.sourceId)) {\n\t\t\t\tthrow new Error(t(\"Registry source already registered: {sourceId}\", { sourceId: source.sourceId }));\n\t\t\t}\n\t\t\tsources.push(source);\n\t\t},\n\t\tresolve({ profileId, versionRange }) {\n\t\t\tconst candidates = sources\n\t\t\t\t.flatMap((source) =>\n\t\t\t\t\tsource.profiles\n\t\t\t\t\t\t.filter((profile) => profile.profileId === profileId)\n\t\t\t\t\t\t.map((profile) => ({ source, profile })),\n\t\t\t\t)\n\t\t\t\t.filter(({ profile }) => {\n\t\t\t\t\tif (versionRange?.min !== undefined && compareVersions(profile.profileVersion, versionRange.min) < 0) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t\tif (versionRange?.max !== undefined && compareVersions(profile.profileVersion, versionRange.max) > 0) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t\treturn true;\n\t\t\t\t})\n\t\t\t\t.sort((a, b) => {\n\t\t\t\t\tconst versionDiff = compareVersions(b.profile.profileVersion, a.profile.profileVersion);\n\t\t\t\t\tif (versionDiff !== 0) return versionDiff;\n\t\t\t\t\treturn a.source.priority - b.source.priority;\n\t\t\t\t});\n\n\t\t\tif (candidates.length === 0) {\n\t\t\t\treturn { status: \"not_found\", profileId };\n\t\t\t}\n\n\t\t\tconst winner = candidates[0]!;\n\t\t\tif (winner.profile.deprecated !== undefined) {\n\t\t\t\treturn {\n\t\t\t\t\tstatus: \"deprecated\",\n\t\t\t\t\tprofileId,\n\t\t\t\t\tprofileVersion: winner.profile.profileVersion,\n\t\t\t\t\tmanifestDigest: winner.profile.manifestDigest,\n\t\t\t\t\tsourceId: winner.source.sourceId,\n\t\t\t\t\treason: winner.profile.deprecated,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tconst superseded = candidates\n\t\t\t\t.slice(1)\n\t\t\t\t.filter(\n\t\t\t\t\t(candidate) => compareVersions(candidate.profile.profileVersion, winner.profile.profileVersion) === 0,\n\t\t\t\t)\n\t\t\t\t.map((candidate) => ({\n\t\t\t\t\tsourceId: candidate.source.sourceId,\n\t\t\t\t\tprofileVersion: candidate.profile.profileVersion,\n\t\t\t\t}));\n\t\t\treturn {\n\t\t\t\tstatus: \"resolved\",\n\t\t\t\tprofileId,\n\t\t\t\tprofileVersion: winner.profile.profileVersion,\n\t\t\t\tmanifestDigest: winner.profile.manifestDigest,\n\t\t\t\tsourceId: winner.source.sourceId,\n\t\t\t\tsuperseded,\n\t\t\t};\n\t\t},\n\t};\n}\n"]}
@@ -1,3 +1,16 @@
1
+ /**
2
+ * Profile registry (2.7a) — multi-source discovery, upgrades, and
3
+ * compatibility for profile manifests on top of the minimal 2.0a identity.
4
+ *
5
+ * Sources register profiles with a priority (lower number wins). Resolution
6
+ * is deterministic and replayable: filter candidates by the requested
7
+ * version range, pick the highest version, break same-version ties by
8
+ * source priority (the losing source is reported as superseded), and mark
9
+ * deprecated winners explicitly (visible, digest still supplied — callers
10
+ * decide whether to proceed). Builds on the minimal 2.0a identity/lock
11
+ * without extending them.
12
+ */
13
+ import { t } from "../core/i18n/index.js";
1
14
  /** Segment-wise numeric semver comparison ("1.2" < "1.10" < "2.0"). */
2
15
  function compareVersions(a, b) {
3
16
  const pa = a.split(".").map((part) => Number.parseInt(part, 10) || 0);
@@ -15,7 +28,7 @@ export function createProfileRegistry() {
15
28
  return {
16
29
  registerSource(source) {
17
30
  if (sources.some((existing) => existing.sourceId === source.sourceId)) {
18
- throw new Error(`Registry source already registered: ${source.sourceId}`);
31
+ throw new Error(t("Registry source already registered: {sourceId}", { sourceId: source.sourceId }));
19
32
  }
20
33
  sources.push(source);
21
34
  },
@@ -1 +1 @@
1
- {"version":3,"file":"profile-registry.js","sourceRoot":"","sources":["../../src/profile/profile-registry.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Profile registry (2.7a) — multi-source discovery, upgrades, and\n * compatibility for profile manifests on top of the minimal 2.0a identity.\n *\n * Sources register profiles with a priority (lower number wins). Resolution\n * is deterministic and replayable: filter candidates by the requested\n * version range, pick the highest version, break same-version ties by\n * source priority (the losing source is reported as superseded), and mark\n * deprecated winners explicitly (visible, digest still supplied — callers\n * decide whether to proceed). Builds on the minimal 2.0a identity/lock\n * without extending them.\n */\nexport interface RegistryProfileEntryV1 {\n\treadonly profileId: string;\n\treadonly profileVersion: string;\n\treadonly manifestDigest: string;\n\treadonly deprecated?: string;\n}\n\nexport interface RegistrySourceV1 {\n\treadonly sourceId: string;\n\t/** Lower priority number wins same-version ties. */\n\treadonly priority: number;\n\treadonly profiles: readonly RegistryProfileEntryV1[];\n}\n\nexport interface ProfileVersionRangeV1 {\n\treadonly min?: string;\n\treadonly max?: string;\n}\n\nexport type ProfileResolutionV1 =\n\t| {\n\t\t\treadonly status: \"resolved\";\n\t\t\treadonly profileId: string;\n\t\t\treadonly profileVersion: string;\n\t\t\treadonly manifestDigest: string;\n\t\t\treadonly sourceId: string;\n\t\t\treadonly superseded: readonly { readonly sourceId: string; readonly profileVersion: string }[];\n\t }\n\t| {\n\t\t\treadonly status: \"deprecated\";\n\t\t\treadonly profileId: string;\n\t\t\treadonly profileVersion: string;\n\t\t\treadonly manifestDigest: string;\n\t\t\treadonly sourceId: string;\n\t\t\treadonly reason: string;\n\t }\n\t| { readonly status: \"not_found\"; readonly profileId: string };\n\nexport interface ProfileRegistryV1 {\n\tregisterSource(source: RegistrySourceV1): void;\n\tresolve(input: { readonly profileId: string; readonly versionRange?: ProfileVersionRangeV1 }): ProfileResolutionV1;\n}\n\n/** Segment-wise numeric semver comparison (\"1.2\" < \"1.10\" < \"2.0\"). */\nfunction compareVersions(a: string, b: string): number {\n\tconst pa = a.split(\".\").map((part) => Number.parseInt(part, 10) || 0);\n\tconst pb = b.split(\".\").map((part) => Number.parseInt(part, 10) || 0);\n\tconst length = Math.max(pa.length, pb.length);\n\tfor (let index = 0; index < length; index += 1) {\n\t\tconst diff = (pa[index] ?? 0) - (pb[index] ?? 0);\n\t\tif (diff !== 0) return diff;\n\t}\n\treturn 0;\n}\n\nexport function createProfileRegistry(): ProfileRegistryV1 {\n\tconst sources: RegistrySourceV1[] = [];\n\n\treturn {\n\t\tregisterSource(source) {\n\t\t\tif (sources.some((existing) => existing.sourceId === source.sourceId)) {\n\t\t\t\tthrow new Error(`Registry source already registered: ${source.sourceId}`);\n\t\t\t}\n\t\t\tsources.push(source);\n\t\t},\n\t\tresolve({ profileId, versionRange }) {\n\t\t\tconst candidates = sources\n\t\t\t\t.flatMap((source) =>\n\t\t\t\t\tsource.profiles\n\t\t\t\t\t\t.filter((profile) => profile.profileId === profileId)\n\t\t\t\t\t\t.map((profile) => ({ source, profile })),\n\t\t\t\t)\n\t\t\t\t.filter(({ profile }) => {\n\t\t\t\t\tif (versionRange?.min !== undefined && compareVersions(profile.profileVersion, versionRange.min) < 0) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t\tif (versionRange?.max !== undefined && compareVersions(profile.profileVersion, versionRange.max) > 0) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t\treturn true;\n\t\t\t\t})\n\t\t\t\t.sort((a, b) => {\n\t\t\t\t\tconst versionDiff = compareVersions(b.profile.profileVersion, a.profile.profileVersion);\n\t\t\t\t\tif (versionDiff !== 0) return versionDiff;\n\t\t\t\t\treturn a.source.priority - b.source.priority;\n\t\t\t\t});\n\n\t\t\tif (candidates.length === 0) {\n\t\t\t\treturn { status: \"not_found\", profileId };\n\t\t\t}\n\n\t\t\tconst winner = candidates[0]!;\n\t\t\tif (winner.profile.deprecated !== undefined) {\n\t\t\t\treturn {\n\t\t\t\t\tstatus: \"deprecated\",\n\t\t\t\t\tprofileId,\n\t\t\t\t\tprofileVersion: winner.profile.profileVersion,\n\t\t\t\t\tmanifestDigest: winner.profile.manifestDigest,\n\t\t\t\t\tsourceId: winner.source.sourceId,\n\t\t\t\t\treason: winner.profile.deprecated,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tconst superseded = candidates\n\t\t\t\t.slice(1)\n\t\t\t\t.filter(\n\t\t\t\t\t(candidate) => compareVersions(candidate.profile.profileVersion, winner.profile.profileVersion) === 0,\n\t\t\t\t)\n\t\t\t\t.map((candidate) => ({\n\t\t\t\t\tsourceId: candidate.source.sourceId,\n\t\t\t\t\tprofileVersion: candidate.profile.profileVersion,\n\t\t\t\t}));\n\t\t\treturn {\n\t\t\t\tstatus: \"resolved\",\n\t\t\t\tprofileId,\n\t\t\t\tprofileVersion: winner.profile.profileVersion,\n\t\t\t\tmanifestDigest: winner.profile.manifestDigest,\n\t\t\t\tsourceId: winner.source.sourceId,\n\t\t\t\tsuperseded,\n\t\t\t};\n\t\t},\n\t};\n}\n"]}
1
+ {"version":3,"file":"profile-registry.js","sourceRoot":"","sources":["../../src/profile/profile-registry.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Profile registry (2.7a) — multi-source discovery, upgrades, and\n * compatibility for profile manifests on top of the minimal 2.0a identity.\n *\n * Sources register profiles with a priority (lower number wins). Resolution\n * is deterministic and replayable: filter candidates by the requested\n * version range, pick the highest version, break same-version ties by\n * source priority (the losing source is reported as superseded), and mark\n * deprecated winners explicitly (visible, digest still supplied — callers\n * decide whether to proceed). Builds on the minimal 2.0a identity/lock\n * without extending them.\n */\nimport { t } from \"../core/i18n/index.ts\";\n\nexport interface RegistryProfileEntryV1 {\n\treadonly profileId: string;\n\treadonly profileVersion: string;\n\treadonly manifestDigest: string;\n\treadonly deprecated?: string;\n}\n\nexport interface RegistrySourceV1 {\n\treadonly sourceId: string;\n\t/** Lower priority number wins same-version ties. */\n\treadonly priority: number;\n\treadonly profiles: readonly RegistryProfileEntryV1[];\n}\n\nexport interface ProfileVersionRangeV1 {\n\treadonly min?: string;\n\treadonly max?: string;\n}\n\nexport type ProfileResolutionV1 =\n\t| {\n\t\t\treadonly status: \"resolved\";\n\t\t\treadonly profileId: string;\n\t\t\treadonly profileVersion: string;\n\t\t\treadonly manifestDigest: string;\n\t\t\treadonly sourceId: string;\n\t\t\treadonly superseded: readonly { readonly sourceId: string; readonly profileVersion: string }[];\n\t }\n\t| {\n\t\t\treadonly status: \"deprecated\";\n\t\t\treadonly profileId: string;\n\t\t\treadonly profileVersion: string;\n\t\t\treadonly manifestDigest: string;\n\t\t\treadonly sourceId: string;\n\t\t\treadonly reason: string;\n\t }\n\t| { readonly status: \"not_found\"; readonly profileId: string };\n\nexport interface ProfileRegistryV1 {\n\tregisterSource(source: RegistrySourceV1): void;\n\tresolve(input: { readonly profileId: string; readonly versionRange?: ProfileVersionRangeV1 }): ProfileResolutionV1;\n}\n\n/** Segment-wise numeric semver comparison (\"1.2\" < \"1.10\" < \"2.0\"). */\nfunction compareVersions(a: string, b: string): number {\n\tconst pa = a.split(\".\").map((part) => Number.parseInt(part, 10) || 0);\n\tconst pb = b.split(\".\").map((part) => Number.parseInt(part, 10) || 0);\n\tconst length = Math.max(pa.length, pb.length);\n\tfor (let index = 0; index < length; index += 1) {\n\t\tconst diff = (pa[index] ?? 0) - (pb[index] ?? 0);\n\t\tif (diff !== 0) return diff;\n\t}\n\treturn 0;\n}\n\nexport function createProfileRegistry(): ProfileRegistryV1 {\n\tconst sources: RegistrySourceV1[] = [];\n\n\treturn {\n\t\tregisterSource(source) {\n\t\t\tif (sources.some((existing) => existing.sourceId === source.sourceId)) {\n\t\t\t\tthrow new Error(t(\"Registry source already registered: {sourceId}\", { sourceId: source.sourceId }));\n\t\t\t}\n\t\t\tsources.push(source);\n\t\t},\n\t\tresolve({ profileId, versionRange }) {\n\t\t\tconst candidates = sources\n\t\t\t\t.flatMap((source) =>\n\t\t\t\t\tsource.profiles\n\t\t\t\t\t\t.filter((profile) => profile.profileId === profileId)\n\t\t\t\t\t\t.map((profile) => ({ source, profile })),\n\t\t\t\t)\n\t\t\t\t.filter(({ profile }) => {\n\t\t\t\t\tif (versionRange?.min !== undefined && compareVersions(profile.profileVersion, versionRange.min) < 0) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t\tif (versionRange?.max !== undefined && compareVersions(profile.profileVersion, versionRange.max) > 0) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t\treturn true;\n\t\t\t\t})\n\t\t\t\t.sort((a, b) => {\n\t\t\t\t\tconst versionDiff = compareVersions(b.profile.profileVersion, a.profile.profileVersion);\n\t\t\t\t\tif (versionDiff !== 0) return versionDiff;\n\t\t\t\t\treturn a.source.priority - b.source.priority;\n\t\t\t\t});\n\n\t\t\tif (candidates.length === 0) {\n\t\t\t\treturn { status: \"not_found\", profileId };\n\t\t\t}\n\n\t\t\tconst winner = candidates[0]!;\n\t\t\tif (winner.profile.deprecated !== undefined) {\n\t\t\t\treturn {\n\t\t\t\t\tstatus: \"deprecated\",\n\t\t\t\t\tprofileId,\n\t\t\t\t\tprofileVersion: winner.profile.profileVersion,\n\t\t\t\t\tmanifestDigest: winner.profile.manifestDigest,\n\t\t\t\t\tsourceId: winner.source.sourceId,\n\t\t\t\t\treason: winner.profile.deprecated,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tconst superseded = candidates\n\t\t\t\t.slice(1)\n\t\t\t\t.filter(\n\t\t\t\t\t(candidate) => compareVersions(candidate.profile.profileVersion, winner.profile.profileVersion) === 0,\n\t\t\t\t)\n\t\t\t\t.map((candidate) => ({\n\t\t\t\t\tsourceId: candidate.source.sourceId,\n\t\t\t\t\tprofileVersion: candidate.profile.profileVersion,\n\t\t\t\t}));\n\t\t\treturn {\n\t\t\t\tstatus: \"resolved\",\n\t\t\t\tprofileId,\n\t\t\t\tprofileVersion: winner.profile.profileVersion,\n\t\t\t\tmanifestDigest: winner.profile.manifestDigest,\n\t\t\t\tsourceId: winner.source.sourceId,\n\t\t\t\tsuperseded,\n\t\t\t};\n\t\t},\n\t};\n}\n"]}
@@ -7,7 +7,6 @@
7
7
  * catalog. Registered roles are validated and served as detached, frozen
8
8
  * snapshots.
9
9
  */
10
- /** Memory scopes a role may write to (aligned with the 1C.1b store scopes). */
11
10
  export type RoleWritableScopeV1 = "session" | "cycle" | "long-term";
12
11
  export interface RoleCapabilityDependencyV1 {
13
12
  readonly capabilityId: string;
@@ -1 +1 @@
1
- {"version":3,"file":"role-catalog.d.ts","sourceRoot":"","sources":["../../src/profile/role-catalog.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,+EAA+E;AAC/E,MAAM,MAAM,mBAAmB,GAAG,SAAS,GAAG,OAAO,GAAG,WAAW,CAAC;AAEpE,MAAM,WAAW,0BAA0B;IAC1C,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;IACnC,+DAA+D;IAC/D,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;CAC3B;AAED,2FAA2F;AAC3F,MAAM,WAAW,iBAAiB;IACjC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;CAC/B;AAED,MAAM,WAAW,cAAc;IAC9B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,iBAAiB,CAAC;IAClC,QAAQ,CAAC,MAAM,EAAE,iBAAiB,CAAC;IACnC,QAAQ,CAAC,sBAAsB,EAAE,SAAS,0BAA0B,EAAE,CAAC;IACvE,QAAQ,CAAC,cAAc,EAAE,SAAS,mBAAmB,EAAE,CAAC;IACxD,QAAQ,CAAC,WAAW,EAAE,QAAQ,GAAG,UAAU,CAAC;IAC5C,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;CACpC;AAED,MAAM,WAAW,aAAa;IAC7B,QAAQ,CAAC,QAAQ,EAAE,cAAc,GAAG,cAAc,CAAC;IACnD,GAAG,CAAC,MAAM,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS,CAAC;IAChD,IAAI,IAAI,SAAS,cAAc,EAAE,CAAC;IAClC,mFAAmF;IACnF,gBAAgB,CAAC,YAAY,EAAE,MAAM,GAAG,SAAS,cAAc,EAAE,CAAC;CAClE;AAwBD,uEAAuE;AACvE,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,OAAO,GAAG,cAAc,CA0ErE;AAED,mFAAmF;AACnF,wBAAgB,iBAAiB,CAAC,OAAO,GAAE,SAAS,cAAc,EAAO,GAAG,aAAa,CA4BxF","sourcesContent":["/**\n * Role metadata catalog (2.2a).\n *\n * Role metadata is DISCOVERY data, not a security policy: roleId, input/output\n * schema references, capability dependencies, writable memory scopes,\n * concurrency, and completion criteria are all discoverable through the\n * catalog. Registered roles are validated and served as detached, frozen\n * snapshots.\n */\n\n/** Memory scopes a role may write to (aligned with the 1C.1b store scopes). */\nexport type RoleWritableScopeV1 = \"session\" | \"cycle\" | \"long-term\";\n\nexport interface RoleCapabilityDependencyV1 {\n\treadonly capabilityId: string;\n\treadonly capabilityVersion: number;\n\t/** Required dependencies fail role activation when missing. */\n\treadonly required: boolean;\n}\n\n/** Versioned input/output schema reference (schema bodies live with the domain plugin). */\nexport interface RoleIOSchemaRefV1 {\n\treadonly schemaId: string;\n\treadonly schemaVersion: number;\n}\n\nexport interface RoleMetadataV1 {\n\treadonly roleId: string;\n\treadonly title: string;\n\treadonly input: RoleIOSchemaRefV1;\n\treadonly output: RoleIOSchemaRefV1;\n\treadonly capabilityDependencies: readonly RoleCapabilityDependencyV1[];\n\treadonly writableScopes: readonly RoleWritableScopeV1[];\n\treadonly concurrency: \"single\" | \"parallel\";\n\treadonly completionCriteria: string;\n}\n\nexport interface RoleCatalogV1 {\n\tregister(metadata: RoleMetadataV1): RoleMetadataV1;\n\tget(roleId: string): RoleMetadataV1 | undefined;\n\tlist(): readonly RoleMetadataV1[];\n\t/** Roles declaring the given capability as a dependency (required or optional). */\n\tfindByCapability(capabilityId: string): readonly RoleMetadataV1[];\n}\n\nconst WRITABLE_SCOPES: readonly RoleWritableScopeV1[] = [\"session\", \"cycle\", \"long-term\"];\n\nfunction assertNonEmptyString(value: unknown, label: string): asserts value is string {\n\tif (typeof value !== \"string\" || value.trim().length === 0) throw new Error(`${label} must be a non-empty string`);\n}\n\nfunction assertIOSchemaRef(value: unknown, label: string): RoleIOSchemaRefV1 {\n\tif (value === null || typeof value !== \"object\" || Array.isArray(value)) {\n\t\tthrow new Error(`${label} must be a plain object`);\n\t}\n\tconst record = value as Record<string, unknown>;\n\tassertNonEmptyString(record.schemaId, `${label}.schemaId`);\n\tif (\n\t\ttypeof record.schemaVersion !== \"number\" ||\n\t\t!Number.isSafeInteger(record.schemaVersion) ||\n\t\trecord.schemaVersion < 1\n\t) {\n\t\tthrow new Error(`${label}.schemaVersion must be a positive safe integer`);\n\t}\n\treturn Object.freeze({ schemaId: record.schemaId, schemaVersion: record.schemaVersion });\n}\n\n/** Validates role metadata and returns a detached, frozen snapshot. */\nexport function validateRoleMetadataV1(value: unknown): RoleMetadataV1 {\n\tif (value === null || typeof value !== \"object\" || Array.isArray(value)) {\n\t\tthrow new Error(\"Role metadata must be a plain object\");\n\t}\n\tconst record = value as Record<string, unknown>;\n\tconst required = [\n\t\t\"roleId\",\n\t\t\"title\",\n\t\t\"input\",\n\t\t\"output\",\n\t\t\"capabilityDependencies\",\n\t\t\"writableScopes\",\n\t\t\"concurrency\",\n\t\t\"completionCriteria\",\n\t];\n\tfor (const key of required) {\n\t\tif (!(key in record)) throw new Error(`Role metadata is missing required field: ${key}`);\n\t}\n\tconst unsupported = Object.keys(record)\n\t\t.filter((key) => !required.includes(key))\n\t\t.sort();\n\tif (unsupported.length > 0) throw new Error(`Role metadata has unsupported fields: ${unsupported.join(\", \")}`);\n\n\tassertNonEmptyString(record.roleId, \"Role metadata.roleId\");\n\tassertNonEmptyString(record.title, \"Role metadata.title\");\n\tconst input = assertIOSchemaRef(record.input, \"Role metadata.input\");\n\tconst output = assertIOSchemaRef(record.output, \"Role metadata.output\");\n\n\tif (!Array.isArray(record.capabilityDependencies)) {\n\t\tthrow new Error(\"Role metadata.capabilityDependencies must be an array\");\n\t}\n\tconst capabilityDependencies = record.capabilityDependencies.map((item, index) => {\n\t\tconst depLabel = `Role metadata.capabilityDependencies[${index}]`;\n\t\tif (item === null || typeof item !== \"object\" || Array.isArray(item)) {\n\t\t\tthrow new Error(`${depLabel} must be a plain object`);\n\t\t}\n\t\tconst dep = item as Record<string, unknown>;\n\t\tassertNonEmptyString(dep.capabilityId, `${depLabel}.capabilityId`);\n\t\tif (\n\t\t\ttypeof dep.capabilityVersion !== \"number\" ||\n\t\t\t!Number.isSafeInteger(dep.capabilityVersion) ||\n\t\t\tdep.capabilityVersion < 1\n\t\t) {\n\t\t\tthrow new Error(`${depLabel}.capabilityVersion must be a positive safe integer`);\n\t\t}\n\t\tif (typeof dep.required !== \"boolean\") throw new Error(`${depLabel}.required must be boolean`);\n\t\treturn Object.freeze({\n\t\t\tcapabilityId: dep.capabilityId,\n\t\t\tcapabilityVersion: dep.capabilityVersion,\n\t\t\trequired: dep.required,\n\t\t});\n\t});\n\n\tif (!Array.isArray(record.writableScopes)) throw new Error(\"Role metadata.writableScopes must be an array\");\n\tfor (const [index, scope] of record.writableScopes.entries()) {\n\t\tif (!WRITABLE_SCOPES.includes(scope as RoleWritableScopeV1)) {\n\t\t\tthrow new Error(`Role metadata.writableScopes[${index}] is invalid`);\n\t\t}\n\t}\n\tassertNonEmptyString(record.completionCriteria, \"Role metadata.completionCriteria\");\n\tif (record.concurrency !== \"single\" && record.concurrency !== \"parallel\") {\n\t\tthrow new Error(\"Role metadata.concurrency is invalid\");\n\t}\n\n\treturn Object.freeze({\n\t\troleId: record.roleId,\n\t\ttitle: record.title,\n\t\tinput,\n\t\toutput,\n\t\tcapabilityDependencies: Object.freeze(capabilityDependencies),\n\t\twritableScopes: Object.freeze([...(record.writableScopes as readonly RoleWritableScopeV1[])]),\n\t\tconcurrency: record.concurrency as RoleMetadataV1[\"concurrency\"],\n\t\tcompletionCriteria: record.completionCriteria,\n\t});\n}\n\n/** Discoverable role catalog: register, get, list (sorted), find by capability. */\nexport function createRoleCatalog(initial: readonly RoleMetadataV1[] = []): RoleCatalogV1 {\n\tconst roles = new Map<string, RoleMetadataV1>();\n\tfor (const metadata of initial) {\n\t\tconst validated = validateRoleMetadataV1(metadata);\n\t\tif (roles.has(validated.roleId)) throw new Error(`Role already registered: ${validated.roleId}`);\n\t\troles.set(validated.roleId, validated);\n\t}\n\treturn {\n\t\tregister(metadata) {\n\t\t\tconst validated = validateRoleMetadataV1(metadata);\n\t\t\tif (roles.has(validated.roleId)) throw new Error(`Role already registered: ${validated.roleId}`);\n\t\t\troles.set(validated.roleId, validated);\n\t\t\treturn validated;\n\t\t},\n\t\tget(roleId) {\n\t\t\treturn roles.get(roleId);\n\t\t},\n\t\tlist() {\n\t\t\treturn Object.freeze([...roles.values()].sort((left, right) => left.roleId.localeCompare(right.roleId)));\n\t\t},\n\t\tfindByCapability(capabilityId) {\n\t\t\treturn Object.freeze(\n\t\t\t\t[...roles.values()].filter((role) =>\n\t\t\t\t\trole.capabilityDependencies.some((dependency) => dependency.capabilityId === capabilityId),\n\t\t\t\t),\n\t\t\t);\n\t\t},\n\t};\n}\n"]}
1
+ {"version":3,"file":"role-catalog.d.ts","sourceRoot":"","sources":["../../src/profile/role-catalog.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAKH,MAAM,MAAM,mBAAmB,GAAG,SAAS,GAAG,OAAO,GAAG,WAAW,CAAC;AAEpE,MAAM,WAAW,0BAA0B;IAC1C,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;IACnC,+DAA+D;IAC/D,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;CAC3B;AAED,2FAA2F;AAC3F,MAAM,WAAW,iBAAiB;IACjC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;CAC/B;AAED,MAAM,WAAW,cAAc;IAC9B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,iBAAiB,CAAC;IAClC,QAAQ,CAAC,MAAM,EAAE,iBAAiB,CAAC;IACnC,QAAQ,CAAC,sBAAsB,EAAE,SAAS,0BAA0B,EAAE,CAAC;IACvE,QAAQ,CAAC,cAAc,EAAE,SAAS,mBAAmB,EAAE,CAAC;IACxD,QAAQ,CAAC,WAAW,EAAE,QAAQ,GAAG,UAAU,CAAC;IAC5C,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;CACpC;AAED,MAAM,WAAW,aAAa;IAC7B,QAAQ,CAAC,QAAQ,EAAE,cAAc,GAAG,cAAc,CAAC;IACnD,GAAG,CAAC,MAAM,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS,CAAC;IAChD,IAAI,IAAI,SAAS,cAAc,EAAE,CAAC;IAClC,mFAAmF;IACnF,gBAAgB,CAAC,YAAY,EAAE,MAAM,GAAG,SAAS,cAAc,EAAE,CAAC;CAClE;AAyBD,uEAAuE;AACvE,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,OAAO,GAAG,cAAc,CA4ErE;AAED,mFAAmF;AACnF,wBAAgB,iBAAiB,CAAC,OAAO,GAAE,SAAS,cAAc,EAAO,GAAG,aAAa,CA8BxF","sourcesContent":["/**\n * Role metadata catalog (2.2a).\n *\n * Role metadata is DISCOVERY data, not a security policy: roleId, input/output\n * schema references, capability dependencies, writable memory scopes,\n * concurrency, and completion criteria are all discoverable through the\n * catalog. Registered roles are validated and served as detached, frozen\n * snapshots.\n */\n\n/** Memory scopes a role may write to (aligned with the 1C.1b store scopes). */\nimport { t } from \"../core/i18n/index.ts\";\n\nexport type RoleWritableScopeV1 = \"session\" | \"cycle\" | \"long-term\";\n\nexport interface RoleCapabilityDependencyV1 {\n\treadonly capabilityId: string;\n\treadonly capabilityVersion: number;\n\t/** Required dependencies fail role activation when missing. */\n\treadonly required: boolean;\n}\n\n/** Versioned input/output schema reference (schema bodies live with the domain plugin). */\nexport interface RoleIOSchemaRefV1 {\n\treadonly schemaId: string;\n\treadonly schemaVersion: number;\n}\n\nexport interface RoleMetadataV1 {\n\treadonly roleId: string;\n\treadonly title: string;\n\treadonly input: RoleIOSchemaRefV1;\n\treadonly output: RoleIOSchemaRefV1;\n\treadonly capabilityDependencies: readonly RoleCapabilityDependencyV1[];\n\treadonly writableScopes: readonly RoleWritableScopeV1[];\n\treadonly concurrency: \"single\" | \"parallel\";\n\treadonly completionCriteria: string;\n}\n\nexport interface RoleCatalogV1 {\n\tregister(metadata: RoleMetadataV1): RoleMetadataV1;\n\tget(roleId: string): RoleMetadataV1 | undefined;\n\tlist(): readonly RoleMetadataV1[];\n\t/** Roles declaring the given capability as a dependency (required or optional). */\n\tfindByCapability(capabilityId: string): readonly RoleMetadataV1[];\n}\n\nconst WRITABLE_SCOPES: readonly RoleWritableScopeV1[] = [\"session\", \"cycle\", \"long-term\"];\n\nfunction assertNonEmptyString(value: unknown, label: string): asserts value is string {\n\tif (typeof value !== \"string\" || value.trim().length === 0)\n\t\tthrow new Error(t(\"{label} must be a non-empty string\", { label }));\n}\n\nfunction assertIOSchemaRef(value: unknown, label: string): RoleIOSchemaRefV1 {\n\tif (value === null || typeof value !== \"object\" || Array.isArray(value)) {\n\t\tthrow new Error(t(\"{label} must be a plain object\", { label }));\n\t}\n\tconst record = value as Record<string, unknown>;\n\tassertNonEmptyString(record.schemaId, `${label}.schemaId`);\n\tif (\n\t\ttypeof record.schemaVersion !== \"number\" ||\n\t\t!Number.isSafeInteger(record.schemaVersion) ||\n\t\trecord.schemaVersion < 1\n\t) {\n\t\tthrow new Error(t(\"{label}.schemaVersion must be a positive safe integer\", { label }));\n\t}\n\treturn Object.freeze({ schemaId: record.schemaId, schemaVersion: record.schemaVersion });\n}\n\n/** Validates role metadata and returns a detached, frozen snapshot. */\nexport function validateRoleMetadataV1(value: unknown): RoleMetadataV1 {\n\tif (value === null || typeof value !== \"object\" || Array.isArray(value)) {\n\t\tthrow new Error(t(\"Role metadata must be a plain object\"));\n\t}\n\tconst record = value as Record<string, unknown>;\n\tconst required = [\n\t\t\"roleId\",\n\t\t\"title\",\n\t\t\"input\",\n\t\t\"output\",\n\t\t\"capabilityDependencies\",\n\t\t\"writableScopes\",\n\t\t\"concurrency\",\n\t\t\"completionCriteria\",\n\t];\n\tfor (const key of required) {\n\t\tif (!(key in record)) throw new Error(t(\"Role metadata is missing required field: {key}\", { key }));\n\t}\n\tconst unsupported = Object.keys(record)\n\t\t.filter((key) => !required.includes(key))\n\t\t.sort();\n\tif (unsupported.length > 0)\n\t\tthrow new Error(t(\"Role metadata has unsupported fields: {fields}\", { fields: unsupported.join(\", \") }));\n\n\tassertNonEmptyString(record.roleId, \"Role metadata.roleId\");\n\tassertNonEmptyString(record.title, \"Role metadata.title\");\n\tconst input = assertIOSchemaRef(record.input, \"Role metadata.input\");\n\tconst output = assertIOSchemaRef(record.output, \"Role metadata.output\");\n\n\tif (!Array.isArray(record.capabilityDependencies)) {\n\t\tthrow new Error(t(\"Role metadata.capabilityDependencies must be an array\"));\n\t}\n\tconst capabilityDependencies = record.capabilityDependencies.map((item, index) => {\n\t\tconst depLabel = `Role metadata.capabilityDependencies[${index}]`;\n\t\tif (item === null || typeof item !== \"object\" || Array.isArray(item)) {\n\t\t\tthrow new Error(t(\"{label} must be a plain object\", { label: depLabel }));\n\t\t}\n\t\tconst dep = item as Record<string, unknown>;\n\t\tassertNonEmptyString(dep.capabilityId, `${depLabel}.capabilityId`);\n\t\tif (\n\t\t\ttypeof dep.capabilityVersion !== \"number\" ||\n\t\t\t!Number.isSafeInteger(dep.capabilityVersion) ||\n\t\t\tdep.capabilityVersion < 1\n\t\t) {\n\t\t\tthrow new Error(t(\"{label}.capabilityVersion must be a positive safe integer\", { label: depLabel }));\n\t\t}\n\t\tif (typeof dep.required !== \"boolean\")\n\t\t\tthrow new Error(t(\"{label}.required must be boolean\", { label: depLabel }));\n\t\treturn Object.freeze({\n\t\t\tcapabilityId: dep.capabilityId,\n\t\t\tcapabilityVersion: dep.capabilityVersion,\n\t\t\trequired: dep.required,\n\t\t});\n\t});\n\n\tif (!Array.isArray(record.writableScopes)) throw new Error(t(\"Role metadata.writableScopes must be an array\"));\n\tfor (const [index, scope] of record.writableScopes.entries()) {\n\t\tif (!WRITABLE_SCOPES.includes(scope as RoleWritableScopeV1)) {\n\t\t\tthrow new Error(t(\"Role metadata.writableScopes[{index}] is invalid\", { index }));\n\t\t}\n\t}\n\tassertNonEmptyString(record.completionCriteria, \"Role metadata.completionCriteria\");\n\tif (record.concurrency !== \"single\" && record.concurrency !== \"parallel\") {\n\t\tthrow new Error(t(\"Role metadata.concurrency is invalid\"));\n\t}\n\n\treturn Object.freeze({\n\t\troleId: record.roleId,\n\t\ttitle: record.title,\n\t\tinput,\n\t\toutput,\n\t\tcapabilityDependencies: Object.freeze(capabilityDependencies),\n\t\twritableScopes: Object.freeze([...(record.writableScopes as readonly RoleWritableScopeV1[])]),\n\t\tconcurrency: record.concurrency as RoleMetadataV1[\"concurrency\"],\n\t\tcompletionCriteria: record.completionCriteria,\n\t});\n}\n\n/** Discoverable role catalog: register, get, list (sorted), find by capability. */\nexport function createRoleCatalog(initial: readonly RoleMetadataV1[] = []): RoleCatalogV1 {\n\tconst roles = new Map<string, RoleMetadataV1>();\n\tfor (const metadata of initial) {\n\t\tconst validated = validateRoleMetadataV1(metadata);\n\t\tif (roles.has(validated.roleId))\n\t\t\tthrow new Error(t(\"Role already registered: {roleId}\", { roleId: validated.roleId }));\n\t\troles.set(validated.roleId, validated);\n\t}\n\treturn {\n\t\tregister(metadata) {\n\t\t\tconst validated = validateRoleMetadataV1(metadata);\n\t\t\tif (roles.has(validated.roleId))\n\t\t\t\tthrow new Error(t(\"Role already registered: {roleId}\", { roleId: validated.roleId }));\n\t\t\troles.set(validated.roleId, validated);\n\t\t\treturn validated;\n\t\t},\n\t\tget(roleId) {\n\t\t\treturn roles.get(roleId);\n\t\t},\n\t\tlist() {\n\t\t\treturn Object.freeze([...roles.values()].sort((left, right) => left.roleId.localeCompare(right.roleId)));\n\t\t},\n\t\tfindByCapability(capabilityId) {\n\t\t\treturn Object.freeze(\n\t\t\t\t[...roles.values()].filter((role) =>\n\t\t\t\t\trole.capabilityDependencies.some((dependency) => dependency.capabilityId === capabilityId),\n\t\t\t\t),\n\t\t\t);\n\t\t},\n\t};\n}\n"]}