@xemahq/biome-sdk 0.1.1

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 (383) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +62 -0
  3. package/dist/adapter/index.d.ts +7 -0
  4. package/dist/adapter/index.d.ts.map +1 -0
  5. package/dist/adapter/index.js +23 -0
  6. package/dist/adapter/index.js.map +1 -0
  7. package/dist/adapter/lib/action.d.ts +25 -0
  8. package/dist/adapter/lib/action.d.ts.map +1 -0
  9. package/dist/adapter/lib/action.js +3 -0
  10. package/dist/adapter/lib/action.js.map +1 -0
  11. package/dist/adapter/lib/provider-module.d.ts +41 -0
  12. package/dist/adapter/lib/provider-module.d.ts.map +1 -0
  13. package/dist/adapter/lib/provider-module.js +7 -0
  14. package/dist/adapter/lib/provider-module.js.map +1 -0
  15. package/dist/adapter/lib/resource.d.ts +25 -0
  16. package/dist/adapter/lib/resource.d.ts.map +1 -0
  17. package/dist/adapter/lib/resource.js +3 -0
  18. package/dist/adapter/lib/resource.js.map +1 -0
  19. package/dist/adapter/lib/result.d.ts +18 -0
  20. package/dist/adapter/lib/result.d.ts.map +1 -0
  21. package/dist/adapter/lib/result.js +12 -0
  22. package/dist/adapter/lib/result.js.map +1 -0
  23. package/dist/adapter/lib/sidecar-contract.d.ts +91 -0
  24. package/dist/adapter/lib/sidecar-contract.d.ts.map +1 -0
  25. package/dist/adapter/lib/sidecar-contract.js +19 -0
  26. package/dist/adapter/lib/sidecar-contract.js.map +1 -0
  27. package/dist/adapter/lib/webhook.d.ts +49 -0
  28. package/dist/adapter/lib/webhook.d.ts.map +1 -0
  29. package/dist/adapter/lib/webhook.js +3 -0
  30. package/dist/adapter/lib/webhook.js.map +1 -0
  31. package/dist/agent-workspace/index.d.ts +8 -0
  32. package/dist/agent-workspace/index.d.ts.map +1 -0
  33. package/dist/agent-workspace/index.js +24 -0
  34. package/dist/agent-workspace/index.js.map +1 -0
  35. package/dist/agent-workspace/lib/errors/error-codes.d.ts +16 -0
  36. package/dist/agent-workspace/lib/errors/error-codes.d.ts.map +1 -0
  37. package/dist/agent-workspace/lib/errors/error-codes.js +37 -0
  38. package/dist/agent-workspace/lib/errors/error-codes.js.map +1 -0
  39. package/dist/agent-workspace/lib/errors/index.d.ts +4 -0
  40. package/dist/agent-workspace/lib/errors/index.d.ts.map +1 -0
  41. package/dist/agent-workspace/lib/errors/index.js +20 -0
  42. package/dist/agent-workspace/lib/errors/index.js.map +1 -0
  43. package/dist/agent-workspace/lib/errors/mount-plan-error.d.ts +16 -0
  44. package/dist/agent-workspace/lib/errors/mount-plan-error.d.ts.map +1 -0
  45. package/dist/agent-workspace/lib/errors/mount-plan-error.js +26 -0
  46. package/dist/agent-workspace/lib/errors/mount-plan-error.js.map +1 -0
  47. package/dist/agent-workspace/lib/errors/mount-resolver-error.d.ts +34 -0
  48. package/dist/agent-workspace/lib/errors/mount-resolver-error.d.ts.map +1 -0
  49. package/dist/agent-workspace/lib/errors/mount-resolver-error.js +50 -0
  50. package/dist/agent-workspace/lib/errors/mount-resolver-error.js.map +1 -0
  51. package/dist/agent-workspace/lib/mount-resolver.d.ts +10 -0
  52. package/dist/agent-workspace/lib/mount-resolver.d.ts.map +1 -0
  53. package/dist/agent-workspace/lib/mount-resolver.js +3 -0
  54. package/dist/agent-workspace/lib/mount-resolver.js.map +1 -0
  55. package/dist/agent-workspace/lib/mount-source.d.ts +4 -0
  56. package/dist/agent-workspace/lib/mount-source.d.ts.map +1 -0
  57. package/dist/agent-workspace/lib/mount-source.js +3 -0
  58. package/dist/agent-workspace/lib/mount-source.js.map +1 -0
  59. package/dist/agent-workspace/lib/refid-resolver.d.ts +23 -0
  60. package/dist/agent-workspace/lib/refid-resolver.d.ts.map +1 -0
  61. package/dist/agent-workspace/lib/refid-resolver.js +103 -0
  62. package/dist/agent-workspace/lib/refid-resolver.js.map +1 -0
  63. package/dist/agent-workspace/lib/registries.d.ts +30 -0
  64. package/dist/agent-workspace/lib/registries.d.ts.map +1 -0
  65. package/dist/agent-workspace/lib/registries.js +88 -0
  66. package/dist/agent-workspace/lib/registries.js.map +1 -0
  67. package/dist/agent-workspace/lib/resolvers/agent-definition.resolver.d.ts +13 -0
  68. package/dist/agent-workspace/lib/resolvers/agent-definition.resolver.d.ts.map +1 -0
  69. package/dist/agent-workspace/lib/resolvers/agent-definition.resolver.js +25 -0
  70. package/dist/agent-workspace/lib/resolvers/agent-definition.resolver.js.map +1 -0
  71. package/dist/agent-workspace/lib/resolvers/artifact-store-collection.resolver.d.ts +13 -0
  72. package/dist/agent-workspace/lib/resolvers/artifact-store-collection.resolver.d.ts.map +1 -0
  73. package/dist/agent-workspace/lib/resolvers/artifact-store-collection.resolver.js +28 -0
  74. package/dist/agent-workspace/lib/resolvers/artifact-store-collection.resolver.js.map +1 -0
  75. package/dist/agent-workspace/lib/resolvers/artifact-version.resolver.d.ts +13 -0
  76. package/dist/agent-workspace/lib/resolvers/artifact-version.resolver.d.ts.map +1 -0
  77. package/dist/agent-workspace/lib/resolvers/artifact-version.resolver.js +25 -0
  78. package/dist/agent-workspace/lib/resolvers/artifact-version.resolver.js.map +1 -0
  79. package/dist/agent-workspace/lib/resolvers/clients.d.ts +122 -0
  80. package/dist/agent-workspace/lib/resolvers/clients.d.ts.map +1 -0
  81. package/dist/agent-workspace/lib/resolvers/clients.js +3 -0
  82. package/dist/agent-workspace/lib/resolvers/clients.js.map +1 -0
  83. package/dist/agent-workspace/lib/resolvers/deliverable-specs.resolver.d.ts +13 -0
  84. package/dist/agent-workspace/lib/resolvers/deliverable-specs.resolver.d.ts.map +1 -0
  85. package/dist/agent-workspace/lib/resolvers/deliverable-specs.resolver.js +24 -0
  86. package/dist/agent-workspace/lib/resolvers/deliverable-specs.resolver.js.map +1 -0
  87. package/dist/agent-workspace/lib/resolvers/deliverables.resolver.d.ts +13 -0
  88. package/dist/agent-workspace/lib/resolvers/deliverables.resolver.d.ts.map +1 -0
  89. package/dist/agent-workspace/lib/resolvers/deliverables.resolver.js +28 -0
  90. package/dist/agent-workspace/lib/resolvers/deliverables.resolver.js.map +1 -0
  91. package/dist/agent-workspace/lib/resolvers/index.d.ts +20 -0
  92. package/dist/agent-workspace/lib/resolvers/index.d.ts.map +1 -0
  93. package/dist/agent-workspace/lib/resolvers/index.js +36 -0
  94. package/dist/agent-workspace/lib/resolvers/index.js.map +1 -0
  95. package/dist/agent-workspace/lib/resolvers/instruction-section.resolver.d.ts +13 -0
  96. package/dist/agent-workspace/lib/resolvers/instruction-section.resolver.d.ts.map +1 -0
  97. package/dist/agent-workspace/lib/resolvers/instruction-section.resolver.js +22 -0
  98. package/dist/agent-workspace/lib/resolvers/instruction-section.resolver.js.map +1 -0
  99. package/dist/agent-workspace/lib/resolvers/kb-pages.resolver.d.ts +13 -0
  100. package/dist/agent-workspace/lib/resolvers/kb-pages.resolver.d.ts.map +1 -0
  101. package/dist/agent-workspace/lib/resolvers/kb-pages.resolver.js +36 -0
  102. package/dist/agent-workspace/lib/resolvers/kb-pages.resolver.js.map +1 -0
  103. package/dist/agent-workspace/lib/resolvers/kb-space.resolver.d.ts +13 -0
  104. package/dist/agent-workspace/lib/resolvers/kb-space.resolver.d.ts.map +1 -0
  105. package/dist/agent-workspace/lib/resolvers/kb-space.resolver.js +26 -0
  106. package/dist/agent-workspace/lib/resolvers/kb-space.resolver.js.map +1 -0
  107. package/dist/agent-workspace/lib/resolvers/rendered-agents-md.resolver.d.ts +13 -0
  108. package/dist/agent-workspace/lib/resolvers/rendered-agents-md.resolver.d.ts.map +1 -0
  109. package/dist/agent-workspace/lib/resolvers/rendered-agents-md.resolver.js +23 -0
  110. package/dist/agent-workspace/lib/resolvers/rendered-agents-md.resolver.js.map +1 -0
  111. package/dist/agent-workspace/lib/resolvers/rendered-context-json.resolver.d.ts +13 -0
  112. package/dist/agent-workspace/lib/resolvers/rendered-context-json.resolver.d.ts.map +1 -0
  113. package/dist/agent-workspace/lib/resolvers/rendered-context-json.resolver.js +24 -0
  114. package/dist/agent-workspace/lib/resolvers/rendered-context-json.resolver.js.map +1 -0
  115. package/dist/agent-workspace/lib/resolvers/rendered-system-overlay.resolver.d.ts +13 -0
  116. package/dist/agent-workspace/lib/resolvers/rendered-system-overlay.resolver.d.ts.map +1 -0
  117. package/dist/agent-workspace/lib/resolvers/rendered-system-overlay.resolver.js +23 -0
  118. package/dist/agent-workspace/lib/resolvers/rendered-system-overlay.resolver.js.map +1 -0
  119. package/dist/agent-workspace/lib/resolvers/scm-repo.resolver.d.ts +13 -0
  120. package/dist/agent-workspace/lib/resolvers/scm-repo.resolver.d.ts.map +1 -0
  121. package/dist/agent-workspace/lib/resolvers/scm-repo.resolver.js +28 -0
  122. package/dist/agent-workspace/lib/resolvers/scm-repo.resolver.js.map +1 -0
  123. package/dist/agent-workspace/lib/resolvers/session-attachment.resolver.d.ts +13 -0
  124. package/dist/agent-workspace/lib/resolvers/session-attachment.resolver.d.ts.map +1 -0
  125. package/dist/agent-workspace/lib/resolvers/session-attachment.resolver.js +28 -0
  126. package/dist/agent-workspace/lib/resolvers/session-attachment.resolver.js.map +1 -0
  127. package/dist/agent-workspace/lib/resolvers/skill-bundle.resolver.d.ts +13 -0
  128. package/dist/agent-workspace/lib/resolvers/skill-bundle.resolver.d.ts.map +1 -0
  129. package/dist/agent-workspace/lib/resolvers/skill-bundle.resolver.js +29 -0
  130. package/dist/agent-workspace/lib/resolvers/skill-bundle.resolver.js.map +1 -0
  131. package/dist/agent-workspace/lib/resolvers/static-literal.resolver.d.ts +11 -0
  132. package/dist/agent-workspace/lib/resolvers/static-literal.resolver.d.ts.map +1 -0
  133. package/dist/agent-workspace/lib/resolvers/static-literal.resolver.js +33 -0
  134. package/dist/agent-workspace/lib/resolvers/static-literal.resolver.js.map +1 -0
  135. package/dist/agent-workspace/lib/resolvers/types.d.ts +35 -0
  136. package/dist/agent-workspace/lib/resolvers/types.d.ts.map +1 -0
  137. package/dist/agent-workspace/lib/resolvers/types.js +3 -0
  138. package/dist/agent-workspace/lib/resolvers/types.js.map +1 -0
  139. package/dist/agent-workspace/lib/resolvers/utils/agent-run-context-cache.d.ts +70 -0
  140. package/dist/agent-workspace/lib/resolvers/utils/agent-run-context-cache.d.ts.map +1 -0
  141. package/dist/agent-workspace/lib/resolvers/utils/agent-run-context-cache.js +90 -0
  142. package/dist/agent-workspace/lib/resolvers/utils/agent-run-context-cache.js.map +1 -0
  143. package/dist/agent-workspace/lib/resolvers/utils/auth.d.ts +5 -0
  144. package/dist/agent-workspace/lib/resolvers/utils/auth.d.ts.map +1 -0
  145. package/dist/agent-workspace/lib/resolvers/utils/auth.js +19 -0
  146. package/dist/agent-workspace/lib/resolvers/utils/auth.js.map +1 -0
  147. package/dist/agent-workspace/lib/resolvers/utils/size-cap.d.ts +3 -0
  148. package/dist/agent-workspace/lib/resolvers/utils/size-cap.d.ts.map +1 -0
  149. package/dist/agent-workspace/lib/resolvers/utils/size-cap.js +23 -0
  150. package/dist/agent-workspace/lib/resolvers/utils/size-cap.js.map +1 -0
  151. package/dist/agent-workspace/lib/resolvers/utils/streaming.d.ts +3 -0
  152. package/dist/agent-workspace/lib/resolvers/utils/streaming.d.ts.map +1 -0
  153. package/dist/agent-workspace/lib/resolvers/utils/streaming.js +11 -0
  154. package/dist/agent-workspace/lib/resolvers/utils/streaming.js.map +1 -0
  155. package/dist/agent-workspace/lib/workspace-renderer.d.ts +13 -0
  156. package/dist/agent-workspace/lib/workspace-renderer.d.ts.map +1 -0
  157. package/dist/agent-workspace/lib/workspace-renderer.js +3 -0
  158. package/dist/agent-workspace/lib/workspace-renderer.js.map +1 -0
  159. package/dist/api/index.d.ts +11 -0
  160. package/dist/api/index.d.ts.map +1 -0
  161. package/dist/api/index.js +27 -0
  162. package/dist/api/index.js.map +1 -0
  163. package/dist/api/lib/api-manifest.d.ts +29 -0
  164. package/dist/api/lib/api-manifest.d.ts.map +1 -0
  165. package/dist/api/lib/api-manifest.js +28 -0
  166. package/dist/api/lib/api-manifest.js.map +1 -0
  167. package/dist/api/lib/biome-db.d.ts +2 -0
  168. package/dist/api/lib/biome-db.d.ts.map +1 -0
  169. package/dist/api/lib/biome-db.js +13 -0
  170. package/dist/api/lib/biome-db.js.map +1 -0
  171. package/dist/api/lib/code-tool-context.d.ts +16 -0
  172. package/dist/api/lib/code-tool-context.d.ts.map +1 -0
  173. package/dist/api/lib/code-tool-context.js +12 -0
  174. package/dist/api/lib/code-tool-context.js.map +1 -0
  175. package/dist/api/lib/code-tool-descriptor.d.ts +49 -0
  176. package/dist/api/lib/code-tool-descriptor.d.ts.map +1 -0
  177. package/dist/api/lib/code-tool-descriptor.js +3 -0
  178. package/dist/api/lib/code-tool-descriptor.js.map +1 -0
  179. package/dist/api/lib/code-tool.decorator.d.ts +17 -0
  180. package/dist/api/lib/code-tool.decorator.d.ts.map +1 -0
  181. package/dist/api/lib/code-tool.decorator.js +38 -0
  182. package/dist/api/lib/code-tool.decorator.js.map +1 -0
  183. package/dist/api/lib/mutation-context.d.ts +16 -0
  184. package/dist/api/lib/mutation-context.d.ts.map +1 -0
  185. package/dist/api/lib/mutation-context.js +17 -0
  186. package/dist/api/lib/mutation-context.js.map +1 -0
  187. package/dist/api/lib/pagination.d.ts +8 -0
  188. package/dist/api/lib/pagination.d.ts.map +1 -0
  189. package/dist/api/lib/pagination.js +7 -0
  190. package/dist/api/lib/pagination.js.map +1 -0
  191. package/dist/api/lib/provider-kind-mirror.d.ts +7 -0
  192. package/dist/api/lib/provider-kind-mirror.d.ts.map +1 -0
  193. package/dist/api/lib/provider-kind-mirror.js +11 -0
  194. package/dist/api/lib/provider-kind-mirror.js.map +1 -0
  195. package/dist/api/lib/request-context.d.ts +21 -0
  196. package/dist/api/lib/request-context.d.ts.map +1 -0
  197. package/dist/api/lib/request-context.js +51 -0
  198. package/dist/api/lib/request-context.js.map +1 -0
  199. package/dist/api/lib/route-registry-entry.d.ts +11 -0
  200. package/dist/api/lib/route-registry-entry.d.ts.map +1 -0
  201. package/dist/api/lib/route-registry-entry.js +3 -0
  202. package/dist/api/lib/route-registry-entry.js.map +1 -0
  203. package/dist/api/nest/controller-base.d.ts +6 -0
  204. package/dist/api/nest/controller-base.d.ts.map +1 -0
  205. package/dist/api/nest/controller-base.js +28 -0
  206. package/dist/api/nest/controller-base.js.map +1 -0
  207. package/dist/api/nest/events/events.controller.d.ts +10 -0
  208. package/dist/api/nest/events/events.controller.d.ts.map +1 -0
  209. package/dist/api/nest/events/events.controller.js +56 -0
  210. package/dist/api/nest/events/events.controller.js.map +1 -0
  211. package/dist/api/nest/health/health.controller.d.ts +19 -0
  212. package/dist/api/nest/health/health.controller.d.ts.map +1 -0
  213. package/dist/api/nest/health/health.controller.js +63 -0
  214. package/dist/api/nest/health/health.controller.js.map +1 -0
  215. package/dist/api/nest/health/health.module.d.ts +6 -0
  216. package/dist/api/nest/health/health.module.d.ts.map +1 -0
  217. package/dist/api/nest/health/health.module.js +29 -0
  218. package/dist/api/nest/health/health.module.js.map +1 -0
  219. package/dist/api/nest/index.d.ts +7 -0
  220. package/dist/api/nest/index.d.ts.map +1 -0
  221. package/dist/api/nest/index.js +23 -0
  222. package/dist/api/nest/index.js.map +1 -0
  223. package/dist/api/nest/module.d.ts +6 -0
  224. package/dist/api/nest/module.d.ts.map +1 -0
  225. package/dist/api/nest/module.js +34 -0
  226. package/dist/api/nest/module.js.map +1 -0
  227. package/dist/api/nest/request-context.d.ts +17 -0
  228. package/dist/api/nest/request-context.d.ts.map +1 -0
  229. package/dist/api/nest/request-context.js +75 -0
  230. package/dist/api/nest/request-context.js.map +1 -0
  231. package/dist/builder/index.d.ts +7 -0
  232. package/dist/builder/index.d.ts.map +1 -0
  233. package/dist/builder/index.js +23 -0
  234. package/dist/builder/index.js.map +1 -0
  235. package/dist/builder/lib/content-walker.d.ts +27 -0
  236. package/dist/builder/lib/content-walker.d.ts.map +1 -0
  237. package/dist/builder/lib/content-walker.js +274 -0
  238. package/dist/builder/lib/content-walker.js.map +1 -0
  239. package/dist/builder/lib/contribution-schemas.d.ts +348 -0
  240. package/dist/builder/lib/contribution-schemas.d.ts.map +1 -0
  241. package/dist/builder/lib/contribution-schemas.js +301 -0
  242. package/dist/builder/lib/contribution-schemas.js.map +1 -0
  243. package/dist/builder/lib/define-biome.d.ts +17 -0
  244. package/dist/builder/lib/define-biome.d.ts.map +1 -0
  245. package/dist/builder/lib/define-biome.js +11 -0
  246. package/dist/builder/lib/define-biome.js.map +1 -0
  247. package/dist/builder/lib/define-helpers.d.ts +6 -0
  248. package/dist/builder/lib/define-helpers.d.ts.map +1 -0
  249. package/dist/builder/lib/define-helpers.js +20 -0
  250. package/dist/builder/lib/define-helpers.js.map +1 -0
  251. package/dist/builder/lib/extends-precedence.d.ts +14 -0
  252. package/dist/builder/lib/extends-precedence.d.ts.map +1 -0
  253. package/dist/builder/lib/extends-precedence.js +113 -0
  254. package/dist/builder/lib/extends-precedence.js.map +1 -0
  255. package/dist/builder/lib/workflow-phase-config-loader.d.ts +18 -0
  256. package/dist/builder/lib/workflow-phase-config-loader.d.ts.map +1 -0
  257. package/dist/builder/lib/workflow-phase-config-loader.js +78 -0
  258. package/dist/builder/lib/workflow-phase-config-loader.js.map +1 -0
  259. package/dist/host/index.d.ts +11 -0
  260. package/dist/host/index.d.ts.map +1 -0
  261. package/dist/host/index.js +38 -0
  262. package/dist/host/index.js.map +1 -0
  263. package/dist/host/lib/agents-cross-validate.d.ts +7 -0
  264. package/dist/host/lib/agents-cross-validate.d.ts.map +1 -0
  265. package/dist/host/lib/agents-cross-validate.js +157 -0
  266. package/dist/host/lib/agents-cross-validate.js.map +1 -0
  267. package/dist/host/lib/biome-manifest.d.ts +808 -0
  268. package/dist/host/lib/biome-manifest.d.ts.map +1 -0
  269. package/dist/host/lib/biome-manifest.js +490 -0
  270. package/dist/host/lib/biome-manifest.js.map +1 -0
  271. package/dist/host/lib/bootstrap-contributions-service.d.ts +35 -0
  272. package/dist/host/lib/bootstrap-contributions-service.d.ts.map +1 -0
  273. package/dist/host/lib/bootstrap-contributions-service.js +79 -0
  274. package/dist/host/lib/bootstrap-contributions-service.js.map +1 -0
  275. package/dist/host/lib/default-state.d.ts +3 -0
  276. package/dist/host/lib/default-state.d.ts.map +1 -0
  277. package/dist/host/lib/default-state.js +20 -0
  278. package/dist/host/lib/default-state.js.map +1 -0
  279. package/dist/host/lib/integration-cross-validate.d.ts +12 -0
  280. package/dist/host/lib/integration-cross-validate.d.ts.map +1 -0
  281. package/dist/host/lib/integration-cross-validate.js +66 -0
  282. package/dist/host/lib/integration-cross-validate.js.map +1 -0
  283. package/dist/host/lib/system-overlay-contribution.d.ts +14 -0
  284. package/dist/host/lib/system-overlay-contribution.d.ts.map +1 -0
  285. package/dist/host/lib/system-overlay-contribution.js +3 -0
  286. package/dist/host/lib/system-overlay-contribution.js.map +1 -0
  287. package/dist/host/lib/topology.d.ts +7 -0
  288. package/dist/host/lib/topology.d.ts.map +1 -0
  289. package/dist/host/lib/topology.js +105 -0
  290. package/dist/host/lib/topology.js.map +1 -0
  291. package/dist/index.d.ts +9 -0
  292. package/dist/index.d.ts.map +1 -0
  293. package/dist/index.js +37 -0
  294. package/dist/index.js.map +1 -0
  295. package/dist/orchestrator-adapter/index.d.ts +3 -0
  296. package/dist/orchestrator-adapter/index.d.ts.map +1 -0
  297. package/dist/orchestrator-adapter/index.js +19 -0
  298. package/dist/orchestrator-adapter/index.js.map +1 -0
  299. package/dist/orchestrator-adapter/lib/orchestrator-adapter-registry.d.ts +6 -0
  300. package/dist/orchestrator-adapter/lib/orchestrator-adapter-registry.d.ts.map +1 -0
  301. package/dist/orchestrator-adapter/lib/orchestrator-adapter-registry.js +11 -0
  302. package/dist/orchestrator-adapter/lib/orchestrator-adapter-registry.js.map +1 -0
  303. package/dist/orchestrator-adapter/lib/orchestrator-adapter.d.ts +11 -0
  304. package/dist/orchestrator-adapter/lib/orchestrator-adapter.d.ts.map +1 -0
  305. package/dist/orchestrator-adapter/lib/orchestrator-adapter.js +3 -0
  306. package/dist/orchestrator-adapter/lib/orchestrator-adapter.js.map +1 -0
  307. package/package.json +110 -0
  308. package/src/adapter/index.ts +6 -0
  309. package/src/adapter/lib/action.ts +60 -0
  310. package/src/adapter/lib/provider-module.ts +140 -0
  311. package/src/adapter/lib/resource.ts +52 -0
  312. package/src/adapter/lib/result.ts +53 -0
  313. package/src/adapter/lib/sidecar-contract.ts +169 -0
  314. package/src/adapter/lib/webhook.ts +142 -0
  315. package/src/agent-workspace/index.ts +7 -0
  316. package/src/agent-workspace/lib/errors/error-codes.ts +44 -0
  317. package/src/agent-workspace/lib/errors/index.ts +3 -0
  318. package/src/agent-workspace/lib/errors/mount-plan-error.ts +29 -0
  319. package/src/agent-workspace/lib/errors/mount-resolver-error.ts +56 -0
  320. package/src/agent-workspace/lib/mount-resolver.ts +35 -0
  321. package/src/agent-workspace/lib/mount-source.ts +11 -0
  322. package/src/agent-workspace/lib/refid-resolver.ts +135 -0
  323. package/src/agent-workspace/lib/registries.ts +150 -0
  324. package/src/agent-workspace/lib/resolvers/agent-definition.resolver.ts +45 -0
  325. package/src/agent-workspace/lib/resolvers/artifact-store-collection.resolver.ts +43 -0
  326. package/src/agent-workspace/lib/resolvers/artifact-version.resolver.ts +52 -0
  327. package/src/agent-workspace/lib/resolvers/clients.ts +297 -0
  328. package/src/agent-workspace/lib/resolvers/deliverable-specs.resolver.ts +33 -0
  329. package/src/agent-workspace/lib/resolvers/deliverables.resolver.ts +41 -0
  330. package/src/agent-workspace/lib/resolvers/index.ts +19 -0
  331. package/src/agent-workspace/lib/resolvers/instruction-section.resolver.ts +36 -0
  332. package/src/agent-workspace/lib/resolvers/kb-pages.resolver.ts +62 -0
  333. package/src/agent-workspace/lib/resolvers/kb-space.resolver.ts +34 -0
  334. package/src/agent-workspace/lib/resolvers/rendered-agents-md.resolver.ts +40 -0
  335. package/src/agent-workspace/lib/resolvers/rendered-context-json.resolver.ts +41 -0
  336. package/src/agent-workspace/lib/resolvers/rendered-system-overlay.resolver.ts +39 -0
  337. package/src/agent-workspace/lib/resolvers/scm-repo.resolver.ts +43 -0
  338. package/src/agent-workspace/lib/resolvers/session-attachment.resolver.ts +37 -0
  339. package/src/agent-workspace/lib/resolvers/skill-bundle.resolver.ts +42 -0
  340. package/src/agent-workspace/lib/resolvers/static-literal.resolver.ts +69 -0
  341. package/src/agent-workspace/lib/resolvers/types.ts +94 -0
  342. package/src/agent-workspace/lib/resolvers/utils/agent-run-context-cache.ts +206 -0
  343. package/src/agent-workspace/lib/resolvers/utils/auth.ts +39 -0
  344. package/src/agent-workspace/lib/resolvers/utils/size-cap.ts +38 -0
  345. package/src/agent-workspace/lib/resolvers/utils/streaming.ts +22 -0
  346. package/src/agent-workspace/lib/workspace-renderer.ts +25 -0
  347. package/src/api/index.ts +10 -0
  348. package/src/api/lib/api-manifest.ts +54 -0
  349. package/src/api/lib/biome-db.ts +28 -0
  350. package/src/api/lib/code-tool-context.ts +45 -0
  351. package/src/api/lib/code-tool-descriptor.ts +102 -0
  352. package/src/api/lib/code-tool.decorator.ts +111 -0
  353. package/src/api/lib/mutation-context.ts +49 -0
  354. package/src/api/lib/pagination.ts +17 -0
  355. package/src/api/lib/provider-kind-mirror.ts +16 -0
  356. package/src/api/lib/request-context.ts +90 -0
  357. package/src/api/lib/route-registry-entry.ts +35 -0
  358. package/src/api/nest/controller-base.ts +59 -0
  359. package/src/api/nest/events/events.controller.ts +48 -0
  360. package/src/api/nest/health/health.controller.ts +36 -0
  361. package/src/api/nest/health/health.module.ts +29 -0
  362. package/src/api/nest/index.ts +6 -0
  363. package/src/api/nest/module.ts +51 -0
  364. package/src/api/nest/request-context.ts +166 -0
  365. package/src/builder/index.ts +26 -0
  366. package/src/builder/lib/content-walker.ts +383 -0
  367. package/src/builder/lib/contribution-schemas.ts +572 -0
  368. package/src/builder/lib/define-biome.ts +84 -0
  369. package/src/builder/lib/define-helpers.ts +42 -0
  370. package/src/builder/lib/extends-precedence.ts +195 -0
  371. package/src/builder/lib/workflow-phase-config-loader.ts +163 -0
  372. package/src/host/index.ts +39 -0
  373. package/src/host/lib/agents-cross-validate.ts +283 -0
  374. package/src/host/lib/biome-manifest.ts +1060 -0
  375. package/src/host/lib/bootstrap-contributions-service.ts +233 -0
  376. package/src/host/lib/default-state.ts +40 -0
  377. package/src/host/lib/integration-cross-validate.ts +140 -0
  378. package/src/host/lib/system-overlay-contribution.ts +53 -0
  379. package/src/host/lib/topology.ts +174 -0
  380. package/src/index.ts +58 -0
  381. package/src/orchestrator-adapter/index.ts +2 -0
  382. package/src/orchestrator-adapter/lib/orchestrator-adapter-registry.ts +8 -0
  383. package/src/orchestrator-adapter/lib/orchestrator-adapter.ts +20 -0
@@ -0,0 +1,1060 @@
1
+ import {
2
+ CAPABILITY_SLUG_PATTERN,
3
+ FilterExprSchema,
4
+ } from '@xemahq/kernel-contracts/connector';
5
+ import { ContributionKindSchema } from '@xemahq/kernel-contracts/contribution';
6
+ import { CapabilityRefSchema } from '@xemahq/kernel-contracts/capability';
7
+ import {
8
+ BiomeEnginesSchema,
9
+ BiomeEventSubscriptionSchema,
10
+ BiomeLifecycleHooksSchema,
11
+ BiomePermissionsManifestSchema,
12
+ type BiomeEventSubscription,
13
+ } from '@xemahq/kernel-contracts/biome';
14
+ import {
15
+ ProvisioningGuardSchema,
16
+ ProvisioningStepKindSchema,
17
+ ProvisioningTriggerSchema,
18
+ } from '@xemahq/kernel-contracts/provisioning';
19
+ import {
20
+ MigrationRunnerKind,
21
+ OrgDatabasePurpose,
22
+ } from '@xemahq/kernel-contracts/org-database';
23
+ import {
24
+ DataLocalitySchema,
25
+ RuntimeIsolationLevelSchema,
26
+ RunnerTrustTier,
27
+ } from '@xemahq/kernel-contracts/runner';
28
+ import { z } from 'zod';
29
+
30
+ /**
31
+ * `xema-biome.json` — declarative description of a Xema biome's
32
+ * identity and the contributions it ships. The schema is a discriminated
33
+ * union on `xema.target`.
34
+ */
35
+
36
+ /**
37
+ * Biome tier (Layered Biome Architecture — plan-of-record v4.6 §22.5.7,
38
+ * "Linux-faithful" model):
39
+ * - `kernel` — L1 universal, mandatory. Must boot before any other biome.
40
+ * Analogue: vmlinuz / the Linux kernel image.
41
+ * - `system` — L2 system biomes (Wave 18): the systemd / dbus / sshd /
42
+ * libc analogues. Independent biomes that boot after the
43
+ * kernel and before any base/domain biome. Examples:
44
+ * identity (referenced as external submodule), audit,
45
+ * biome-host, biome-fetcher, public-gateway,
46
+ * workload-runtime, authorization, …
47
+ * - `base` — L2.5 base biomes (Wave 16E-3, Wave 17): foundational
48
+ * user-facing primitives any domain biome may depend on
49
+ * (agent-runtime, integration-platform, document-rendering,
50
+ * workflow-runtime). Linux analogy: shared libraries +
51
+ * high-level daemons (libsystemd, libdbus).
52
+ * - `platform` — L3 first-party domain biomes (software-dev, …) and
53
+ * integration biomes (integration-<provider>/…).
54
+ * - `third-party` — external (future: npm or git).
55
+ */
56
+ export const BiomeScopeSchema = z.enum([
57
+ 'kernel',
58
+ 'system',
59
+ 'base',
60
+ 'platform',
61
+ 'third-party',
62
+ ]);
63
+ export type BiomeScope = z.infer<typeof BiomeScopeSchema>;
64
+
65
+ /** Target the biome executes in. */
66
+ export const BiomeTargetSchema = z.enum(['server', 'web']);
67
+ export type BiomeTarget = z.infer<typeof BiomeTargetSchema>;
68
+
69
+ /**
70
+ * The Contribution Protocol (`@xemahq/kernel-contracts/contribution`) is the
71
+ * single authoritative enum for kinds a biome may ship; `ContributionKind`
72
+ * is re-exported from this package's `index.ts`.
73
+ *
74
+ * Conventional on-disk directory name per `ships.content[]` / `ships.modules[]`
75
+ * string. Used ONLY for the `ships`-based file-walk seeders that have not yet
76
+ * migrated to the `contributions/` directory protocol. New code MUST use the
77
+ * `xema.contributions` block (or inline contributions) instead of
78
+ * `ships.content` / `ships.modules`.
79
+ *
80
+ * Keys are the camelCase tokens accepted in `xema-biome.json`; the mapping
81
+ * returns `null` for any key it does not recognise so callers can fail fast.
82
+ */
83
+ const LEGACY_SHIPS_CONTENT_DIR: Readonly<Record<string, string>> = {
84
+ agents: 'agents',
85
+ workflowConfig: 'workflow-config',
86
+ deliverableSpecs: 'deliverable-specs',
87
+ workspaceManifests: 'workspace-manifests',
88
+ workspaceManifestTemplates: 'workspace-manifest-templates',
89
+ toolProfiles: 'tool-profiles',
90
+ mcpCatalog: 'mcp-catalog',
91
+ mcpTools: 'mcp-tools',
92
+ openCodeSkills: 'skills',
93
+ openCodeTools: 'opencode-tools',
94
+ openCodePlugins: 'opencode-plugins',
95
+ roleCapabilities: 'role-capabilities',
96
+ artifactTypes: 'artifact-types',
97
+ biomeInstallSchema: 'install-schema',
98
+ icons: 'icons',
99
+ projectKits: 'project-kits',
100
+ provisioningScaffolds: 'provisioning',
101
+ };
102
+
103
+ const LEGACY_SHIPS_MODULES_DIR: Readonly<Record<string, string>> = {
104
+ agents: 'agents',
105
+ actions: 'actions',
106
+ mountSourceKinds: 'mount-source-kinds',
107
+ deliverableSpecKinds: 'deliverable-spec-kinds',
108
+ runtimeMountKinds: 'runtime-mount-kinds',
109
+ workspaceSpecOverlay: 'workspace-spec-overlay',
110
+ systemOverlayContributions: 'system-overlay-contributions',
111
+ adapterKinds: 'adapter-kinds',
112
+ integrationProviders: 'integration-providers',
113
+ };
114
+
115
+ /**
116
+ * Resolve a legacy `ships.content[]` value to its conventional directory
117
+ * name, or `null` for unknown tokens. Used by the legacy file-walk
118
+ * catalog/seeders; new code should use the contributions protocol.
119
+ */
120
+ export function contentKindToDir(kind: string): string {
121
+ const dir = LEGACY_SHIPS_CONTENT_DIR[kind];
122
+ if (!dir) {
123
+ throw new Error(
124
+ `biome-host-sdk: unknown legacy ships.content[] value "${kind}". ` +
125
+ `Either migrate the biome to xema.contributions or extend LEGACY_SHIPS_CONTENT_DIR.`,
126
+ );
127
+ }
128
+ return dir;
129
+ }
130
+
131
+ /**
132
+ * Resolve a legacy `ships.modules[]` value to its conventional directory
133
+ * name. Same legacy-only scope as `contentKindToDir`.
134
+ */
135
+ export function moduleKindToDir(kind: string): string {
136
+ const dir = LEGACY_SHIPS_MODULES_DIR[kind];
137
+ if (!dir) {
138
+ throw new Error(
139
+ `biome-host-sdk: unknown legacy ships.modules[] value "${kind}". ` +
140
+ `Either migrate the biome to xema.contributions or extend LEGACY_SHIPS_MODULES_DIR.`,
141
+ );
142
+ }
143
+ return dir;
144
+ }
145
+
146
+ /**
147
+ * Org-managed database declaration for biomes that need a dedicated
148
+ * schema in a provisioned org database.
149
+ */
150
+ export const BiomeDatabaseDeclarationSchema = z
151
+ .object({
152
+ purpose: z.literal(OrgDatabasePurpose.Biome),
153
+ runnerKind: z.literal(MigrationRunnerKind.Prisma),
154
+ })
155
+ .strict();
156
+ export type BiomeDatabaseDeclaration = z.infer<typeof BiomeDatabaseDeclarationSchema>;
157
+
158
+ /**
159
+ * Per-API declaration shipped under `xema.ships.apis[]` (Phase 9).
160
+ * Each entry becomes one subdomain (`<name>.api.<base-domain>`)
161
+ * served by a biome-shipped NestJS service. biome-host-api applies
162
+ * the Helm sub-chart at install time and writes a route-registry
163
+ * entry the ingress shim consults. Validated structurally here;
164
+ * detailed contract semantics live in `@xemahq/biome-api-sdk`.
165
+ */
166
+ export const BiomeApiDeclarationSchema = z
167
+ .object({
168
+ name: z
169
+ .string()
170
+ .min(1)
171
+ .regex(
172
+ /^[a-z][a-z0-9-]*$/,
173
+ 'API name must be lowercase kebab-case; becomes the subdomain slug',
174
+ ),
175
+ basePath: z
176
+ .string()
177
+ .regex(/^\/.*$/)
178
+ .optional(),
179
+ /** Workspace package name + port — the deployment image. */
180
+ image: z
181
+ .object({
182
+ package: z.string().min(1),
183
+ port: z.number().int().min(1).max(65_535),
184
+ })
185
+ .strict(),
186
+ openapiSpec: z.string().optional(),
187
+ scopes: z.array(z.enum(['public', 'org', 'project', 'installation'])).min(1),
188
+ })
189
+ .strict();
190
+ export type BiomeApiDeclaration = z.infer<typeof BiomeApiDeclarationSchema>;
191
+
192
+ /**
193
+ * Phase-C Contribution Protocol entry. The body of an
194
+ * `*.contribution.json` file under a biome's `contributions/` directory,
195
+ * or an inline entry under `xema.contributions.inline[]` in
196
+ * `xema-biome.json`.
197
+ *
198
+ * Validated structurally here (kind + slug + opaque manifest). The
199
+ * authoritative per-kind manifest validation lives in the kind-specific
200
+ * contracts package and is exercised at boot by the generic
201
+ * `BootstrapContributionsService` template (see
202
+ * `bootstrap-contributions-service.ts`).
203
+ *
204
+ * See `.claude/plans/following-up-the-xema-os-plan-md-abstract-stream.md` §6.C.1.
205
+ */
206
+ export const BiomeContributionEntrySchema = z
207
+ .object({
208
+ kind: ContributionKindSchema,
209
+ /**
210
+ * Kind-local slug; uniqueness is per `(kind, biomeId)`. The full
211
+ * `<namespace>/<local-slug>` slug expected by the kernel
212
+ * `ContributionSlugSchema` is composed at install time by the biome
213
+ * host (`namespace = biomeId`).
214
+ */
215
+ id: z
216
+ .string()
217
+ .min(1)
218
+ .regex(
219
+ /^[a-z0-9][a-z0-9._-]*(?:\/[a-z0-9][a-z0-9._-]*)*$/,
220
+ 'Contribution id must be lowercase kebab/dot-case, optionally with nested `/` segments',
221
+ ),
222
+ manifest: z.unknown(),
223
+ })
224
+ .strict();
225
+ export type BiomeContributionEntry = z.infer<typeof BiomeContributionEntrySchema>;
226
+
227
+ /**
228
+ * Per-biome Contribution Protocol declaration. Either points at a
229
+ * `contributions/` directory containing one `*.contribution.json` per
230
+ * entry, OR carries the entries inline. Both forms are allowed in one
231
+ * manifest — directory entries are walked first, inline entries layered
232
+ * on top with last-write-wins on `(kind, id)` collision (the host fails
233
+ * fast on duplicates at boot).
234
+ *
235
+ * Phase C plan-of-record: §6.C.1.
236
+ */
237
+ export const BiomeContributionsSchema = z
238
+ .object({
239
+ /**
240
+ * Directory under the biome root (relative path). Defaults to
241
+ * `./contributions` when omitted but the block is present. The host
242
+ * silently ignores a missing directory — empty contribution sets are
243
+ * legal.
244
+ */
245
+ directory: z.string().min(1).optional(),
246
+ /** Inline contribution entries. */
247
+ inline: z.array(BiomeContributionEntrySchema).optional(),
248
+ })
249
+ .strict();
250
+ export type BiomeContributions = z.infer<typeof BiomeContributionsSchema>;
251
+
252
+ export const BiomeShipsSchema = z
253
+ .object({
254
+ /**
255
+ * @deprecated PHASE-C-SWEEP: superseded by top-level
256
+ * `xema.contributions`. Kept as a free-form string array until the
257
+ * codemod sweep migrates every biome to the Contribution Protocol.
258
+ * Values are matched against `ContributionKind` at registration time.
259
+ */
260
+ content: z.array(z.string().min(1)).optional(),
261
+ /**
262
+ * @deprecated PHASE-C-SWEEP: superseded by top-level
263
+ * `xema.contributions`. See `content` above — same rationale.
264
+ */
265
+ modules: z.array(z.string().min(1)).optional(),
266
+ apis: z.array(BiomeApiDeclarationSchema).optional(),
267
+ })
268
+ .strict();
269
+ export type BiomeShips = z.infer<typeof BiomeShipsSchema>;
270
+
271
+ /**
272
+ * Hosting/trust posture for a server biome. Used by integration-host
273
+ * plumbing (Phase 7) to decide whether to load adapter-contribution
274
+ * modules in-process or via a sidecar deployment. Manifests authored
275
+ * by Xema and audited third parties may set `first-party`; everything
276
+ * else defaults to `third-party`.
277
+ */
278
+ export const BiomeTrustTierSchema = z.enum(['first-party', 'third-party']);
279
+ export type BiomeTrustTier = z.infer<typeof BiomeTrustTierSchema>;
280
+
281
+ /**
282
+ * AdapterKind slug — accepts a built-in slug verbatim, plus any
283
+ * lowercase kebab-case slug a biome-contributed kind could register.
284
+ * The runtime registry in integration-adapters-api is the authority on
285
+ * which slugs actually resolve; manifest parsing only enforces shape.
286
+ */
287
+ const AdapterKindRefSchema = z
288
+ .string()
289
+ .min(1)
290
+ .regex(/^[a-z][a-z0-9-]*$/, 'adapterKind must be lowercase kebab-case');
291
+
292
+ /**
293
+ * Execution mode for a shipped agent. Mirrors the `mode:` field in the
294
+ * agent .md frontmatter (and the `executionMode` column in
295
+ * llm-registry's `agent_definitions` table). Closed enum — every agent
296
+ * is either the session's primary or a delegate available via the
297
+ * `task` tool.
298
+ *
299
+ * The on-disk convention for backwards compatibility is that a missing
300
+ * frontmatter `mode:` is treated as `primary`. The manifest declaration
301
+ * is the authoritative answer; the cross-validator
302
+ * (`crossValidateAgentDeclarations`) accepts a declared `primary` against
303
+ * a missing frontmatter mode but rejects any other mismatch.
304
+ */
305
+ export const BiomeAgentModeSchema = z.enum(['primary', 'subagent']);
306
+ export type BiomeAgentMode = z.infer<typeof BiomeAgentModeSchema>;
307
+
308
+ /**
309
+ * Declaration of a single agent shipped by a biome. Path is implicit:
310
+ * `<biomeRoot>/agents/<slug>.md` (the convention enforced by
311
+ * `enumerateContentAcrossBiomeTree`). The slug also becomes the
312
+ * agent's canonical id in llm-registry, so it must match the filename.
313
+ *
314
+ * `mode` is duplicated between the manifest and the .md frontmatter on
315
+ * purpose: the manifest field makes the agent roster greppable and
316
+ * lets biome-host refuse to boot on drift; the frontmatter is what
317
+ * the agent-definition seeder consumes when materialising the agent
318
+ * into the registry. The boot-time cross-validator ensures both agree.
319
+ */
320
+ export const BiomeAgentDeclarationSchema = z
321
+ .object({
322
+ slug: z
323
+ .string()
324
+ .min(1)
325
+ .regex(
326
+ /^[a-z][a-z0-9-_]*$/,
327
+ 'agent slug must be lowercase kebab/underscore-case and match the .md basename',
328
+ ),
329
+ mode: BiomeAgentModeSchema,
330
+ })
331
+ .strict();
332
+ export type BiomeAgentDeclaration = z.infer<typeof BiomeAgentDeclarationSchema>;
333
+
334
+ const CapabilitySlugSchema = z
335
+ .string()
336
+ .min(1)
337
+ .regex(CAPABILITY_SLUG_PATTERN, 'capability slug must be <domain>.<verb-qualifier>');
338
+
339
+ /**
340
+ * Declared integration dependency. The install wizard surfaces these
341
+ * as a consent screen; `biome-host-api` refuses to activate a
342
+ * `BiomeInstallation` whose non-optional requirements are not bound.
343
+ * `purpose` is mandatory (one short sentence) so users see *why* the
344
+ * biome needs the integration.
345
+ */
346
+ export const IntegrationRequirementSchema = z
347
+ .object({
348
+ adapterKind: AdapterKindRefSchema,
349
+ optional: z.boolean().optional(),
350
+ purpose: z.string().min(1),
351
+ capabilities: z.array(CapabilitySlugSchema).min(1),
352
+ })
353
+ .strict();
354
+ export type IntegrationRequirement = z.infer<typeof IntegrationRequirementSchema>;
355
+
356
+ /**
357
+ * Per-(workflow, event) filter expression. The workflow YAML's
358
+ * `on.webhook[].event` value must match `event` here; the workflow
359
+ * compiler enforces this at publish time. `workflowId` is the
360
+ * shipped-workflow id (the `id` field inside the YAML), not a runtime
361
+ * `WorkflowDefinition.id`. At install time `biome-host-api` resolves
362
+ * the bundle and copies the relevant entries onto the
363
+ * `WorkflowDefinition.biomeWebhookFilters` column so the dispatcher
364
+ * can evaluate without re-reading the manifest.
365
+ */
366
+ export const WebhookFilterSchema = z
367
+ .object({
368
+ workflowId: z
369
+ .string()
370
+ .min(1)
371
+ .regex(/^[a-z][a-z0-9-]*$/, 'workflowId must be lowercase kebab-case'),
372
+ event: z.string().min(1),
373
+ /**
374
+ * Optional canonical entity kind the filter targets (e.g. `push`,
375
+ * `change_request`, `item`). When set, the manifest cross-validator
376
+ * narrows `$envelope.*` path checking to that entity kind's
377
+ * payload — typos against the specific kind fail fast at boot.
378
+ * Omitted = union path check across every entity kind under the
379
+ * referenced workflow's required adapter kinds (over-permissive
380
+ * but still catches the obvious typo class).
381
+ */
382
+ entityKind: z.string().min(1).optional(),
383
+ predicate: FilterExprSchema,
384
+ })
385
+ .strict();
386
+ export type WebhookFilter = z.infer<typeof WebhookFilterSchema>;
387
+
388
+ /**
389
+ * Server-side capability declarations. Validated at boot for shape +
390
+ * closed-set membership; runtime enforcement is Phase 4 (network
391
+ * allow-list, MCP ACL, secret scope). Declaring intent now means every
392
+ * biome already states it — no migration when enforcement turns on.
393
+ */
394
+ export const ServerBiomeCapabilitiesSchema = z
395
+ .object({
396
+ mcp: z.array(z.string().min(1)).optional(),
397
+ network: z
398
+ .object({ allowList: z.array(z.string().min(1)) })
399
+ .strict()
400
+ .optional(),
401
+ secrets: z.array(z.string().min(1)).optional(),
402
+ })
403
+ .strict();
404
+ export type ServerBiomeCapabilities = z.infer<typeof ServerBiomeCapabilitiesSchema>;
405
+
406
+ /** Web-side capability declarations. Same Phase-4 timing as server. */
407
+ export const WebBiomeCapabilitiesSchema = z
408
+ .object({
409
+ slots: z.array(z.string().min(1)).optional(),
410
+ apiClients: z.array(z.string().min(1)).optional(),
411
+ })
412
+ .strict();
413
+ export type WebBiomeCapabilities = z.infer<typeof WebBiomeCapabilitiesSchema>;
414
+
415
+ /**
416
+ * How the `provisioning-plan-resolver` expands one scaffold declaration
417
+ * into resolved steps. Closed enum — `each-app-target` evaluates
418
+ * `selector.configPointer` against the session's `customConfig` and emits
419
+ * one step per matched array element (webapp-studio's `/appTargets`).
420
+ * Adding a strategy is a one-line schema change here plus a matching
421
+ * branch in the resolver.
422
+ */
423
+ export const ProvisioningScaffoldMatchKindSchema = z.enum(['each-app-target']);
424
+ export type ProvisioningScaffoldMatchKind = z.infer<
425
+ typeof ProvisioningScaffoldMatchKindSchema
426
+ >;
427
+
428
+ /**
429
+ * Declaration of one provisioning scaffold a biome ships. The scaffold
430
+ * *content* (command spec + template files) lives at
431
+ * `<biomeRoot>/provisioning/<id>.yaml`; this manifest entry is the
432
+ * lightweight "I ship this scaffold, and here is when/whether it runs"
433
+ * declaration the resolver reads.
434
+ *
435
+ * `selector` is what makes provisioning "run only if instructed" — a
436
+ * scaffold whose `configPointer` resolves to nothing in the session's
437
+ * `customConfig` never enters the plan.
438
+ */
439
+ export const ProvisioningScaffoldDeclarationSchema = z
440
+ .object({
441
+ id: z
442
+ .string()
443
+ .min(1)
444
+ .regex(
445
+ /^[a-z][a-z0-9-]*$/,
446
+ 'scaffold id must be lowercase kebab-case and match the provisioning/<id>.yaml basename',
447
+ ),
448
+ kind: ProvisioningStepKindSchema,
449
+ triggers: z.array(ProvisioningTriggerSchema).min(1),
450
+ guard: ProvisioningGuardSchema,
451
+ selector: z
452
+ .object({
453
+ /**
454
+ * JSON Pointer (RFC 6901) into the session's `customConfig`. The
455
+ * resolver expands the scaffold only when this resolves; for
456
+ * `each-app-target` it must resolve to an array.
457
+ */
458
+ configPointer: z.string().min(1),
459
+ matchKind: ProvisioningScaffoldMatchKindSchema,
460
+ })
461
+ .strict(),
462
+ })
463
+ .strict();
464
+ export type ProvisioningScaffoldDeclaration = z.infer<
465
+ typeof ProvisioningScaffoldDeclarationSchema
466
+ >;
467
+
468
+ const BiomeIdSchema = z
469
+ .string()
470
+ .min(1)
471
+ .regex(/^[a-z][a-z0-9-]*$/, 'biome id must be kebab-case');
472
+
473
+ /**
474
+ * Per-handler declarative event subscription. Type-aliased to the kernel
475
+ * `BiomeEventSubscription` so the SDK's manifest field and the eventual
476
+ * `xema-biome.json` parser share one shape. See plan §12.4.
477
+ */
478
+ export type BiomeManifestSubscribe = BiomeEventSubscription;
479
+
480
+ /**
481
+ * `requires`: biome id → semver range. Same shape as the kernel biome
482
+ * manifest's `requires` block (plan §12.4); the platform refuses to
483
+ * enable a biome/biome whose `requires` cannot be satisfied by the
484
+ * other enabled biomes/biomes in the org.
485
+ */
486
+ export type BiomeManifestRequires = Readonly<Record<string, string>>;
487
+
488
+ /**
489
+ * Additive XSI fields layered onto the per-target `xema` block in Phase
490
+ * 1A (plan §17.2 item 2). Pure additive — no rename of the SDK package
491
+ * itself yet (that happens in Phase 6). All fields are OPTIONAL at this
492
+ * phase; `engines` is promoted to required in Phase 6.
493
+ *
494
+ * - `subscribes[]` — declarative event wiring (§12.4). Each entry binds
495
+ * one CloudEvents `type` to a handler module path.
496
+ * - `requires` — typed semver dependency declaration on other
497
+ * biomes/biomes (§12.4).
498
+ * - `contributes[]` — closed `ContributionKind` enum from
499
+ * `@xemahq/kernel-contracts/contribution`. The biome-host uses this to know
500
+ * which slot registries to walk on install (§12.1).
501
+ * - `requiresCapabilities[]` — capability refs the biome needs the host
502
+ * to grant before any of its handlers/contributions execute (§30.2).
503
+ * - `exposesCapabilities[]` — capability refs the biome itself
504
+ * implements and offers to others (§30.2).
505
+ * - `permissions` — install-time consent metadata (default profile +
506
+ * per-ref hints + UX groupings) for `requiresCapabilities[]` (§30.2).
507
+ * - `lifecycle` — module paths the host invokes on
508
+ * install/upgrade/enable/disable/uninstall transitions (§24.5).
509
+ * - `engines.xema` — semver range the host enforces against the running
510
+ * platform version (§24.4). Optional in 1A; required in Phase 6.
511
+ *
512
+ * Kernel-owned types are referenced through the kernel packages — never
513
+ * redefined here.
514
+ */
515
+ const XsiManifestExtensionsShape = {
516
+ subscribes: z.array(BiomeEventSubscriptionSchema).optional(),
517
+ requires: z.record(z.string().min(1), z.string().min(1)).optional(),
518
+ contributes: z.array(ContributionKindSchema).optional(),
519
+ /**
520
+ * Phase-C Contribution Protocol entries (the actual envelopes, not just
521
+ * the kind whitelist). Replaces the legacy `ships.content` +
522
+ * `ships.modules` per-kind file-walk seeders with a single generic
523
+ * `BootstrapContributionsService` template; see Phase C.1 of the
524
+ * plan-of-record. Either inline entries or a pointer to a
525
+ * `contributions/` directory at the biome root.
526
+ */
527
+ contributions: BiomeContributionsSchema.optional(),
528
+ requiresCapabilities: z.array(CapabilityRefSchema).optional(),
529
+ exposesCapabilities: z.array(CapabilityRefSchema).optional(),
530
+ permissions: BiomePermissionsManifestSchema.optional(),
531
+ lifecycle: BiomeLifecycleHooksSchema.optional(),
532
+ engines: BiomeEnginesSchema.optional(),
533
+ } as const;
534
+
535
+ /**
536
+ * `runtimeRequirements` — what a biome NEEDS from the runtime/runner that
537
+ * executes it. This is the *requirements* half of the scheduling contract:
538
+ * the package states constraints; the installer decides who installs it;
539
+ * the runtime binding decides where it may run; the router schedules onto a
540
+ * matching healthy runner.
541
+ *
542
+ * HARD RULE — requirements, NEVER placement. A manifest MAY declare
543
+ * required/preferred labels, resource hints, allowed isolation levels,
544
+ * allowed data localities, and a minimum runner trust tier. It MUST NOT
545
+ * name a concrete target: `runtimeId`, `runnerId`, `runnerName`, `host`,
546
+ * `serverUrl`, or any infra address. Those are placement decisions owned by
547
+ * the scheduler, never the package. Enforced two ways: this object is
548
+ * `.strict()` (an unknown key — including any placement field — fails the
549
+ * parse fast) AND `tooling/boundaries/check-biome-no-placement.mjs` scans
550
+ * the raw manifest for forbidden keys anywhere in the tree with an
551
+ * actionable message.
552
+ *
553
+ * Enums are reused from `@xemahq/kernel-contracts/runner` so the requirement side
554
+ * (this manifest) and the capability side (a runtime/runner descriptor)
555
+ * speak the same closed vocabulary and can never drift.
556
+ */
557
+ const RuntimeRequirementsSchema = z
558
+ .object({
559
+ /**
560
+ * Capability/tag labels the executing runner must (`required`) or
561
+ * preferably should (`preferred`) advertise — e.g.
562
+ * `xema.runner/docker`, `xema.runner/gpu`, `region`. Matched against a
563
+ * runner's advertised `labels` by the router's selector.
564
+ */
565
+ labels: z
566
+ .object({
567
+ required: z.array(z.string().min(1)).optional(),
568
+ preferred: z.array(z.string().min(1)).optional(),
569
+ })
570
+ .strict()
571
+ .optional(),
572
+ /**
573
+ * Coarse resource hints (Kubernetes-style quantity strings). Advisory
574
+ * scheduling input, not a hard guarantee at this phase.
575
+ */
576
+ resources: z
577
+ .object({
578
+ cpu: z.string().min(1).optional(),
579
+ memory: z.string().min(1).optional(),
580
+ })
581
+ .strict()
582
+ .optional(),
583
+ /**
584
+ * Isolation boundaries the biome ACCEPTS. A runtime whose provided
585
+ * isolation is not in this set is ineligible. Omit to accept any.
586
+ */
587
+ isolation: z
588
+ .object({
589
+ allowed: z.array(RuntimeIsolationLevelSchema).min(1),
590
+ })
591
+ .strict()
592
+ .optional(),
593
+ /**
594
+ * Data localities the biome ACCEPTS (e.g. pin to `customer-private`).
595
+ * A runtime/runner whose locality is not in this set is ineligible.
596
+ */
597
+ locality: z
598
+ .object({
599
+ allowed: z.array(DataLocalitySchema).min(1),
600
+ })
601
+ .strict()
602
+ .optional(),
603
+ /**
604
+ * Minimum attestation trust tier the executing runner must meet.
605
+ */
606
+ trustTier: z
607
+ .object({
608
+ minimum: z.nativeEnum(RunnerTrustTier),
609
+ })
610
+ .strict()
611
+ .optional(),
612
+ })
613
+ .strict();
614
+
615
+ export type RuntimeRequirements = z.infer<typeof RuntimeRequirementsSchema>;
616
+
617
+ const ServerBiomeXemaSchema = z
618
+ .object({
619
+ id: BiomeIdSchema,
620
+ displayName: z.string().min(1),
621
+ description: z.string().optional(),
622
+ scope: BiomeScopeSchema,
623
+ target: z.literal('server'),
624
+ /**
625
+ * What this biome needs from the runtime/runner that executes it
626
+ * (labels, resources, isolation, locality, trust). Requirements only —
627
+ * a manifest may NOT name a concrete runtime/runner/host (see
628
+ * {@link RuntimeRequirementsSchema}). Server biomes only; web biomes are
629
+ * static bundles served by the host shell and never run on a runner.
630
+ */
631
+ runtimeRequirements: RuntimeRequirementsSchema.optional(),
632
+ /**
633
+ * Whether biome-host must refuse to start without this biome
634
+ * resolving. Defaults to `true` for `scope: 'kernel'` and `false`
635
+ * for every other scope. Manifests may set this explicitly.
636
+ */
637
+ mandatory: z.boolean().optional(),
638
+ /**
639
+ * Server biome ids this biome depends on. Biome-host topologically
640
+ * sorts the server set at boot and fails fast on cycles or unsatisfied
641
+ * dependencies. A kernel biome may only depend on other kernel
642
+ * biomes (enforced by biome-host).
643
+ */
644
+ dependencies: z.array(BiomeIdSchema).optional(),
645
+ /**
646
+ * Biome id(s) this biome EXTENDS. An extending biome is the
647
+ * same-or-upgraded variant of the biome(s) it extends and MAY re-ship
648
+ * their content (agent slugs, workspace manifests, skills); when both
649
+ * are installed the extending biome's version takes precedence. This is
650
+ * the machine-readable form of the "the commercial cultivar extends this
651
+ * community reference biome" relationship — e.g. `document-buddy`
652
+ * (platform cultivar) extends `document-buddy-reference` (community
653
+ * reference). Distinct from `dependencies`: an extended biome need NOT be
654
+ * installed (the extension is self-contained), whereas a dependency must
655
+ * resolve at boot. `extends` is what lets the agent-slug uniqueness
656
+ * invariant tolerate the re-shipped slug — see
657
+ * tooling/boundaries/check-agent-duplication.mjs.
658
+ */
659
+ extends: z.union([BiomeIdSchema, z.array(BiomeIdSchema)]).optional(),
660
+ ships: BiomeShipsSchema.optional(),
661
+ capabilities: ServerBiomeCapabilitiesSchema.optional(),
662
+ /**
663
+ * Hosting posture for adapter-contribution modules (Phase 7). Other
664
+ * biome kinds ignore this field. Defaults to `third-party`.
665
+ */
666
+ trustTier: BiomeTrustTierSchema.optional(),
667
+ /**
668
+ * Integration dependencies the biome needs to be useful. Surfaced
669
+ * to the install wizard as a consent screen. Non-optional entries
670
+ * gate the `BiomeInstallation` state transition to `active`.
671
+ */
672
+ integrationRequirements: z.array(IntegrationRequirementSchema).optional(),
673
+ /**
674
+ * Per-(workflow, event) filter expressions evaluated by the
675
+ * workflow-engine dispatcher at webhook time. Each entry MUST
676
+ * resolve to a workflow shipped by this biome and an event that
677
+ * workflow declares under `on.webhook[].event`. The DSL compiler
678
+ * cross-validates at publish time; manifest parsing only enforces
679
+ * shape.
680
+ */
681
+ webhookFilters: z.array(WebhookFilterSchema).optional(),
682
+ /**
683
+ * Workflows the biome wants exposed as MCP tools. The MCP gateway
684
+ * (`mcp-gateway-api`) projects each entry into the catalog-mode
685
+ * tool listing surfaced to agents via OpenCode. When an agent
686
+ * invokes the tool, the gateway dispatches the workflow run
687
+ * (auto-attaching the calling installation's id, JWT-derived org
688
+ * + actor context) and returns the named deliverable plus an
689
+ * optional workspace mount entry so the result lands on disk
690
+ * automatically.
691
+ *
692
+ * Each `key` is unique within the biome and becomes the MCP tool
693
+ * id (`<biomeId>__<key>`). `workflowSlug` MUST resolve to a
694
+ * workflow this biome ships; the workflow-engine cross-validates
695
+ * at publish time. `outputProjection.deliverable.slug` picks one
696
+ * of the workflow's declared `produces:` entries to surface as the
697
+ * tool's primary content payload. The optional `mount` block
698
+ * issues a `POST /workspace/mounts/apply` on the calling agent's
699
+ * session so the result file appears under `/workspace/<slot>/...`
700
+ * — seamless from the agent's point of view.
701
+ */
702
+ mcpWorkflowTools: z
703
+ .array(
704
+ z
705
+ .object({
706
+ key: z
707
+ .string()
708
+ .min(1)
709
+ .regex(/^[a-z][a-z0-9-]*$/, 'key must be lowercase-kebab'),
710
+ workflowSlug: z.string().min(1),
711
+ displayName: z.string().min(1),
712
+ description: z.string().min(1),
713
+ outputProjection: z
714
+ .object({
715
+ kind: z.literal('deliverable'),
716
+ slug: z.string().min(1),
717
+ })
718
+ .strict(),
719
+ mount: z
720
+ .object({
721
+ slot: z.enum(['inputs', 'references', 'deliverables']),
722
+ as: z.string().min(1),
723
+ })
724
+ .strict()
725
+ .optional(),
726
+ })
727
+ .strict(),
728
+ )
729
+ .optional(),
730
+ /**
731
+ * Plain handler functions the biome's API service exposes as MCP
732
+ * tools. The platform wraps them via the `biome_code_tools`
733
+ * provider — biome authors never see MCP protocol bytes.
734
+ *
735
+ * Each entry's `key` is unique within the biome and maps to a
736
+ * decorated method on the biome's API service via the
737
+ * `@BiomeCodeTool` decorator from `@xemahq/biome-api-sdk`. The
738
+ * full descriptor (inputSchema, displayName, output kind) is
739
+ * authoritative on the biome API side and surfaced through
740
+ * `GET /code-tools-manifest`; this manifest entry is the
741
+ * lightweight "I ship this tool" declaration the platform reads
742
+ * at install time.
743
+ */
744
+ mcpTools: z
745
+ .array(
746
+ z
747
+ .object({
748
+ key: z
749
+ .string()
750
+ .min(1)
751
+ .regex(/^[a-z][a-z0-9-]*$/, 'key must be lowercase-kebab'),
752
+ handler: z
753
+ .object({
754
+ kind: z.literal('biome_api'),
755
+ method: z.enum(['POST']).default('POST'),
756
+ })
757
+ .strict(),
758
+ })
759
+ .strict(),
760
+ )
761
+ .optional(),
762
+ /**
763
+ * Tools the biome recommends are made available when a user
764
+ * adopts it. Surfaced in the install UX as "this biome recommends
765
+ * these tools" — NOT auto-injected into every session. Each entry
766
+ * matches the kernel `ToolSelectionEntry` shape from
767
+ * `@xemahq/kernel-contracts/mcp-tool`. The frontend picker drops these
768
+ * directly into the session's selection on user opt-in.
769
+ *
770
+ * Validation: shape-only at boot. `resourceId` references resolve
771
+ * at install time (e.g. biome-installation-id is materialized by
772
+ * biome-host-api when the installation is created). Cross-tenant
773
+ * misuse is blocked downstream by the resolver (Layer 2) and the
774
+ * PATCH-time validator (Layer 1) when the user actually adopts the
775
+ * selection.
776
+ */
777
+ defaultToolSelection: z
778
+ .array(
779
+ z
780
+ .discriminatedUnion('kind', [
781
+ z
782
+ .object({
783
+ kind: z.literal('provider'),
784
+ providerKind: z.enum([
785
+ 'mcp_server',
786
+ 'catalog',
787
+ 'biome_workflow_tools',
788
+ 'biome_code_tools',
789
+ ]),
790
+ resourceId: z.string().min(1).max(256),
791
+ })
792
+ .strict(),
793
+ z
794
+ .object({
795
+ kind: z.literal('tool'),
796
+ providerKind: z.enum([
797
+ 'mcp_server',
798
+ 'catalog',
799
+ 'biome_workflow_tools',
800
+ 'biome_code_tools',
801
+ ]),
802
+ resourceId: z.string().min(1).max(256),
803
+ toolName: z.string().min(1).max(256),
804
+ })
805
+ .strict(),
806
+ ]),
807
+ )
808
+ .max(64)
809
+ .optional(),
810
+ /**
811
+ * Explicit roster of agents this biome ships. Required when
812
+ * `ships.content` includes `'agents'`; forbidden otherwise. Each
813
+ * entry pins one `agents/<slug>.md` file with its execution mode
814
+ * (primary vs subagent).
815
+ *
816
+ * Why both this field AND the on-disk `agents/` scan exist:
817
+ * - The declaration makes the roster greppable from outside the
818
+ * biome tree (`grep '"slug": "build"' biomes/*\/xema-biome.json`).
819
+ * - It lets biome-host fail fast at boot when an agent file is
820
+ * added or removed without updating the manifest — the prior
821
+ * convention silently accepted drift.
822
+ * - The closed `mode` enum surfaces primary-vs-subagent intent at
823
+ * install time instead of requiring readers to parse YAML
824
+ * frontmatter from every .md.
825
+ *
826
+ * Cross-validated by `crossValidateAgentDeclarations` at
827
+ * biome-host boot; the seeder still reads frontmatter for the rest
828
+ * of each agent's attributes.
829
+ */
830
+ agents: z.array(BiomeAgentDeclarationSchema).optional(),
831
+ /**
832
+ * Workspace-provisioning scaffolds the biome ships (Epic A). Each
833
+ * entry pins one `provisioning/<id>.yaml` recipe and declares when it
834
+ * runs + how the resolver expands it. Required ⟺ `ships.content`
835
+ * includes `provisioningScaffolds`; cross-validated in `superRefine`.
836
+ */
837
+ provisioning: z.array(ProvisioningScaffoldDeclarationSchema).optional(),
838
+ /**
839
+ * Biome-specific org-managed database declaration. When present the
840
+ * host provisions an org database, runs the declared migrations, and
841
+ * injects the org database identifiers into the runtime workload env.
842
+ */
843
+ database: BiomeDatabaseDeclarationSchema.optional(),
844
+ /** Reserved for Phase 4 third-party signing. Validated only when present. */
845
+ signature: z
846
+ .object({
847
+ algorithm: z.string().min(1),
848
+ value: z.string().min(1),
849
+ keyId: z.string().min(1),
850
+ })
851
+ .strict()
852
+ .optional(),
853
+ // XSI Phase 1A additive fields. See `XsiManifestExtensionsShape`
854
+ // doc-comment above for the per-field meaning + plan citations.
855
+ ...XsiManifestExtensionsShape,
856
+ })
857
+ .strict()
858
+ .superRefine((value, ctx) => {
859
+ validateServerPluginWebhookAndIntegrationRequirements(value, ctx);
860
+ validateServerBiomeAgentDeclarations(value, ctx);
861
+ validateServerPluginProvisioningDeclarations(value, ctx);
862
+ });
863
+
864
+ const WebBiomeXemaSchema = z
865
+ .object({
866
+ id: BiomeIdSchema,
867
+ displayName: z.string().min(1),
868
+ description: z.string().optional(),
869
+ scope: BiomeScopeSchema,
870
+ target: z.literal('web'),
871
+ mandatory: z.boolean().optional(),
872
+ /**
873
+ * Server biomes this web biome REQUIRES — its backend counterpart(s).
874
+ * Web biomes never depend on other web biomes — intentional, keeps the
875
+ * dependency graph two-tiered (web → server). Cross-target validation at
876
+ * boot ensures every referenced server id resolves in the catalog;
877
+ * otherwise biome-host refuses to start. Per-org, a web biome whose
878
+ * required server biomes are not all enabled resolves to ORPHANED.
879
+ */
880
+ requiresServerBiomes: z.array(BiomeIdSchema).optional(),
881
+ /**
882
+ * Server biomes this web biome can OPTIONALLY integrate with (e.g. a
883
+ * GitHub/Jira connector). The web biome stays active without them; they
884
+ * are NOT part of the cross-target boot validation and never cause an
885
+ * ORPHANED state.
886
+ */
887
+ optionalServerBiomes: z.array(BiomeIdSchema).optional(),
888
+ capabilities: WebBiomeCapabilitiesSchema.optional(),
889
+ signature: z
890
+ .object({
891
+ algorithm: z.string().min(1),
892
+ value: z.string().min(1),
893
+ keyId: z.string().min(1),
894
+ })
895
+ .strict()
896
+ .optional(),
897
+ // XSI Phase 1A additive fields — same shape on both targets so the
898
+ // biome-host can read them uniformly regardless of where the biome
899
+ // executes. See `XsiManifestExtensionsShape` above.
900
+ ...XsiManifestExtensionsShape,
901
+ })
902
+ .strict();
903
+
904
+ export const BiomeXemaSchema = z.discriminatedUnion('target', [
905
+ ServerBiomeXemaSchema,
906
+ WebBiomeXemaSchema,
907
+ ]);
908
+ export type BiomeXema = z.infer<typeof BiomeXemaSchema>;
909
+ export type ServerBiomeXema = z.infer<typeof ServerBiomeXemaSchema>;
910
+ export type WebBiomeXema = z.infer<typeof WebBiomeXemaSchema>;
911
+
912
+ function validateServerPluginWebhookAndIntegrationRequirements(
913
+ value: ServerBiomeXema,
914
+ ctx: z.RefinementCtx,
915
+ ): void {
916
+ if (value.webhookFilters && value.webhookFilters.length > 0) {
917
+ const requirements = value.integrationRequirements ?? [];
918
+ if (requirements.length === 0) {
919
+ ctx.addIssue({
920
+ code: 'custom',
921
+ path: ['webhookFilters'],
922
+ message:
923
+ 'webhookFilters is set but integrationRequirements is empty — a biome gating workflows on webhook events must declare which integration(s) it requires',
924
+ });
925
+ }
926
+ }
927
+ if (value.integrationRequirements && value.integrationRequirements.length > 0) {
928
+ const shipsInstallSchema = value.ships?.content?.includes('biomeInstallSchema') ?? false;
929
+ if (!shipsInstallSchema) {
930
+ ctx.addIssue({
931
+ code: 'custom',
932
+ path: ['ships', 'content'],
933
+ message:
934
+ 'biomes declaring integrationRequirements must also ship a `biomeInstallSchema` content kind so the install wizard can render a resource-selection form',
935
+ });
936
+ }
937
+ }
938
+ }
939
+
940
+ function validateServerBiomeAgentDeclarations(
941
+ value: ServerBiomeXema,
942
+ ctx: z.RefinementCtx,
943
+ ): void {
944
+ const shipsAgents = value.ships?.content?.includes('agents') ?? false;
945
+ const hasAgents = (value.agents?.length ?? 0) > 0;
946
+ if (shipsAgents && !hasAgents) {
947
+ ctx.addIssue({
948
+ code: 'custom',
949
+ path: ['agents'],
950
+ message:
951
+ 'ships.content includes "agents" — manifest must declare each shipped agent under `agents[]` (slug + mode). The boot-time cross-validator enforces parity with on-disk agents/*.md files.',
952
+ });
953
+ }
954
+ if (!shipsAgents && hasAgents) {
955
+ ctx.addIssue({
956
+ code: 'custom',
957
+ path: ['agents'],
958
+ message:
959
+ 'agents[] is declared but ships.content does not include "agents" — add "agents" to ships.content or remove the agents[] block',
960
+ });
961
+ }
962
+ if (hasAgents) {
963
+ const slugs = new Set<string>();
964
+ value.agents?.forEach((decl, idx) => {
965
+ if (slugs.has(decl.slug)) {
966
+ ctx.addIssue({
967
+ code: 'custom',
968
+ path: ['agents', idx, 'slug'],
969
+ message: `duplicate agent slug "${decl.slug}" — each slug maps to a single agents/<slug>.md file`,
970
+ });
971
+ }
972
+ slugs.add(decl.slug);
973
+ });
974
+ }
975
+ }
976
+
977
+ function validateServerPluginProvisioningDeclarations(
978
+ value: ServerBiomeXema,
979
+ ctx: z.RefinementCtx,
980
+ ): void {
981
+ const shipsProvisioning = value.ships?.content?.includes('provisioningScaffolds') ?? false;
982
+ const hasProvisioning = (value.provisioning?.length ?? 0) > 0;
983
+ if (shipsProvisioning && !hasProvisioning) {
984
+ ctx.addIssue({
985
+ code: 'custom',
986
+ path: ['provisioning'],
987
+ message:
988
+ 'ships.content includes "provisioningScaffolds" — manifest must declare each scaffold under `provisioning[]`',
989
+ });
990
+ }
991
+ if (!shipsProvisioning && hasProvisioning) {
992
+ ctx.addIssue({
993
+ code: 'custom',
994
+ path: ['provisioning'],
995
+ message:
996
+ 'provisioning[] is declared but ships.content does not include "provisioningScaffolds" — add it or remove the provisioning[] block',
997
+ });
998
+ }
999
+ }
1000
+
1001
+ const ManifestNameSchema = z
1002
+ .string()
1003
+ .min(1)
1004
+ .regex(/^@[^/]+\/[^/]+$/, 'biome package name must be scoped');
1005
+
1006
+ export const BiomeManifestSchema = z
1007
+ .object({
1008
+ name: ManifestNameSchema,
1009
+ version: z.string().min(1),
1010
+ xema: BiomeXemaSchema,
1011
+ })
1012
+ .passthrough(); // tolerate extra top-level npm fields
1013
+
1014
+ export type BiomeManifest = z.infer<typeof BiomeManifestSchema>;
1015
+ export type ServerBiomeManifest = BiomeManifest & { xema: ServerBiomeXema };
1016
+ export type WebBiomeManifest = BiomeManifest & { xema: WebBiomeXema };
1017
+
1018
+ export class BiomeManifestParseError extends Error {
1019
+ readonly issues: readonly z.core.$ZodIssue[];
1020
+ constructor(issues: readonly z.core.$ZodIssue[]) {
1021
+ super(
1022
+ `Invalid xema-biome.json: ${issues
1023
+ .map((i) => `[${i.path.join('.')}] ${i.message}`)
1024
+ .join('; ')}`,
1025
+ );
1026
+ this.name = 'BiomeManifestParseError';
1027
+ this.issues = issues;
1028
+ }
1029
+ }
1030
+
1031
+ export function parseBiomeManifest(raw: unknown): BiomeManifest {
1032
+ const result = BiomeManifestSchema.safeParse(raw);
1033
+ if (!result.success) {
1034
+ throw new BiomeManifestParseError(result.error.issues);
1035
+ }
1036
+ return result.data;
1037
+ }
1038
+
1039
+ export function isServerBiomeManifest(
1040
+ manifest: BiomeManifest,
1041
+ ): manifest is ServerBiomeManifest {
1042
+ return manifest.xema.target === 'server';
1043
+ }
1044
+
1045
+ export function isWebBiomeManifest(
1046
+ manifest: BiomeManifest,
1047
+ ): manifest is WebBiomeManifest {
1048
+ return manifest.xema.target === 'web';
1049
+ }
1050
+
1051
+ /**
1052
+ * Whether `mandatory` is true for this manifest, applying the default
1053
+ * (kernel → true; everything else → false) when the field is omitted.
1054
+ */
1055
+ export function isBiomeMandatory(manifest: BiomeManifest): boolean {
1056
+ if (typeof manifest.xema.mandatory === 'boolean') {
1057
+ return manifest.xema.mandatory;
1058
+ }
1059
+ return manifest.xema.scope === 'kernel';
1060
+ }