@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,195 @@
1
+ // ═══════════════════════════════════════════════════════════════════════════
2
+ // Biome `xema.extends` precedence — runtime side.
3
+ //
4
+ // A biome MAY declare `xema.extends: <id> | <id>[]` in its xema-biome.json.
5
+ // An extending biome is the same-or-upgraded variant of the biome(s) it
6
+ // extends and MAY re-ship their content (agent slugs, workspace manifests,
7
+ // skills, role capabilities, …). When BOTH are installed (both present under
8
+ // the seeder scan roots), the extending biome's contribution must WIN — not
9
+ // crash the seeder with a "duplicate slug" error.
10
+ //
11
+ // This module is the runtime counterpart to the boundary tooling's
12
+ // `buildExtendsIndex` / `extendsOf` in
13
+ // `tooling/boundaries/lib/carved-biomes.mjs`. The two MUST agree on the
14
+ // relation: the CI duplication check allows a dup slug iff the biomes are
15
+ // extends-related; the runtime seeders resolve that same relation into a
16
+ // concrete winner. Keep the two in sync.
17
+ //
18
+ // Precedence rule: the extending (descendant) biome overrides the base
19
+ // (ancestor) it extends, transitively. Two unrelated biomes — or the same
20
+ // biome contributing a slug twice — are a genuine packaging conflict the
21
+ // caller MUST reject (fail-fast, no silent winner).
22
+ // ═══════════════════════════════════════════════════════════════════════════
23
+
24
+ import type { Dirent } from 'node:fs';
25
+ import { existsSync, readdirSync, readFileSync } from 'node:fs';
26
+ import { join } from 'node:path';
27
+
28
+ /**
29
+ * Read a biome manifest's `xema.extends` (string | string[]) from a raw
30
+ * parsed manifest object. Mirrors the boundary tooling's `extendsOf()` so
31
+ * runtime precedence and the CI duplication check resolve the identical
32
+ * relation. Non-string / missing values yield an empty list.
33
+ */
34
+ function readExtendsTargets(raw: unknown): string[] {
35
+ const ext = (raw as { xema?: { extends?: unknown } } | null | undefined)?.xema
36
+ ?.extends;
37
+ if (Array.isArray(ext)) {
38
+ return ext.filter((x): x is string => typeof x === 'string');
39
+ }
40
+ if (typeof ext === 'string') {
41
+ return [ext];
42
+ }
43
+ return [];
44
+ }
45
+
46
+ export interface BiomeExtendsIndex {
47
+ /**
48
+ * True when `descendant` extends `ancestor` directly OR transitively. The
49
+ * extending biome is the same-or-upgraded variant and wins on a slug
50
+ * collision. Returns false for `descendant === ancestor`.
51
+ */
52
+ extendsTransitively(descendant: string, ancestor: string): boolean;
53
+ /** Direct `xema.extends` targets declared by each scanned biome id. */
54
+ readonly directTargets: ReadonlyMap<string, ReadonlySet<string>>;
55
+ }
56
+
57
+ /**
58
+ * Build the extends graph over every biome under the given scan roots by
59
+ * reading each `xema-biome.json`'s `xema.extends`. Cheap (one stat + read
60
+ * per biome dir) and side-effect free; safe to call once per seeder boot
61
+ * alongside `enumerateContentAcrossBiomeTree` (same roots).
62
+ *
63
+ * Malformed / unreadable manifests are skipped silently here — the same
64
+ * contract `enumerateContentAcrossBiomeTree` follows (biome-host owns
65
+ * manifest validation; a seeder must not crash the whole boot on one bad
66
+ * sibling manifest).
67
+ */
68
+ export function buildBiomeExtendsIndex(
69
+ scanRoots: readonly string[],
70
+ ): BiomeExtendsIndex {
71
+ const directTargets = new Map<string, Set<string>>();
72
+
73
+ for (const root of scanRoots) {
74
+ if (!existsSync(root)) continue;
75
+ let entries: Dirent[];
76
+ try {
77
+ entries = readdirSync(root, { withFileTypes: true }) as Dirent[];
78
+ } catch {
79
+ continue;
80
+ }
81
+ for (const entry of entries) {
82
+ if (!entry.isDirectory()) continue;
83
+ const manifestPath = join(root, entry.name, 'xema-biome.json');
84
+ if (!existsSync(manifestPath)) continue;
85
+ let raw: unknown;
86
+ try {
87
+ raw = JSON.parse(readFileSync(manifestPath, 'utf-8'));
88
+ } catch {
89
+ continue;
90
+ }
91
+ const id = (raw as { xema?: { id?: unknown } } | null | undefined)?.xema
92
+ ?.id;
93
+ if (typeof id !== 'string') continue;
94
+ // A biome may appear under more than one scan root in dev; union its
95
+ // declared targets rather than overwriting.
96
+ const existing = directTargets.get(id) ?? new Set<string>();
97
+ for (const t of readExtendsTargets(raw)) existing.add(t);
98
+ directTargets.set(id, existing);
99
+ }
100
+ }
101
+
102
+ const extendsTransitively = (
103
+ descendant: string,
104
+ ancestor: string,
105
+ ): boolean => {
106
+ if (descendant === ancestor) return false;
107
+ const seen = new Set<string>();
108
+ const stack = [...(directTargets.get(descendant) ?? [])];
109
+ while (stack.length > 0) {
110
+ const current = stack.pop();
111
+ if (current === undefined) break;
112
+ if (current === ancestor) return true;
113
+ if (seen.has(current)) continue; // cycle guard
114
+ seen.add(current);
115
+ for (const next of directTargets.get(current) ?? []) stack.push(next);
116
+ }
117
+ return false;
118
+ };
119
+
120
+ return { extendsTransitively, directTargets };
121
+ }
122
+
123
+ export type ExtendsPrecedence = 'keep-existing' | 'replace' | 'conflict';
124
+
125
+ /**
126
+ * Decide which of two biomes contributing the SAME slug wins. The extending
127
+ * (same-or-upgraded) biome overrides the base it extends; two unrelated
128
+ * biomes — or the same biome contributing a slug twice — are a genuine
129
+ * packaging conflict (`'conflict'`) the caller must reject.
130
+ */
131
+ export function resolveExtendsPrecedence(
132
+ index: BiomeExtendsIndex,
133
+ existingBiomeId: string,
134
+ incomingBiomeId: string,
135
+ ): ExtendsPrecedence {
136
+ if (existingBiomeId === incomingBiomeId) return 'conflict';
137
+ if (index.extendsTransitively(incomingBiomeId, existingBiomeId)) {
138
+ return 'replace';
139
+ }
140
+ if (index.extendsTransitively(existingBiomeId, incomingBiomeId)) {
141
+ return 'keep-existing';
142
+ }
143
+ return 'conflict';
144
+ }
145
+
146
+ /**
147
+ * Deduplicate slug-keyed contributions across biomes, honoring
148
+ * `xema.extends`. Non-colliding items keep their first-seen order; on a
149
+ * collision the extending biome's item replaces the base's. A collision
150
+ * between unrelated biomes (or within one biome) is reported through
151
+ * `onConflict`, which MUST throw (its `never` return type enforces this) so
152
+ * a real packaging conflict fails fast instead of silently picking a winner.
153
+ */
154
+ export function dedupeBySlugWithExtends<T>(
155
+ items: readonly T[],
156
+ opts: {
157
+ readonly index: BiomeExtendsIndex;
158
+ readonly slugOf: (item: T) => string;
159
+ readonly biomeIdOf: (item: T) => string;
160
+ readonly onConflict: (slug: string, existing: T, incoming: T) => never;
161
+ },
162
+ ): T[] {
163
+ const winners = new Map<string, T>();
164
+ const order: string[] = [];
165
+
166
+ for (const item of items) {
167
+ const slug = opts.slugOf(item);
168
+ const existing = winners.get(slug);
169
+ if (existing === undefined) {
170
+ winners.set(slug, item);
171
+ order.push(slug);
172
+ continue;
173
+ }
174
+ const decision = resolveExtendsPrecedence(
175
+ opts.index,
176
+ opts.biomeIdOf(existing),
177
+ opts.biomeIdOf(item),
178
+ );
179
+ if (decision === 'replace') {
180
+ winners.set(slug, item);
181
+ } else if (decision === 'conflict') {
182
+ opts.onConflict(slug, existing, item);
183
+ }
184
+ // 'keep-existing' → leave the current winner in place.
185
+ }
186
+
187
+ return order.map((slug) => {
188
+ const winner = winners.get(slug);
189
+ if (winner === undefined) {
190
+ // Unreachable: every slug in `order` has a winner.
191
+ throw new Error(`dedupeBySlugWithExtends: lost winner for slug "${slug}"`);
192
+ }
193
+ return winner;
194
+ });
195
+ }
@@ -0,0 +1,163 @@
1
+ // ═══════════════════════════════════════════════════════════════════════════
2
+ // Workflow phase-config loader.
3
+ //
4
+ // A sub-app biome that defines a gated delivery pipeline ships exactly one
5
+ // `workflow-config/phase-config.json` (validated by `WorkflowPhaseConfigSchema`).
6
+ // The kernel carries no domain phase enum — platform services that need the
7
+ // ordered phase list, the coordinator→parent hierarchy, or the per-phase
8
+ // gate-reviewer map load it AT RUNTIME via this single shared helper, so the
9
+ // FS-discovery + merge logic stays DRY across consumers (llm-registry-api,
10
+ // opencode-pool-api, …).
11
+ //
12
+ // The file lives under the existing `workflowConfig` content kind — no new
13
+ // content kind, no new manifest field. A biome already listing
14
+ // `workflowConfig` in `xema.ships.content[]` is scanned automatically.
15
+ // ═══════════════════════════════════════════════════════════════════════════
16
+
17
+ import { existsSync, readFileSync } from 'node:fs';
18
+ import { join } from 'node:path';
19
+
20
+ import {
21
+ parseContribution,
22
+ type WorkflowPhaseConfig,
23
+ } from './contribution-schemas';
24
+ import { WorkflowPhaseConfigSchema } from './contribution-schemas';
25
+ import { enumerateBiomesWithContent } from './content-walker';
26
+
27
+ /** Conventional filename for the phase-config document inside `workflow-config/`. */
28
+ const PHASE_CONFIG_FILENAME = 'phase-config.json';
29
+
30
+ /**
31
+ * A phase-config loaded from one biome, tagged with the originating
32
+ * biome id so a merge collision can name the culprit.
33
+ */
34
+ export interface LoadedWorkflowPhaseConfig {
35
+ readonly biomeId: string;
36
+ readonly config: WorkflowPhaseConfig;
37
+ }
38
+
39
+ /**
40
+ * The merged, cross-biome view of every shipped phase-config. Phase keys
41
+ * are globally unique by contract — `loadWorkflowPhaseConfigs` throws on a
42
+ * collision rather than silently picking a winner.
43
+ */
44
+ export interface MergedWorkflowPhaseConfig {
45
+ /** Ordered phase keys across all biomes (biome order, then file order). */
46
+ readonly orderedPhaseKeys: readonly string[];
47
+ /** Phase key → lifecycle | delivery. */
48
+ readonly phaseCategory: ReadonlyMap<string, 'lifecycle' | 'delivery'>;
49
+ /** Direct-call agent phase keys (run outside the sequential pipeline). */
50
+ readonly directAgentPhases: readonly string[];
51
+ /**
52
+ * All configurable phase keys = ordered pipeline phases followed by
53
+ * direct-agent phases. Mirrors the legacy `ALL_CONFIGURABLE_PHASES`.
54
+ */
55
+ readonly allConfigurablePhases: readonly string[];
56
+ /** Sub-phase coordinator agent slug → parent phase key. */
57
+ readonly subPhaseToParent: ReadonlyMap<string, string>;
58
+ /** Phase key → required review-capability keys. */
59
+ readonly reviewCapabilities: ReadonlyMap<string, readonly string[]>;
60
+ /** Every distinct review-capability key across all phases. */
61
+ readonly allReviewCapabilities: readonly string[];
62
+ }
63
+
64
+ /**
65
+ * Scan every server biome under `scanRoots` for a
66
+ * `workflow-config/phase-config.json` and return one validated entry per
67
+ * biome that ships one. Biomes without the file are skipped (a biome
68
+ * may ship workflows without defining a gated phase pipeline).
69
+ */
70
+ export function loadWorkflowPhaseConfigs(
71
+ scanRoots: readonly string[],
72
+ ): LoadedWorkflowPhaseConfig[] {
73
+ const out: LoadedWorkflowPhaseConfig[] = [];
74
+ for (const binding of enumerateBiomesWithContent(scanRoots, 'workflowConfig')) {
75
+ const path = join(binding.contentDir, PHASE_CONFIG_FILENAME);
76
+ if (!existsSync(path)) {
77
+ continue;
78
+ }
79
+ let raw: unknown;
80
+ try {
81
+ raw = JSON.parse(readFileSync(path, 'utf-8'));
82
+ } catch (err) {
83
+ throw new Error(
84
+ `Biome "${binding.biomeId}" ships a malformed ${PHASE_CONFIG_FILENAME}: ${
85
+ (err as Error).message
86
+ }`,
87
+ );
88
+ }
89
+ const config = parseContribution(WorkflowPhaseConfigSchema, raw, path);
90
+ out.push({ biomeId: binding.biomeId, config });
91
+ }
92
+ return out;
93
+ }
94
+
95
+ /**
96
+ * Load and merge every biome's phase-config into a single runtime view.
97
+ * Throws on a phase-key collision across biomes — phase keys flow onto
98
+ * the artifact natural key and must be globally unique.
99
+ */
100
+ export function loadMergedWorkflowPhaseConfig(
101
+ scanRoots: readonly string[],
102
+ ): MergedWorkflowPhaseConfig {
103
+ const loaded = loadWorkflowPhaseConfigs(scanRoots);
104
+
105
+ const orderedPhaseKeys: string[] = [];
106
+ const phaseCategory = new Map<string, 'lifecycle' | 'delivery'>();
107
+ const directAgentPhases: string[] = [];
108
+ const subPhaseToParent = new Map<string, string>();
109
+ const reviewCapabilities = new Map<string, readonly string[]>();
110
+ const phaseOwner = new Map<string, string>();
111
+
112
+ for (const { biomeId, config } of loaded) {
113
+ for (const phase of config.phases) {
114
+ const existingOwner = phaseOwner.get(phase.key);
115
+ if (existingOwner !== undefined) {
116
+ throw new Error(
117
+ `Workflow phase key "${phase.key}" is declared by both biome ` +
118
+ `"${existingOwner}" and biome "${biomeId}". Phase keys must be ` +
119
+ `globally unique — they flow onto the artifact natural key.`,
120
+ );
121
+ }
122
+ phaseOwner.set(phase.key, biomeId);
123
+ orderedPhaseKeys.push(phase.key);
124
+ phaseCategory.set(phase.key, phase.category);
125
+ }
126
+ for (const direct of config.directAgentPhases) {
127
+ directAgentPhases.push(direct);
128
+ }
129
+ for (const [slug, parent] of Object.entries(config.subPhaseToParent)) {
130
+ subPhaseToParent.set(slug, parent);
131
+ }
132
+ for (const [key, caps] of Object.entries(config.reviewCapabilities)) {
133
+ reviewCapabilities.set(key, caps);
134
+ }
135
+ }
136
+
137
+ const allConfigurablePhases = [...orderedPhaseKeys, ...directAgentPhases];
138
+ const allReviewCapabilities = [
139
+ ...new Set([...reviewCapabilities.values()].flat()),
140
+ ];
141
+
142
+ return {
143
+ orderedPhaseKeys,
144
+ phaseCategory,
145
+ directAgentPhases,
146
+ allConfigurablePhases,
147
+ subPhaseToParent,
148
+ reviewCapabilities,
149
+ allReviewCapabilities,
150
+ };
151
+ }
152
+
153
+ /**
154
+ * Resolve a coordinator/sub-phase agent slug to its parent phase key.
155
+ * Returns the slug unchanged when it is itself a base phase or unknown —
156
+ * the same fall-through contract the kernel `resolveParentPhaseKey` had.
157
+ */
158
+ export function resolveParentPhaseKey(
159
+ merged: MergedWorkflowPhaseConfig,
160
+ agentSlug: string,
161
+ ): string {
162
+ return merged.subPhaseToParent.get(agentSlug) ?? agentSlug;
163
+ }
@@ -0,0 +1,39 @@
1
+ export * from './lib/biome-manifest';
2
+ export * from './lib/topology';
3
+ export * from './lib/default-state';
4
+ export * from './lib/system-overlay-contribution';
5
+ export * from './lib/integration-cross-validate';
6
+ export * from './lib/agents-cross-validate';
7
+ export * from './lib/bootstrap-contributions-service';
8
+
9
+ // Kernel-owned XSI types re-exported under the SDK namespace so
10
+ // consumers can write `import { ContributionKind, CapabilityRef,
11
+ // BiomePermissionsManifest, BiomeLifecycleHooks, BiomeEngines } from
12
+ // '@xemahq/biome-host-sdk'`. Kernel-owned; do not redefine here — the
13
+ // authoritative shapes live in `@xemahq/kernel-contracts/contribution`,
14
+ // `@xemahq/kernel-contracts/capability`, and `@xemahq/kernel-contracts/biome`.
15
+ export {
16
+ ContributionKind,
17
+ ContributionKindSchema,
18
+ type ContributionKindValue,
19
+ ContributionSource,
20
+ ContributionSourceSchema,
21
+ type ContributionSourceValue,
22
+ type Contribution,
23
+ type ContributionIngestContext,
24
+ type ContributionKindHandler,
25
+ AnyContributionEnvelopeSchema,
26
+ ContributionSlugSchema,
27
+ } from '@xemahq/kernel-contracts/contribution';
28
+ export {
29
+ type CapabilityRef,
30
+ CapabilityRefSchema,
31
+ } from '@xemahq/kernel-contracts/capability';
32
+ export {
33
+ type BiomeEngines,
34
+ BiomeEnginesSchema,
35
+ type BiomeLifecycleHooks,
36
+ BiomeLifecycleHooksSchema,
37
+ type BiomePermissionsManifest,
38
+ BiomePermissionsManifestSchema,
39
+ } from '@xemahq/kernel-contracts/biome';
@@ -0,0 +1,283 @@
1
+ // ═══════════════════════════════════════════════════════════════════════════
2
+ // ── Agent declarations cross-validator ──
3
+ //
4
+ // Cross-checks a biome's `xema.agents[]` declaration against the on-disk
5
+ // `agents/*.md` files at boot. Sibling of `crossValidateIntegrationContract`
6
+ // — same shape (fail-fast, collect every issue, throw with the full list).
7
+ //
8
+ // Why this exists: prior to the explicit `agents[]` field, the on-disk
9
+ // `agents/` directory scan was the only source of truth for "what agents
10
+ // does this biome ship?". A file added without seeder awareness silently
11
+ // appeared; a deleted file silently disappeared. The manifest declaration
12
+ // makes the roster authoritative and greppable; this validator enforces
13
+ // parity between declaration and disk.
14
+ // ═══════════════════════════════════════════════════════════════════════════
15
+
16
+ import { existsSync, readdirSync, readFileSync, statSync } from 'node:fs';
17
+ import { join } from 'node:path';
18
+
19
+ import type {
20
+ BiomeAgentMode,
21
+ ServerBiomeManifest,
22
+ } from './biome-manifest';
23
+
24
+ /**
25
+ * Convention: agent files live at `<biomeRoot>/agents/<slug>.md`.
26
+ * Kept standalone here so the validator has no circular import back into
27
+ * the schema module.
28
+ */
29
+ const AGENTS_DIR_NAME = 'agents';
30
+
31
+ export class AgentDeclarationCrossValidationError extends Error {
32
+ readonly issues: readonly string[];
33
+ constructor(biomeId: string, issues: readonly string[]) {
34
+ super(
35
+ `biome "${biomeId}": agent-declaration cross-validation failed:\n - ${issues.join('\n - ')}`,
36
+ );
37
+ this.name = 'AgentDeclarationCrossValidationError';
38
+ this.issues = issues;
39
+ }
40
+ }
41
+
42
+ /**
43
+ * Fail-fast invariants:
44
+ *
45
+ * 1. Every declared `agents[].slug` MUST have a matching
46
+ * `<biomeRoot>/agents/<slug>.md` file on disk.
47
+ * 2. Every on-disk `agents/*.md` file MUST appear in `agents[]`.
48
+ * 3. Every declared `agents[].mode` MUST agree with the file's YAML
49
+ * frontmatter `mode:` field. A missing frontmatter mode is accepted
50
+ * only when the declaration says `primary` (matches the legacy
51
+ * seeder default; explicit beats implicit going forward).
52
+ * 4. If the biome does NOT ship the `agents` content kind, neither
53
+ * the declaration nor the directory may exist. (The schema
54
+ * `superRefine` already enforces declaration parity; this catches
55
+ * orphan directories left over from refactors.)
56
+ *
57
+ * The function returns nothing on success and throws
58
+ * `AgentDeclarationCrossValidationError` with the full issue list on
59
+ * failure. Boot continues no further when this throws.
60
+ */
61
+ export function crossValidateAgentDeclarations(
62
+ manifest: ServerBiomeManifest,
63
+ biomeRoot: string,
64
+ ): void {
65
+ const issues: string[] = [];
66
+ const shipsAgents = manifest.xema.ships?.content?.includes('agents') ?? false;
67
+ const declared = manifest.xema.agents ?? [];
68
+ const agentsDir = join(biomeRoot, AGENTS_DIR_NAME);
69
+ const dirExists = existsSync(agentsDir);
70
+
71
+ if (!shipsAgents) {
72
+ if (dirExists) {
73
+ issues.push(
74
+ `agents/ directory exists at ${agentsDir} but the manifest does not ship the "agents" content kind — remove the directory or add "agents" to ships.content`,
75
+ );
76
+ }
77
+ if (issues.length > 0) {
78
+ throw new AgentDeclarationCrossValidationError(manifest.xema.id, issues);
79
+ }
80
+ return;
81
+ }
82
+
83
+ if (!dirExists) {
84
+ throw new AgentDeclarationCrossValidationError(manifest.xema.id, [
85
+ `ships.content includes "agents" but ${agentsDir} does not exist — create the directory and add at least one agents/<slug>.md file`,
86
+ ]);
87
+ }
88
+
89
+ const onDiskSlugs = new Set<string>();
90
+ for (const entry of readdirSync(agentsDir)) {
91
+ if (entry.startsWith('.')) continue;
92
+ if (!entry.endsWith('.md')) continue;
93
+ const abs = join(agentsDir, entry);
94
+ try {
95
+ if (!statSync(abs).isFile()) continue;
96
+ } catch {
97
+ continue;
98
+ }
99
+ onDiskSlugs.add(entry.slice(0, -'.md'.length));
100
+ }
101
+
102
+ const declaredBySlug = new Map<string, BiomeAgentMode>();
103
+ for (const decl of declared) {
104
+ declaredBySlug.set(decl.slug, decl.mode);
105
+ }
106
+
107
+ // (1) Every declared slug must exist on disk.
108
+ for (const decl of declared) {
109
+ if (!onDiskSlugs.has(decl.slug)) {
110
+ issues.push(
111
+ `declared agents[].slug="${decl.slug}" has no matching file at ${join(agentsDir, decl.slug + '.md')}`,
112
+ );
113
+ }
114
+ }
115
+
116
+ // (2) Every on-disk file must be declared.
117
+ for (const slug of onDiskSlugs) {
118
+ if (!declaredBySlug.has(slug)) {
119
+ issues.push(
120
+ `agents/${slug}.md exists on disk but is not declared under agents[] — add { slug: "${slug}", mode: "primary" | "subagent" }`,
121
+ );
122
+ }
123
+ }
124
+
125
+ // (3) Mode parity for files that are both declared AND on-disk.
126
+ for (const decl of declared) {
127
+ if (!onDiskSlugs.has(decl.slug)) continue;
128
+ const filePath = join(agentsDir, decl.slug + '.md');
129
+ let frontmatter: ParsedFrontmatter;
130
+ try {
131
+ frontmatter = readFrontmatter(filePath);
132
+ } catch (err) {
133
+ issues.push(
134
+ `failed to read ${filePath}: ${(err as Error).message}`,
135
+ );
136
+ continue;
137
+ }
138
+ if (frontmatter.mode === null) {
139
+ // Legacy convention: missing frontmatter mode = primary.
140
+ if (decl.mode !== 'primary') {
141
+ issues.push(
142
+ `agents/${decl.slug}.md frontmatter has no "mode:" field (treated as primary by the seeder) but the manifest declares mode="${decl.mode}" — add "mode: ${decl.mode}" to the frontmatter or change the declaration to "primary"`,
143
+ );
144
+ }
145
+ } else if (frontmatter.mode !== decl.mode) {
146
+ issues.push(
147
+ `agents/${decl.slug}.md frontmatter mode="${frontmatter.mode}" does not match manifest declaration mode="${decl.mode}"`,
148
+ );
149
+ }
150
+
151
+ // (5) Description quality: opencode's `task` tool re-uses this
152
+ // verbatim as the "when to use" surface (`registry.ts:260-273`).
153
+ // Sub-agent descriptions ARE the routing prompt — primaries get
154
+ // stricter scrutiny too because the same string lands in agent
155
+ // pickers and audit dashboards. See Phase H of
156
+ // `.claude/plans/runtime-loading-consolidation.md`.
157
+ const descriptionIssue = validateAgentDescription(
158
+ decl.slug,
159
+ frontmatter.description,
160
+ );
161
+ if (descriptionIssue) {
162
+ issues.push(descriptionIssue);
163
+ }
164
+ }
165
+
166
+ if (issues.length > 0) {
167
+ throw new AgentDeclarationCrossValidationError(manifest.xema.id, issues);
168
+ }
169
+ }
170
+
171
+ /**
172
+ * Quality bar for the frontmatter `description:` field.
173
+ *
174
+ * Why these rules: opencode's `task` tool description is composed by
175
+ * iterating every sub-agent's `description:` and printing
176
+ * `"- <slug>: <description>"`. The primary's prompt routes via that
177
+ * surface — a weak description tells the planner literally nothing
178
+ * about when to delegate. The "Agent that…" boilerplate that ChatGPT
179
+ * tends to default to fails the bar twice (low information density,
180
+ * everyone's agents end up sounding identical).
181
+ *
182
+ * - Minimum 40 chars (typical strong description is 60-200).
183
+ * - No leading "Agent that…", "An agent…", "This agent…", "Agent for…".
184
+ */
185
+ const DESCRIPTION_MIN_LENGTH = 40;
186
+ const BANNED_DESCRIPTION_OPENERS = [
187
+ /^\s*agent\s+(that|for|which|to)\b/i,
188
+ /^\s*an\s+agent\b/i,
189
+ /^\s*this\s+agent\b/i,
190
+ ];
191
+
192
+ function validateAgentDescription(
193
+ slug: string,
194
+ description: string | null,
195
+ ): string | null {
196
+ if (description === null) {
197
+ return (
198
+ `agents/${slug}.md frontmatter is missing a "description:" field — ` +
199
+ `opencode's task tool uses this as the "when to use" surface for ` +
200
+ `delegate routing; an empty value silently breaks delegation`
201
+ );
202
+ }
203
+ const trimmed = description.trim();
204
+ if (trimmed.length < DESCRIPTION_MIN_LENGTH) {
205
+ return (
206
+ `agents/${slug}.md description is too short (${trimmed.length} chars, ` +
207
+ `min ${DESCRIPTION_MIN_LENGTH}) — describe the situation a primary ` +
208
+ `agent should delegate to this agent in, not just a label`
209
+ );
210
+ }
211
+ for (const banned of BANNED_DESCRIPTION_OPENERS) {
212
+ if (banned.test(trimmed)) {
213
+ return (
214
+ `agents/${slug}.md description starts with boilerplate matching ${banned} ` +
215
+ `— skip the "Agent that…" preamble and lead with the situation/output`
216
+ );
217
+ }
218
+ }
219
+ return null;
220
+ }
221
+
222
+ const FRONTMATTER_RE = /^---\r?\n([\s\S]*?)\r?\n---/;
223
+ const MODE_LINE_RE = /^\s*mode\s*:\s*(\S+)\s*$/m;
224
+ const DESCRIPTION_LINE_RE = /^\s*description\s*:\s*(.+?)\s*$/m;
225
+
226
+ interface ParsedFrontmatter {
227
+ readonly mode: BiomeAgentMode | null;
228
+ readonly description: string | null;
229
+ }
230
+
231
+ /**
232
+ * Extract the fields we care about from an agent .md file's YAML
233
+ * frontmatter. Returns:
234
+ * - `mode`: `'primary' | 'subagent'`, or `null` when the line is
235
+ * absent (handled by the legacy default in the caller).
236
+ * - `description`: the raw value of `description:` (single-line) or
237
+ * `null` when the line is absent. Block-scalar descriptions (`>`
238
+ * or `|`) are not supported by this minimal parser; agents that
239
+ * want multi-line copy in `description:` would surface as `null`
240
+ * here and fail the description quality gate, which is the
241
+ * intended push to keep delegate-routing copy single-line.
242
+ *
243
+ * Throws on a frontmatter-less file or an unrecognised mode value.
244
+ *
245
+ * Deliberately a minimal regex parser instead of pulling in `js-yaml` —
246
+ * this file is a kernel-tier validator and we want zero runtime deps
247
+ * beyond `node:fs`/`node:path`. The frontmatter format is constrained
248
+ * enough that the regex is unambiguous.
249
+ */
250
+ function readFrontmatter(filePath: string): ParsedFrontmatter {
251
+ const raw = readFileSync(filePath, 'utf8');
252
+ const match = FRONTMATTER_RE.exec(raw);
253
+ if (!match) {
254
+ throw new Error('missing YAML frontmatter (every agent .md must have one)');
255
+ }
256
+ const fm = match[1] ?? '';
257
+ return {
258
+ mode: parseFrontmatterMode(fm),
259
+ description: parseFrontmatterDescription(fm),
260
+ };
261
+ }
262
+
263
+ function parseFrontmatterMode(fm: string): BiomeAgentMode | null {
264
+ const modeMatch = MODE_LINE_RE.exec(fm);
265
+ if (!modeMatch) return null;
266
+ const value = modeMatch[1];
267
+ if (value === 'primary' || value === 'subagent') return value;
268
+ throw new Error(`frontmatter mode="${value}" is not a valid BiomeAgentMode (expected "primary" | "subagent")`);
269
+ }
270
+
271
+ function parseFrontmatterDescription(fm: string): string | null {
272
+ const m = DESCRIPTION_LINE_RE.exec(fm);
273
+ if (!m) return null;
274
+ // Strip surrounding quotes ("…" or '…') the YAML author may have
275
+ // added — `description: "…"` is common and our quality gate counts
276
+ // chars after the strip.
277
+ const raw = m[1] ?? '';
278
+ const quote = raw[0];
279
+ if (raw.length >= 2 && (quote === '"' || quote === "'") && raw.endsWith(quote)) {
280
+ return raw.slice(1, -1);
281
+ }
282
+ return raw;
283
+ }