@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,10 +1,13 @@
1
1
  import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
2
2
  import { randomBytes } from 'node:crypto';
3
+ import type { SQL } from 'drizzle-orm';
4
+ import { PgDialect } from 'drizzle-orm/pg-core';
3
5
  import {
4
6
  DeploymentSettingsService,
5
7
  SettingsValidationError,
6
8
  CORE_SETTINGS,
7
9
  LEGACY_LAYOUT_ENV_VARS,
10
+ retireMergedBranchesOn,
8
11
  } from '../deployment-settings.service.js';
9
12
  import type { Database } from '../../database/connection.js';
10
13
 
@@ -28,13 +31,54 @@ function makeDb() {
28
31
  else rows.push({ key: v.key, value: v.value, encrypted: v.encrypted });
29
32
  return Promise.resolve();
30
33
  },
34
+ onConflictDoNothing: () => ({
35
+ returning: () => {
36
+ if (rows.some((r) => r.key === v.key)) return Promise.resolve([]);
37
+ rows.push({ key: v.key, value: v.value, encrypted: v.encrypted });
38
+ return Promise.resolve([{ key: v.key }]);
39
+ },
40
+ }),
41
+ }),
42
+ }),
43
+ // `delete … where … returning` / `update … set … where … returning`: the
44
+ // conditional swap. The fake applies the one predicate the service sends,
45
+ // key AND value, by reading the bound parameters off the drizzle `where`.
46
+ delete: () => ({
47
+ where: (predicate: unknown) => {
48
+ const done = Promise.resolve();
49
+ return Object.assign(done, {
50
+ returning: () => {
51
+ const [key, value] = boundParams(predicate);
52
+ const at = rows.findIndex((r) => r.key === key && r.value === value);
53
+ if (at === -1) return Promise.resolve([]);
54
+ rows.splice(at, 1);
55
+ return Promise.resolve([{ key }]);
56
+ },
57
+ });
58
+ },
59
+ }),
60
+ update: () => ({
61
+ set: (v: { value: string }) => ({
62
+ where: (predicate: unknown) => ({
63
+ returning: () => {
64
+ const [key, value] = boundParams(predicate);
65
+ const row = rows.find((r) => r.key === key && r.value === value);
66
+ if (!row) return Promise.resolve([]);
67
+ row.value = v.value;
68
+ return Promise.resolve([{ key }]);
69
+ },
70
+ }),
31
71
  }),
32
72
  }),
33
- delete: () => ({ where: () => Promise.resolve() }),
34
73
  } as unknown as Database;
35
74
  return { db, rows };
36
75
  }
37
76
 
77
+ /** The parameters a drizzle predicate binds, in order — what the fake table matches on. */
78
+ function boundParams(predicate: unknown): unknown[] {
79
+ return new PgDialect().sqlToQuery(predicate as SQL).params;
80
+ }
81
+
38
82
  let saved: NodeJS.ProcessEnv;
39
83
  beforeEach(() => {
40
84
  saved = { ...process.env };
@@ -119,6 +163,56 @@ describe('DeploymentSettingsService — a blank that means the default', () => {
119
163
  });
120
164
  });
121
165
 
166
+ describe('DeploymentSettingsService — the leftover-branch cleanup switch', () => {
167
+ /**
168
+ * On by default; an admin switches it off on the Deployment page, and the
169
+ * environment variable wins over the page, as for every setting.
170
+ */
171
+ it('is on by default, off once saved as false, and on again when cleared — after a reload too', async () => {
172
+ const { db, rows } = makeDb();
173
+ // Clearing deletes the row: the fake does so for real, so a reload proves it.
174
+ (db as unknown as { delete: () => unknown }).delete = () => ({
175
+ where: () => {
176
+ const at = rows.findIndex((r) => r.key === 'retireMergedBranches');
177
+ if (at >= 0) rows.splice(at, 1);
178
+ return Promise.resolve();
179
+ },
180
+ });
181
+ const settings = new DeploymentSettingsService(db, ENC_KEY);
182
+ const on = (s: DeploymentSettingsService) => retireMergedBranchesOn(s.resolve('retireMergedBranches'));
183
+ const reloaded = async () => {
184
+ const fresh = new DeploymentSettingsService(db, ENC_KEY);
185
+ await fresh.load();
186
+ return fresh;
187
+ };
188
+ expect(on(settings)).toBe(true);
189
+ await settings.save({ retireMergedBranches: 'false' }, null);
190
+ expect(on(settings)).toBe(false);
191
+ expect(on(await reloaded())).toBe(false);
192
+ await settings.save({ retireMergedBranches: '' }, null);
193
+ expect(on(settings)).toBe(true);
194
+ expect(rows.some((r) => r.key === 'retireMergedBranches')).toBe(false);
195
+ expect(on(await reloaded())).toBe(true);
196
+ });
197
+
198
+ it('lets RETIRE_MERGED_BRANCHES win over the page', async () => {
199
+ const { db } = makeDb();
200
+ const settings = new DeploymentSettingsService(db, ENC_KEY);
201
+ await settings.save({ retireMergedBranches: 'true' }, null);
202
+ process.env.RETIRE_MERGED_BRANCHES = 'false';
203
+ expect(settings.sourceOf('retireMergedBranches')).toBe('env');
204
+ expect(retireMergedBranchesOn(settings.resolve('retireMergedBranches'))).toBe(false);
205
+ });
206
+
207
+ it('saves only true or false, and reads the ways a person writes "off" as off', async () => {
208
+ const { db } = makeDb();
209
+ const settings = new DeploymentSettingsService(db, ENC_KEY);
210
+ await expect(settings.save({ retireMergedBranches: 'maybe' }, null)).rejects.toBeInstanceOf(SettingsValidationError);
211
+ for (const off of ['false', 'FALSE', '0', 'off', 'no']) expect(retireMergedBranchesOn(off), off).toBe(false);
212
+ for (const on of ['', 'true', '1', 'yes']) expect(retireMergedBranchesOn(on), on).toBe(true);
213
+ });
214
+ });
215
+
122
216
  describe('DeploymentSettingsService — secrets', () => {
123
217
  it('stores the token as ciphertext and reads it back', async () => {
124
218
  const { db, rows } = makeDb();
@@ -191,8 +285,6 @@ describe('DeploymentSettingsService — KB layout', () => {
191
285
  pluginsDir: 'Plugins',
192
286
  agentsFile: 'AGENTS.md',
193
287
  });
194
- // The pointer is on until someone says otherwise.
195
- expect(settings.resolveAgentsFileLink()).toBe(true);
196
288
  });
197
289
 
198
290
  /**
@@ -225,9 +317,9 @@ describe('DeploymentSettingsService — KB layout', () => {
225
317
  it('ignores the environment for the four layout names', async () => {
226
318
  const { db } = makeDb();
227
319
  const settings = new DeploymentSettingsService(db, ENC_KEY);
228
- await settings.save({ skillsDir: 'skills', pluginsDir: 'plugins', agentsFile: 'HEXIS.md' }, null);
320
+ await settings.save({ skillsDir: 'skills', pluginsDir: 'plugins' }, null);
229
321
  process.env.KB_SKILLS_DIR = 'capabilities';
230
- expect(settings.resolveKbLayout()).toMatchObject({ skillsDir: 'skills', agentsFile: 'HEXIS.md' });
322
+ expect(settings.resolveKbLayout()).toMatchObject({ skillsDir: 'skills' });
231
323
  expect(settings.sourceOf('skillsDir')).toBe('stored');
232
324
  // Not locked: the field stays editable in the app, and a save of it is
233
325
  // accepted rather than refused as 'set by the environment'.
@@ -284,68 +376,41 @@ describe('DeploymentSettingsService — KB layout', () => {
284
376
  });
285
377
 
286
378
  /**
287
- * The guide's file name is saved beside the folders and judged with them:
288
- * the four must differ, and a name that is not one markdown file is refused
289
- * with the rule it broke.
379
+ * The guide's name was a setting while the guide was written to disk. It is
380
+ * gone: the setup screen no longer offers it, a save naming it is refused
381
+ * as unknown, and the guide is read as `AGENTS.md` on every deployment
382
+ * whatever a deployment saved before.
290
383
  */
291
- it('refuses a guide name that is not one markdown file of its own', async () => {
292
- const { db } = makeDb();
293
- const settings = new DeploymentSettingsService(db, ENC_KEY);
294
- for (const bad of ['guides/HEXIS.md', 'HEXIS.txt', 'CLAUDE.md', 'access.md', 'roles.yaml']) {
295
- await expect(settings.save({ agentsFile: bad }, null)).rejects.toBeInstanceOf(
296
- SettingsValidationError,
297
- );
298
- }
299
- await expect(settings.save({ agentsFile: 'HEXIS.md' }, null)).resolves.toBeTruthy();
300
- });
301
-
302
- it('refuses a guide named after a root folder, from either side of the pair', async () => {
303
- const { db } = makeDb();
304
- const settings = new DeploymentSettingsService(db, ENC_KEY);
305
- // The plugins folder already in effect, named by the guide alone.
306
- await settings.save({ pluginsDir: 'Guide.md' }, null);
307
- await expect(settings.save({ agentsFile: 'guide.md' }, null)).rejects.toBeInstanceOf(
308
- SettingsValidationError,
309
- );
310
- // And the other way round, in one batch.
311
- await expect(
312
- settings.save({ agentsFile: 'HEXIS.md', skillsDir: 'hexis.md' }, null),
313
- ).rejects.toBeInstanceOf(SettingsValidationError);
314
- });
315
-
316
- it('marks the guide name and its pointer setting as restart-to-apply', async () => {
317
- const { db } = makeDb();
384
+ it('knows no guide name any more: a save naming one is refused, and the layout always says AGENTS.md', async () => {
385
+ const { db, rows } = makeDb();
386
+ // The row a deployment saved while the setting existed is still in its
387
+ // database. It is loaded like any other row, and changes nothing.
388
+ rows.push({ key: 'agentsFile', value: 'HEXIS.md', encrypted: false });
318
389
  const settings = new DeploymentSettingsService(db, ENC_KEY);
319
- expect((await settings.save({ agentsFile: 'HEXIS.md' }, null)).restartKeys).toContain('agentsFile');
320
- expect((await settings.save({ agentsFileLink: 'false' }, null)).restartKeys).toContain(
321
- 'agentsFileLink',
322
- );
323
- expect(settings.resolveAgentsFileLink()).toBe(false);
390
+ await settings.load();
391
+ expect(settings.resolveKbLayout().agentsFile).toBe('AGENTS.md');
392
+ await expect(settings.save({ agentsFile: 'HEXIS.md' }, null)).rejects.toMatchObject({
393
+ problems: { agentsFile: 'Unknown setting.' },
394
+ });
395
+ await expect(settings.save({ agentsFile: 'HEXIS.md' }, null, 'deployment')).rejects.toMatchObject({
396
+ problems: { agentsFile: 'Unknown setting.' },
397
+ });
398
+ expect(settings.resolveKbLayout().agentsFile).toBe('AGENTS.md');
399
+ expect(settings.describe().map((s) => s.key)).not.toContain('agentsFile');
324
400
  });
325
401
 
326
402
  /**
327
403
  * A restart is owed for a CHANGE, and saving what a deployment is already
328
- * running on is not one. Both of these settings mean something while unset —
329
- * the guide is `AGENTS.md`, the pointer is on — so the first save of that
330
- * same answer changes nothing the process would pick up at a restart.
404
+ * running on is not one. A root name means something while unset — the
405
+ * default — so the first save of that same answer changes nothing the
406
+ * process would pick up at a restart.
331
407
  */
332
408
  it('owes no restart for saving the value an unset setting already meant', async () => {
333
409
  const { db } = makeDb();
334
410
  const settings = new DeploymentSettingsService(db, ENC_KEY);
335
- // The checkbox arrives ticked, and ticked is what an unset one already is.
336
- expect((await settings.save({ agentsFileLink: 'true' }, null)).restartKeys).not.toContain(
337
- 'agentsFileLink',
338
- );
339
- expect((await settings.save({ agentsFile: 'AGENTS.md' }, null)).restartKeys).not.toContain(
340
- 'agentsFile',
341
- );
342
411
  expect((await settings.save({ skillsDir: 'Skills' }, null)).restartKeys).not.toContain('skillsDir');
343
- // And the setting still reads as it did.
344
- expect(settings.resolveAgentsFileLink()).toBe(true);
345
- // Turning it off from there IS a change, and still reports one.
346
- expect((await settings.save({ agentsFileLink: 'false' }, null)).restartKeys).toContain(
347
- 'agentsFileLink',
348
- );
412
+ // Renaming it from there IS a change, and still reports one.
413
+ expect((await settings.save({ skillsDir: 'Abilities' }, null)).restartKeys).toContain('skillsDir');
349
414
  });
350
415
 
351
416
  /**
@@ -557,3 +622,58 @@ describe('DeploymentSettingsService — an environment of its own', () => {
557
622
  expect(shared.resolve('kbRepoUrl')).toBe('https://host.example/leaks-into-every-tenant.git');
558
623
  });
559
624
  });
625
+
626
+ describe('DeploymentSettingsService — recordIfAbsent', () => {
627
+ /**
628
+ * The claim a once-only flow rests on: the row is the lock, and the
629
+ * database — shared by every replica — lets exactly one insert through.
630
+ */
631
+ it('claims a setting once, and tells the second caller it was not theirs', async () => {
632
+ const { db, rows } = makeDb();
633
+ const one = new DeploymentSettingsService(db, ENC_KEY);
634
+ const two = new DeploymentSettingsService(db, ENC_KEY);
635
+ await one.load();
636
+ await two.load();
637
+
638
+ expect(await one.recordIfAbsent('starterPack', 'sales', 'u-ada')).toBe(true);
639
+ expect(await two.recordIfAbsent('starterPack', 'none', 'u-bo')).toBe(false);
640
+
641
+ expect(rows.filter((r) => r.key === 'starterPack')).toEqual([{ key: 'starterPack', value: 'sales', encrypted: false }]);
642
+ expect(one.resolve('starterPack')).toBe('sales');
643
+ // The loser's cache was not touched: it reads the winner's row on its next `reload`.
644
+ expect(two.resolve('starterPack')).toBe('');
645
+ });
646
+
647
+ it('is no claim at all with a blank value, which would be a clear', async () => {
648
+ const { db, rows } = makeDb();
649
+ const settings = new DeploymentSettingsService(db, ENC_KEY);
650
+ await settings.load();
651
+ expect(await settings.recordIfAbsent('starterPack', '', null)).toBe(false);
652
+ expect(rows).toEqual([]);
653
+ });
654
+
655
+ /**
656
+ * The conditional swap the claim flows rest on: a value is replaced, or
657
+ * removed, only while it still reads what the caller saw — so two
658
+ * replicas acting on one read cannot both succeed.
659
+ */
660
+ it('swaps a value only while it still reads what was expected, and removes it the same way', async () => {
661
+ const { db, rows } = makeDb();
662
+ const settings = new DeploymentSettingsService(db, ENC_KEY);
663
+ await settings.load();
664
+ expect(await settings.recordIfAbsent('starterPackClaim', 'u-a 1', 'u-a')).toBe(true);
665
+
666
+ // The value moved under the second caller: refused, untouched.
667
+ expect(await settings.swapIfValue('starterPackClaim', 'u-z 0', 'u-b 2', 'u-b')).toBe(false);
668
+ expect(await settings.swapIfValue('starterPackClaim', 'u-a 1', 'u-b 2', 'u-b')).toBe(true);
669
+ expect(rows.find((r) => r.key === 'starterPackClaim')?.value).toBe('u-b 2');
670
+ expect(settings.resolve('starterPackClaim')).toBe('u-b 2');
671
+
672
+ // A release names its own claim: the holder's row stays for a stale one.
673
+ expect(await settings.swapIfValue('starterPackClaim', 'u-a 1', null, null)).toBe(false);
674
+ expect(rows.find((r) => r.key === 'starterPackClaim')?.value).toBe('u-b 2');
675
+ expect(await settings.swapIfValue('starterPackClaim', 'u-b 2', null, null)).toBe(true);
676
+ expect(rows.find((r) => r.key === 'starterPackClaim')).toBeUndefined();
677
+ expect(settings.resolve('starterPackClaim')).toBe('');
678
+ });
679
+ });
@@ -124,6 +124,15 @@ describe('RepositorySource: a repository reached through a GitHub App', () => {
124
124
  expect(renewed).toBe(1);
125
125
  });
126
126
 
127
+ it("hands the app the runner's word that the host refused the token", async () => {
128
+ const seen: unknown[] = [];
129
+ const githubApp = app({ prepare: async (opts) => void seen.push(opts) });
130
+ const { source: s } = source({ gitMode: 'github-app' }, { githubApp });
131
+ await s.credentials.prepare?.({ refused: true });
132
+ await s.credentials.prepare?.();
133
+ expect(seen).toEqual([{ refused: true }, undefined]);
134
+ });
135
+
127
136
  it('is unanswered on a deployment that has no such app', () => {
128
137
  const { source: s } = source({ gitMode: 'github-app' });
129
138
  expect(s.answered()).toBe(false);
@@ -1,4 +1,4 @@
1
- import { eq, inArray } from 'drizzle-orm';
1
+ import { and, eq, inArray } from 'drizzle-orm';
2
2
  import { logger } from '../../shared/logging.js';
3
3
 
4
4
  const log = logger('settings');
@@ -7,7 +7,6 @@ import { deploymentSettings } from '../database/core-schema.js';
7
7
  import {
8
8
  DEFAULT_KB_LAYOUT,
9
9
  type KbLayout,
10
- validateAgentsFileName,
11
10
  validateBranchModel,
12
11
  validateKbLayout,
13
12
  validateKbRootName,
@@ -110,6 +109,16 @@ export const validateHttpsRemote = (value: string): string | null => {
110
109
  /**
111
110
  * The core catalogue. Order is the order the setup screen renders them in.
112
111
  */
112
+ /**
113
+ * What the `retireMergedBranches` value in effect means: on, unless it says
114
+ * off. The page saves only `true` or `false`; the environment variable is
115
+ * typed by a person, so `0`, `off` and `no` (any case) mean off too, and
116
+ * anything else — unset included — leaves the cleanup on.
117
+ */
118
+ export function retireMergedBranchesOn(raw: string): boolean {
119
+ return !/^(false|0|off|no)$/i.test(raw.trim());
120
+ }
121
+
113
122
  export const CORE_SETTINGS: SettingDef[] = [
114
123
  {
115
124
  /**
@@ -228,14 +237,16 @@ export const CORE_SETTINGS: SettingDef[] = [
228
237
  /**
229
238
  * The KB layout: the three root folders a deployment may rename so hexis can
230
239
  * read a repository laid out by someone else (`skills/` and `plugins/` in
231
- * lowercase, say), and the file name of the managed agent guide.
240
+ * lowercase, say). The agent guide's name is not among them any more: the
241
+ * guide is served by the platform as `AGENTS.md` everywhere, and a name a
242
+ * deployment saved for the written guide is ignored.
232
243
  * Restart-to-apply like the branch model — the names are applied once at boot
233
244
  * through `configureKbLayout` and served to the browser once by
234
245
  * `/api/config`. Each has a default, so an unset field means the default, not
235
- * an unconfigured deployment. Checked as a QUARTET in `save`: the four must
246
+ * an unconfigured deployment. Checked as a TRIO in `save`: the three must
236
247
  * differ, and one field alone cannot see the other three.
237
248
  *
238
- * NO `envVar`, on any of the four. Layout is deployment configuration that is
249
+ * NO `envVar`, on any of the three. Layout is deployment configuration that is
239
250
  * entered once in the app; the three that used to be environment-driven are
240
251
  * imported into their saved setting on the first boot after the upgrade
241
252
  * ({@link DeploymentSettingsService.importLegacyLayoutEnv}) so nothing
@@ -262,37 +273,6 @@ export const CORE_SETTINGS: SettingDef[] = [
262
273
  restartToApply: true,
263
274
  unsetMeans: DEFAULT_KB_LAYOUT.pluginsDir,
264
275
  },
265
- {
266
- /**
267
- * The managed agent guide's file name. Its own validator says what a guide
268
- * may be called; the quartet check in `plan` is what keeps it clear of the
269
- * three folder names it is saved beside.
270
- */
271
- key: 'agentsFile',
272
- section: 'knowledge-base',
273
- // Judged against the default roots here; the quartet check in `plan`
274
- // judges it against the roots the same save puts in effect.
275
- validate: (v) => validateAgentsFileName(v, DEFAULT_KB_LAYOUT),
276
- restartToApply: true,
277
- unsetMeans: DEFAULT_KB_LAYOUT.agentsFile,
278
- },
279
- {
280
- /**
281
- * Whether to keep the platform's one-sentence pointer in a customer's own
282
- * `AGENTS.md` — the admin's consent to the only text the platform ever adds
283
- * to a file it does not own. On unless it is explicitly turned off, because
284
- * a renamed guide nothing points at is a guide no coding agent will find.
285
- *
286
- * Restart-to-apply like the name it belongs to: the check runs once per
287
- * start, in the KB startup phase.
288
- */
289
- key: 'agentsFileLink',
290
- section: 'knowledge-base',
291
- validate: (v) => (v === 'true' || v === 'false' ? null : 'Use "true" or "false".'),
292
- restartToApply: true,
293
- // On unless explicitly turned off — the reading `resolveAgentsFileLink` applies.
294
- unsetMeans: 'true',
295
- },
296
276
 
297
277
 
298
278
  /**
@@ -319,6 +299,23 @@ export const CORE_SETTINGS: SettingDef[] = [
319
299
  restartToApply: true,
320
300
  },
321
301
 
302
+ {
303
+ /**
304
+ * Whether the server removes, on its own, the branches merged change
305
+ * requests left behind (`WorkflowService.retireLeftoverMergedBranches`).
306
+ * On unless set to `false`; a blanked field puts the default back. Read
307
+ * at every round, so it applies without a restart. It covers that cleanup
308
+ * only: the removal of a branch when its change request is merged does
309
+ * not ask it.
310
+ */
311
+ key: 'retireMergedBranches',
312
+ envVar: 'RETIRE_MERGED_BRANCHES',
313
+ section: 'knowledge-base',
314
+ blankMeansDefault: true,
315
+ unsetMeans: 'true',
316
+ validate: (v) => (v === 'true' || v === 'false' ? null : 'Either true or false.'),
317
+ },
318
+
322
319
  {
323
320
  /**
324
321
  * The credential a git host's webhook or a pipeline presents to
@@ -402,6 +399,35 @@ export const CORE_SETTINGS: SettingDef[] = [
402
399
  validate: (v) =>
403
400
  parseRetentionWindow(v) === null ? 'Enter a whole number of days, or 0 to keep events forever.' : null,
404
401
  },
402
+
403
+ {
404
+ /**
405
+ * Which starter pack the first admin chose for a new knowledge base — a
406
+ * pack's id, or `none` for "I'll start from scratch" — written once, by
407
+ * the deployment, when the choice landed (see
408
+ * `modules/onboarding/starter-pack.service.ts`). Its presence is what
409
+ * retires the "What does your team do?" card for good; its value is what
410
+ * the first-page prompt and the agent's first-run note follow. Internal:
411
+ * a fact about what happened, not something the setup screen offers.
412
+ */
413
+ key: 'starterPack',
414
+ section: 'knowledge-base',
415
+ internal: true,
416
+ validate: (v) => (/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(v) ? null : 'A starter pack id is lowercase letters, digits and hyphens.'),
417
+ },
418
+ {
419
+ /**
420
+ * The claim an admin holds while their starter-pack choice is being
421
+ * written: `<user id> <epoch ms>`, inserted only if absent so two replicas
422
+ * cannot both write, and released once the choice is recorded. A claim
423
+ * nobody released in time is a process that died mid-write and is taken
424
+ * over (see `starter-pack.service.ts`). Internal, like the choice.
425
+ */
426
+ key: 'starterPackClaim',
427
+ section: 'knowledge-base',
428
+ internal: true,
429
+ validate: (v) => (/^\S+ \d+$/.test(v) ? null : 'A claim is a user id and a time.'),
430
+ },
405
431
  ];
406
432
 
407
433
  /**
@@ -587,20 +613,10 @@ export class DeploymentSettingsService {
587
613
  knowledgeBaseDir: this.resolve('knowledgeBaseDir') || DEFAULT_KB_LAYOUT.knowledgeBaseDir,
588
614
  skillsDir: this.resolve('skillsDir') || DEFAULT_KB_LAYOUT.skillsDir,
589
615
  pluginsDir: this.resolve('pluginsDir') || DEFAULT_KB_LAYOUT.pluginsDir,
590
- agentsFile: this.resolve('agentsFile') || DEFAULT_KB_LAYOUT.agentsFile,
616
+ agentsFile: DEFAULT_KB_LAYOUT.agentsFile,
591
617
  };
592
618
  }
593
619
 
594
- /**
595
- * Whether the platform should keep its pointer sentence in a customer-owned
596
- * `AGENTS.md`. On unless the admin turned it off — an unset setting is a
597
- * deployment that never saw the checkbox, and the sentence is what makes a
598
- * renamed guide findable at all.
599
- */
600
- resolveAgentsFileLink(): boolean {
601
- return this.resolve('agentsFileLink') !== 'false';
602
- }
603
-
604
620
  /**
605
621
  * Import the retired layout environment variables into their saved settings,
606
622
  * ONCE, on a deployment that still sets them.
@@ -764,6 +780,61 @@ export class DeploymentSettingsService {
764
780
  await this.save(entries, updatedBy, 'deployment');
765
781
  }
766
782
 
783
+ /**
784
+ * {@link record} one value ONLY IF NOTHING IS THERE, and say whether it was
785
+ * this call that put it there. The row is the claim for a flow that must
786
+ * happen once across every replica (the starter-pack choice): the insert
787
+ * yields to a row already there, so of two replicas claiming at once the
788
+ * database lets exactly one through. Validated as `record` is; a blank
789
+ * value is no claim (it would be a clear) and answers false.
790
+ */
791
+ async recordIfAbsent(key: string, value: string, updatedBy: string | null): Promise<boolean> {
792
+ const write = this.plan({ [key]: value }, 'deployment').toWrite.find((w) => w.key === key);
793
+ if (!write) return false;
794
+ const encrypted = write.def.secret === true;
795
+ const stored = encrypted ? this.crypto!.encrypt(write.value) : write.value;
796
+ const inserted = await this.db
797
+ .insert(deploymentSettings)
798
+ .values({ key, value: stored, encrypted, updatedBy })
799
+ .onConflictDoNothing({ target: deploymentSettings.key })
800
+ .returning({ key: deploymentSettings.key });
801
+ if (inserted.length === 0) return false;
802
+ this.stored.set(key, write.value);
803
+ return true;
804
+ }
805
+
806
+ /**
807
+ * Replace a plain setting's value ONLY IF it still reads `expected` —
808
+ * with `next`, or with nothing when `next` is null — and say whether it
809
+ * was this call that did it. One statement, so of two replicas acting on
810
+ * what they both read, the database lets exactly one through: the other
811
+ * finds the value gone or changed and answers false. For the claim flows
812
+ * that {@link recordIfAbsent} opens: taking over a claim that expired, and
813
+ * releasing one's own without touching a successor's. Plain settings only;
814
+ * `next` is validated as {@link record} would.
815
+ */
816
+ async swapIfValue(key: string, expected: string, next: string | null, updatedBy: string | null): Promise<boolean> {
817
+ const def = this.defs.get(key);
818
+ if (!def || def.secret) return false;
819
+ const same = and(eq(deploymentSettings.key, key), eq(deploymentSettings.value, expected));
820
+ if (next === null) {
821
+ const gone = await this.db.delete(deploymentSettings).where(same).returning({ key: deploymentSettings.key });
822
+ if (gone.length === 0) return false;
823
+ this.stored.delete(key);
824
+ return true;
825
+ }
826
+ const write = this.plan({ [key]: next }, 'deployment').toWrite.find((w) => w.key === key);
827
+ if (!write) return false;
828
+ const swapped = await this.db
829
+ .update(deploymentSettings)
830
+ .set({ value: write.value, updatedBy, updatedAt: new Date() })
831
+ .where(same)
832
+ .returning({ key: deploymentSettings.key });
833
+ if (swapped.length === 0) return false;
834
+ this.stored.set(key, write.value);
835
+ return true;
836
+ }
837
+
767
838
  /** Validate a batch and return the writes (and the clears) it amounts to; throws on any problem. */
768
839
  private plan(
769
840
  entries: Record<string, string>,
@@ -832,12 +903,12 @@ export class DeploymentSettingsService {
832
903
  if (problem) problems.protectedBranches = problem;
833
904
  }
834
905
 
835
- // The layout quartet is the other cross-field rule: three folder names and
836
- // a guide file name that must all differ. Judged on the layout this save
837
- // WOULD produce, with the default standing in for anything neither written
838
- // nor stored — so renaming the plugins folder to what the guide is already
839
- // called is refused whichever of the two the save names.
840
- const layoutKeys = ['knowledgeBaseDir', 'skillsDir', 'pluginsDir', 'agentsFile'] as const;
906
+ // The layout trio is the other cross-field rule: three folder names that
907
+ // must all differ. Judged on the layout this save WOULD produce, with the
908
+ // default standing in for anything neither written nor stored — so
909
+ // renaming one folder to what another is already called is refused
910
+ // whichever of the two the save names.
911
+ const layoutKeys = ['knowledgeBaseDir', 'skillsDir', 'pluginsDir'] as const;
841
912
  if (toWrite.some((w) => (layoutKeys as readonly string[]).includes(w.key))) {
842
913
  const effective = (key: (typeof layoutKeys)[number]) =>
843
914
  toWrite.find((w) => w.key === key)?.value || this.resolve(key) || DEFAULT_KB_LAYOUT[key];
@@ -845,7 +916,6 @@ export class DeploymentSettingsService {
845
916
  knowledgeBaseDir: effective('knowledgeBaseDir'),
846
917
  skillsDir: effective('skillsDir'),
847
918
  pluginsDir: effective('pluginsDir'),
848
- agentsFile: effective('agentsFile'),
849
919
  });
850
920
  // Against the field being written — the first one in the batch — since
851
921
  // any of the three could be the one that collides.
@@ -873,7 +943,7 @@ export class DeploymentSettingsService {
873
943
  knowledgeBaseDir: effective('knowledgeBaseDir'),
874
944
  skillsDir: effective('skillsDir'),
875
945
  pluginsDir: effective('pluginsDir'),
876
- agentsFile: effective('agentsFile'),
946
+ agentsFile: DEFAULT_KB_LAYOUT.agentsFile,
877
947
  });
878
948
  } catch (err) {
879
949
  // Against the field this save is writing — the checkout name when that
@@ -993,6 +1063,25 @@ export class DeploymentSettingsService {
993
1063
  return `${OIDC_VERIFICATION_PREFIX}${fingerprint}`;
994
1064
  }
995
1065
 
1066
+ /**
1067
+ * One plain (never sealed) setting as the DATABASE has it now, taken into
1068
+ * this replica's cache on the way: for the rare setting a running
1069
+ * deployment writes, so a replica that did not serve the write still
1070
+ * answers with it. The environment still wins, as in {@link resolve}.
1071
+ */
1072
+ async reload(key: string): Promise<string> {
1073
+ const def = this.defs.get(key);
1074
+ if (!def || def.secret) return this.resolve(key);
1075
+ const rows = await this.db
1076
+ .select({ value: deploymentSettings.value, encrypted: deploymentSettings.encrypted })
1077
+ .from(deploymentSettings)
1078
+ .where(eq(deploymentSettings.key, key));
1079
+ const row = rows.find((r) => !r.encrypted);
1080
+ if (row) this.stored.set(key, row.value);
1081
+ else this.stored.delete(key);
1082
+ return this.resolve(key);
1083
+ }
1084
+
996
1085
  /** Remove one stored row (used by tests and by `prune`). */
997
1086
  async clear(key: string): Promise<void> {
998
1087
  await this.db.delete(deploymentSettings).where(eq(deploymentSettings.key, key));
@@ -34,7 +34,7 @@ export interface GitHubAppRepository {
34
34
  * Make sure {@link token} answers with one that is still good. `asked`
35
35
  * is for a caller waiting on the answer itself, who is told a failure.
36
36
  */
37
- prepare(opts?: { asked?: boolean }): Promise<void>;
37
+ prepare(opts?: { asked?: boolean; refused?: boolean }): Promise<void>;
38
38
  /** Whether the deployment may be pointed at this repository (`owner/name`). */
39
39
  permits(repository: string, read: SettingReader): boolean;
40
40
  /** Whether the app, its installation and a repository are all there. */
@@ -98,7 +98,7 @@ export class RepositorySource {
98
98
  this.credentials = {
99
99
  username: () => this.username(),
100
100
  token: () => this.token(),
101
- prepare: () => this.prepare(),
101
+ prepare: (opts) => this.prepare(opts),
102
102
  };
103
103
  }
104
104
 
@@ -185,8 +185,8 @@ export class RepositorySource {
185
185
  }
186
186
  }
187
187
 
188
- private async prepare(): Promise<void> {
189
- if (this.inEffect === 'github-app') await this.opts.githubApp?.prepare();
188
+ private async prepare(opts?: { refused?: boolean }): Promise<void> {
189
+ if (this.inEffect === 'github-app') await this.opts.githubApp?.prepare(opts);
190
190
  }
191
191
 
192
192
  private tokenIn(read: SettingReader): string {
@@ -64,17 +64,14 @@ const SECRET_FOR_THAT_PROVIDER =
64
64
  'Enter the application secret for that provider — the saved one is only sent to the provider it was saved for.';
65
65
 
66
66
  /**
67
- * The knowledge-base layout as setting keys: the three renameable roots, the
68
- * guide's file name, and the consent that rides with it — which the KB startup
69
- * phase reads through a getter, so the completing save puts it in effect along
70
- * with the names.
67
+ * The knowledge-base layout as setting keys: the three renameable roots. The
68
+ * guide's file name is not one of them — the settings layer sets none, so the
69
+ * layout it produces carries the default, `AGENTS.md`.
71
70
  */
72
71
  const LAYOUT_KEYS: readonly string[] = [
73
72
  'knowledgeBaseDir',
74
73
  'skillsDir',
75
74
  'pluginsDir',
76
- 'agentsFile',
77
- 'agentsFileLink',
78
75
  ];
79
76
  /** The branch model, as setting keys. */
80
77
  const BRANCH_KEYS: readonly string[] = ['defaultBranch', 'protectedBranches'];