@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
@@ -17,6 +17,10 @@ import { getDb, type Database } from '../modules/database/connection.js';
17
17
  import { runCoreMigrations } from '../modules/database/migrate.js';
18
18
  import { coreMigrationsDir } from '../assets.js';
19
19
  import { WorkspaceService } from '../modules/workspace/workspace.service.js';
20
+ import { AccountLinkService } from '../modules/embed/account-link.service.js';
21
+ import { EmbedService } from '../modules/embed/embed.service.js';
22
+ import { McpAppService, type IMcpAppService } from '../modules/embed/mcp-app.js';
23
+ import { createFileReaderRegistry } from '../modules/workspace/file-readers/file-reader.registry.js';
20
24
  import { RoutineWritePolicyService } from '../modules/workspace/routine-write-policy.js';
21
25
  import { KbStartupRunner } from '../modules/workspace/startup/kb-startup-runner.js';
22
26
  import { GroupsToPluginsStep } from '../modules/workspace/startup/steps/groups-to-plugins.step.js';
@@ -26,7 +30,7 @@ import { PersonalSpacesStep } from '../modules/workspace/startup/steps/personal-
26
30
  import { TemplateFilesStep } from '../modules/workspace/startup/steps/template-files.step.js';
27
31
  import { RolesYamlStep } from '../modules/workspace/startup/steps/roles-yaml.step.js';
28
32
  import { buildSeedTree } from '../modules/workspace/startup/steps/seed-tree.js';
29
- import { DeploymentSettingsService } from '../modules/settings/deployment-settings.service.js';
33
+ import { DeploymentSettingsService, retireMergedBranchesOn } from '../modules/settings/deployment-settings.service.js';
30
34
  import { KbSyncService } from '../modules/kb-sync/kb-sync.service.js';
31
35
  import { NodeFs } from '../modules/kb-fs/node-fs.js';
32
36
  import { assertKbDirNameFree } from '../modules/kb-fs/repo-path.js';
@@ -55,17 +59,21 @@ function parseDomainList(raw: string): string[] {
55
59
  }
56
60
  import { SpillStore } from '../modules/workspace/spill-store.js';
57
61
  import { AgentUploadStore, assertUploadsRootOutsideWorkspaces } from '../modules/workspace/agent-upload.store.js';
62
+ import { AgentDownloadStore, type IAgentDownloadStore } from '../modules/workspace/agent-download.store.js';
63
+ import { createDownloadFetcherIdentifier } from '../modules/workspace/agent-download.routes.js';
64
+ import type { Request } from 'express';
58
65
  import { DocExtractService } from '../modules/workspace/file-readers/doc-extract.service.js';
59
66
  import { UuidSessionSink, type ISessionSink } from '../modules/workspace/session-sink.js';
60
67
  import { AuthService } from '../modules/auth/auth.service.js';
61
68
  import { AccountErasureService } from '../modules/auth/account-erasure.service.js';
62
69
  import { OidcAuthProvider, oidcSettingsFrom } from '../modules/auth/oidc-auth-provider.js';
63
- import { createAuthMiddleware } from '../modules/auth/auth.middleware.js';
70
+ import { createAuthMiddleware, readAuthCookie } from '../modules/auth/auth.middleware.js';
64
71
  import { AccessControlService, loadActiveGroups } from '../modules/access/access-control.service.js';
65
72
  import { CreatorAccessService } from '../modules/access/creator-access.js';
66
73
  import { ChangeReadGate } from '../modules/access/change-read-gate.js';
67
74
  import { GroupsAdminService } from '../modules/access/groups-admin.service.js';
68
75
  import { UserAccessRemovalService } from '../modules/access/user-access-removal.service.js';
76
+ import { makeRolesYamlWriteValidator } from '../modules/access-model/roles-yaml-guard.js';
69
77
  import { PendingSkillsService, SkillService } from '../modules/skills/index.js';
70
78
  import { PendingToolsService, ToolManualService } from '../modules/tool-manuals/index.js';
71
79
  import { McpServerEditService } from '../modules/tool-manuals/mcp-server-edit.service.js';
@@ -110,6 +118,7 @@ import { ReviewWorkflowService } from '../modules/workflow/review-workflow/revie
110
118
  import { FileLockService } from '../modules/workflow/file-lock.service.js';
111
119
  import { WorkflowEventBus } from '../modules/workflow/event-bus.js';
112
120
  import { FileChangeNotifier } from '../modules/kb-fs/file-change-notifier.js';
121
+ import { StarterPackService } from '../modules/onboarding/starter-pack.service.js';
113
122
  import { WorkflowService } from '../modules/workflow/workflow.service.js';
114
123
  import { WorkflowHooks } from '../modules/workflow/workflow-hooks.js';
115
124
  import { PendingCommitsService } from '../modules/workflow/pending-commits.service.js';
@@ -132,12 +141,19 @@ import {
132
141
  } from '../modules/tool-auth/internal-token.service.js';
133
142
  import {
134
143
  createToolAuthMiddleware,
144
+ createTokenVerifier,
135
145
  createManualAuthMiddleware,
136
146
  } from '../modules/tool-auth/tool-auth.middleware.js';
137
147
  import { unmeteredLlmUsage, type ILlmUsageMeter } from '../modules/tool-auth/llm-usage-meter.js';
138
148
  import { McpService } from '../modules/mcp/mcp.service.js';
139
149
  import { AgentAuditService, retentionDaysFrom } from '../modules/audit/agent-audit.service.js';
140
150
  import { readAgentPreamble, type AgentPreambleReader } from '../modules/agent-instructions/index.js';
151
+ import {
152
+ agentGuideSections,
153
+ joinGuideSections,
154
+ type AgentGuideReader,
155
+ type AgentGuideSectionsReader,
156
+ } from '../modules/agent-guide/index.js';
141
157
  import { createMcpAuthMiddleware } from '../modules/mcp/mcp-auth.middleware.js';
142
158
  import { BevelOAuthProvider } from '../modules/mcp/oauth/bevel-oauth-provider.js';
143
159
  import { getOAuthProtectedResourceMetadataUrl } from '@modelcontextprotocol/sdk/server/auth/router.js';
@@ -223,6 +239,14 @@ export interface CoreServices {
223
239
  spillStore: SpillStore;
224
240
  /** The bytes an agent uploaded, held until `apply_file_upload` lands them or their token expires. */
225
241
  agentUploadStore: AgentUploadStore;
242
+ /** The bytes `request_file_download` captured, held until their one-time link is fetched or expires. */
243
+ agentDownloadStore: IAgentDownloadStore;
244
+ /**
245
+ * Every user a download fetch identifies itself as, by its bearer and its
246
+ * session cookie — none when it carries none that verifies — so the
247
+ * download route can refuse a link presented by someone it was not issued to.
248
+ */
249
+ agentDownloadFetcher: (req: Request) => Promise<string[]>;
226
250
  docExtractService: DocExtractService;
227
251
  accessControl: AccessControlService;
228
252
  creatorAccess: CreatorAccessService;
@@ -239,11 +263,24 @@ export interface CoreServices {
239
263
  * and `GET /api/agent/instructions`. See modules/agent-instructions.
240
264
  */
241
265
  readAgentPreamble: AgentPreambleReader;
266
+ /**
267
+ * Composes the platform's agent guide for the layout in effect, through
268
+ * the distribution's hook when it passed one: what `get_agent_guide` and a
269
+ * `read_file` of the guide's name answer. See modules/agent-guide.
270
+ */
271
+ agentGuide: AgentGuideReader;
272
+ /** The same guide as its sections, each with its title — what `get_agent_guide` lists and serves one of. */
273
+ agentGuideSections: AgentGuideSectionsReader;
242
274
  mcpServerEditService: McpServerEditService;
243
275
  /** Deleting one tool — the owner's verb (see ToolDeleteService). */
244
276
  toolDeleteService: ToolDeleteService;
245
277
  pluginIndexService: PluginIndexService;
246
278
  pluginProvisionService: PluginProvisionService;
279
+ /**
280
+ * "What does your team do?" — the starter pack a new knowledge base's admin
281
+ * may fill it from, and the record of what was chosen. See modules/onboarding.
282
+ */
283
+ starterPackService: StarterPackService;
247
284
  joinRequestsService: JoinRequestsService;
248
285
  /**
249
286
  * Records a join request and finishes it in the background. Its `sweep()`
@@ -321,6 +358,14 @@ export interface CoreServices {
321
358
  connectionProbeService: ConnectionProbeService;
322
359
  externalApiKeyService: ExternalApiKeyService;
323
360
  internalTokenService: InternalTokenService;
361
+ /**
362
+ * The embed surface: the token-minted page a chat host frames, and the
363
+ * account links that let an outside identity reach it. Exposed so an
364
+ * overlay can mint for its own consumers and register a node-id resolver.
365
+ */
366
+ embedService: EmbedService;
367
+ /** The MCP Apps this deployment serves — the `open_page` view and its sandbox metadata. */
368
+ mcpAppService: IMcpAppService;
324
369
  mcpService: McpService;
325
370
  mcpAuthMiddleware: ReturnType<typeof createMcpAuthMiddleware>;
326
371
  mcpOAuthProvider: BevelOAuthProvider;
@@ -606,10 +651,7 @@ export async function createCoreServices(
606
651
  // backfill would walk a tree still missing those manifests.
607
652
  new PluginDisplayNamesStep(disk, kb),
608
653
  new PersonalSpacesStep(disk, kb),
609
- // A getter, not a value: the step is built here, while the process may
610
- // still hold the defaults, and the save that completes first-run setup
611
- // applies the admin's answer afterwards.
612
- new TemplateFilesStep(disk, kb, extraDirs, () => settings.resolveAgentsFileLink()),
654
+ new TemplateFilesStep(disk, kb, extraDirs),
613
655
  new RolesYamlStep(disk, [config.adminEmail]),
614
656
  ...(ports.kbStartupSteps ?? []),
615
657
  ];
@@ -674,6 +716,29 @@ export async function createCoreServices(
674
716
  publicBaseUrl: config.publicBackendUrl,
675
717
  tokenPrefix: config.uploadTokenPrefix,
676
718
  });
719
+ // The way OUT: bytes `request_file_download` captured, held beside the
720
+ // upload root — outside every workspace, for the same reason — until their
721
+ // one-time link is fetched or expires.
722
+ const agentDownloadsRoot = path.resolve(config.agentUploadsRoot, '..', 'agent-downloads');
723
+ // An upload root that is itself named `agent-downloads` would make the two
724
+ // stores one directory, each sweeping the other's files.
725
+ if (agentDownloadsRoot === path.resolve(config.agentUploadsRoot)) {
726
+ throw new Error(
727
+ 'AGENT_UPLOADS_ROOT must not be a directory named `agent-downloads`: that name, beside it, is the agent download root.',
728
+ );
729
+ }
730
+ await assertUploadsRootOutsideWorkspaces(agentDownloadsRoot, config.workspacesRoot, {
731
+ name: 'The agent download root (`agent-downloads`, beside AGENT_UPLOADS_ROOT)',
732
+ why:
733
+ 'captured download bytes wait there for their one-time links, so a root inside a workspace would let the ' +
734
+ 'file tools read them. Point AGENT_UPLOADS_ROOT at a directory whose parent is outside WORKSPACES_ROOT.',
735
+ });
736
+ const agentDownloadStore = new AgentDownloadStore({
737
+ root: agentDownloadsRoot,
738
+ publicBaseUrl: config.publicBackendUrl,
739
+ // `<tenant>-down_`: recognisable by shape beside the upload token.
740
+ tokenPrefix: config.uploadTokenPrefix.replace(/up_$/, 'down_'),
741
+ });
677
742
  // Office-document/PDF text extraction for `read_file`/`grep`, cached by
678
743
  // content hash beside the workspaces root (see `DocExtractionCache`).
679
744
  const docExtractService = new DocExtractService(config.docExtractCacheRoot);
@@ -858,6 +923,9 @@ export async function createCoreServices(
858
923
  // it reach every hook point.
859
924
  workflowHooks,
860
925
  );
926
+ // The leftover-branch cleanup asks the Deployment page at every round, so
927
+ // switching it off there applies without a restart.
928
+ workflowService.leftoverCleanupEnabled = () => retireMergedBranchesOn(settings.resolve('retireMergedBranches'));
861
929
 
862
930
  // Join requests: derived entirely from two copies of a plugin's `access.md`
863
931
  // (the request's branch vs the default branch), so it holds no state — it
@@ -1042,6 +1110,27 @@ export async function createCoreServices(
1042
1110
  [config.adminEmail],
1043
1111
  );
1044
1112
 
1113
+ // The starter-pack question: one commit on the default branch through the
1114
+ // same batch write the roles admin uses, the choice kept as a deployment
1115
+ // setting. Read by its routes and by `start_session`'s first-run note.
1116
+ const starterPackService = new StarterPackService({
1117
+ packsDir: config.starterPacksDir,
1118
+ kb,
1119
+ workspaceService,
1120
+ workflow: workflowService,
1121
+ adminAccess,
1122
+ settings,
1123
+ accessControl,
1124
+ disk,
1125
+ pluginSource,
1126
+ pluginLocks: pluginProvisionService,
1127
+ events: eventBus,
1128
+ fileChanges: fileChangeNotifier,
1129
+ // Its own lock: one starter-pack choice at a time, a concern no other
1130
+ // service's mutex serialises.
1131
+ choosing: new WorkspaceMutex(),
1132
+ });
1133
+
1045
1134
  // In-app update check: lazily compares the running release version against
1046
1135
  // the newest published GitHub release, only when an admin's browser asks —
1047
1136
  // no timers, so a deployment nobody looks at makes zero calls. The flag
@@ -1141,9 +1230,13 @@ export async function createCoreServices(
1141
1230
  // Connection keys also come as GitHub-shaped links (`gho_…`, kind
1142
1231
  // `github-link`): the same key, minted by the marketplace facade below when
1143
1232
  // a person connects an account on claude.ai, told apart by its stored kind.
1144
- const externalApiKeyService = new ExternalApiKeyService(db, config.externalApiKeyPrefix, {
1145
- [GITHUB_LINK_KEY_KIND]: GITHUB_LINK_KEY_SPEC,
1146
- });
1233
+ const externalApiKeyService = new ExternalApiKeyService(
1234
+ db,
1235
+ config.externalApiKeyPrefix,
1236
+ { [GITHUB_LINK_KEY_KIND]: GITHUB_LINK_KEY_SPEC },
1237
+ // A key's first use tells its owner's open tabs that the agent arrived.
1238
+ eventBus,
1239
+ );
1147
1240
 
1148
1241
  // The facade that lets products which sync marketplaces only from a GitHub
1149
1242
  // Enterprise Server (claude.ai, Cowork) add the per-user marketplace:
@@ -1168,6 +1261,12 @@ export async function createCoreServices(
1168
1261
  // the proxy below composes in-process per request; the agent-facing route
1169
1262
  // serves the same composition to the local bridge and the frontend card.
1170
1263
  const readPreamble: AgentPreambleReader = () => readAgentPreamble(workspaceService, kb, disk);
1264
+ // The guide every agent is told to read first, composed when asked for —
1265
+ // the layout is read per call, so a name the setup save applies lands
1266
+ // without a restart, and the distribution's hook sees every composition.
1267
+ const agentGuideSectionsReader: AgentGuideSectionsReader = () =>
1268
+ agentGuideSections(kb.layout, ports.agentGuide, { kbDirName });
1269
+ const agentGuide: AgentGuideReader = async () => joinGuideSections(await agentGuideSectionsReader());
1171
1270
  // The Audit log. Records through the proxy below (every call an external
1172
1271
  // agent makes), reads keys through the key service so their shape is
1173
1272
  // defined once, and prunes past the retention setting — read per sweep, so
@@ -1175,6 +1274,34 @@ export async function createCoreServices(
1175
1274
  const agentAuditService = new AgentAuditService(db, externalApiKeyService, () =>
1176
1275
  retentionDaysFrom(settings.resolve('auditRetentionDays')),
1177
1276
  );
1277
+ // The embed surface. It reads files through the workspace service and
1278
+ // judges them with the same access resolver the app file page uses, so what
1279
+ // a reader may see and change inside a chat is what they may see and change
1280
+ // in the app — never a second answer to the same question.
1281
+ const embedService = new EmbedService(
1282
+ // The RESOLVED checkout folder, not the env's: `config.kbDirName` is only
1283
+ // the environment value, empty on a deployment that took the default or
1284
+ // named it in setup, and every path the embed builds starts with it.
1285
+ { ...config, kbDirName },
1286
+ kb,
1287
+ workspaceService,
1288
+ accessControl,
1289
+ authService,
1290
+ workflowService,
1291
+ gitService,
1292
+ new AccountLinkService(db),
1293
+ // The SAME extension-to-reader registry `read_file` dispatches on, so the
1294
+ // embed answer to "is this text, or bytes a renderer fetches?" cannot
1295
+ // disagree with what a read of the file returns.
1296
+ createFileReaderRegistry(docExtractService),
1297
+ // The SAME pre-disk gate the file editor and the agent tools run: a
1298
+ // `roles.yaml` that would not parse is refused before it is written, from
1299
+ // a chat exactly as from the app.
1300
+ makeRolesYamlWriteValidator(kbDirName),
1301
+ );
1302
+ // The `ui://` view `open_page` carries, with the one origin it may frame:
1303
+ // this deployment own public origin.
1304
+ const mcpAppService = new McpAppService({ publicFrontendUrl: config.publicFrontendUrl });
1178
1305
  const mcpService = new McpService(
1179
1306
  {
1180
1307
  // Loopback to our own REST tool surface — 127.0.0.1 (not localhost) to pin
@@ -1208,12 +1335,20 @@ export async function createCoreServices(
1208
1335
  (bearer) => mcpOAuthProvider.revokeByAccessToken(bearer),
1209
1336
  // Every attributable call lands in the Audit log through this.
1210
1337
  agentAuditService,
1338
+ // The views the endpoint serves over resources/read, and the tools that
1339
+ // carry them.
1340
+ mcpAppService,
1211
1341
  );
1212
1342
  // A changed secret invalidates what the proxy built from the old value for
1213
1343
  // that user (null = shared secret → everyone): remembered manual failures,
1214
1344
  // so a just-repaired credential is retried on the very next request instead
1215
1345
  // of waiting out the failure memo's TTL, and pooled downstream connections.
1216
1346
  secretsVaultService.onMutation((changedUserId) => mcpService.onSecretsChanged(changedUserId));
1347
+ // The proxy is the one place a connected server's tools are loaded, so it is
1348
+ // the one place their schemas are checked — and the tool catalog is where the
1349
+ // people who manage a server read what it found. Setter injection, like the
1350
+ // OAuth discovery above: the proxy is constructed after the catalog.
1351
+ toolManualService.setHiddenTools(mcpService.hiddenTools);
1217
1352
  // MCP OAuth 2.1 authorization server (our own AS): lets MCP clients with no
1218
1353
  // pre-shared connection key connect via the standard 401 → discovery → DCR →
1219
1354
  // authorize (PKCE) flow. The authorize step routes the browser to /connect
@@ -1225,6 +1360,8 @@ export async function createCoreServices(
1225
1360
  stateSecret: config.jwtSecret,
1226
1361
  publicFrontendUrl: config.publicFrontendUrl,
1227
1362
  tokenPrefix: config.mcpOAuthTokenPrefix,
1363
+ // An agent connection's first use tells its owner's open tabs the agent arrived.
1364
+ events: eventBus,
1228
1365
  });
1229
1366
  // RFC 9728 pointer carried on every MCP 401 challenge so OAuth-capable
1230
1367
  // clients discover the AS. Single source of truth for the resource id.
@@ -1261,8 +1398,22 @@ export async function createCoreServices(
1261
1398
  loadActiveGroups,
1262
1399
  });
1263
1400
  const writeAccess = ports.writeAccess ?? alwaysWritable;
1264
- const toolHandlerFactory = createToolHandlerFactory(resolveToolContext, writeAccess);
1401
+ // The branch every tool call runs on is resolved by the handler, before the
1402
+ // tool: the default read live (a rename in the settings is the next call's
1403
+ // default), the existence asked without cloning anything.
1404
+ const toolHandlerFactory = createToolHandlerFactory(resolveToolContext, writeAccess, {
1405
+ defaultBranch: () => kb.defaultBranch,
1406
+ isMissing: (branch) => workspaceService.isBranchMissing(branch),
1407
+ });
1265
1408
  const toolAuthMiddleware = createToolAuthMiddleware(externalApiKeyService, internalTokenService, authService);
1409
+ const verifyToolToken = createTokenVerifier(externalApiKeyService, internalTokenService, authService);
1410
+ // Every credential kind this server issues — connection keys, internal
1411
+ // tokens and app sessions (bearer or cookie) — so a fetch carrying another
1412
+ // user's identity of ANY kind is refused the link.
1413
+ const agentDownloadFetcher: (req: Request) => Promise<string[]> = createDownloadFetcherIdentifier(
1414
+ { verifyToolToken, verifySession: (token) => authService.verifyToken(token) },
1415
+ readAuthCookie,
1416
+ );
1266
1417
  // Read-only manual endpoints accept the above PLUS a browser JWT, so a
1267
1418
  // logged-in user can browse the catalog with their session. Execution routes
1268
1419
  // keep `toolAuthMiddleware` (no JWT), so a session can read but not invoke.
@@ -1430,6 +1581,8 @@ export async function createCoreServices(
1430
1581
  kbDirName,
1431
1582
  spillStore,
1432
1583
  agentUploadStore,
1584
+ agentDownloadStore,
1585
+ agentDownloadFetcher,
1433
1586
  docExtractService,
1434
1587
  accessControl,
1435
1588
  creatorAccess,
@@ -1440,8 +1593,11 @@ export async function createCoreServices(
1440
1593
  toolManualService,
1441
1594
  pendingToolsService,
1442
1595
  readAgentPreamble: readPreamble,
1596
+ agentGuide,
1597
+ agentGuideSections: agentGuideSectionsReader,
1443
1598
  pluginIndexService,
1444
1599
  pluginProvisionService,
1600
+ starterPackService,
1445
1601
  joinRequestsService,
1446
1602
  pluginJoinRequestJobs,
1447
1603
  pluginLinkIndex,
@@ -1475,6 +1631,8 @@ export async function createCoreServices(
1475
1631
  connectionProbeService,
1476
1632
  externalApiKeyService,
1477
1633
  internalTokenService,
1634
+ embedService,
1635
+ mcpAppService,
1478
1636
  mcpService,
1479
1637
  mcpAuthMiddleware,
1480
1638
  mcpOAuthProvider,
@@ -291,7 +291,7 @@ export interface BootableCore {
291
291
  config: { workspacesRoot: string };
292
292
  kbDirName: string;
293
293
  kbStartupRunner: Pick<KbStartupRunner, 'runAll' | 'retryUntilMaintained'>;
294
- workflowService: Pick<WorkflowService, 'closeChangeRequestsWithDeletedBranches'>;
294
+ workflowService: Pick<WorkflowService, 'closeChangeRequestsWithDeletedBranches' | 'tidyAfterSweep'>;
295
295
  pluginJoinRequestJobs: Pick<PluginJoinRequestJobs, 'startSweeping'>;
296
296
  /**
297
297
  * The startup phase's retry, when the boot survived an unreachable remote
@@ -390,7 +390,11 @@ export async function startCore<C extends BootableCore>(
390
390
  crLog.info(`closed ${n} change request${n === 1 ? '' : 's'} with a deleted branch`);
391
391
  }
392
392
  })
393
- .catch((err) => crLog.warn('deleted-branch sweep failed:', { err }));
393
+ .catch((err) => crLog.warn('deleted-branch sweep failed:', { err }))
394
+ // Then the tidy-up: open requests that propose nothing are closed, and the
395
+ // branches merged requests left behind removed (behind its own setting).
396
+ // Fails safe on a failed fetch, and never throws.
397
+ .then(() => core.workflowService.tidyAfterSweep());
394
398
 
395
399
  // Recorded join requests that are still owed, resumed — now, and then on a
396
400
  // timer. SEQUENCED AFTER the startup phase for the same reason as the sweep
@@ -437,6 +441,15 @@ export interface CoreStopDeps {
437
441
  * Optional: a caller that has not built one passes nothing.
438
442
  */
439
443
  agentUploadStore?: { stopSweeping(): void; drainSweep(): Promise<void> };
444
+ /** The agent download store, whose sweep deletes captured bytes nobody fetched — stopped for the same reason. */
445
+ agentDownloadStore?: { stopSweeping(): void; drainSweep(): Promise<void> };
446
+ /**
447
+ * The workflow service, for the tidy-up it runs after each sweep (closing
448
+ * empty requests, removing leftover branches): detached from whatever
449
+ * started it, so stopped and awaited here before the pool goes. Optional:
450
+ * a caller that has not built one passes nothing.
451
+ */
452
+ workflowService?: { stopTidying(): void; drainTidy(): Promise<void> };
440
453
  /** The startup phase's retry, if the boot left one asking — see {@link BootableCore.startupRetry}. */
441
454
  startupRetry?: { stop(): void } | null;
442
455
  /** The database — its pool is ended last, once nothing above can still need it. */
@@ -524,10 +537,14 @@ async function releaseCore(deps: CoreStopDeps, remaining: () => number, log: (m:
524
537
  // synchronous, and it only clears an interval and tells a sweep already
525
538
  // running to stop deleting.
526
539
  deps.agentUploadStore?.stopSweeping();
540
+ deps.agentDownloadStore?.stopSweeping();
527
541
  // A startup phase still asking for an unreachable remote stops asking:
528
542
  // synchronous, and nothing after it must be able to clone into a
529
543
  // workspaces folder that is about to belong to nobody.
530
544
  deps.startupRetry?.stop();
545
+ // The post-sweep tidy-up: no new round, and the one under way stops at its
546
+ // next request or branch. Synchronous.
547
+ deps.workflowService?.stopTidying();
531
548
  // Clearing the interval stops future ticks; it does nothing to a job a
532
549
  // tick already started, which holds a claim it heartbeats through the
533
550
  // pool and is mid-clone or mid-push. Awaited here, in the budget: a job
@@ -543,6 +560,15 @@ async function releaseCore(deps: CoreStopDeps, remaining: () => number, log: (m:
543
560
  if (deps.agentUploadStore) {
544
561
  await bounded(deps.agentUploadStore.drainSweep(), remaining(), 'finishing the upload sweep', log);
545
562
  }
563
+ if (deps.agentDownloadStore) {
564
+ await bounded(deps.agentDownloadStore.drainSweep(), remaining(), 'finishing the download sweep', log);
565
+ }
566
+ // The tidy-up in flight fetches and deletes branches through the pool and
567
+ // the default branch's checkout: awaited, so the next graph for this
568
+ // tenant cannot find a branch deletion still running under it.
569
+ if (deps.workflowService) {
570
+ await bounded(deps.workflowService.drainTidy(), remaining(), 'finishing the branch tidy-up', log);
571
+ }
546
572
  await bounded(deps.commitWorker.stop(), remaining(), 'stopping the commit worker', log);
547
573
  if (deps.secretsScope !== undefined) unregisterBevelSecretsVariableLoader(deps.secretsScope);
548
574
  await bounded(closeDb(deps.db), remaining(), 'ending the database pool', log);
@@ -1,7 +1,7 @@
1
1
  import dotenv from 'dotenv';
2
2
  import path from 'node:path';
3
3
  import { fileURLToPath } from 'node:url';
4
- import { defaultKbTemplateDir } from './assets.js';
4
+ import { defaultKbTemplateDir, defaultStarterPacksDir } from './assets.js';
5
5
  import { assertKeyDecodesTo32Bytes } from './shared/token-crypto.js';
6
6
  import { DEFAULT_GIT_TIMEOUT_MS } from './modules/workflow/git/node-git-runner.js';
7
7
  import { DEFAULT_DB_SCHEMA, assertSchemaName } from './modules/database/connection.js';
@@ -103,11 +103,13 @@ export interface TenantConfig {
103
103
  readonly gitUsername: string;
104
104
  readonly gitToken: string;
105
105
  readonly kbTemplateDir: string;
106
+ readonly starterPacksDir: string;
106
107
  readonly updateCheckEnabled: boolean;
107
108
  readonly loginPasswordEnabled: boolean;
108
109
  readonly allowedEmailDomains: string[];
109
110
  readonly secretsEncKey: string;
110
111
  readonly internalTokenSecret: string;
112
+ readonly embedSharedSecret: string;
111
113
  readonly trustProxy: string;
112
114
  readonly gitTimeoutMs: number;
113
115
  readonly publicBackendUrl: string;
@@ -276,6 +278,14 @@ export class CoreConfig implements TenantConfig, ProcessConfig {
276
278
  * existing one. Override with `KB_TEMPLATE_DIR`.
277
279
  */
278
280
  readonly kbTemplateDir: string;
281
+ /**
282
+ * Filesystem path to the starter packs a new knowledge base's admin may
283
+ * pick from (the `starter-packs/` folder shipped inside this package — see
284
+ * `defaultStarterPacksDir()`): one folder per team, each a `pack.yaml` with
285
+ * the pages and the plugin it adds. A distribution offers its own with
286
+ * `STARTER_PACKS_DIR`; a folder holding no valid pack offers none.
287
+ */
288
+ readonly starterPacksDir: string;
279
289
  /**
280
290
  * In-app update check. When true (default), `GET /api/update-check` lazily
281
291
  * asks api.github.com for the newest Hexis release — only when an admin's
@@ -337,6 +347,17 @@ export class CoreConfig implements TenantConfig, ProcessConfig {
337
347
  * independently of user sessions.
338
348
  */
339
349
  readonly internalTokenSecret: string;
350
+ /**
351
+ * The shared secret the Atlassian connector presents to \`POST
352
+ * /api/embed/token\` (\`EMBED_SHARED_SECRET\`). Unset on a deployment that
353
+ * has no connector pointed at it, which 404s that one route — the embed
354
+ * surface itself needs no secret, because the MCP App mints through the
355
+ * authenticated MCP session instead.
356
+ *
357
+ * There is deliberately NO framing setting beside it: any site may frame
358
+ * the embed page (see the embed module), so there is no allowlist to keep.
359
+ */
360
+ readonly embedSharedSecret: string;
340
361
  /**
341
362
  * Express `trust proxy` setting, from `TRUST_PROXY`: the number of reverse
342
363
  * proxy hops in front of this backend (e.g. `1`), or an address/CIDR list
@@ -477,6 +498,7 @@ export class CoreConfig implements TenantConfig, ProcessConfig {
477
498
  // Default: the `kb-template/` folder shipped inside this package (works
478
499
  // both from src/ and compiled dist/ — see assets.ts).
479
500
  this.kbTemplateDir = process.env.KB_TEMPLATE_DIR || defaultKbTemplateDir();
501
+ this.starterPacksDir = process.env.STARTER_PACKS_DIR || defaultStarterPacksDir();
480
502
  this.updateCheckEnabled =
481
503
  (process.env.UPDATE_CHECK ?? 'true').trim().toLowerCase() !== 'false';
482
504
  this.allowedEmailDomains = (process.env.ALLOWED_EMAIL_DOMAINS || '')
@@ -503,6 +525,7 @@ export class CoreConfig implements TenantConfig, ProcessConfig {
503
525
  // key never gets past this line.
504
526
  assertKeyDecodesTo32Bytes(this.secretsEncKey, secretsKeySource);
505
527
  this.internalTokenSecret = (process.env.INTERNAL_TOKEN_SECRET || '').trim();
528
+ this.embedSharedSecret = (process.env.EMBED_SHARED_SECRET || '').trim();
506
529
  // Setting DOMAIN declares "the bundled Caddy `https` profile fronts this
507
530
  // deployment" — one proxy hop, and the public origin IS that domain. The
508
531
  // three values below therefore default from it, so `DOMAIN=x.example.com`
package/src/index.ts CHANGED
@@ -47,8 +47,8 @@ export {
47
47
  type LeasedWorker,
48
48
  } from './core/lifecycle.js';
49
49
 
50
- // Packaged assets (migrations/, kb-template/) + the migration runners.
51
- export { coreMigrationsDir, defaultKbTemplateDir } from './assets.js';
50
+ // Packaged assets (migrations/, kb-template/, agent-guide/, starter-packs/) + the migration runners.
51
+ export { agentGuideDir, coreMigrationsDir, defaultKbTemplateDir, defaultStarterPacksDir } from './assets.js';
52
52
  export {
53
53
  runCoreMigrations,
54
54
  runEnterpriseMigrations,
@@ -25,6 +25,8 @@ describe('AccessControlService — at-ref batch reads (git cat-file --batch)', (
25
25
  let svc: AccessControlService;
26
26
  const workspaceId = 'ws-atref-1';
27
27
  const admin = 'razvan@bevel.software';
28
+ /** In no role and named nowhere — read is default-deny for them. */
29
+ const stranger = 'mia@bevel.software';
28
30
 
29
31
  async function git(...args: string[]): Promise<void> {
30
32
  await execFileAsync('git', ['-C', repo, ...args]);
@@ -44,6 +46,10 @@ describe('AccessControlService — at-ref batch reads (git cat-file --batch)', (
44
46
  '---\nwrite:\n - deny razvan <razvan@bevel.software>\n---\n# denied\n',
45
47
  );
46
48
  await fs.writeFile(path.join(repo, 'Knowledge/with space.md'), '# spaced\n');
49
+ // For the read batch: a folder the whole organisation may open.
50
+ await fs.mkdir(path.join(repo, 'Knowledge/shared'), { recursive: true });
51
+ await fs.writeFile(path.join(repo, 'Knowledge/shared/access.md'), '---\nread:\n - everyone\n---\n');
52
+ await fs.writeFile(path.join(repo, 'Knowledge/shared/note.md'), '# shared\n');
47
53
 
48
54
  await execFileAsync('git', ['init', '-b', 'main', repo]);
49
55
  await git('config', 'user.email', 'test@example.com');
@@ -96,4 +102,56 @@ describe('AccessControlService — at-ref batch reads (git cat-file --batch)', (
96
102
  expect(map!.get('Knowledge/denied.md')!.emails.has(admin)).toBe(false);
97
103
  expect(map!.get('Knowledge/plain.md')!.emails.has(admin)).toBe(true);
98
104
  });
105
+
106
+ /**
107
+ * The read side of the same batch, used by the change-request read tools to
108
+ * decide which of a request's files their caller may see. The verdicts must
109
+ * be identical to the single-path `canReadAtRef` the app's own content routes
110
+ * gate on — a batch that answered even one path differently would show an
111
+ * agent a file the app refuses to open.
112
+ */
113
+ it('canReadBatchAtRef answers default-deny, an `everyone` grant, and write-implies-read in one pass', async () => {
114
+ const paths = [
115
+ 'Knowledge/plain.md',
116
+ 'Knowledge/shared/note.md',
117
+ 'Knowledge/with space.md',
118
+ 'Knowledge/not-there.md',
119
+ ];
120
+ const forStranger = await svc.canReadBatchAtRef(workspaceId, 'main', stranger, paths);
121
+ expect(forStranger).not.toBeNull();
122
+ // Nothing names them, so read is refused — except where the folder says everyone.
123
+ expect(forStranger!.get('Knowledge/plain.md')).toBe(false);
124
+ expect(forStranger!.get('Knowledge/shared/note.md')).toBe(true);
125
+ expect(forStranger!.get('Knowledge/with space.md')).toBe(false);
126
+ expect(forStranger!.get('Knowledge/not-there.md')).toBe(false);
127
+
128
+ // The Admin write grant folds into read.
129
+ const forAdmin = await svc.canReadBatchAtRef(workspaceId, 'main', admin, paths);
130
+ expect([...forAdmin!.values()]).toEqual([true, true, true, true]);
131
+ });
132
+
133
+ it('canReadBatchAtRef matches the single-path read verdict on every path', async () => {
134
+ const paths = [
135
+ 'Knowledge/plain.md',
136
+ 'Knowledge/shared/note.md',
137
+ 'Knowledge/with space.md',
138
+ 'Knowledge/not-there.md',
139
+ ];
140
+ for (const who of [admin, stranger]) {
141
+ const batch = await svc.canReadBatchAtRef(workspaceId, 'main', who, paths);
142
+ for (const path of paths) {
143
+ const single = await svc.canReadAtRef(workspaceId, 'main', who, path);
144
+ expect(batch!.get(path), `${who} on ${path}`).toBe(single);
145
+ }
146
+ }
147
+ });
148
+
149
+ it('canReadBatchAtRef answers an empty map for no paths, and null for a ref it cannot resolve', async () => {
150
+ expect(await svc.canReadBatchAtRef(workspaceId, 'main', admin, [])).toEqual(new Map());
151
+ expect(await svc.canReadBatchAtRef(workspaceId, 'no-such-ref', admin, ['Knowledge/plain.md'])).toBeNull();
152
+ // The null-semantics hold for the empty set too: the ref is validated
153
+ // whatever was asked about, so no caller can read an empty map as proof
154
+ // that the ref resolved.
155
+ expect(await svc.canReadBatchAtRef(workspaceId, 'no-such-ref', admin, [])).toBeNull();
156
+ });
99
157
  });
@@ -67,9 +67,10 @@ describe('restoring a platform file', () => {
67
67
  // only because it is the file that says who the admin is — the repository
68
68
  // that lost that one too is the last case in this file.
69
69
  const svc = service();
70
- for (const name of ['.bevelignore', 'AGENTS.md']) {
71
- expect(await svc.canRestorePlatformFile(WS, ADMIN, name)).toBe(true);
72
- }
70
+ expect(await svc.canRestorePlatformFile(WS, ADMIN, '.bevelignore')).toBe(true);
71
+ // The agent guide is not a platform file: it is served from code, never
72
+ // written to the root, so a root `AGENTS.md` is content and no restore.
73
+ expect(await svc.canRestorePlatformFile(WS, ADMIN, 'AGENTS.md')).toBe(false);
73
74
  // Nothing is missing at `roles.yaml`: the root has one. A move is a rename
74
75
  // on disk, so landing another there would REPLACE the admin model rather
75
76
  // than put it back, and no exception carries that.
@@ -95,9 +96,9 @@ describe('restoring a platform file', () => {
95
96
  expect(await svc.canRestorePlatformFile(WS, ENGINEER, 'Sales/Legal/access.md')).toBe(false);
96
97
  });
97
98
 
98
- it('the three root-only names are a restore at the root and nowhere else', async () => {
99
+ it('the root-only names are a restore at the root and nowhere else', async () => {
99
100
  const svc = service();
100
- for (const dest of ['Sales/roles.yaml', 'Sales/.bevelignore', 'Sales/AGENTS.md']) {
101
+ for (const dest of ['Sales/roles.yaml', 'Sales/.bevelignore']) {
101
102
  expect(await svc.canRestorePlatformFile(WS, ADMIN, dest)).toBe(false);
102
103
  }
103
104
  });
@@ -113,14 +114,14 @@ describe('restoring a platform file', () => {
113
114
 
114
115
  it('a non-admin never gets the exception, wherever it would land', async () => {
115
116
  const svc = service();
116
- for (const dest of ['roles.yaml', '.bevelignore', 'AGENTS.md', 'access.md', 'Legal/access.md']) {
117
+ for (const dest of ['roles.yaml', '.bevelignore', 'access.md', 'Legal/access.md']) {
117
118
  expect(await svc.canRestorePlatformFile(WS, ENGINEER, dest)).toBe(false);
118
119
  }
119
120
  });
120
121
 
121
122
  it('the deployment owner is an admin for it, and an ordinary destination is not a restore for anyone', async () => {
122
123
  const svc = service();
123
- expect(await svc.canRestorePlatformFile(WS, OWNER, 'AGENTS.md')).toBe(true);
124
+ expect(await svc.canRestorePlatformFile(WS, OWNER, '.bevelignore')).toBe(true);
124
125
  for (const email of [ADMIN, OWNER]) {
125
126
  expect(await svc.canRestorePlatformFile(WS, email, 'Sales/deal.md')).toBe(false);
126
127
  expect(await svc.canRestorePlatformFile(WS, email, 'Sales/notes.md')).toBe(false);
@@ -216,6 +216,25 @@ describe('AccessControlService', () => {
216
216
  expect(await svc.canWrite(workspaceId, 'ali@bevel.software', 'Knowledge/Secret/Foo.md')).toBe(false);
217
217
  });
218
218
 
219
+ // What deleting a nested access.md (delete_file, or the app's delete) does:
220
+ // the folder falls back to its parent's rules, nothing else to undo.
221
+ it('once a nested access.md is deleted, its folder follows the parent\'s rules', async () => {
222
+ const { workspaceDir, repo } = await seedWorkspace(root, workspaceId);
223
+ await writeFile(repo, 'roles.yaml', ROLES_YAML);
224
+ await writeFile(repo, 'access.md', '---\nread:\n - everyone\nwrite:\n - Admin\n---\n');
225
+ await writeFile(repo, 'Team/access.md', '---\nread:\n - deny Felix Kissel <felix@example.com>\n---\n');
226
+ await writeFile(repo, 'Team/plan.md', 'plan');
227
+
228
+ const svc = new AccessControlService(stubWorkspaceService(workspaceId, workspaceDir), PROCESS_MAP_DIR, new NodeFs());
229
+ expect(await svc.canRead(workspaceId, 'felix@example.com', 'Team/plan.md')).toBe(false);
230
+
231
+ await fs.rm(path.join(repo, 'Team/access.md'));
232
+ svc.invalidate(workspaceId);
233
+
234
+ expect(await svc.canRead(workspaceId, 'felix@example.com', 'Team/plan.md')).toBe(true);
235
+ expect(await svc.canWrite(workspaceId, 'felix@example.com', 'Team/plan.md')).toBe(false);
236
+ });
237
+
219
238
  it('closeness beats tier: a closer everyone grant overrides a farther email deny', async () => {
220
239
  const { workspaceDir, repo } = await seedWorkspace(root, workspaceId);
221
240
  await writeFile(repo, 'roles.yaml', ROLES_YAML);