@bevel-software/platform-core-backend 0.25.2 → 0.27.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (733) hide show
  1. package/agent-guide/access-control.md +251 -0
  2. package/agent-guide/conventions.md +35 -0
  3. package/agent-guide/directory-structure.md +145 -0
  4. package/agent-guide/finding-things.md +7 -0
  5. package/agent-guide/html-views.md +83 -0
  6. package/agent-guide/introduction.md +27 -0
  7. package/agent-guide/new-knowledge-base.md +24 -0
  8. package/agent-guide/skills.md +47 -0
  9. package/agent-guide/tool-manuals.md +227 -0
  10. package/agent-guide/where-a-new-file-goes.md +36 -0
  11. package/dist/assets.d.ts +26 -0
  12. package/dist/assets.d.ts.map +1 -1
  13. package/dist/assets.js +35 -2
  14. package/dist/assets.js.map +1 -1
  15. package/dist/core/catalog-revision.d.ts +19 -1
  16. package/dist/core/catalog-revision.d.ts.map +1 -1
  17. package/dist/core/catalog-revision.js +14 -3
  18. package/dist/core/catalog-revision.js.map +1 -1
  19. package/dist/core/core-ports.d.ts +11 -0
  20. package/dist/core/core-ports.d.ts.map +1 -1
  21. package/dist/core/core-ports.js.map +1 -1
  22. package/dist/core/create-core-server.d.ts +5 -0
  23. package/dist/core/create-core-server.d.ts.map +1 -1
  24. package/dist/core/create-core-server.js +65 -3
  25. package/dist/core/create-core-server.js.map +1 -1
  26. package/dist/core/create-core-services.d.ts +35 -0
  27. package/dist/core/create-core-services.d.ts.map +1 -1
  28. package/dist/core/create-core-services.js +114 -12
  29. package/dist/core/create-core-services.js.map +1 -1
  30. package/dist/core/lifecycle.d.ts +16 -1
  31. package/dist/core/lifecycle.d.ts.map +1 -1
  32. package/dist/core/lifecycle.js +18 -1
  33. package/dist/core/lifecycle.js.map +1 -1
  34. package/dist/core-config.d.ts +21 -0
  35. package/dist/core-config.d.ts.map +1 -1
  36. package/dist/core-config.js +22 -1
  37. package/dist/core-config.js.map +1 -1
  38. package/dist/index.d.ts +1 -1
  39. package/dist/index.d.ts.map +1 -1
  40. package/dist/index.js +2 -2
  41. package/dist/index.js.map +1 -1
  42. package/dist/modules/access/access-control.interface.d.ts +17 -0
  43. package/dist/modules/access/access-control.interface.d.ts.map +1 -1
  44. package/dist/modules/access/access-control.service.d.ts +2 -0
  45. package/dist/modules/access/access-control.service.d.ts.map +1 -1
  46. package/dist/modules/access/access-control.service.js +27 -0
  47. package/dist/modules/access/access-control.service.js.map +1 -1
  48. package/dist/modules/access/directory-sync-bot.js +1 -1
  49. package/dist/modules/access/directory-sync-bot.js.map +1 -1
  50. package/dist/modules/agent-guide/agent-guide.d.ts +145 -0
  51. package/dist/modules/agent-guide/agent-guide.d.ts.map +1 -0
  52. package/dist/modules/agent-guide/agent-guide.js +199 -0
  53. package/dist/modules/agent-guide/agent-guide.js.map +1 -0
  54. package/dist/modules/agent-guide/agent-guide.tools.d.ts +24 -0
  55. package/dist/modules/agent-guide/agent-guide.tools.d.ts.map +1 -0
  56. package/dist/modules/agent-guide/agent-guide.tools.js +100 -0
  57. package/dist/modules/agent-guide/agent-guide.tools.js.map +1 -0
  58. package/dist/modules/agent-guide/index.d.ts +4 -0
  59. package/dist/modules/agent-guide/index.d.ts.map +1 -0
  60. package/dist/modules/agent-guide/index.js +4 -0
  61. package/dist/modules/agent-guide/index.js.map +1 -0
  62. package/dist/modules/agent-instructions/agent-instructions.routes.d.ts +3 -2
  63. package/dist/modules/agent-instructions/agent-instructions.routes.d.ts.map +1 -1
  64. package/dist/modules/agent-instructions/agent-instructions.routes.js +3 -2
  65. package/dist/modules/agent-instructions/agent-instructions.routes.js.map +1 -1
  66. package/dist/modules/agent-instructions/compose.d.ts +14 -6
  67. package/dist/modules/agent-instructions/compose.d.ts.map +1 -1
  68. package/dist/modules/agent-instructions/compose.js +28 -8
  69. package/dist/modules/agent-instructions/compose.js.map +1 -1
  70. package/dist/modules/agent-instructions/index.d.ts +1 -1
  71. package/dist/modules/agent-instructions/index.d.ts.map +1 -1
  72. package/dist/modules/agent-instructions/index.js +1 -1
  73. package/dist/modules/agent-instructions/index.js.map +1 -1
  74. package/dist/modules/agent-instructions/shared-file-rules.d.ts +10 -50
  75. package/dist/modules/agent-instructions/shared-file-rules.d.ts.map +1 -1
  76. package/dist/modules/agent-instructions/shared-file-rules.js +51 -104
  77. package/dist/modules/agent-instructions/shared-file-rules.js.map +1 -1
  78. package/dist/modules/audit/agent-audit.service.d.ts +21 -2
  79. package/dist/modules/audit/agent-audit.service.d.ts.map +1 -1
  80. package/dist/modules/audit/agent-audit.service.js +43 -2
  81. package/dist/modules/audit/agent-audit.service.js.map +1 -1
  82. package/dist/modules/audit/agent-connection.routes.d.ts +34 -0
  83. package/dist/modules/audit/agent-connection.routes.d.ts.map +1 -0
  84. package/dist/modules/audit/agent-connection.routes.js +38 -0
  85. package/dist/modules/audit/agent-connection.routes.js.map +1 -0
  86. package/dist/modules/audit/audit.contract.d.ts +24 -0
  87. package/dist/modules/audit/audit.contract.d.ts.map +1 -1
  88. package/dist/modules/audit/audit.contract.js.map +1 -1
  89. package/dist/modules/audit/index.d.ts +1 -0
  90. package/dist/modules/audit/index.d.ts.map +1 -1
  91. package/dist/modules/audit/index.js +1 -0
  92. package/dist/modules/audit/index.js.map +1 -1
  93. package/dist/modules/auth/account.routes.d.ts.map +1 -1
  94. package/dist/modules/auth/account.routes.js +10 -3
  95. package/dist/modules/auth/account.routes.js.map +1 -1
  96. package/dist/modules/auth/auth.middleware.d.ts +7 -0
  97. package/dist/modules/auth/auth.middleware.d.ts.map +1 -1
  98. package/dist/modules/auth/auth.middleware.js +1 -1
  99. package/dist/modules/auth/auth.middleware.js.map +1 -1
  100. package/dist/modules/code-mode/code-mode.tool.d.ts.map +1 -1
  101. package/dist/modules/code-mode/code-mode.tool.js +11 -3
  102. package/dist/modules/code-mode/code-mode.tool.js.map +1 -1
  103. package/dist/modules/database/core-schema.d.ts +96 -0
  104. package/dist/modules/database/core-schema.d.ts.map +1 -1
  105. package/dist/modules/database/core-schema.js +32 -3
  106. package/dist/modules/database/core-schema.js.map +1 -1
  107. package/dist/modules/embed/account-link.service.d.ts +42 -0
  108. package/dist/modules/embed/account-link.service.d.ts.map +1 -0
  109. package/dist/modules/embed/account-link.service.js +50 -0
  110. package/dist/modules/embed/account-link.service.js.map +1 -0
  111. package/dist/modules/embed/embed-link.d.ts +58 -0
  112. package/dist/modules/embed/embed-link.d.ts.map +1 -0
  113. package/dist/modules/embed/embed-link.js +160 -0
  114. package/dist/modules/embed/embed-link.js.map +1 -0
  115. package/dist/modules/embed/embed.errors.d.ts +30 -0
  116. package/dist/modules/embed/embed.errors.d.ts.map +1 -0
  117. package/dist/modules/embed/embed.errors.js +42 -0
  118. package/dist/modules/embed/embed.errors.js.map +1 -0
  119. package/dist/modules/embed/embed.interface.d.ts +204 -0
  120. package/dist/modules/embed/embed.interface.d.ts.map +1 -0
  121. package/dist/modules/embed/embed.interface.js +2 -0
  122. package/dist/modules/embed/embed.interface.js.map +1 -0
  123. package/dist/modules/embed/embed.routes.d.ts +59 -0
  124. package/dist/modules/embed/embed.routes.d.ts.map +1 -0
  125. package/dist/modules/embed/embed.routes.js +343 -0
  126. package/dist/modules/embed/embed.routes.js.map +1 -0
  127. package/dist/modules/embed/embed.service.d.ts +169 -0
  128. package/dist/modules/embed/embed.service.d.ts.map +1 -0
  129. package/dist/modules/embed/embed.service.js +627 -0
  130. package/dist/modules/embed/embed.service.js.map +1 -0
  131. package/dist/modules/embed/embed.tools.d.ts +51 -0
  132. package/dist/modules/embed/embed.tools.d.ts.map +1 -0
  133. package/dist/modules/embed/embed.tools.js +170 -0
  134. package/dist/modules/embed/embed.tools.js.map +1 -0
  135. package/dist/modules/embed/mcp-app.d.ts +64 -0
  136. package/dist/modules/embed/mcp-app.d.ts.map +1 -0
  137. package/dist/modules/embed/mcp-app.js +147 -0
  138. package/dist/modules/embed/mcp-app.js.map +1 -0
  139. package/dist/modules/embed/mcp-app.routes.d.ts +21 -0
  140. package/dist/modules/embed/mcp-app.routes.d.ts.map +1 -0
  141. package/dist/modules/embed/mcp-app.routes.js +36 -0
  142. package/dist/modules/embed/mcp-app.routes.js.map +1 -0
  143. package/dist/modules/github-app/github-app.connection.d.ts +15 -0
  144. package/dist/modules/github-app/github-app.connection.d.ts.map +1 -1
  145. package/dist/modules/github-app/github-app.connection.js +34 -3
  146. package/dist/modules/github-app/github-app.connection.js.map +1 -1
  147. package/dist/modules/kb-fs/locking-filesystem.d.ts +65 -0
  148. package/dist/modules/kb-fs/locking-filesystem.d.ts.map +1 -1
  149. package/dist/modules/kb-fs/locking-filesystem.js +300 -0
  150. package/dist/modules/kb-fs/locking-filesystem.js.map +1 -1
  151. package/dist/modules/kb-sync/kb-sync.interface.d.ts +5 -0
  152. package/dist/modules/kb-sync/kb-sync.interface.d.ts.map +1 -1
  153. package/dist/modules/kb-sync/kb-sync.service.d.ts.map +1 -1
  154. package/dist/modules/kb-sync/kb-sync.service.js +6 -0
  155. package/dist/modules/kb-sync/kb-sync.service.js.map +1 -1
  156. package/dist/modules/mcp/mcp-auth.middleware.d.ts.map +1 -1
  157. package/dist/modules/mcp/mcp-auth.middleware.js +2 -1
  158. package/dist/modules/mcp/mcp-auth.middleware.js.map +1 -1
  159. package/dist/modules/mcp/mcp.service.d.ts +57 -3
  160. package/dist/modules/mcp/mcp.service.d.ts.map +1 -1
  161. package/dist/modules/mcp/mcp.service.js +177 -24
  162. package/dist/modules/mcp/mcp.service.js.map +1 -1
  163. package/dist/modules/mcp/oauth/bevel-oauth-provider.d.ts +24 -0
  164. package/dist/modules/mcp/oauth/bevel-oauth-provider.d.ts.map +1 -1
  165. package/dist/modules/mcp/oauth/bevel-oauth-provider.js +32 -4
  166. package/dist/modules/mcp/oauth/bevel-oauth-provider.js.map +1 -1
  167. package/dist/modules/mcp/tool-schema-guard.d.ts +105 -0
  168. package/dist/modules/mcp/tool-schema-guard.d.ts.map +1 -0
  169. package/dist/modules/mcp/tool-schema-guard.js +171 -0
  170. package/dist/modules/mcp/tool-schema-guard.js.map +1 -0
  171. package/dist/modules/onboarding/onboarding.contract.d.ts +80 -0
  172. package/dist/modules/onboarding/onboarding.contract.d.ts.map +1 -0
  173. package/dist/modules/onboarding/onboarding.contract.js +7 -0
  174. package/dist/modules/onboarding/onboarding.contract.js.map +1 -0
  175. package/dist/modules/onboarding/onboarding.routes.d.ts +18 -0
  176. package/dist/modules/onboarding/onboarding.routes.d.ts.map +1 -0
  177. package/dist/modules/onboarding/onboarding.routes.js +81 -0
  178. package/dist/modules/onboarding/onboarding.routes.js.map +1 -0
  179. package/dist/modules/onboarding/starter-pack.service.d.ts +213 -0
  180. package/dist/modules/onboarding/starter-pack.service.d.ts.map +1 -0
  181. package/dist/modules/onboarding/starter-pack.service.js +492 -0
  182. package/dist/modules/onboarding/starter-pack.service.js.map +1 -0
  183. package/dist/modules/onboarding/starter-packs.d.ts +78 -0
  184. package/dist/modules/onboarding/starter-packs.d.ts.map +1 -0
  185. package/dist/modules/onboarding/starter-packs.js +156 -0
  186. package/dist/modules/onboarding/starter-packs.js.map +1 -0
  187. package/dist/modules/plugins/index.d.ts +1 -1
  188. package/dist/modules/plugins/index.d.ts.map +1 -1
  189. package/dist/modules/plugins/index.js +1 -1
  190. package/dist/modules/plugins/index.js.map +1 -1
  191. package/dist/modules/plugins/plugin-provision.service.d.ts +19 -0
  192. package/dist/modules/plugins/plugin-provision.service.d.ts.map +1 -1
  193. package/dist/modules/plugins/plugin-provision.service.js +18 -1
  194. package/dist/modules/plugins/plugin-provision.service.js.map +1 -1
  195. package/dist/modules/plugins/plugins.routes.d.ts +0 -36
  196. package/dist/modules/plugins/plugins.routes.d.ts.map +1 -1
  197. package/dist/modules/plugins/plugins.routes.js +31 -0
  198. package/dist/modules/plugins/plugins.routes.js.map +1 -1
  199. package/dist/modules/plugins/plugins.tools.d.ts +36 -2
  200. package/dist/modules/plugins/plugins.tools.d.ts.map +1 -1
  201. package/dist/modules/plugins/plugins.tools.js +71 -14
  202. package/dist/modules/plugins/plugins.tools.js.map +1 -1
  203. package/dist/modules/settings/deployment-settings.service.d.ts +34 -7
  204. package/dist/modules/settings/deployment-settings.service.d.ts.map +1 -1
  205. package/dist/modules/settings/deployment-settings.service.js +148 -54
  206. package/dist/modules/settings/deployment-settings.service.js.map +1 -1
  207. package/dist/modules/settings/repository-source.d.ts +1 -0
  208. package/dist/modules/settings/repository-source.d.ts.map +1 -1
  209. package/dist/modules/settings/repository-source.js +3 -3
  210. package/dist/modules/settings/repository-source.js.map +1 -1
  211. package/dist/modules/settings/setup.routes.d.ts.map +1 -1
  212. package/dist/modules/settings/setup.routes.js +3 -6
  213. package/dist/modules/settings/setup.routes.js.map +1 -1
  214. package/dist/modules/skills/skills.tools.d.ts.map +1 -1
  215. package/dist/modules/skills/skills.tools.js +103 -43
  216. package/dist/modules/skills/skills.tools.js.map +1 -1
  217. package/dist/modules/tool-auth/connection-key-rejection.d.ts +10 -1
  218. package/dist/modules/tool-auth/connection-key-rejection.d.ts.map +1 -1
  219. package/dist/modules/tool-auth/connection-key-rejection.js +11 -3
  220. package/dist/modules/tool-auth/connection-key-rejection.js.map +1 -1
  221. package/dist/modules/tool-auth/external-api-key.interface.d.ts +8 -0
  222. package/dist/modules/tool-auth/external-api-key.interface.d.ts.map +1 -1
  223. package/dist/modules/tool-auth/external-api-key.service.d.ts +24 -2
  224. package/dist/modules/tool-auth/external-api-key.service.d.ts.map +1 -1
  225. package/dist/modules/tool-auth/external-api-key.service.js +59 -2
  226. package/dist/modules/tool-auth/external-api-key.service.js.map +1 -1
  227. package/dist/modules/tool-auth/tool-auth.middleware.d.ts.map +1 -1
  228. package/dist/modules/tool-auth/tool-auth.middleware.js +9 -4
  229. package/dist/modules/tool-auth/tool-auth.middleware.js.map +1 -1
  230. package/dist/modules/tool-helpers/index.d.ts +28 -1
  231. package/dist/modules/tool-helpers/index.d.ts.map +1 -1
  232. package/dist/modules/tool-helpers/index.js +28 -1
  233. package/dist/modules/tool-helpers/index.js.map +1 -1
  234. package/dist/modules/tool-helpers/route-argument-check.d.ts +10 -0
  235. package/dist/modules/tool-helpers/route-argument-check.d.ts.map +1 -0
  236. package/dist/modules/tool-helpers/route-argument-check.js +132 -0
  237. package/dist/modules/tool-helpers/route-argument-check.js.map +1 -0
  238. package/dist/modules/tool-helpers/route-tool-schemas.d.ts +89 -0
  239. package/dist/modules/tool-helpers/route-tool-schemas.d.ts.map +1 -0
  240. package/dist/modules/tool-helpers/route-tool-schemas.js +113 -0
  241. package/dist/modules/tool-helpers/route-tool-schemas.js.map +1 -0
  242. package/dist/modules/tool-helpers/tool-def.d.ts +71 -0
  243. package/dist/modules/tool-helpers/tool-def.d.ts.map +1 -1
  244. package/dist/modules/tool-helpers/tool-def.js +70 -6
  245. package/dist/modules/tool-helpers/tool-def.js.map +1 -1
  246. package/dist/modules/tool-helpers/tool-handler.d.ts +46 -6
  247. package/dist/modules/tool-helpers/tool-handler.d.ts.map +1 -1
  248. package/dist/modules/tool-helpers/tool-handler.js +157 -8
  249. package/dist/modules/tool-helpers/tool-handler.js.map +1 -1
  250. package/dist/modules/tool-helpers/tool.contract.d.ts +9 -0
  251. package/dist/modules/tool-helpers/tool.contract.d.ts.map +1 -1
  252. package/dist/modules/tool-helpers/tool.contract.js.map +1 -1
  253. package/dist/modules/tool-manuals/tool-manuals.contract.d.ts +23 -4
  254. package/dist/modules/tool-manuals/tool-manuals.contract.d.ts.map +1 -1
  255. package/dist/modules/tool-manuals/tool-manuals.contract.js.map +1 -1
  256. package/dist/modules/tool-manuals/tool-manuals.service.d.ts +4 -0
  257. package/dist/modules/tool-manuals/tool-manuals.service.d.ts.map +1 -1
  258. package/dist/modules/tool-manuals/tool-manuals.service.js +14 -0
  259. package/dist/modules/tool-manuals/tool-manuals.service.js.map +1 -1
  260. package/dist/modules/tool-manuals/tool-manuals.tools.d.ts +7 -0
  261. package/dist/modules/tool-manuals/tool-manuals.tools.d.ts.map +1 -1
  262. package/dist/modules/tool-manuals/tool-manuals.tools.js +77 -38
  263. package/dist/modules/tool-manuals/tool-manuals.tools.js.map +1 -1
  264. package/dist/modules/tool-registry/description-length.d.ts +20 -16
  265. package/dist/modules/tool-registry/description-length.d.ts.map +1 -1
  266. package/dist/modules/tool-registry/description-length.js +50 -30
  267. package/dist/modules/tool-registry/description-length.js.map +1 -1
  268. package/dist/modules/tool-registry/guide-first.d.ts +27 -0
  269. package/dist/modules/tool-registry/guide-first.d.ts.map +1 -0
  270. package/dist/modules/tool-registry/guide-first.js +40 -0
  271. package/dist/modules/tool-registry/guide-first.js.map +1 -0
  272. package/dist/modules/tool-registry/tool-registry.d.ts +6 -0
  273. package/dist/modules/tool-registry/tool-registry.d.ts.map +1 -1
  274. package/dist/modules/tool-registry/tool-registry.js +9 -2
  275. package/dist/modules/tool-registry/tool-registry.js.map +1 -1
  276. package/dist/modules/workflow/agent-tools/change-request-read-shape.d.ts +449 -0
  277. package/dist/modules/workflow/agent-tools/change-request-read-shape.d.ts.map +1 -0
  278. package/dist/modules/workflow/agent-tools/change-request-read-shape.js +481 -0
  279. package/dist/modules/workflow/agent-tools/change-request-read-shape.js.map +1 -0
  280. package/dist/modules/workflow/agent-tools/change-request-read.tools.d.ts +126 -0
  281. package/dist/modules/workflow/agent-tools/change-request-read.tools.d.ts.map +1 -0
  282. package/dist/modules/workflow/agent-tools/change-request-read.tools.js +611 -0
  283. package/dist/modules/workflow/agent-tools/change-request-read.tools.js.map +1 -0
  284. package/dist/modules/workflow/agent-tools/change-request-summary.d.ts +12 -1
  285. package/dist/modules/workflow/agent-tools/change-request-summary.d.ts.map +1 -1
  286. package/dist/modules/workflow/agent-tools/change-request-summary.js +5 -1
  287. package/dist/modules/workflow/agent-tools/change-request-summary.js.map +1 -1
  288. package/dist/modules/workflow/agent-tools/workflow.tools.d.ts +8 -1
  289. package/dist/modules/workflow/agent-tools/workflow.tools.d.ts.map +1 -1
  290. package/dist/modules/workflow/agent-tools/workflow.tools.js +133 -37
  291. package/dist/modules/workflow/agent-tools/workflow.tools.js.map +1 -1
  292. package/dist/modules/workflow/file-lock.service.d.ts +29 -5
  293. package/dist/modules/workflow/file-lock.service.d.ts.map +1 -1
  294. package/dist/modules/workflow/file-lock.service.js +62 -5
  295. package/dist/modules/workflow/file-lock.service.js.map +1 -1
  296. package/dist/modules/workflow/git/git.service.d.ts +282 -14
  297. package/dist/modules/workflow/git/git.service.d.ts.map +1 -1
  298. package/dist/modules/workflow/git/git.service.js +627 -126
  299. package/dist/modules/workflow/git/git.service.js.map +1 -1
  300. package/dist/modules/workflow/git/merge-commit.d.ts +73 -0
  301. package/dist/modules/workflow/git/merge-commit.d.ts.map +1 -0
  302. package/dist/modules/workflow/git/merge-commit.js +89 -0
  303. package/dist/modules/workflow/git/merge-commit.js.map +1 -0
  304. package/dist/modules/workflow/git/node-git-runner.d.ts +15 -0
  305. package/dist/modules/workflow/git/node-git-runner.d.ts.map +1 -1
  306. package/dist/modules/workflow/git/node-git-runner.js +78 -6
  307. package/dist/modules/workflow/git/node-git-runner.js.map +1 -1
  308. package/dist/modules/workflow/git/pull-request.service.d.ts +94 -1
  309. package/dist/modules/workflow/git/pull-request.service.d.ts.map +1 -1
  310. package/dist/modules/workflow/git/pull-request.service.js +332 -37
  311. package/dist/modules/workflow/git/pull-request.service.js.map +1 -1
  312. package/dist/modules/workflow/pending-commits.service.d.ts +15 -0
  313. package/dist/modules/workflow/pending-commits.service.d.ts.map +1 -1
  314. package/dist/modules/workflow/pending-commits.service.js +25 -1
  315. package/dist/modules/workflow/pending-commits.service.js.map +1 -1
  316. package/dist/modules/workflow/pending-commits.worker.d.ts +6 -1
  317. package/dist/modules/workflow/pending-commits.worker.d.ts.map +1 -1
  318. package/dist/modules/workflow/pending-commits.worker.js +23 -6
  319. package/dist/modules/workflow/pending-commits.worker.js.map +1 -1
  320. package/dist/modules/workflow/recovery-bot.js +1 -1
  321. package/dist/modules/workflow/recovery-bot.js.map +1 -1
  322. package/dist/modules/workflow/review-workflow/review-workflow.service.d.ts +35 -0
  323. package/dist/modules/workflow/review-workflow/review-workflow.service.d.ts.map +1 -1
  324. package/dist/modules/workflow/review-workflow/review-workflow.service.js +180 -13
  325. package/dist/modules/workflow/review-workflow/review-workflow.service.js.map +1 -1
  326. package/dist/modules/workflow/sanitize-error.d.ts +16 -0
  327. package/dist/modules/workflow/sanitize-error.d.ts.map +1 -1
  328. package/dist/modules/workflow/sanitize-error.js +45 -0
  329. package/dist/modules/workflow/sanitize-error.js.map +1 -1
  330. package/dist/modules/workflow/workflow.routes.d.ts +6 -2
  331. package/dist/modules/workflow/workflow.routes.d.ts.map +1 -1
  332. package/dist/modules/workflow/workflow.routes.js +7 -2
  333. package/dist/modules/workflow/workflow.routes.js.map +1 -1
  334. package/dist/modules/workflow/workflow.service.d.ts +187 -15
  335. package/dist/modules/workflow/workflow.service.d.ts.map +1 -1
  336. package/dist/modules/workflow/workflow.service.js +808 -106
  337. package/dist/modules/workflow/workflow.service.js.map +1 -1
  338. package/dist/modules/workspace/agent-download.builder.d.ts +105 -0
  339. package/dist/modules/workspace/agent-download.builder.d.ts.map +1 -0
  340. package/dist/modules/workspace/agent-download.builder.js +238 -0
  341. package/dist/modules/workspace/agent-download.builder.js.map +1 -0
  342. package/dist/modules/workspace/agent-download.routes.d.ts +77 -0
  343. package/dist/modules/workspace/agent-download.routes.d.ts.map +1 -0
  344. package/dist/modules/workspace/agent-download.routes.js +156 -0
  345. package/dist/modules/workspace/agent-download.routes.js.map +1 -0
  346. package/dist/modules/workspace/agent-download.store.d.ts +225 -0
  347. package/dist/modules/workspace/agent-download.store.d.ts.map +1 -0
  348. package/dist/modules/workspace/agent-download.store.js +423 -0
  349. package/dist/modules/workspace/agent-download.store.js.map +1 -0
  350. package/dist/modules/workspace/agent-upload.store.d.ts +10 -1
  351. package/dist/modules/workspace/agent-upload.store.d.ts.map +1 -1
  352. package/dist/modules/workspace/agent-upload.store.js +16 -6
  353. package/dist/modules/workspace/agent-upload.store.js.map +1 -1
  354. package/dist/modules/workspace/file-readers/raw-mime.d.ts +6 -0
  355. package/dist/modules/workspace/file-readers/raw-mime.d.ts.map +1 -0
  356. package/dist/modules/workspace/file-readers/raw-mime.js +38 -0
  357. package/dist/modules/workspace/file-readers/raw-mime.js.map +1 -0
  358. package/dist/modules/workspace/file-readers/text-reader.d.ts +5 -5
  359. package/dist/modules/workspace/file-readers/text-reader.d.ts.map +1 -1
  360. package/dist/modules/workspace/file-readers/text-reader.js +5 -8
  361. package/dist/modules/workspace/file-readers/text-reader.js.map +1 -1
  362. package/dist/modules/workspace/first-run.d.ts +111 -0
  363. package/dist/modules/workspace/first-run.d.ts.map +1 -0
  364. package/dist/modules/workspace/first-run.js +181 -0
  365. package/dist/modules/workspace/first-run.js.map +1 -0
  366. package/dist/modules/workspace/move-links.d.ts +92 -0
  367. package/dist/modules/workspace/move-links.d.ts.map +1 -0
  368. package/dist/modules/workspace/move-links.js +173 -0
  369. package/dist/modules/workspace/move-links.js.map +1 -0
  370. package/dist/modules/workspace/startup/steps/seed-tree.d.ts.map +1 -1
  371. package/dist/modules/workspace/startup/steps/seed-tree.js +24 -39
  372. package/dist/modules/workspace/startup/steps/seed-tree.js.map +1 -1
  373. package/dist/modules/workspace/startup/steps/template-files.step.d.ts +58 -52
  374. package/dist/modules/workspace/startup/steps/template-files.step.d.ts.map +1 -1
  375. package/dist/modules/workspace/startup/steps/template-files.step.js +209 -223
  376. package/dist/modules/workspace/startup/steps/template-files.step.js.map +1 -1
  377. package/dist/modules/workspace/startup/steps/template-source.d.ts +5 -3
  378. package/dist/modules/workspace/startup/steps/template-source.d.ts.map +1 -1
  379. package/dist/modules/workspace/startup/steps/template-source.js +5 -3
  380. package/dist/modules/workspace/startup/steps/template-source.js.map +1 -1
  381. package/dist/modules/workspace/workspace.routes.d.ts.map +1 -1
  382. package/dist/modules/workspace/workspace.routes.js +63 -22
  383. package/dist/modules/workspace/workspace.routes.js.map +1 -1
  384. package/dist/modules/workspace/workspace.service.d.ts +75 -2
  385. package/dist/modules/workspace/workspace.service.d.ts.map +1 -1
  386. package/dist/modules/workspace/workspace.service.js +197 -24
  387. package/dist/modules/workspace/workspace.service.js.map +1 -1
  388. package/dist/modules/workspace/workspace.tools.d.ts +68 -1
  389. package/dist/modules/workspace/workspace.tools.d.ts.map +1 -1
  390. package/dist/modules/workspace/workspace.tools.js +642 -71
  391. package/dist/modules/workspace/workspace.tools.js.map +1 -1
  392. package/dist/modules/write-access/write-access.d.ts.map +1 -1
  393. package/dist/modules/write-access/write-access.js +9 -0
  394. package/dist/modules/write-access/write-access.js.map +1 -1
  395. package/dist/shared/domain-errors.d.ts +84 -1
  396. package/dist/shared/domain-errors.d.ts.map +1 -1
  397. package/dist/shared/domain-errors.js +100 -12
  398. package/dist/shared/domain-errors.js.map +1 -1
  399. package/dist/shared/git.contract.d.ts +10 -1
  400. package/dist/shared/git.contract.d.ts.map +1 -1
  401. package/dist/shared/git.contract.js.map +1 -1
  402. package/dist/shared/hidden-tools.d.ts +44 -0
  403. package/dist/shared/hidden-tools.d.ts.map +1 -0
  404. package/dist/shared/hidden-tools.js +13 -0
  405. package/dist/shared/hidden-tools.js.map +1 -0
  406. package/dist/shared/utf8-text.d.ts +15 -0
  407. package/dist/shared/utf8-text.d.ts.map +1 -0
  408. package/dist/shared/utf8-text.js +20 -0
  409. package/dist/shared/utf8-text.js.map +1 -0
  410. package/dist/tenancy/static-tenant-source.d.ts +2 -1
  411. package/dist/tenancy/static-tenant-source.d.ts.map +1 -1
  412. package/dist/tenancy/static-tenant-source.js +9 -2
  413. package/dist/tenancy/static-tenant-source.js.map +1 -1
  414. package/kb-template/.bevelignore +0 -5
  415. package/mcp-app/page.html +349 -0
  416. package/migrations/0017_atlassian_account_links.sql +37 -0
  417. package/migrations/meta/0017_snapshot.json +2396 -0
  418. package/migrations/meta/_journal.json +8 -1
  419. package/package.json +6 -3
  420. package/src/__tests__/kb-layout-config.test.ts +10 -100
  421. package/src/__tests__/packaged-assets-ship.test.ts +66 -0
  422. package/src/assets.ts +38 -2
  423. package/src/core/__tests__/catalog-revision.test.ts +40 -0
  424. package/src/core/__tests__/gated-boot.test.ts +1 -0
  425. package/src/core/__tests__/lifecycle.test.ts +14 -0
  426. package/src/core/catalog-revision.ts +15 -2
  427. package/src/core/core-ports.ts +11 -0
  428. package/src/core/create-core-server.ts +78 -3
  429. package/src/core/create-core-services.ts +168 -10
  430. package/src/core/lifecycle.ts +28 -2
  431. package/src/core-config.ts +24 -1
  432. package/src/index.ts +2 -2
  433. package/src/modules/access/__tests__/access-control.atref-batch.test.ts +58 -0
  434. package/src/modules/access/__tests__/access-control.platform-restore.test.ts +8 -7
  435. package/src/modules/access/__tests__/access-control.service.test.ts +19 -0
  436. package/src/modules/access/__tests__/access-personal-plugin.test.ts +1 -18
  437. package/src/modules/access/access-control.interface.ts +28 -0
  438. package/src/modules/access/access-control.service.ts +37 -0
  439. package/src/modules/access/directory-sync-bot.ts +1 -1
  440. package/src/modules/agent-guide/__tests__/agent-guide.test.ts +386 -0
  441. package/src/modules/agent-guide/__tests__/agent-guide.tools.test.ts +207 -0
  442. package/src/modules/agent-guide/agent-guide.tools.ts +122 -0
  443. package/src/modules/agent-guide/agent-guide.ts +300 -0
  444. package/src/modules/agent-guide/index.ts +22 -0
  445. package/src/modules/agent-instructions/__tests__/shared-file-rules.test.ts +39 -118
  446. package/src/modules/agent-instructions/agent-instructions.routes.ts +3 -2
  447. package/src/modules/agent-instructions/compose.ts +26 -8
  448. package/src/modules/agent-instructions/index.ts +0 -3
  449. package/src/modules/agent-instructions/shared-file-rules.ts +50 -112
  450. package/src/modules/audit/__tests__/agent-audit.service.test.ts +64 -4
  451. package/src/modules/audit/__tests__/agent-connection.routes.test.ts +102 -0
  452. package/src/modules/audit/agent-audit.service.ts +58 -3
  453. package/src/modules/audit/agent-connection.routes.ts +56 -0
  454. package/src/modules/audit/audit.contract.ts +26 -0
  455. package/src/modules/audit/index.ts +1 -0
  456. package/src/modules/auth/__tests__/account.routes.test.ts +5 -3
  457. package/src/modules/auth/account.routes.ts +10 -3
  458. package/src/modules/auth/auth.middleware.ts +1 -1
  459. package/src/modules/code-mode/__tests__/code-mode.tool.test.ts +18 -2
  460. package/src/modules/code-mode/code-mode.tool.ts +13 -2
  461. package/src/modules/database/core-schema.ts +33 -3
  462. package/src/modules/embed/__tests__/account-links.migration.test.ts +98 -0
  463. package/src/modules/embed/__tests__/embed-link.test.ts +122 -0
  464. package/src/modules/embed/__tests__/embed.routes.test.ts +362 -0
  465. package/src/modules/embed/__tests__/embed.service.lock.test.ts +193 -0
  466. package/src/modules/embed/__tests__/embed.service.test.ts +805 -0
  467. package/src/modules/embed/__tests__/embed.tools.test.ts +304 -0
  468. package/src/modules/embed/__tests__/mcp-app.test.ts +207 -0
  469. package/src/modules/embed/account-link.service.ts +76 -0
  470. package/src/modules/embed/embed-link.ts +180 -0
  471. package/src/modules/embed/embed.errors.ts +43 -0
  472. package/src/modules/embed/embed.interface.ts +203 -0
  473. package/src/modules/embed/embed.routes.ts +363 -0
  474. package/src/modules/embed/embed.service.ts +705 -0
  475. package/src/modules/embed/embed.tools.ts +206 -0
  476. package/src/modules/embed/mcp-app.routes.ts +41 -0
  477. package/src/modules/embed/mcp-app.ts +173 -0
  478. package/src/modules/github-app/__tests__/github-app.test.ts +76 -0
  479. package/src/modules/github-app/github-app.connection.ts +38 -4
  480. package/src/modules/kb-fs/__tests__/move-with-edits.test.ts +304 -0
  481. package/src/modules/kb-fs/locking-filesystem.ts +287 -0
  482. package/src/modules/kb-sync/__tests__/kb-sync.service.test.ts +35 -0
  483. package/src/modules/kb-sync/kb-sync.interface.ts +2 -0
  484. package/src/modules/kb-sync/kb-sync.service.ts +6 -0
  485. package/src/modules/mcp/__tests__/bevel-oauth-provider.test.ts +68 -11
  486. package/src/modules/mcp/__tests__/fake-downstream-mcp-server.ts +14 -3
  487. package/src/modules/mcp/__tests__/mcp-proxy-helpers.test.ts +37 -2
  488. package/src/modules/mcp/__tests__/mcp.app.e2e.test.ts +200 -0
  489. package/src/modules/mcp/__tests__/mcp.e2e.test.ts +252 -0
  490. package/src/modules/mcp/__tests__/mcp.service.test.ts +42 -24
  491. package/src/modules/mcp/__tests__/tool-call-interface.e2e.test.ts +499 -0
  492. package/src/modules/mcp/__tests__/tool-schema-guard.test.ts +266 -0
  493. package/src/modules/mcp/mcp-auth.middleware.ts +2 -1
  494. package/src/modules/mcp/mcp.service.ts +218 -31
  495. package/src/modules/mcp/oauth/bevel-oauth-provider.ts +42 -4
  496. package/src/modules/mcp/tool-schema-guard.ts +196 -0
  497. package/src/modules/onboarding/__tests__/onboarding.routes.test.ts +163 -0
  498. package/src/modules/onboarding/__tests__/starter-pack.service.test.ts +635 -0
  499. package/src/modules/onboarding/__tests__/starter-packs.test.ts +169 -0
  500. package/src/modules/onboarding/onboarding.contract.ts +85 -0
  501. package/src/modules/onboarding/onboarding.routes.ts +85 -0
  502. package/src/modules/onboarding/starter-pack.service.ts +580 -0
  503. package/src/modules/onboarding/starter-packs.ts +182 -0
  504. package/src/modules/plugins/__tests__/plugins.tools.test.ts +177 -4
  505. package/src/modules/plugins/index.ts +1 -0
  506. package/src/modules/plugins/plugin-provision.service.ts +22 -1
  507. package/src/modules/plugins/plugins.routes.ts +29 -0
  508. package/src/modules/plugins/plugins.tools.ts +75 -15
  509. package/src/modules/settings/__tests__/deployment-settings.service.test.ts +176 -56
  510. package/src/modules/settings/__tests__/repository-source.test.ts +9 -0
  511. package/src/modules/settings/deployment-settings.service.ts +144 -55
  512. package/src/modules/settings/repository-source.ts +4 -4
  513. package/src/modules/settings/setup.routes.ts +3 -6
  514. package/src/modules/skills/__tests__/skills.tools.description.test.ts +95 -0
  515. package/src/modules/skills/skills.tools.ts +112 -46
  516. package/src/modules/tool-auth/__tests__/connection-key-rejection.test.ts +32 -0
  517. package/src/modules/tool-auth/__tests__/external-api-key.service.test.ts +65 -0
  518. package/src/modules/tool-auth/connection-key-rejection.ts +13 -3
  519. package/src/modules/tool-auth/external-api-key.interface.ts +9 -0
  520. package/src/modules/tool-auth/external-api-key.service.ts +61 -4
  521. package/src/modules/tool-auth/tool-auth.middleware.ts +13 -4
  522. package/src/modules/tool-helpers/__tests__/branch-declaration.test.ts +502 -0
  523. package/src/modules/tool-helpers/__tests__/route-argument-check.test.ts +337 -0
  524. package/src/modules/tool-helpers/index.ts +34 -1
  525. package/src/modules/tool-helpers/route-argument-check.ts +149 -0
  526. package/src/modules/tool-helpers/route-tool-schemas.ts +171 -0
  527. package/src/modules/tool-helpers/tool-def.ts +132 -7
  528. package/src/modules/tool-helpers/tool-handler.ts +196 -8
  529. package/src/modules/tool-helpers/tool.contract.ts +9 -0
  530. package/src/modules/tool-manuals/__tests__/tool-manuals.detail.route.test.ts +57 -0
  531. package/src/modules/tool-manuals/__tests__/tool-manuals.tools.test.ts +73 -4
  532. package/src/modules/tool-manuals/tool-manuals.contract.ts +24 -4
  533. package/src/modules/tool-manuals/tool-manuals.service.ts +17 -0
  534. package/src/modules/tool-manuals/tool-manuals.tools.ts +86 -38
  535. package/src/modules/tool-registry/__tests__/own-tool-schemas.test.ts +173 -0
  536. package/src/modules/tool-registry/__tests__/tool-description-length.test.ts +81 -66
  537. package/src/modules/tool-registry/description-length.ts +57 -32
  538. package/src/modules/tool-registry/guide-first.ts +41 -0
  539. package/src/modules/tool-registry/tool-registry.ts +9 -2
  540. package/src/modules/workflow/__tests__/apply-failure.test.ts +6 -1
  541. package/src/modules/workflow/__tests__/file-lock.service.deletion-gate.test.ts +104 -0
  542. package/src/modules/workflow/__tests__/pending-commits.repository-replaced.test.ts +66 -0
  543. package/src/modules/workflow/__tests__/pending-commits.worker.test.ts +31 -2
  544. package/src/modules/workflow/__tests__/preserve-roles-yaml.test.ts +110 -6
  545. package/src/modules/workflow/__tests__/sanitize-error.test.ts +89 -1
  546. package/src/modules/workflow/__tests__/workflow.routes.push-refused.test.ts +202 -0
  547. package/src/modules/workflow/__tests__/workflow.service.branch-in-use.test.ts +6 -6
  548. package/src/modules/workflow/__tests__/workflow.service.delete-branch.test.ts +1026 -0
  549. package/src/modules/workflow/__tests__/workflow.service.facade.test.ts +468 -10
  550. package/src/modules/workflow/__tests__/workflow.service.folder-proposals.test.ts +4 -0
  551. package/src/modules/workflow/__tests__/workflow.service.releaseLock.test.ts +5 -4
  552. package/src/modules/workflow/__tests__/workflow.service.update-from-target.test.ts +54 -2
  553. package/src/modules/workflow/agent-tools/__tests__/change-request-read-shape.test.ts +705 -0
  554. package/src/modules/workflow/agent-tools/__tests__/change-request-read.tools.test.ts +1554 -0
  555. package/src/modules/workflow/agent-tools/__tests__/workflow.tools.test.ts +150 -4
  556. package/src/modules/workflow/agent-tools/change-request-read-shape.ts +712 -0
  557. package/src/modules/workflow/agent-tools/change-request-read.tools.ts +759 -0
  558. package/src/modules/workflow/agent-tools/change-request-summary.ts +5 -1
  559. package/src/modules/workflow/agent-tools/workflow.tools.ts +137 -35
  560. package/src/modules/workflow/file-lock.service.ts +67 -5
  561. package/src/modules/workflow/git/__tests__/git.service.appliedChange.test.ts +285 -0
  562. package/src/modules/workflow/git/__tests__/git.service.changedFilesForPr.test.ts +124 -0
  563. package/src/modules/workflow/git/__tests__/git.service.deleteBranch.test.ts +164 -0
  564. package/src/modules/workflow/git/__tests__/git.service.mergeChangeRequest.test.ts +334 -0
  565. package/src/modules/workflow/git/__tests__/git.service.pull.test.ts +48 -1
  566. package/src/modules/workflow/git/__tests__/node-git-runner.test.ts +231 -2
  567. package/src/modules/workflow/git/__tests__/pull-request.service.list-fetch.test.ts +72 -2
  568. package/src/modules/workflow/git/__tests__/pull-request.service.placeholder.test.ts +24 -2
  569. package/src/modules/workflow/git/__tests__/pull-request.service.test.ts +620 -1
  570. package/src/modules/workflow/git/git.service.ts +714 -133
  571. package/src/modules/workflow/git/merge-commit.ts +88 -0
  572. package/src/modules/workflow/git/node-git-runner.ts +82 -7
  573. package/src/modules/workflow/git/pull-request.service.ts +380 -54
  574. package/src/modules/workflow/pending-commits.service.ts +29 -1
  575. package/src/modules/workflow/pending-commits.worker.ts +24 -6
  576. package/src/modules/workflow/recovery-bot.ts +1 -1
  577. package/src/modules/workflow/review-workflow/__tests__/approval-states.test.ts +7 -1
  578. package/src/modules/workflow/review-workflow/__tests__/merge-records-own-commit.test.ts +407 -0
  579. package/src/modules/workflow/review-workflow/review-workflow.service.ts +191 -12
  580. package/src/modules/workflow/sanitize-error.ts +50 -0
  581. package/src/modules/workflow/workflow.routes.ts +7 -2
  582. package/src/modules/workflow/workflow.service.ts +886 -112
  583. package/src/modules/workspace/__tests__/agent-downloads.test.ts +823 -0
  584. package/src/modules/workspace/__tests__/escape-sequences.routes.test.ts +4 -3
  585. package/src/modules/workspace/__tests__/first-run.test.ts +234 -0
  586. package/src/modules/workspace/__tests__/git-internals.security.test.ts +5 -2
  587. package/src/modules/workspace/__tests__/md-links.test.ts +353 -0
  588. package/src/modules/workspace/__tests__/move-links.test.ts +261 -0
  589. package/src/modules/workspace/__tests__/rest-tool-arguments.test.ts +219 -0
  590. package/src/modules/workspace/__tests__/workspace-paths-inside-the-repo.test.ts +3 -0
  591. package/src/modules/workspace/__tests__/workspace.routes.delete.test.ts +102 -0
  592. package/src/modules/workspace/__tests__/workspace.routes.download.test.ts +52 -5
  593. package/src/modules/workspace/__tests__/workspace.routes.folder-zip-access.test.ts +190 -0
  594. package/src/modules/workspace/__tests__/workspace.routes.move-platform-files.test.ts +21 -10
  595. package/src/modules/workspace/__tests__/workspace.service.forget-clone-races.test.ts +8 -4
  596. package/src/modules/workspace/__tests__/workspace.service.test.ts +50 -8
  597. package/src/modules/workspace/__tests__/workspace.tools.agents-file.test.ts +33 -55
  598. package/src/modules/workspace/__tests__/workspace.tools.branch-errors.test.ts +44 -1
  599. package/src/modules/workspace/__tests__/workspace.tools.test.ts +664 -34
  600. package/src/modules/workspace/agent-download.builder.ts +308 -0
  601. package/src/modules/workspace/agent-download.routes.ts +183 -0
  602. package/src/modules/workspace/agent-download.store.ts +533 -0
  603. package/src/modules/workspace/agent-upload.store.ts +23 -7
  604. package/src/modules/workspace/file-readers/raw-mime.ts +40 -0
  605. package/src/modules/workspace/file-readers/text-reader.ts +5 -8
  606. package/src/modules/workspace/first-run.ts +222 -0
  607. package/src/modules/workspace/move-links.ts +237 -0
  608. package/src/modules/workspace/startup/steps/__tests__/steps.test.ts +191 -489
  609. package/src/modules/workspace/startup/steps/seed-tree.ts +23 -38
  610. package/src/modules/workspace/startup/steps/template-files.step.ts +217 -249
  611. package/src/modules/workspace/startup/steps/template-source.ts +5 -3
  612. package/src/modules/workspace/workspace.routes.ts +64 -22
  613. package/src/modules/workspace/workspace.service.ts +202 -25
  614. package/src/modules/workspace/workspace.tools.ts +707 -68
  615. package/src/modules/write-access/__tests__/write-access.test.ts +13 -0
  616. package/src/modules/write-access/write-access.ts +9 -0
  617. package/src/shared/domain-errors.ts +123 -11
  618. package/src/shared/git.contract.ts +8 -1
  619. package/src/shared/hidden-tools.ts +45 -0
  620. package/src/shared/utf8-text.ts +21 -0
  621. package/src/tenancy/__tests__/static-tenant-source.test.ts +1 -0
  622. package/src/tenancy/static-tenant-source.ts +10 -2
  623. package/starter-packs/README.md +103 -0
  624. package/starter-packs/engineering/KnowledgeBase/About us.md +9 -0
  625. package/starter-packs/engineering/KnowledgeBase/Architecture.md +9 -0
  626. package/starter-packs/engineering/KnowledgeBase/Glossary.md +9 -0
  627. package/starter-packs/engineering/KnowledgeBase/How we ship.md +9 -0
  628. package/starter-packs/engineering/Plugins/engineering-starter/LICENSE +21 -0
  629. package/starter-packs/engineering/Plugins/engineering-starter/SOURCE.md +20 -0
  630. package/starter-packs/engineering/Plugins/engineering-starter/access.md +19 -0
  631. package/starter-packs/engineering/Plugins/engineering-starter/plugin.json +10 -0
  632. package/starter-packs/engineering/Plugins/engineering-starter/skills/office-hours/SKILL.md +171 -0
  633. package/starter-packs/engineering/Plugins/engineering-starter/skills/office-hours/sections/phase-2a-startup-diagnostic.md +157 -0
  634. package/starter-packs/engineering/Plugins/engineering-starter/skills/office-hours/sections/phase-2b-builder-brainstorm.md +39 -0
  635. package/starter-packs/engineering/Plugins/engineering-starter/skills/plan-ceo-review/SKILL.md +144 -0
  636. package/starter-packs/engineering/Plugins/engineering-starter/skills/plan-eng-review/SKILL.md +144 -0
  637. package/starter-packs/engineering/Plugins/engineering-starter/skills/review/SKILL.md +80 -0
  638. package/starter-packs/engineering/Plugins/engineering-starter/skills/review/checklist.md +184 -0
  639. package/starter-packs/engineering/pack.yaml +11 -0
  640. package/starter-packs/general/KnowledgeBase/About us.md +9 -0
  641. package/starter-packs/general/KnowledgeBase/Glossary.md +9 -0
  642. package/starter-packs/general/KnowledgeBase/How we work.md +9 -0
  643. package/starter-packs/general/Plugins/general-starter/LICENSE +202 -0
  644. package/starter-packs/general/Plugins/general-starter/SOURCE.md +10 -0
  645. package/starter-packs/general/Plugins/general-starter/access.md +19 -0
  646. package/starter-packs/general/Plugins/general-starter/plugin.json +10 -0
  647. package/starter-packs/general/Plugins/general-starter/skills/memory-management/SKILL.md +332 -0
  648. package/starter-packs/general/Plugins/general-starter/skills/productivity-start/SKILL.md +163 -0
  649. package/starter-packs/general/Plugins/general-starter/skills/productivity-update/SKILL.md +167 -0
  650. package/starter-packs/general/Plugins/general-starter/skills/task-management/SKILL.md +83 -0
  651. package/starter-packs/general/pack.yaml +10 -0
  652. package/starter-packs/operations/KnowledgeBase/Glossary.md +9 -0
  653. package/starter-packs/operations/KnowledgeBase/How we work.md +9 -0
  654. package/starter-packs/operations/KnowledgeBase/Processes.md +9 -0
  655. package/starter-packs/operations/KnowledgeBase/Tools we use.md +9 -0
  656. package/starter-packs/operations/KnowledgeBase/Vendors.md +9 -0
  657. package/starter-packs/operations/Plugins/operations-starter/LICENSE +202 -0
  658. package/starter-packs/operations/Plugins/operations-starter/SOURCE.md +10 -0
  659. package/starter-packs/operations/Plugins/operations-starter/access.md +19 -0
  660. package/starter-packs/operations/Plugins/operations-starter/plugin.json +10 -0
  661. package/starter-packs/operations/Plugins/operations-starter/skills/capacity-plan/SKILL.md +111 -0
  662. package/starter-packs/operations/Plugins/operations-starter/skills/change-request/SKILL.md +119 -0
  663. package/starter-packs/operations/Plugins/operations-starter/skills/compliance-tracking/SKILL.md +44 -0
  664. package/starter-packs/operations/Plugins/operations-starter/skills/process-doc/SKILL.md +80 -0
  665. package/starter-packs/operations/Plugins/operations-starter/skills/process-optimization/SKILL.md +39 -0
  666. package/starter-packs/operations/Plugins/operations-starter/skills/risk-assessment/SKILL.md +40 -0
  667. package/starter-packs/operations/Plugins/operations-starter/skills/runbook/SKILL.md +85 -0
  668. package/starter-packs/operations/Plugins/operations-starter/skills/status-report/SKILL.md +75 -0
  669. package/starter-packs/operations/Plugins/operations-starter/skills/vendor-review/SKILL.md +102 -0
  670. package/starter-packs/operations/pack.yaml +12 -0
  671. package/starter-packs/sales/KnowledgeBase/About us.md +9 -0
  672. package/starter-packs/sales/KnowledgeBase/Customers.md +9 -0
  673. package/starter-packs/sales/KnowledgeBase/Glossary.md +9 -0
  674. package/starter-packs/sales/KnowledgeBase/How we sell.md +9 -0
  675. package/starter-packs/sales/KnowledgeBase/Objections.md +9 -0
  676. package/starter-packs/sales/KnowledgeBase/Pricing.md +9 -0
  677. package/starter-packs/sales/Plugins/sales-starter/LICENSE +202 -0
  678. package/starter-packs/sales/Plugins/sales-starter/SOURCE.md +10 -0
  679. package/starter-packs/sales/Plugins/sales-starter/access.md +19 -0
  680. package/starter-packs/sales/Plugins/sales-starter/plugin.json +10 -0
  681. package/starter-packs/sales/Plugins/sales-starter/skills/account-context/SKILL.md +94 -0
  682. package/starter-packs/sales/Plugins/sales-starter/skills/account-plan/SKILL.md +95 -0
  683. package/starter-packs/sales/Plugins/sales-starter/skills/account-research/SKILL.md +99 -0
  684. package/starter-packs/sales/Plugins/sales-starter/skills/account-tiering/SKILL.md +101 -0
  685. package/starter-packs/sales/Plugins/sales-starter/skills/call-prep/SKILL.md +111 -0
  686. package/starter-packs/sales/Plugins/sales-starter/skills/call-summary/SKILL.md +111 -0
  687. package/starter-packs/sales/Plugins/sales-starter/skills/close-plan/SKILL.md +106 -0
  688. package/starter-packs/sales/Plugins/sales-starter/skills/competitive-intelligence/SKILL.md +102 -0
  689. package/starter-packs/sales/Plugins/sales-starter/skills/create-an-asset/SKILL.md +105 -0
  690. package/starter-packs/sales/Plugins/sales-starter/skills/crm-hygiene-check/SKILL.md +103 -0
  691. package/starter-packs/sales/Plugins/sales-starter/skills/customer-health/SKILL.md +108 -0
  692. package/starter-packs/sales/Plugins/sales-starter/skills/customer-voice/SKILL.md +94 -0
  693. package/starter-packs/sales/Plugins/sales-starter/skills/daily-briefing/SKILL.md +61 -0
  694. package/starter-packs/sales/Plugins/sales-starter/skills/deal-advance-gap/SKILL.md +102 -0
  695. package/starter-packs/sales/Plugins/sales-starter/skills/deal-review/SKILL.md +105 -0
  696. package/starter-packs/sales/Plugins/sales-starter/skills/deal-signals/SKILL.md +96 -0
  697. package/starter-packs/sales/Plugins/sales-starter/skills/deal-slip-scenario/SKILL.md +104 -0
  698. package/starter-packs/sales/Plugins/sales-starter/skills/draft-outreach/SKILL.md +116 -0
  699. package/starter-packs/sales/Plugins/sales-starter/skills/end-of-day/SKILL.md +114 -0
  700. package/starter-packs/sales/Plugins/sales-starter/skills/expansion-whitespace/SKILL.md +97 -0
  701. package/starter-packs/sales/Plugins/sales-starter/skills/forecast/SKILL.md +100 -0
  702. package/starter-packs/sales/Plugins/sales-starter/skills/handle-objection/SKILL.md +93 -0
  703. package/starter-packs/sales/Plugins/sales-starter/skills/inbox-sweep/SKILL.md +114 -0
  704. package/starter-packs/sales/Plugins/sales-starter/skills/lead-triage/SKILL.md +106 -0
  705. package/starter-packs/sales/Plugins/sales-starter/skills/log-activity/SKILL.md +111 -0
  706. package/starter-packs/sales/Plugins/sales-starter/skills/pipeline-review/SKILL.md +97 -0
  707. package/starter-packs/sales/Plugins/sales-starter/skills/renewal-radar/SKILL.md +95 -0
  708. package/starter-packs/sales/Plugins/sales-starter/skills/rep-context/SKILL.md +90 -0
  709. package/starter-packs/sales/Plugins/sales-starter/skills/route-lead/SKILL.md +111 -0
  710. package/starter-packs/sales/Plugins/sales-starter/skills/sales-setup/SKILL.md +200 -0
  711. package/starter-packs/sales/Plugins/sales-starter/skills/schedule-meeting/SKILL.md +99 -0
  712. package/starter-packs/sales/Plugins/sales-starter/skills/stakeholder-map/SKILL.md +107 -0
  713. package/starter-packs/sales/Plugins/sales-starter/skills/team-pipeline/SKILL.md +105 -0
  714. package/starter-packs/sales/Plugins/sales-starter/skills/update-opportunity/SKILL.md +112 -0
  715. package/starter-packs/sales/Plugins/sales-starter/skills/weekly-wrap/SKILL.md +90 -0
  716. package/starter-packs/sales/Plugins/sales-starter/skills/win-loss-review/SKILL.md +88 -0
  717. package/starter-packs/sales/pack.yaml +13 -0
  718. package/starter-packs/support/KnowledgeBase/Escalations.md +9 -0
  719. package/starter-packs/support/KnowledgeBase/Glossary.md +9 -0
  720. package/starter-packs/support/KnowledgeBase/Known issues.md +9 -0
  721. package/starter-packs/support/KnowledgeBase/Products.md +9 -0
  722. package/starter-packs/support/KnowledgeBase/Tone of voice.md +9 -0
  723. package/starter-packs/support/Plugins/support-starter/LICENSE +202 -0
  724. package/starter-packs/support/Plugins/support-starter/SOURCE.md +10 -0
  725. package/starter-packs/support/Plugins/support-starter/access.md +19 -0
  726. package/starter-packs/support/Plugins/support-starter/plugin.json +10 -0
  727. package/starter-packs/support/Plugins/support-starter/skills/customer-escalation/SKILL.md +246 -0
  728. package/starter-packs/support/Plugins/support-starter/skills/customer-research/SKILL.md +250 -0
  729. package/starter-packs/support/Plugins/support-starter/skills/draft-response/SKILL.md +416 -0
  730. package/starter-packs/support/Plugins/support-starter/skills/kb-article/SKILL.md +350 -0
  731. package/starter-packs/support/Plugins/support-starter/skills/ticket-triage/SKILL.md +273 -0
  732. package/starter-packs/support/pack.yaml +12 -0
  733. package/kb-template/AGENTS.md +0 -730
@@ -1,11 +1,12 @@
1
1
  import { describe, it, expect, vi, beforeEach } from 'vitest';
2
2
  import type { PullRequestSummary } from '@bevel-software/platform-shared';
3
- import { PullRequestService } from '../pull-request.service.js';
3
+ import { PullRequestService, changeSourceFor } from '../pull-request.service.js';
4
4
  import type { GitService } from '../git.service.js';
5
5
  import type { Database } from '../../../database/connection.js';
6
6
  import type { WorkspaceService } from '../../../workspace/workspace.service.js';
7
7
  import type { IAccessControl } from '../../../access/access-control.interface.js';
8
8
  import { hashEmail as hash } from '../../../../shared/email-identity.js';
9
+ import { AppliedChangeMismatchError, WorkflowValidationError } from '../../../../shared/domain-errors.js';
9
10
 
10
11
  function pr(overrides: Partial<PullRequestSummary>): PullRequestSummary {
11
12
  return {
@@ -37,6 +38,7 @@ function makeAccessControl(byRef: WritersByRefAndPath): IAccessControl {
37
38
  canReadBatch: async () => new Map(),
38
39
  eligibleReaders: async () => ({ restricted: false, roles: [], users: [] }),
39
40
  canReadAtRef: async () => null,
41
+ canReadBatchAtRef: async () => null,
40
42
  canDownload: async () => false,
41
43
  canOwner: async () => false,
42
44
  eligibleOwners: async () => ({ roles: [], users: [] }),
@@ -222,3 +224,620 @@ describe('PullRequestService.listPrsForOwnerEmail', () => {
222
224
  expect(fetchSpy).not.toHaveBeenCalled();
223
225
  });
224
226
  });
227
+
228
+ /**
229
+ * `listPrsByState` — what the agent read tools call so a reader can catch up on
230
+ * requests that have already been applied or declined. The open-only path is
231
+ * delegated (and keeps its cache); every other state set is read from the table.
232
+ */
233
+ describe('PullRequestService.listPrsByState', () => {
234
+ /** The merge commit an applied row records, and the one its diff is read from. */
235
+ const MERGE_SHA = 'a'.repeat(40);
236
+
237
+ /** A `change_requests` row as drizzle hands it back. */
238
+ function row(over: Record<string, unknown> = {}): Record<string, unknown> {
239
+ return {
240
+ number: 1,
241
+ sourceBranch: 'feature/x',
242
+ targetBranch: 'main',
243
+ title: 'A proposal',
244
+ body: 'why',
245
+ authorEmail: 'juan@bevel.software',
246
+ authorName: 'Juan',
247
+ state: 'merged',
248
+ mergedSha: MERGE_SHA,
249
+ createdAt: new Date('2026-04-01T00:00:00Z'),
250
+ updatedAt: null,
251
+ closedAt: new Date('2026-04-03T09:30:00Z'),
252
+ applyFailureReason: null,
253
+ applyFailureConflicts: null,
254
+ applyFailedAt: null,
255
+ applyFailedByName: null,
256
+ applyFailureKind: null,
257
+ closedReason: null,
258
+ ...over,
259
+ };
260
+ }
261
+
262
+ /** The service over a drizzle-shaped select that answers `rows`. */
263
+ function svcOver(rows: Record<string, unknown>[], changedPaths: string[] = []) {
264
+ const orderBy = vi.fn(async () => rows);
265
+ const select = vi.fn(() => ({ from: () => ({ where: () => ({ orderBy }) }) }));
266
+ const db = { select } as unknown as Database;
267
+ const answer = (paths: string[]) => ({ paths, pairs: paths.map((path) => ({ path })) });
268
+ const ensureRemotesFetched = vi.fn(async () => undefined);
269
+ const workspace = {
270
+ ensureRemotesFetched,
271
+ findAnyWorkspaceId: async () => 'ws',
272
+ } as unknown as WorkspaceService;
273
+ // Both diff paths are stubbed, so a test can prove WHICH one a row's state
274
+ // took — the point of the routing, and of the finding behind it.
275
+ const forPr = vi.fn(async () => answer(changedPaths));
276
+ const atCommit = vi.fn(async () => answer(changedPaths));
277
+ const git = {
278
+ changedPathsAndPairsForPr: forPr,
279
+ changedPathsAndPairsOfAppliedChange: atCommit,
280
+ } as unknown as GitService;
281
+ const svc = new PullRequestService(db, workspace, makeAccessControl({}), git);
282
+ return { svc, select, forPr, atCommit, ensureRemotesFetched };
283
+ }
284
+
285
+ beforeEach(() => {
286
+ vi.restoreAllMocks();
287
+ });
288
+
289
+ it('delegates the open-only case so the list the app polls keeps its cache', async () => {
290
+ const { svc, select } = svcOver([]);
291
+ const open = [pr({ number: 7 })];
292
+ const spy = vi.spyOn(svc, 'listOpenPrs').mockResolvedValue(open);
293
+ expect(await svc.listPrsByState(['open'])).toBe(open);
294
+ expect(await svc.listPrsByState(['open', 'open'])).toBe(open);
295
+ expect(spy).toHaveBeenCalledTimes(2);
296
+ expect(select).not.toHaveBeenCalled();
297
+ });
298
+
299
+ it('answers nothing, and asks nothing, for an empty state set', async () => {
300
+ const { svc, select } = svcOver([row()]);
301
+ expect(await svc.listPrsByState([])).toEqual([]);
302
+ expect(select).not.toHaveBeenCalled();
303
+ });
304
+
305
+ it('reads the closed and merged rows from the table', async () => {
306
+ const { svc, select, atCommit, forPr } = svcOver(
307
+ [row({ number: 9, state: 'merged' })],
308
+ ['Knowledge/A.md'],
309
+ );
310
+ const [summary] = await svc.listPrsByState(['closed', 'merged']);
311
+ expect(select).toHaveBeenCalledTimes(1);
312
+ // The merge commit, not the branch pair: the source branch is retired, so
313
+ // asking for it is what sent one fetch per row at the remote.
314
+ // The ref carries the NUMBER as well as the sha: the git layer refuses a
315
+ // commit that is not this request's own merge commit. And the TITLE, so a
316
+ // commit written in the old message format is recognised too.
317
+ expect(atCommit).toHaveBeenCalledWith('ws', { number: 9, mergeSha: MERGE_SHA, title: 'A proposal' });
318
+ expect(forPr).not.toHaveBeenCalled();
319
+ expect(summary).toMatchObject({
320
+ number: 9,
321
+ state: 'merged',
322
+ branch: 'feature/x',
323
+ base: 'main',
324
+ touchedNodePaths: ['Knowledge/A.md'],
325
+ });
326
+ // The close time is the latest moment the row records, so it is `updatedAt`.
327
+ expect(summary.updatedAt).toBe('2026-04-03T09:30:00.000Z');
328
+ });
329
+
330
+ it('reads the table for a set that contains `open` ALONGSIDE another state', async () => {
331
+ // Only a deduplicated singleton `['open']` may delegate: a guard loosened to
332
+ // `states.includes('open')` would answer `['open', 'merged']` with the open
333
+ // rows alone and silently drop the merged ones. `listOpenPrs` is spied so
334
+ // delegation would be visible rather than merely wrong.
335
+ const { svc, select } = svcOver([row({ number: 9, state: 'merged' })], ['Knowledge/A.md']);
336
+ const spy = vi.spyOn(svc, 'listOpenPrs').mockResolvedValue([]);
337
+ const summaries = await svc.listPrsByState(['open', 'closed', 'merged']);
338
+ expect(spy).not.toHaveBeenCalled();
339
+ expect(select).toHaveBeenCalledTimes(1);
340
+ expect(summaries.map((s) => s.number)).toEqual([9]);
341
+ });
342
+
343
+ it('falls back to the creation time when the row records nothing later', async () => {
344
+ const { svc } = svcOver([row({ state: 'closed', closedAt: null })]);
345
+ const [summary] = await svc.listPrsByState(['closed']);
346
+ expect(summary.updatedAt).toBe('2026-04-01T00:00:00.000Z');
347
+ });
348
+
349
+ // Razvan's review of #347, finding 1: a closed row's branch is retired, so
350
+ // `publishedPrCommits` answered null and the diff FETCHED two refs — one of
351
+ // which no longer exists — once per row, logging a warning for each. A few
352
+ // hundred applied requests opened a few hundred concurrent fetches to answer
353
+ // nothing. Nothing about a closed row needs the network.
354
+ describe('listing closed and merged requests costs at most one fetch, never one per row', () => {
355
+ it('asks for no clone refresh when only declined rows are in scope — they read from nothing', async () => {
356
+ const { svc, ensureRemotesFetched } = svcOver([row({ state: 'closed', mergedSha: null })], ['A.md']);
357
+ await svc.listPrsByState(['closed', 'merged']);
358
+ expect(ensureRemotesFetched).not.toHaveBeenCalled();
359
+ });
360
+
361
+ it('refreshes the clone ONCE for a list of merged rows — their commits are immutable, but a clone must hold them', async () => {
362
+ // A clone that has not fetched since the merges would otherwise read
363
+ // every applied request as author-only for good (cubic P1 on #373).
364
+ const { svc, ensureRemotesFetched } = svcOver(
365
+ [row({ number: 1, state: 'merged' }), row({ number: 2, state: 'merged' }), row({ number: 3, state: 'merged' })],
366
+ ['A.md'],
367
+ );
368
+ await svc.listPrsByState(['closed', 'merged']);
369
+ expect(ensureRemotesFetched).toHaveBeenCalledTimes(1);
370
+ });
371
+
372
+ it('keeps the ONE refresh for a set that does contain open rows', async () => {
373
+ const { svc, ensureRemotesFetched } = svcOver([row({ state: 'merged' })], ['A.md']);
374
+ vi.spyOn(svc, 'listOpenPrs').mockResolvedValue([]);
375
+ await svc.listPrsByState(['open', 'merged']);
376
+ expect(ensureRemotesFetched).toHaveBeenCalledTimes(1);
377
+ });
378
+
379
+ it('remembers a recorded commit that is not the request\'s own, and never asks git for it again', async () => {
380
+ // Rows whose `merged_sha` is not this request's own commit — written
381
+ // before merges recorded their own — fail the verification for good;
382
+ // re-running their git calls on every poll, serialized under the
383
+ // workspace mutex, is what a deployment with hundreds of them paid.
384
+ const { svc, atCommit } = svcOver([row({ number: 9, state: 'merged' })], ['A.md']);
385
+ atCommit.mockRejectedValue(new AppliedChangeMismatchError('commit is not the merge commit of change request #9'));
386
+ const first = await svc.listPrsByState(['closed', 'merged']);
387
+ expect(first[0]?.touchedNodePaths).toEqual([]);
388
+ await svc.listPrsByState(['closed', 'merged']);
389
+ await svc.listPrsByState(['closed', 'merged']);
390
+ expect(atCommit).toHaveBeenCalledTimes(1);
391
+ });
392
+
393
+ it('asks again for a commit the clone did not hold — that one the next fetch may bring', async () => {
394
+ const { svc, atCommit } = svcOver([row({ number: 9, state: 'merged' })], ['A.md']);
395
+ atCommit.mockRejectedValueOnce(new WorkflowValidationError('commit is not in this clone'));
396
+ expect((await svc.listPrsByState(['closed', 'merged']))[0]?.touchedNodePaths).toEqual([]);
397
+ expect((await svc.listPrsByState(['closed', 'merged']))[0]?.touchedNodePaths).toEqual(['A.md']);
398
+ expect(atCommit).toHaveBeenCalledTimes(2);
399
+ });
400
+
401
+ it('asks git NOTHING about a declined row — there is no diff to compute', async () => {
402
+ const { svc, forPr, atCommit } = svcOver([row({ state: 'closed' })], ['A.md']);
403
+ const [summary] = await svc.listPrsByState(['closed']);
404
+ expect(forPr).not.toHaveBeenCalled();
405
+ expect(atCommit).not.toHaveBeenCalled();
406
+ // No files resolved, which downstream reads as "nothing proven": a
407
+ // declined request stays readable by its author alone.
408
+ expect(summary.touchedNodePaths).toEqual([]);
409
+ expect(summary.touchedNodeFiles).toEqual([]);
410
+ });
411
+
412
+ it('asks git nothing about a merged row that records no merge commit', async () => {
413
+ const { svc, forPr, atCommit } = svcOver(
414
+ [row({ state: 'merged', mergedSha: null })],
415
+ ['A.md'],
416
+ );
417
+ const [summary] = await svc.listPrsByState(['merged']);
418
+ expect(forPr).not.toHaveBeenCalled();
419
+ expect(atCommit).not.toHaveBeenCalled();
420
+ expect(summary.touchedNodePaths).toEqual([]);
421
+ });
422
+ });
423
+
424
+ it('degrades to no touched paths when a merge commit this clone lacks cannot be diffed', async () => {
425
+ const orderBy = vi.fn(async () => [row()]);
426
+ const db = {
427
+ select: () => ({ from: () => ({ where: () => ({ orderBy }) }) }),
428
+ } as unknown as Database;
429
+ const workspace = {
430
+ ensureRemotesFetched: vi.fn(async () => undefined),
431
+ findAnyWorkspaceId: async () => 'ws',
432
+ } as unknown as WorkspaceService;
433
+ const git = {
434
+ changedPathsAndPairsOfAppliedChange: vi.fn(async () => {
435
+ throw new WorkflowValidationError(
436
+ `commit ${MERGE_SHA} is not a merge commit in this clone, so it cannot be change request #1's`,
437
+ );
438
+ }),
439
+ } as unknown as GitService;
440
+ const svc = new PullRequestService(db, workspace, makeAccessControl({}), git);
441
+ const [summary] = await svc.listPrsByState(['merged']);
442
+ // Empty, not thrown — and a caller gating on these paths must read an empty
443
+ // set as "cannot prove read access", never as "nothing to protect".
444
+ expect(summary.touchedNodePaths).toEqual([]);
445
+ });
446
+ });
447
+
448
+ /**
449
+ * `getPrDetail` when nothing is left to read the change from. Since the
450
+ * 2026-10-02 decision an applied request is read from its merge commit (see the
451
+ * describe below this one), so what lands here is a row recording no usable sha:
452
+ * one written before `merged_sha` was, or a declined one.
453
+ *
454
+ * A declined row no longer even TRIES the branch pair — `changeSourceFor` sends
455
+ * it nowhere, so the throwing stub below is never reached for it. That is the
456
+ * point: a declined request's branch is usually alive, so a suite that can only
457
+ * make the branch throw cannot see what such a request actually answers. The
458
+ * describe two below this one drives the live-branch case.
459
+ */
460
+ describe('PullRequestService.getPrDetail with a retired branch and no merge commit', () => {
461
+ function svcFor(state: string) {
462
+ const row = {
463
+ number: 4,
464
+ sourceBranch: 'feature/x',
465
+ targetBranch: 'main',
466
+ title: 'A proposal',
467
+ body: 'why it was needed',
468
+ authorEmail: 'juan@bevel.software',
469
+ authorName: 'Juan',
470
+ state,
471
+ createdAt: new Date('2026-04-01T00:00:00Z'),
472
+ updatedAt: null,
473
+ closedAt: new Date('2026-04-03T09:30:00Z'),
474
+ applyFailureReason: null,
475
+ applyFailureConflicts: null,
476
+ applyFailedAt: null,
477
+ applyFailedByName: null,
478
+ applyFailureKind: null,
479
+ closedReason: null,
480
+ };
481
+ const db = {
482
+ select: () => ({ from: () => ({ where: () => ({ limit: async () => [row] }) }) }),
483
+ } as unknown as Database;
484
+ const workspace = {
485
+ ensureRemotesFetched: async () => undefined,
486
+ findAnyWorkspaceId: async () => 'ws',
487
+ } as unknown as WorkspaceService;
488
+ const git = {
489
+ resolvePrShas: async () => {
490
+ throw new WorkflowValidationError('unknown branch: feature/x');
491
+ },
492
+ } as unknown as GitService;
493
+ return new PullRequestService(db, workspace, makeAccessControl({}), git);
494
+ }
495
+
496
+ it('answers an applied request from its row alone, rather than failing', async () => {
497
+ const detail = await svcFor('merged').getPrDetail(4);
498
+ expect(detail).toMatchObject({
499
+ number: 4,
500
+ state: 'merged',
501
+ title: 'A proposal',
502
+ body: 'why it was needed',
503
+ files: [],
504
+ headSha: '',
505
+ baseSha: '',
506
+ mergeBaseSha: null,
507
+ behind: false,
508
+ needsUpdate: false,
509
+ });
510
+ });
511
+
512
+ it('answers a withdrawn request the same way', async () => {
513
+ expect(await svcFor('closed').getPrDetail(4)).toMatchObject({ state: 'closed', files: [] });
514
+ });
515
+
516
+ it('still fails loudly on an OPEN request, so no live proposal reads as empty', async () => {
517
+ await expect(svcFor('open').getPrDetail(4)).rejects.toThrow('unknown branch');
518
+ });
519
+ });
520
+
521
+ /**
522
+ * An APPLIED request is read from the merge commit its row records (Razvan's
523
+ * decision, 2026-10-02). Its branch is retired, so reading it from the branch
524
+ * pair answered no files — and since an empty file set proves no read access,
525
+ * that made every applied request readable by its author alone. Catching up on
526
+ * what happened is what the ticket exists for.
527
+ */
528
+ describe('PullRequestService.getPrDetail of an applied request', () => {
529
+ const MERGE_SHA = 'c'.repeat(40);
530
+ const BASE_SHA = '1'.repeat(40);
531
+ const HEAD_SHA = '2'.repeat(40);
532
+
533
+ function svcFor(over: Record<string, unknown> = {}) {
534
+ const row = {
535
+ number: 4,
536
+ sourceBranch: 'feature/x',
537
+ targetBranch: 'main',
538
+ title: 'A proposal',
539
+ body: 'why it was needed',
540
+ authorEmail: 'juan@bevel.software',
541
+ authorName: 'Juan',
542
+ state: 'merged',
543
+ mergedSha: MERGE_SHA,
544
+ createdAt: new Date('2026-04-01T00:00:00Z'),
545
+ updatedAt: null,
546
+ closedAt: new Date('2026-04-03T09:30:00Z'),
547
+ applyFailureReason: null,
548
+ applyFailureConflicts: null,
549
+ applyFailedAt: null,
550
+ applyFailedByName: null,
551
+ applyFailureKind: null,
552
+ closedReason: null,
553
+ ...over,
554
+ };
555
+ const db = {
556
+ select: () => ({ from: () => ({ where: () => ({ limit: async () => [row] }) }) }),
557
+ } as unknown as Database;
558
+ const ensureRemotesFetched = vi.fn(async () => undefined);
559
+ const workspace = {
560
+ ensureRemotesFetched,
561
+ findAnyWorkspaceId: async () => 'ws',
562
+ } as unknown as WorkspaceService;
563
+ const resolvePrShas = vi.fn(async () => {
564
+ throw new WorkflowValidationError('unknown branch: feature/x');
565
+ });
566
+ const appliedChangeShas = vi.fn(async () => ({ baseSha: BASE_SHA, headSha: HEAD_SHA }));
567
+ const changedFilesOfAppliedChange = vi.fn(async () => [
568
+ {
569
+ path: 'Knowledge/A.md',
570
+ previousPath: undefined,
571
+ status: 'modified' as const,
572
+ additions: 2,
573
+ deletions: 1,
574
+ patch: '@@ -1 +1 @@',
575
+ isBinary: false,
576
+ sha: '',
577
+ rawUrl: '',
578
+ },
579
+ ]);
580
+ const git = {
581
+ resolvePrShas,
582
+ appliedChangeShas,
583
+ changedFilesOfAppliedChange,
584
+ } as unknown as GitService;
585
+ const svc = new PullRequestService(db, workspace, makeAccessControl({}), git);
586
+ return {
587
+ svc,
588
+ resolvePrShas,
589
+ appliedChangeShas,
590
+ changedFilesOfAppliedChange,
591
+ ensureRemotesFetched,
592
+ };
593
+ }
594
+
595
+ it('reads its files from the merge commit, and never asks for its branches', async () => {
596
+ const { svc, resolvePrShas, changedFilesOfAppliedChange } = svcFor();
597
+ const detail = await svc.getPrDetail(4);
598
+ expect(changedFilesOfAppliedChange).toHaveBeenCalledWith('ws', { number: 4, mergeSha: MERGE_SHA, title: 'A proposal' }, {});
599
+ // Not one branch resolution, so not one fetch: the branch no longer exists
600
+ // and the commit cannot change.
601
+ expect(resolvePrShas).not.toHaveBeenCalled();
602
+ expect(detail).toMatchObject({
603
+ number: 4,
604
+ state: 'merged',
605
+ files: [{ path: 'Knowledge/A.md', additions: 2, deletions: 1 }],
606
+ });
607
+ });
608
+
609
+ it("reports the merge commit's two parents as the request's base and head", async () => {
610
+ // `headSha` is not decoration: an approval is called stale when the head it
611
+ // was given against is not this one, so answering the merge commit here would
612
+ // report every approval the request ever collected as stale.
613
+ const { svc } = svcFor();
614
+ expect(await svc.getPrDetail(4)).toMatchObject({ baseSha: BASE_SHA, headSha: HEAD_SHA });
615
+ });
616
+
617
+ it('asks no "is it behind its target" question of an applied request', async () => {
618
+ const { svc } = svcFor();
619
+ expect(await svc.getPrDetail(4)).toMatchObject({
620
+ mergeBaseSha: null,
621
+ behind: false,
622
+ needsUpdate: false,
623
+ });
624
+ });
625
+
626
+ it('skips the patches when the caller asked for none', async () => {
627
+ const { svc, changedFilesOfAppliedChange } = svcFor();
628
+ await svc.getPrDetail(4, { patches: false });
629
+ expect(changedFilesOfAppliedChange).toHaveBeenCalledWith(
630
+ 'ws',
631
+ { number: 4, mergeSha: MERGE_SHA, title: 'A proposal' },
632
+ { patchCap: 0 },
633
+ );
634
+ });
635
+
636
+ it('falls back to the row alone when this clone does not hold the merge commit', async () => {
637
+ const { svc } = svcFor();
638
+ const git = (svc as unknown as { gitService: Record<string, unknown> }).gitService;
639
+ git.appliedChangeShas = async () => {
640
+ throw new WorkflowValidationError(`no first parent for commit ${MERGE_SHA}`);
641
+ };
642
+ // Fail-closed, as before the decision: no files, so author-only — never
643
+ // somebody else's file list.
644
+ expect(await svc.getPrDetail(4)).toMatchObject({ state: 'merged', files: [], headSha: '' });
645
+ });
646
+ });
647
+
648
+ /**
649
+ * A DECLINED request whose source branch is STILL ALIVE — the case the suite
650
+ * could not see, and the one Local Testing failed on.
651
+ *
652
+ * Declining a change request does not retire its branch; only merging deletes
653
+ * it. So `resolvePrShas` and `changedFilesForPr` answer a declined request
654
+ * perfectly well, and `getPrDetail` used to let them: its file list made the
655
+ * request readable by anyone who could read one of those files, against the
656
+ * owner's criterion that a declined request stays readable by its author alone,
657
+ * while `listPrsByState` — which asks git nothing about a declined row — hid the
658
+ * very same request from the very same caller. The earlier test for this stubbed
659
+ * `resolvePrShas` to THROW, pinning a precondition the service does not produce;
660
+ * here the branch resolves, which is what actually happens.
661
+ */
662
+ describe('PullRequestService.getPrDetail of a declined request whose branch still resolves', () => {
663
+ const BASE_SHA = '3'.repeat(40);
664
+ const HEAD_SHA = '4'.repeat(40);
665
+
666
+ function svcFor(state: string) {
667
+ const row = {
668
+ number: 9,
669
+ sourceBranch: 'feature/declined',
670
+ targetBranch: 'main',
671
+ title: 'A proposal that was turned down',
672
+ body: 'why it was asked for',
673
+ authorEmail: 'juan@bevel.software',
674
+ authorName: 'Juan',
675
+ state,
676
+ mergedSha: null,
677
+ createdAt: new Date('2026-04-01T00:00:00Z'),
678
+ updatedAt: null,
679
+ closedAt: state === 'open' ? null : new Date('2026-04-03T09:30:00Z'),
680
+ applyFailureReason: null,
681
+ applyFailureConflicts: null,
682
+ applyFailedAt: null,
683
+ applyFailedByName: null,
684
+ applyFailureKind: null,
685
+ closedReason: null,
686
+ };
687
+ const orderBy = vi.fn(async () => [row]);
688
+ const db = {
689
+ select: () => ({
690
+ from: () => ({ where: () => ({ limit: async () => [row], orderBy }) }),
691
+ }),
692
+ } as unknown as Database;
693
+ const ensureRemotesFetched = vi.fn(async () => undefined);
694
+ const workspace = {
695
+ ensureRemotesFetched,
696
+ findAnyWorkspaceId: async () => 'ws',
697
+ } as unknown as WorkspaceService;
698
+ // The branch pair RESOLVES — the whole point. A stub that threw would prove
699
+ // nothing about a declined request, because a live branch does not throw.
700
+ const resolvePrShas = vi.fn(async () => ({ baseSha: BASE_SHA, headSha: HEAD_SHA }));
701
+ const changedFilesForPr = vi.fn(async () => [
702
+ {
703
+ path: 'KnowledgeBase/Readable.md',
704
+ previousPath: undefined,
705
+ status: 'modified' as const,
706
+ additions: 1,
707
+ deletions: 0,
708
+ patch: '@@ -1 +1 @@',
709
+ isBinary: false,
710
+ sha: '',
711
+ rawUrl: '',
712
+ },
713
+ ]);
714
+ const changedPathsAndPairsForPr = vi.fn(async () => ({
715
+ paths: ['KnowledgeBase/Readable.md'],
716
+ pairs: [{ path: 'KnowledgeBase/Readable.md' }],
717
+ }));
718
+ const forkPointForPr = vi.fn(async () => ({ mergeBaseSha: BASE_SHA, behind: false }));
719
+ const git = {
720
+ resolvePrShas,
721
+ changedFilesForPr,
722
+ changedPathsAndPairsForPr,
723
+ forkPointForPr,
724
+ } as unknown as GitService;
725
+ const svc = new PullRequestService(db, workspace, makeAccessControl({}), git);
726
+ return { svc, resolvePrShas, changedFilesForPr, changedPathsAndPairsForPr, forkPointForPr };
727
+ }
728
+
729
+ beforeEach(() => {
730
+ vi.restoreAllMocks();
731
+ });
732
+
733
+ it('answers from the row alone, though the branch pair would have answered', async () => {
734
+ const { svc, resolvePrShas, changedFilesForPr, forkPointForPr } = svcFor('closed');
735
+ const detail = await svc.getPrDetail(9);
736
+ expect(detail).toMatchObject({
737
+ number: 9,
738
+ state: 'closed',
739
+ title: 'A proposal that was turned down',
740
+ // The row's own prose survives; only the file list goes.
741
+ body: 'why it was asked for',
742
+ files: [],
743
+ headSha: '',
744
+ baseSha: '',
745
+ });
746
+ // Not asked, so a declined request cannot publish a file list — and cannot
747
+ // publish the branch's CURRENT diff as the proposal that was turned down,
748
+ // which is what it did while the author kept committing to that branch.
749
+ expect(resolvePrShas).not.toHaveBeenCalled();
750
+ expect(changedFilesForPr).not.toHaveBeenCalled();
751
+ expect(forkPointForPr).not.toHaveBeenCalled();
752
+ });
753
+
754
+ it('costs no network round trip per by-number read', async () => {
755
+ // Three reads of a declined request spent three two-ref fetches before this
756
+ // — the per-request network call finding 1 of the review was about, removed
757
+ // from the list path but left on the by-number one.
758
+ const { svc, resolvePrShas, changedFilesForPr } = svcFor('closed');
759
+ await svc.getPrDetail(9, { fresh: true });
760
+ await svc.getPrDetail(9, { fresh: true });
761
+ await svc.getPrDetail(9, { fresh: true });
762
+ expect(resolvePrShas).not.toHaveBeenCalled();
763
+ expect(changedFilesForPr).not.toHaveBeenCalled();
764
+ });
765
+
766
+ it('agrees with the list about which files a declined request has', async () => {
767
+ // The contradiction itself: one caller, one request, two surfaces. Both
768
+ // answer "no files proven", so both make it author-only.
769
+ const { svc } = svcFor('closed');
770
+ const detail = await svc.getPrDetail(9);
771
+ const [summary] = await svc.listPrsByState(['closed']);
772
+ expect(detail?.files).toEqual([]);
773
+ expect(summary.touchedNodeFiles).toEqual([]);
774
+ expect(summary.touchedNodePaths).toEqual([]);
775
+ });
776
+
777
+ it('still reads an OPEN request from the very same live branch pair', async () => {
778
+ // The control: the stubs DO answer, so the declined case above is the
779
+ // routing refusing to ask, not a stub that could not have replied.
780
+ const { svc, resolvePrShas, changedFilesForPr } = svcFor('open');
781
+ const detail = await svc.getPrDetail(9);
782
+ expect(resolvePrShas).toHaveBeenCalled();
783
+ expect(changedFilesForPr).toHaveBeenCalled();
784
+ expect(detail).toMatchObject({
785
+ state: 'open',
786
+ headSha: HEAD_SHA,
787
+ baseSha: BASE_SHA,
788
+ files: [{ path: 'KnowledgeBase/Readable.md' }],
789
+ });
790
+ });
791
+ });
792
+
793
+ /**
794
+ * The routing itself, asked once and shared: the list and the by-number detail
795
+ * both read a row's change from whatever this answers, so neither can drift
796
+ * into its own reading of which files a request has.
797
+ */
798
+ describe('changeSourceFor', () => {
799
+ it('reads an open request from its branch pair', () => {
800
+ expect(changeSourceFor({ number: 9, state: 'open', mergedSha: null })).toEqual({
801
+ kind: 'branches',
802
+ });
803
+ });
804
+
805
+ // The NUMBER travels with the sha, and that is not decoration: the git layer
806
+ // refuses a commit whose subject does not name this request, because a merge
807
+ // with nothing to merge used to record the target tip — usually another
808
+ // request's merge commit (cubic P1 on #347).
809
+ it("reads an applied request from the merge commit its row records, named by number", () => {
810
+ const sha = 'f'.repeat(40);
811
+ expect(changeSourceFor({ number: 9, state: 'merged', mergedSha: sha })).toEqual({
812
+ kind: 'commit',
813
+ applied: { number: 9, mergeSha: sha },
814
+ });
815
+ });
816
+
817
+ it('reads a declined request from nothing — no sha records what it proposed', () => {
818
+ expect(changeSourceFor({ number: 9, state: 'closed', mergedSha: null })).toEqual({
819
+ kind: 'none',
820
+ });
821
+ });
822
+
823
+ it('reads a declined request from nothing even if a sha somehow sits on the row', () => {
824
+ // A row flipped to `closed` after an apply recorded a sha would otherwise
825
+ // publish a merge commit as a declined request's content.
826
+ expect(changeSourceFor({ number: 9, state: 'closed', mergedSha: 'e'.repeat(40) })).toEqual({
827
+ kind: 'none',
828
+ });
829
+ });
830
+
831
+ it('reads a merged row recording no merge commit from nothing', () => {
832
+ expect(changeSourceFor({ number: 9, state: 'merged', mergedSha: null })).toEqual({
833
+ kind: 'none',
834
+ });
835
+ expect(changeSourceFor({ number: 9, state: 'merged' })).toEqual({ kind: 'none' });
836
+ });
837
+
838
+ it('reads a state it has never heard of from nothing, rather than guessing', () => {
839
+ expect(changeSourceFor({ number: 9, state: 'draft', mergedSha: 'd'.repeat(40) })).toEqual({
840
+ kind: 'none',
841
+ });
842
+ });
843
+ });