@bevel-software/platform-core-backend 0.32.0 → 0.34.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 (1188) hide show
  1. package/agent-guide/access-control.md +24 -8
  2. package/agent-guide/html-views.md +277 -15
  3. package/agent-guide/tool-manuals.md +1 -1
  4. package/dist/core/catalog-revision.d.ts +12 -1
  5. package/dist/core/catalog-revision.d.ts.map +1 -1
  6. package/dist/core/catalog-revision.js +23 -3
  7. package/dist/core/catalog-revision.js.map +1 -1
  8. package/dist/core/core-ports.d.ts +41 -0
  9. package/dist/core/core-ports.d.ts.map +1 -1
  10. package/dist/core/core-ports.js.map +1 -1
  11. package/dist/core/create-core-server.d.ts.map +1 -1
  12. package/dist/core/create-core-server.js +42 -10
  13. package/dist/core/create-core-server.js.map +1 -1
  14. package/dist/core/create-core-services.d.ts +22 -6
  15. package/dist/core/create-core-services.d.ts.map +1 -1
  16. package/dist/core/create-core-services.js +58 -17
  17. package/dist/core/create-core-services.js.map +1 -1
  18. package/dist/core/lifecycle.d.ts +24 -0
  19. package/dist/core/lifecycle.d.ts.map +1 -1
  20. package/dist/core/lifecycle.js +16 -2
  21. package/dist/core/lifecycle.js.map +1 -1
  22. package/dist/core/public-config.d.ts +10 -0
  23. package/dist/core/public-config.d.ts.map +1 -1
  24. package/dist/core/public-config.js +10 -0
  25. package/dist/core/public-config.js.map +1 -1
  26. package/dist/index.d.ts +1 -1
  27. package/dist/index.d.ts.map +1 -1
  28. package/dist/index.js.map +1 -1
  29. package/dist/modules/access/access-control.interface.d.ts +17 -9
  30. package/dist/modules/access/access-control.interface.d.ts.map +1 -1
  31. package/dist/modules/access/access-control.service.d.ts +13 -3
  32. package/dist/modules/access/access-control.service.d.ts.map +1 -1
  33. package/dist/modules/access/access-control.service.js +165 -77
  34. package/dist/modules/access/access-control.service.js.map +1 -1
  35. package/dist/modules/access/access-declarations.d.ts +1 -1
  36. package/dist/modules/access/access-declarations.d.ts.map +1 -1
  37. package/dist/modules/access/access-declarations.js +1 -1
  38. package/dist/modules/access/access-declarations.js.map +1 -1
  39. package/dist/modules/access/access-mutation.service.d.ts +28 -25
  40. package/dist/modules/access/access-mutation.service.d.ts.map +1 -1
  41. package/dist/modules/access/access-mutation.service.js +50 -53
  42. package/dist/modules/access/access-mutation.service.js.map +1 -1
  43. package/dist/modules/access/access-requests.contract.d.ts +1 -1
  44. package/dist/modules/access/access-requests.contract.d.ts.map +1 -1
  45. package/dist/modules/access/access-requests.routes.d.ts +3 -3
  46. package/dist/modules/access/access-requests.routes.d.ts.map +1 -1
  47. package/dist/modules/access/access-requests.routes.js +7 -7
  48. package/dist/modules/access/access-requests.routes.js.map +1 -1
  49. package/dist/modules/access/access-requests.service.d.ts +21 -20
  50. package/dist/modules/access/access-requests.service.d.ts.map +1 -1
  51. package/dist/modules/access/access-requests.service.js +22 -68
  52. package/dist/modules/access/access-requests.service.js.map +1 -1
  53. package/dist/modules/access/access-view.d.ts +1 -1
  54. package/dist/modules/access/access-view.d.ts.map +1 -1
  55. package/dist/modules/access/access-view.js +12 -11
  56. package/dist/modules/access/access-view.js.map +1 -1
  57. package/dist/modules/access/access.routes.d.ts +8 -7
  58. package/dist/modules/access/access.routes.d.ts.map +1 -1
  59. package/dist/modules/access/access.routes.js +38 -32
  60. package/dist/modules/access/access.routes.js.map +1 -1
  61. package/dist/modules/access/admin-locked-commit.d.ts +2 -2
  62. package/dist/modules/access/admin-locked-commit.d.ts.map +1 -1
  63. package/dist/modules/access/admin-locked-commit.js +1 -1
  64. package/dist/modules/access/admin-locked-commit.js.map +1 -1
  65. package/dist/modules/access/capability-registry.js +1 -1
  66. package/dist/modules/access/capability-registry.js.map +1 -1
  67. package/dist/modules/access/change-read-gate.d.ts +2 -2
  68. package/dist/modules/access/change-read-gate.d.ts.map +1 -1
  69. package/dist/modules/access/change-read-gate.js +1 -3
  70. package/dist/modules/access/change-read-gate.js.map +1 -1
  71. package/dist/modules/access/creator-access.d.ts +2 -2
  72. package/dist/modules/access/creator-access.d.ts.map +1 -1
  73. package/dist/modules/access/creator-access.js +2 -4
  74. package/dist/modules/access/creator-access.js.map +1 -1
  75. package/dist/modules/access/directory-sync-bot.d.ts +1 -1
  76. package/dist/modules/access/directory-sync-bot.d.ts.map +1 -1
  77. package/dist/modules/access/directory-sync-bot.js +1 -1
  78. package/dist/modules/access/directory-sync-bot.js.map +1 -1
  79. package/dist/modules/access/groups-admin.routes.d.ts +2 -2
  80. package/dist/modules/access/groups-admin.routes.d.ts.map +1 -1
  81. package/dist/modules/access/groups-admin.routes.js +6 -4
  82. package/dist/modules/access/groups-admin.routes.js.map +1 -1
  83. package/dist/modules/access/groups-admin.service.d.ts +45 -14
  84. package/dist/modules/access/groups-admin.service.d.ts.map +1 -1
  85. package/dist/modules/access/groups-admin.service.js +80 -39
  86. package/dist/modules/access/groups-admin.service.js.map +1 -1
  87. package/dist/modules/access/groups-edit.d.ts +1 -1
  88. package/dist/modules/access/groups-edit.d.ts.map +1 -1
  89. package/dist/modules/access/groups-edit.js +3 -3
  90. package/dist/modules/access/groups-edit.js.map +1 -1
  91. package/dist/modules/access/index.d.ts +17 -0
  92. package/dist/modules/access/index.d.ts.map +1 -0
  93. package/dist/modules/access/index.js +6 -0
  94. package/dist/modules/access/index.js.map +1 -0
  95. package/dist/modules/access/reference-scan.d.ts +116 -24
  96. package/dist/modules/access/reference-scan.d.ts.map +1 -1
  97. package/dist/modules/access/reference-scan.js +305 -44
  98. package/dist/modules/access/reference-scan.js.map +1 -1
  99. package/dist/modules/access/roles-admin.service.d.ts +18 -9
  100. package/dist/modules/access/roles-admin.service.d.ts.map +1 -1
  101. package/dist/modules/access/roles-admin.service.js +32 -26
  102. package/dist/modules/access/roles-admin.service.js.map +1 -1
  103. package/dist/modules/access/roles-edit.js +1 -1
  104. package/dist/modules/access/roles-edit.js.map +1 -1
  105. package/dist/modules/access/synced-groups-committer.d.ts +2 -2
  106. package/dist/modules/access/synced-groups-committer.d.ts.map +1 -1
  107. package/dist/modules/access/synced-groups-committer.js +2 -2
  108. package/dist/modules/access/synced-groups-committer.js.map +1 -1
  109. package/dist/modules/access/synced-groups-writer.js +2 -2
  110. package/dist/modules/access/synced-groups-writer.js.map +1 -1
  111. package/dist/modules/access/user-access-removal.service.d.ts +1 -1
  112. package/dist/modules/access/user-access-removal.service.d.ts.map +1 -1
  113. package/dist/modules/access/user-access-removal.service.js +2 -5
  114. package/dist/modules/access/user-access-removal.service.js.map +1 -1
  115. package/dist/modules/access-model/access-grammar.d.ts +35 -10
  116. package/dist/modules/access-model/access-grammar.d.ts.map +1 -1
  117. package/dist/modules/access-model/access-grammar.js +60 -20
  118. package/dist/modules/access-model/access-grammar.js.map +1 -1
  119. package/dist/modules/access-model/access-splice.d.ts +22 -18
  120. package/dist/modules/access-model/access-splice.d.ts.map +1 -1
  121. package/dist/modules/access-model/access-splice.js +20 -14
  122. package/dist/modules/access-model/access-splice.js.map +1 -1
  123. package/dist/modules/access-model/group-files.d.ts +1 -0
  124. package/dist/modules/access-model/group-files.d.ts.map +1 -1
  125. package/dist/modules/access-model/group-files.js +5 -1
  126. package/dist/modules/access-model/group-files.js.map +1 -1
  127. package/dist/modules/access-model/index.d.ts +20 -5
  128. package/dist/modules/access-model/index.d.ts.map +1 -1
  129. package/dist/modules/access-model/index.js +18 -5
  130. package/dist/modules/access-model/index.js.map +1 -1
  131. package/dist/modules/access-model/roles-yaml-guard.d.ts +1 -1
  132. package/dist/modules/access-model/roles-yaml-guard.d.ts.map +1 -1
  133. package/dist/modules/admin/admin-access.routes.d.ts +1 -1
  134. package/dist/modules/admin/admin-access.routes.d.ts.map +1 -1
  135. package/dist/modules/admin/admin-access.routes.js +1 -1
  136. package/dist/modules/admin/admin-access.routes.js.map +1 -1
  137. package/dist/modules/admin/admin-access.service.d.ts +2 -2
  138. package/dist/modules/admin/admin-access.service.d.ts.map +1 -1
  139. package/dist/modules/admin/index.d.ts +8 -0
  140. package/dist/modules/admin/index.d.ts.map +1 -0
  141. package/dist/modules/admin/index.js +2 -0
  142. package/dist/modules/admin/index.js.map +1 -0
  143. package/dist/modules/agent-guide/agent-guide.js +1 -1
  144. package/dist/modules/agent-guide/agent-guide.js.map +1 -1
  145. package/dist/modules/agent-guide/agent-guide.tools.d.ts +3 -3
  146. package/dist/modules/agent-guide/agent-guide.tools.d.ts.map +1 -1
  147. package/dist/modules/agent-guide/agent-guide.tools.js +15 -7
  148. package/dist/modules/agent-guide/agent-guide.tools.js.map +1 -1
  149. package/dist/modules/agent-guide/index.d.ts +1 -1
  150. package/dist/modules/agent-guide/index.d.ts.map +1 -1
  151. package/dist/modules/agent-guide/index.js +1 -1
  152. package/dist/modules/agent-guide/index.js.map +1 -1
  153. package/dist/modules/agent-instructions/compose.d.ts +3 -1
  154. package/dist/modules/agent-instructions/compose.d.ts.map +1 -1
  155. package/dist/modules/agent-instructions/compose.js +3 -1
  156. package/dist/modules/agent-instructions/compose.js.map +1 -1
  157. package/dist/modules/agent-instructions/read-preamble.d.ts +1 -1
  158. package/dist/modules/agent-instructions/read-preamble.d.ts.map +1 -1
  159. package/dist/modules/agent-instructions/shared-file-rules.d.ts +5 -1
  160. package/dist/modules/agent-instructions/shared-file-rules.d.ts.map +1 -1
  161. package/dist/modules/agent-instructions/shared-file-rules.js +16 -1
  162. package/dist/modules/agent-instructions/shared-file-rules.js.map +1 -1
  163. package/dist/modules/agent-scope/agent-scope.contract.d.ts +67 -0
  164. package/dist/modules/agent-scope/agent-scope.contract.d.ts.map +1 -0
  165. package/dist/modules/agent-scope/agent-scope.contract.js +27 -0
  166. package/dist/modules/agent-scope/agent-scope.contract.js.map +1 -0
  167. package/dist/modules/agent-scope/connection-scope.d.ts +111 -0
  168. package/dist/modules/agent-scope/connection-scope.d.ts.map +1 -0
  169. package/dist/modules/agent-scope/connection-scope.js +165 -0
  170. package/dist/modules/agent-scope/connection-scope.js.map +1 -0
  171. package/dist/modules/agent-scope/index.d.ts +3 -0
  172. package/dist/modules/agent-scope/index.d.ts.map +1 -0
  173. package/dist/modules/agent-scope/index.js +3 -0
  174. package/dist/modules/agent-scope/index.js.map +1 -0
  175. package/dist/modules/audit/agent-audit.service.d.ts +2 -2
  176. package/dist/modules/audit/agent-audit.service.d.ts.map +1 -1
  177. package/dist/modules/audit/agent-audit.service.js +3 -1
  178. package/dist/modules/audit/agent-audit.service.js.map +1 -1
  179. package/dist/modules/audit/agent-connection.routes.d.ts +1 -1
  180. package/dist/modules/audit/agent-connection.routes.d.ts.map +1 -1
  181. package/dist/modules/audit/agent-connection.routes.js +1 -1
  182. package/dist/modules/audit/agent-connection.routes.js.map +1 -1
  183. package/dist/modules/audit/agent-rest-audit.middleware.d.ts +1 -1
  184. package/dist/modules/audit/agent-rest-audit.middleware.d.ts.map +1 -1
  185. package/dist/modules/audit/agent-rest-audit.middleware.js +1 -1
  186. package/dist/modules/audit/agent-rest-audit.middleware.js.map +1 -1
  187. package/dist/modules/audit/audit.contract.d.ts +6 -0
  188. package/dist/modules/audit/audit.contract.d.ts.map +1 -1
  189. package/dist/modules/audit/audit.contract.js.map +1 -1
  190. package/dist/modules/audit/audit.routes.d.ts +3 -3
  191. package/dist/modules/audit/audit.routes.d.ts.map +1 -1
  192. package/dist/modules/audit/audit.routes.js +2 -2
  193. package/dist/modules/audit/audit.routes.js.map +1 -1
  194. package/dist/modules/auth/account-admission.d.ts +12 -0
  195. package/dist/modules/auth/account-admission.d.ts.map +1 -1
  196. package/dist/modules/auth/account-admission.js +15 -0
  197. package/dist/modules/auth/account-admission.js.map +1 -1
  198. package/dist/modules/auth/account-erasure.service.d.ts +3 -3
  199. package/dist/modules/auth/account-erasure.service.d.ts.map +1 -1
  200. package/dist/modules/auth/account-erasure.service.js +1 -5
  201. package/dist/modules/auth/account-erasure.service.js.map +1 -1
  202. package/dist/modules/auth/account-switch-lock.d.ts +1 -1
  203. package/dist/modules/auth/account-switch-lock.d.ts.map +1 -1
  204. package/dist/modules/auth/account-switch-lock.js +1 -1
  205. package/dist/modules/auth/account-switch-lock.js.map +1 -1
  206. package/dist/modules/auth/account.routes.d.ts +2 -2
  207. package/dist/modules/auth/account.routes.d.ts.map +1 -1
  208. package/dist/modules/auth/account.routes.js +1 -1
  209. package/dist/modules/auth/account.routes.js.map +1 -1
  210. package/dist/modules/auth/auth.middleware.d.ts +27 -1
  211. package/dist/modules/auth/auth.middleware.d.ts.map +1 -1
  212. package/dist/modules/auth/auth.middleware.js +42 -4
  213. package/dist/modules/auth/auth.middleware.js.map +1 -1
  214. package/dist/modules/auth/auth.routes.d.ts +13 -9
  215. package/dist/modules/auth/auth.routes.d.ts.map +1 -1
  216. package/dist/modules/auth/auth.routes.js +35 -29
  217. package/dist/modules/auth/auth.routes.js.map +1 -1
  218. package/dist/modules/auth/auth.service.d.ts +56 -7
  219. package/dist/modules/auth/auth.service.d.ts.map +1 -1
  220. package/dist/modules/auth/auth.service.js +131 -37
  221. package/dist/modules/auth/auth.service.js.map +1 -1
  222. package/dist/modules/auth/index.d.ts +3 -1
  223. package/dist/modules/auth/index.d.ts.map +1 -1
  224. package/dist/modules/auth/index.js +1 -1
  225. package/dist/modules/auth/index.js.map +1 -1
  226. package/dist/modules/auth/oidc-auth-provider.d.ts.map +1 -1
  227. package/dist/modules/auth/oidc-auth-provider.js +3 -10
  228. package/dist/modules/auth/oidc-auth-provider.js.map +1 -1
  229. package/dist/modules/code-mode/code-mode.tool.d.ts +1 -1
  230. package/dist/modules/code-mode/code-mode.tool.d.ts.map +1 -1
  231. package/dist/modules/connection-probe/connection-probe.service.d.ts +2 -2
  232. package/dist/modules/connection-probe/connection-probe.service.d.ts.map +1 -1
  233. package/dist/modules/connection-probe/connection-probe.service.js +1 -4
  234. package/dist/modules/connection-probe/connection-probe.service.js.map +1 -1
  235. package/dist/modules/database/core-schema.d.ts +175 -234
  236. package/dist/modules/database/core-schema.d.ts.map +1 -1
  237. package/dist/modules/database/core-schema.js +72 -35
  238. package/dist/modules/database/core-schema.js.map +1 -1
  239. package/dist/modules/database/index.d.ts +10 -0
  240. package/dist/modules/database/index.d.ts.map +1 -0
  241. package/dist/modules/database/index.js +4 -0
  242. package/dist/modules/database/index.js.map +1 -0
  243. package/dist/modules/database/migrate.d.ts.map +1 -1
  244. package/dist/modules/database/migrate.js +78 -3
  245. package/dist/modules/database/migrate.js.map +1 -1
  246. package/dist/modules/declared-variables/declared-variables.routes.d.ts +10 -3
  247. package/dist/modules/declared-variables/declared-variables.routes.d.ts.map +1 -1
  248. package/dist/modules/declared-variables/declared-variables.routes.js +13 -2
  249. package/dist/modules/declared-variables/declared-variables.routes.js.map +1 -1
  250. package/dist/modules/diff/diff.routes.d.ts +3 -3
  251. package/dist/modules/diff/diff.routes.d.ts.map +1 -1
  252. package/dist/modules/diff/diff.routes.js +3 -3
  253. package/dist/modules/diff/diff.routes.js.map +1 -1
  254. package/dist/modules/diff/diff.service.d.ts +2 -2
  255. package/dist/modules/diff/diff.service.d.ts.map +1 -1
  256. package/dist/modules/diff/index.d.ts +7 -0
  257. package/dist/modules/diff/index.d.ts.map +1 -0
  258. package/dist/modules/diff/index.js +2 -0
  259. package/dist/modules/diff/index.js.map +1 -0
  260. package/dist/modules/embed/account-link.service.d.ts +1 -1
  261. package/dist/modules/embed/account-link.service.d.ts.map +1 -1
  262. package/dist/modules/embed/account-link.service.js +1 -1
  263. package/dist/modules/embed/account-link.service.js.map +1 -1
  264. package/dist/modules/embed/embed.routes.d.ts +1 -1
  265. package/dist/modules/embed/embed.routes.d.ts.map +1 -1
  266. package/dist/modules/embed/embed.routes.js +2 -2
  267. package/dist/modules/embed/embed.routes.js.map +1 -1
  268. package/dist/modules/embed/embed.service.d.ts +1 -1
  269. package/dist/modules/embed/embed.service.d.ts.map +1 -1
  270. package/dist/modules/embed/embed.tools.d.ts +4 -4
  271. package/dist/modules/embed/embed.tools.d.ts.map +1 -1
  272. package/dist/modules/embed/embed.tools.js +8 -5
  273. package/dist/modules/embed/embed.tools.js.map +1 -1
  274. package/dist/modules/github-app/github-app.connection.d.ts +1 -1
  275. package/dist/modules/github-app/github-app.connection.d.ts.map +1 -1
  276. package/dist/modules/github-app/github-app.routes.d.ts +3 -3
  277. package/dist/modules/github-app/github-app.routes.d.ts.map +1 -1
  278. package/dist/modules/github-app/github-app.routes.js +1 -1
  279. package/dist/modules/github-app/github-app.routes.js.map +1 -1
  280. package/dist/modules/kb-fs/index.d.ts +12 -0
  281. package/dist/modules/kb-fs/index.d.ts.map +1 -1
  282. package/dist/modules/kb-fs/index.js +11 -0
  283. package/dist/modules/kb-fs/index.js.map +1 -1
  284. package/dist/modules/kb-fs/locking-filesystem.d.ts +1 -1
  285. package/dist/modules/kb-fs/locking-filesystem.d.ts.map +1 -1
  286. package/dist/modules/kb-fs/locking-filesystem.js +7 -1
  287. package/dist/modules/kb-fs/locking-filesystem.js.map +1 -1
  288. package/dist/modules/kb-fs/repo-path.d.ts +26 -6
  289. package/dist/modules/kb-fs/repo-path.d.ts.map +1 -1
  290. package/dist/modules/kb-fs/repo-path.js +22 -7
  291. package/dist/modules/kb-fs/repo-path.js.map +1 -1
  292. package/dist/modules/kb-fs/tmp-ref.d.ts +36 -0
  293. package/dist/modules/kb-fs/tmp-ref.d.ts.map +1 -0
  294. package/dist/modules/kb-fs/tmp-ref.js +76 -0
  295. package/dist/modules/kb-fs/tmp-ref.js.map +1 -0
  296. package/dist/modules/kb-sync/kb-sync.routes.d.ts +1 -1
  297. package/dist/modules/kb-sync/kb-sync.routes.d.ts.map +1 -1
  298. package/dist/modules/kb-sync/kb-sync.routes.js +2 -2
  299. package/dist/modules/kb-sync/kb-sync.routes.js.map +1 -1
  300. package/dist/modules/kb-sync/kb-sync.service.js +1 -1
  301. package/dist/modules/kb-sync/kb-sync.service.js.map +1 -1
  302. package/dist/modules/kb-sync/sync-auth.js +1 -1
  303. package/dist/modules/kb-sync/sync-auth.js.map +1 -1
  304. package/dist/modules/kb-sync/sync-payload.js +1 -1
  305. package/dist/modules/kb-sync/sync-payload.js.map +1 -1
  306. package/dist/modules/marketplace/git-http.routes.d.ts +1 -1
  307. package/dist/modules/marketplace/git-http.routes.d.ts.map +1 -1
  308. package/dist/modules/marketplace/git-http.routes.js +1 -1
  309. package/dist/modules/marketplace/git-http.routes.js.map +1 -1
  310. package/dist/modules/marketplace/github-facade/github-facade-admin.routes.d.ts +1 -1
  311. package/dist/modules/marketplace/github-facade/github-facade-admin.routes.d.ts.map +1 -1
  312. package/dist/modules/marketplace/github-facade/github-facade-admin.routes.js +1 -1
  313. package/dist/modules/marketplace/github-facade/github-facade-admin.routes.js.map +1 -1
  314. package/dist/modules/marketplace/github-facade/github-facade-codes.store.d.ts +1 -1
  315. package/dist/modules/marketplace/github-facade/github-facade-codes.store.d.ts.map +1 -1
  316. package/dist/modules/marketplace/github-facade/github-facade-codes.store.js +1 -1
  317. package/dist/modules/marketplace/github-facade/github-facade-codes.store.js.map +1 -1
  318. package/dist/modules/marketplace/github-facade/github-facade-credentials.service.d.ts +1 -1
  319. package/dist/modules/marketplace/github-facade/github-facade-credentials.service.d.ts.map +1 -1
  320. package/dist/modules/marketplace/github-facade/github-facade-credentials.service.js +1 -1
  321. package/dist/modules/marketplace/github-facade/github-facade-credentials.service.js.map +1 -1
  322. package/dist/modules/marketplace/github-facade/github-facade.routes.d.ts +2 -2
  323. package/dist/modules/marketplace/github-facade/github-facade.routes.d.ts.map +1 -1
  324. package/dist/modules/marketplace/github-facade/github-facade.routes.js +2 -2
  325. package/dist/modules/marketplace/github-facade/github-facade.routes.js.map +1 -1
  326. package/dist/modules/marketplace/github-facade/github-facade.service.d.ts +2 -2
  327. package/dist/modules/marketplace/github-facade/github-facade.service.d.ts.map +1 -1
  328. package/dist/modules/marketplace/github-facade/github-facade.service.js +1 -1
  329. package/dist/modules/marketplace/github-facade/github-facade.service.js.map +1 -1
  330. package/dist/modules/marketplace/marketplace-repo.service.d.ts +1 -1
  331. package/dist/modules/marketplace/marketplace-repo.service.d.ts.map +1 -1
  332. package/dist/modules/marketplace/marketplace-repo.service.js +1 -1
  333. package/dist/modules/mcp/index.d.ts +8 -0
  334. package/dist/modules/mcp/index.d.ts.map +1 -0
  335. package/dist/modules/mcp/index.js +7 -0
  336. package/dist/modules/mcp/index.js.map +1 -0
  337. package/dist/modules/mcp/mcp-auth.middleware.d.ts +11 -5
  338. package/dist/modules/mcp/mcp-auth.middleware.d.ts.map +1 -1
  339. package/dist/modules/mcp/mcp-auth.middleware.js +18 -5
  340. package/dist/modules/mcp/mcp-auth.middleware.js.map +1 -1
  341. package/dist/modules/mcp/mcp.routes.d.ts +9 -5
  342. package/dist/modules/mcp/mcp.routes.d.ts.map +1 -1
  343. package/dist/modules/mcp/mcp.routes.js +41 -6
  344. package/dist/modules/mcp/mcp.routes.js.map +1 -1
  345. package/dist/modules/mcp/mcp.service.d.ts +25 -4
  346. package/dist/modules/mcp/mcp.service.d.ts.map +1 -1
  347. package/dist/modules/mcp/mcp.service.js +84 -19
  348. package/dist/modules/mcp/mcp.service.js.map +1 -1
  349. package/dist/modules/mcp/oauth/bevel-oauth-provider.d.ts +25 -2
  350. package/dist/modules/mcp/oauth/bevel-oauth-provider.d.ts.map +1 -1
  351. package/dist/modules/mcp/oauth/bevel-oauth-provider.js +46 -11
  352. package/dist/modules/mcp/oauth/bevel-oauth-provider.js.map +1 -1
  353. package/dist/modules/mcp/oauth/oauth-consent.routes.d.ts +10 -1
  354. package/dist/modules/mcp/oauth/oauth-consent.routes.d.ts.map +1 -1
  355. package/dist/modules/mcp/oauth/oauth-consent.routes.js +35 -2
  356. package/dist/modules/mcp/oauth/oauth-consent.routes.js.map +1 -1
  357. package/dist/modules/onboarding/onboarding.routes.d.ts +1 -1
  358. package/dist/modules/onboarding/onboarding.routes.d.ts.map +1 -1
  359. package/dist/modules/onboarding/onboarding.routes.js +1 -1
  360. package/dist/modules/onboarding/onboarding.routes.js.map +1 -1
  361. package/dist/modules/onboarding/starter-pack.service.d.ts +4 -5
  362. package/dist/modules/onboarding/starter-pack.service.d.ts.map +1 -1
  363. package/dist/modules/onboarding/starter-pack.service.js +2 -2
  364. package/dist/modules/onboarding/starter-pack.service.js.map +1 -1
  365. package/dist/modules/plugins/compile/compile-marketplace.d.ts +1 -1
  366. package/dist/modules/plugins/compile/compile-marketplace.d.ts.map +1 -1
  367. package/dist/modules/plugins/compile/compile-marketplace.js +1 -1
  368. package/dist/modules/plugins/compile/compile-marketplace.js.map +1 -1
  369. package/dist/modules/plugins/compile/marketplace-compiler.service.d.ts +3 -3
  370. package/dist/modules/plugins/compile/marketplace-compiler.service.d.ts.map +1 -1
  371. package/dist/modules/plugins/discovery/bundle-dialect/registry.d.ts +1 -1
  372. package/dist/modules/plugins/discovery/bundle-dialect/registry.d.ts.map +1 -1
  373. package/dist/modules/plugins/discovery/bundle-dialect/registry.js +1 -1
  374. package/dist/modules/plugins/discovery/bundle-dialect/registry.js.map +1 -1
  375. package/dist/modules/plugins/index.d.ts +2 -1
  376. package/dist/modules/plugins/index.d.ts.map +1 -1
  377. package/dist/modules/plugins/index.js +2 -0
  378. package/dist/modules/plugins/index.js.map +1 -1
  379. package/dist/modules/plugins/join-proposals.d.ts +2 -2
  380. package/dist/modules/plugins/join-proposals.d.ts.map +1 -1
  381. package/dist/modules/plugins/join-proposals.js +1 -1
  382. package/dist/modules/plugins/join-proposals.js.map +1 -1
  383. package/dist/modules/plugins/join-request-jobs.service.d.ts +1 -1
  384. package/dist/modules/plugins/join-request-jobs.service.d.ts.map +1 -1
  385. package/dist/modules/plugins/join-request-jobs.service.js +2 -2
  386. package/dist/modules/plugins/join-request-jobs.service.js.map +1 -1
  387. package/dist/modules/plugins/join-request-records.store.d.ts +1 -1
  388. package/dist/modules/plugins/join-request-records.store.d.ts.map +1 -1
  389. package/dist/modules/plugins/join-request-records.store.js +1 -1
  390. package/dist/modules/plugins/join-request-records.store.js.map +1 -1
  391. package/dist/modules/plugins/join-requests.service.d.ts +3 -3
  392. package/dist/modules/plugins/join-requests.service.d.ts.map +1 -1
  393. package/dist/modules/plugins/join-requests.service.js +1 -1
  394. package/dist/modules/plugins/join-requests.service.js.map +1 -1
  395. package/dist/modules/plugins/plugin-links.d.ts +21 -5
  396. package/dist/modules/plugins/plugin-links.d.ts.map +1 -1
  397. package/dist/modules/plugins/plugin-links.js +1 -1
  398. package/dist/modules/plugins/plugin-links.js.map +1 -1
  399. package/dist/modules/plugins/plugin-links.service.d.ts +8 -5
  400. package/dist/modules/plugins/plugin-links.service.d.ts.map +1 -1
  401. package/dist/modules/plugins/plugin-links.service.js +8 -6
  402. package/dist/modules/plugins/plugin-links.service.js.map +1 -1
  403. package/dist/modules/plugins/plugin-provision.service.d.ts +2 -2
  404. package/dist/modules/plugins/plugin-provision.service.d.ts.map +1 -1
  405. package/dist/modules/plugins/plugin-provision.service.js +2 -3
  406. package/dist/modules/plugins/plugin-provision.service.js.map +1 -1
  407. package/dist/modules/plugins/plugin-rename.service.d.ts +2 -2
  408. package/dist/modules/plugins/plugin-rename.service.d.ts.map +1 -1
  409. package/dist/modules/plugins/plugin-rename.service.js +1 -1
  410. package/dist/modules/plugins/plugin-rename.service.js.map +1 -1
  411. package/dist/modules/plugins/plugins.contract.d.ts +1 -1
  412. package/dist/modules/plugins/plugins.contract.d.ts.map +1 -1
  413. package/dist/modules/plugins/plugins.routes.d.ts +7 -3
  414. package/dist/modules/plugins/plugins.routes.d.ts.map +1 -1
  415. package/dist/modules/plugins/plugins.routes.js +35 -8
  416. package/dist/modules/plugins/plugins.routes.js.map +1 -1
  417. package/dist/modules/plugins/plugins.service.d.ts +4 -4
  418. package/dist/modules/plugins/plugins.service.d.ts.map +1 -1
  419. package/dist/modules/plugins/plugins.service.js +1 -1
  420. package/dist/modules/plugins/plugins.service.js.map +1 -1
  421. package/dist/modules/plugins/plugins.tools.d.ts +1 -1
  422. package/dist/modules/plugins/plugins.tools.d.ts.map +1 -1
  423. package/dist/modules/plugins/plugins.tools.js +3 -3
  424. package/dist/modules/plugins/plugins.tools.js.map +1 -1
  425. package/dist/modules/plugins/teams.routes.d.ts +3 -3
  426. package/dist/modules/plugins/teams.routes.d.ts.map +1 -1
  427. package/dist/modules/secrets-vault/db-secrets-vault.service.d.ts +1 -1
  428. package/dist/modules/secrets-vault/db-secrets-vault.service.d.ts.map +1 -1
  429. package/dist/modules/secrets-vault/db-secrets-vault.service.js +1 -1
  430. package/dist/modules/secrets-vault/db-secrets-vault.service.js.map +1 -1
  431. package/dist/modules/secrets-vault/index.d.ts +1 -0
  432. package/dist/modules/secrets-vault/index.d.ts.map +1 -1
  433. package/dist/modules/secrets-vault/index.js +2 -0
  434. package/dist/modules/secrets-vault/index.js.map +1 -1
  435. package/dist/modules/secrets-vault/secrets-vault.routes.d.ts +13 -4
  436. package/dist/modules/secrets-vault/secrets-vault.routes.d.ts.map +1 -1
  437. package/dist/modules/secrets-vault/secrets-vault.routes.js +16 -4
  438. package/dist/modules/secrets-vault/secrets-vault.routes.js.map +1 -1
  439. package/dist/modules/settings/connection-check.js +1 -1
  440. package/dist/modules/settings/connection-check.js.map +1 -1
  441. package/dist/modules/settings/deployment-settings.service.d.ts +7 -1
  442. package/dist/modules/settings/deployment-settings.service.d.ts.map +1 -1
  443. package/dist/modules/settings/deployment-settings.service.js +45 -3
  444. package/dist/modules/settings/deployment-settings.service.js.map +1 -1
  445. package/dist/modules/settings/git-root-folders.js +1 -1
  446. package/dist/modules/settings/git-root-folders.js.map +1 -1
  447. package/dist/modules/settings/index.d.ts +13 -0
  448. package/dist/modules/settings/index.d.ts.map +1 -0
  449. package/dist/modules/settings/index.js +3 -0
  450. package/dist/modules/settings/index.js.map +1 -0
  451. package/dist/modules/settings/setup.routes.d.ts +3 -3
  452. package/dist/modules/settings/setup.routes.d.ts.map +1 -1
  453. package/dist/modules/settings/setup.routes.js +2 -2
  454. package/dist/modules/settings/setup.routes.js.map +1 -1
  455. package/dist/modules/skills/allowed-tools-check.d.ts +2 -2
  456. package/dist/modules/skills/allowed-tools-check.d.ts.map +1 -1
  457. package/dist/modules/skills/allowed-tools-check.js +1 -1
  458. package/dist/modules/skills/allowed-tools-check.js.map +1 -1
  459. package/dist/modules/skills/index.d.ts +4 -3
  460. package/dist/modules/skills/index.d.ts.map +1 -1
  461. package/dist/modules/skills/index.js +0 -2
  462. package/dist/modules/skills/index.js.map +1 -1
  463. package/dist/modules/skills/pending-skills.service.d.ts +3 -3
  464. package/dist/modules/skills/pending-skills.service.d.ts.map +1 -1
  465. package/dist/modules/skills/pending-skills.service.js.map +1 -1
  466. package/dist/modules/skills/skill-access-requests.routes.d.ts +5 -5
  467. package/dist/modules/skills/skill-access-requests.routes.d.ts.map +1 -1
  468. package/dist/modules/skills/skill-access-requests.routes.js +6 -13
  469. package/dist/modules/skills/skill-access-requests.routes.js.map +1 -1
  470. package/dist/modules/skills/skills.contract.d.ts +16 -0
  471. package/dist/modules/skills/skills.contract.d.ts.map +1 -1
  472. package/dist/modules/skills/skills.routes.d.ts +1 -1
  473. package/dist/modules/skills/skills.routes.d.ts.map +1 -1
  474. package/dist/modules/skills/skills.routes.js +1 -1
  475. package/dist/modules/skills/skills.routes.js.map +1 -1
  476. package/dist/modules/skills/skills.service.d.ts +2 -2
  477. package/dist/modules/skills/skills.service.d.ts.map +1 -1
  478. package/dist/modules/skills/skills.service.js +6 -1
  479. package/dist/modules/skills/skills.service.js.map +1 -1
  480. package/dist/modules/skills/skills.tools.d.ts +3 -3
  481. package/dist/modules/skills/skills.tools.d.ts.map +1 -1
  482. package/dist/modules/skills/skills.tools.js +27 -19
  483. package/dist/modules/skills/skills.tools.js.map +1 -1
  484. package/dist/modules/tool-auth/connection-key-rejection.js +1 -1
  485. package/dist/modules/tool-auth/connection-key-rejection.js.map +1 -1
  486. package/dist/modules/tool-auth/connection-keys-admin.routes.d.ts +2 -2
  487. package/dist/modules/tool-auth/connection-keys-admin.routes.d.ts.map +1 -1
  488. package/dist/modules/tool-auth/connection-keys-admin.routes.js +1 -1
  489. package/dist/modules/tool-auth/connection-keys-admin.routes.js.map +1 -1
  490. package/dist/modules/tool-auth/external-api-key.interface.d.ts +11 -0
  491. package/dist/modules/tool-auth/external-api-key.interface.d.ts.map +1 -1
  492. package/dist/modules/tool-auth/external-api-key.interface.js.map +1 -1
  493. package/dist/modules/tool-auth/external-api-key.service.d.ts +2 -1
  494. package/dist/modules/tool-auth/external-api-key.service.d.ts.map +1 -1
  495. package/dist/modules/tool-auth/external-api-key.service.js +5 -2
  496. package/dist/modules/tool-auth/external-api-key.service.js.map +1 -1
  497. package/dist/modules/tool-auth/index.d.ts +15 -0
  498. package/dist/modules/tool-auth/index.d.ts.map +1 -0
  499. package/dist/modules/tool-auth/index.js +11 -0
  500. package/dist/modules/tool-auth/index.js.map +1 -0
  501. package/dist/modules/tool-auth/internal-token.service.d.ts +9 -0
  502. package/dist/modules/tool-auth/internal-token.service.d.ts.map +1 -1
  503. package/dist/modules/tool-auth/internal-token.service.js +1 -0
  504. package/dist/modules/tool-auth/internal-token.service.js.map +1 -1
  505. package/dist/modules/tool-auth/tool-auth.middleware.d.ts +29 -5
  506. package/dist/modules/tool-auth/tool-auth.middleware.d.ts.map +1 -1
  507. package/dist/modules/tool-auth/tool-auth.middleware.js +33 -7
  508. package/dist/modules/tool-auth/tool-auth.middleware.js.map +1 -1
  509. package/dist/modules/tool-helpers/default-branch-write.d.ts +1 -1
  510. package/dist/modules/tool-helpers/default-branch-write.d.ts.map +1 -1
  511. package/dist/modules/tool-helpers/index.d.ts +4 -1
  512. package/dist/modules/tool-helpers/index.d.ts.map +1 -1
  513. package/dist/modules/tool-helpers/index.js +3 -0
  514. package/dist/modules/tool-helpers/index.js.map +1 -1
  515. package/dist/modules/tool-helpers/route-argument-check.js +1 -1
  516. package/dist/modules/tool-helpers/route-argument-check.js.map +1 -1
  517. package/dist/modules/tool-helpers/route-tool-schemas.d.ts +1 -1
  518. package/dist/modules/tool-helpers/route-tool-schemas.d.ts.map +1 -1
  519. package/dist/modules/tool-helpers/tool-context.d.ts +12 -6
  520. package/dist/modules/tool-helpers/tool-context.d.ts.map +1 -1
  521. package/dist/modules/tool-helpers/tool-context.js +5 -3
  522. package/dist/modules/tool-helpers/tool-context.js.map +1 -1
  523. package/dist/modules/tool-helpers/tool-def.d.ts +4 -2
  524. package/dist/modules/tool-helpers/tool-def.d.ts.map +1 -1
  525. package/dist/modules/tool-helpers/tool-def.js +3 -1
  526. package/dist/modules/tool-helpers/tool-def.js.map +1 -1
  527. package/dist/modules/tool-helpers/tool-handler.d.ts +17 -2
  528. package/dist/modules/tool-helpers/tool-handler.d.ts.map +1 -1
  529. package/dist/modules/tool-helpers/tool-handler.js +21 -2
  530. package/dist/modules/tool-helpers/tool-handler.js.map +1 -1
  531. package/dist/modules/tool-helpers/tool.contract.d.ts +12 -2
  532. package/dist/modules/tool-helpers/tool.contract.d.ts.map +1 -1
  533. package/dist/modules/tool-helpers/tool.contract.js.map +1 -1
  534. package/dist/modules/tool-helpers/validate-token.d.ts +3 -2
  535. package/dist/modules/tool-helpers/validate-token.d.ts.map +1 -1
  536. package/dist/modules/tool-helpers/validate-token.js +2 -2
  537. package/dist/modules/tool-helpers/validate-token.js.map +1 -1
  538. package/dist/modules/tool-manuals/index.d.ts +8 -3
  539. package/dist/modules/tool-manuals/index.d.ts.map +1 -1
  540. package/dist/modules/tool-manuals/index.js +4 -2
  541. package/dist/modules/tool-manuals/index.js.map +1 -1
  542. package/dist/modules/tool-manuals/mcp-server-edit.service.d.ts +2 -2
  543. package/dist/modules/tool-manuals/mcp-server-edit.service.d.ts.map +1 -1
  544. package/dist/modules/tool-manuals/pending-tools.service.d.ts +2 -2
  545. package/dist/modules/tool-manuals/pending-tools.service.d.ts.map +1 -1
  546. package/dist/modules/tool-manuals/tool-delete.service.d.ts +5 -6
  547. package/dist/modules/tool-manuals/tool-delete.service.d.ts.map +1 -1
  548. package/dist/modules/tool-manuals/tool-delete.service.js.map +1 -1
  549. package/dist/modules/tool-manuals/tool-manuals.contract.d.ts +19 -6
  550. package/dist/modules/tool-manuals/tool-manuals.contract.d.ts.map +1 -1
  551. package/dist/modules/tool-manuals/tool-manuals.routes.d.ts +12 -6
  552. package/dist/modules/tool-manuals/tool-manuals.routes.d.ts.map +1 -1
  553. package/dist/modules/tool-manuals/tool-manuals.routes.js +43 -6
  554. package/dist/modules/tool-manuals/tool-manuals.routes.js.map +1 -1
  555. package/dist/modules/tool-manuals/tool-manuals.service.d.ts +16 -9
  556. package/dist/modules/tool-manuals/tool-manuals.service.d.ts.map +1 -1
  557. package/dist/modules/tool-manuals/tool-manuals.service.js +23 -15
  558. package/dist/modules/tool-manuals/tool-manuals.service.js.map +1 -1
  559. package/dist/modules/tool-manuals/tool-manuals.tools.d.ts +3 -3
  560. package/dist/modules/tool-manuals/tool-manuals.tools.d.ts.map +1 -1
  561. package/dist/modules/tool-manuals/tool-manuals.tools.js +26 -12
  562. package/dist/modules/tool-manuals/tool-manuals.tools.js.map +1 -1
  563. package/dist/modules/tool-registry/description-length.js +2 -2
  564. package/dist/modules/tool-registry/description-length.js.map +1 -1
  565. package/dist/modules/tool-registry/index.d.ts +8 -0
  566. package/dist/modules/tool-registry/index.d.ts.map +1 -0
  567. package/dist/modules/tool-registry/index.js +8 -0
  568. package/dist/modules/tool-registry/index.js.map +1 -0
  569. package/dist/modules/tool-registry/manual.routes.d.ts +44 -2
  570. package/dist/modules/tool-registry/manual.routes.d.ts.map +1 -1
  571. package/dist/modules/tool-registry/manual.routes.js +38 -11
  572. package/dist/modules/tool-registry/manual.routes.js.map +1 -1
  573. package/dist/modules/tool-registry/read-only-hints.contract.d.ts +52 -0
  574. package/dist/modules/tool-registry/read-only-hints.contract.d.ts.map +1 -0
  575. package/dist/modules/tool-registry/read-only-hints.contract.js +2 -0
  576. package/dist/modules/tool-registry/read-only-hints.contract.js.map +1 -0
  577. package/dist/modules/tool-registry/read-only-hints.d.ts +89 -0
  578. package/dist/modules/tool-registry/read-only-hints.d.ts.map +1 -0
  579. package/dist/modules/tool-registry/read-only-hints.js +212 -0
  580. package/dist/modules/tool-registry/read-only-hints.js.map +1 -0
  581. package/dist/modules/tool-registry/tool.contract.d.ts +15 -0
  582. package/dist/modules/tool-registry/tool.contract.d.ts.map +1 -1
  583. package/dist/modules/tool-registry/tool.contract.js +10 -1
  584. package/dist/modules/tool-registry/tool.contract.js.map +1 -1
  585. package/dist/modules/update-check/update-check.routes.d.ts +2 -2
  586. package/dist/modules/update-check/update-check.routes.d.ts.map +1 -1
  587. package/dist/modules/update-check/update-check.routes.js +1 -1
  588. package/dist/modules/update-check/update-check.routes.js.map +1 -1
  589. package/dist/modules/workflow/agent-tools/change-request-read-shape.d.ts +9 -104
  590. package/dist/modules/workflow/agent-tools/change-request-read-shape.d.ts.map +1 -1
  591. package/dist/modules/workflow/agent-tools/change-request-read-shape.js +8 -118
  592. package/dist/modules/workflow/agent-tools/change-request-read-shape.js.map +1 -1
  593. package/dist/modules/workflow/agent-tools/change-request-read.tools.d.ts +16 -17
  594. package/dist/modules/workflow/agent-tools/change-request-read.tools.d.ts.map +1 -1
  595. package/dist/modules/workflow/agent-tools/change-request-read.tools.js +19 -86
  596. package/dist/modules/workflow/agent-tools/change-request-read.tools.js.map +1 -1
  597. package/dist/modules/workflow/agent-tools/change-request-summary.d.ts +5 -1
  598. package/dist/modules/workflow/agent-tools/change-request-summary.d.ts.map +1 -1
  599. package/dist/modules/workflow/agent-tools/change-request-summary.js +10 -1
  600. package/dist/modules/workflow/agent-tools/change-request-summary.js.map +1 -1
  601. package/dist/modules/workflow/agent-tools/workflow.tools.d.ts +7 -5
  602. package/dist/modules/workflow/agent-tools/workflow.tools.d.ts.map +1 -1
  603. package/dist/modules/workflow/agent-tools/workflow.tools.js +60 -77
  604. package/dist/modules/workflow/agent-tools/workflow.tools.js.map +1 -1
  605. package/dist/modules/workflow/change-request-hooks.d.ts +1 -1
  606. package/dist/modules/workflow/event-bus.d.ts.map +1 -1
  607. package/dist/modules/workflow/event-bus.js +3 -1
  608. package/dist/modules/workflow/event-bus.js.map +1 -1
  609. package/dist/modules/workflow/events-delivery.d.ts +120 -0
  610. package/dist/modules/workflow/events-delivery.d.ts.map +1 -0
  611. package/dist/modules/workflow/events-delivery.js +202 -0
  612. package/dist/modules/workflow/events-delivery.js.map +1 -0
  613. package/dist/modules/workflow/events.routes.d.ts +16 -7
  614. package/dist/modules/workflow/events.routes.d.ts.map +1 -1
  615. package/dist/modules/workflow/events.routes.js +23 -4
  616. package/dist/modules/workflow/events.routes.js.map +1 -1
  617. package/dist/modules/workflow/file-lock.service.d.ts +1 -1
  618. package/dist/modules/workflow/file-lock.service.d.ts.map +1 -1
  619. package/dist/modules/workflow/file-lock.service.js +1 -1
  620. package/dist/modules/workflow/file-lock.service.js.map +1 -1
  621. package/dist/modules/workflow/git/git.service.d.ts +4 -4
  622. package/dist/modules/workflow/git/git.service.d.ts.map +1 -1
  623. package/dist/modules/workflow/git/git.service.js +23 -41
  624. package/dist/modules/workflow/git/git.service.js.map +1 -1
  625. package/dist/modules/workflow/git/node-git-runner.js +1 -1
  626. package/dist/modules/workflow/git/node-git-runner.js.map +1 -1
  627. package/dist/modules/workflow/git/pull-request.service.d.ts +6 -7
  628. package/dist/modules/workflow/git/pull-request.service.d.ts.map +1 -1
  629. package/dist/modules/workflow/git/pull-request.service.js +40 -33
  630. package/dist/modules/workflow/git/pull-request.service.js.map +1 -1
  631. package/dist/modules/workflow/index.d.ts +14 -2
  632. package/dist/modules/workflow/index.d.ts.map +1 -1
  633. package/dist/modules/workflow/index.js +11 -2
  634. package/dist/modules/workflow/index.js.map +1 -1
  635. package/dist/modules/workflow/pending-commits.service.d.ts +1 -1
  636. package/dist/modules/workflow/pending-commits.service.d.ts.map +1 -1
  637. package/dist/modules/workflow/pending-commits.service.js +1 -1
  638. package/dist/modules/workflow/pending-commits.service.js.map +1 -1
  639. package/dist/modules/workflow/read-on-branch.d.ts +1 -1
  640. package/dist/modules/workflow/read-on-branch.d.ts.map +1 -1
  641. package/dist/modules/workflow/recovery-bot.d.ts +1 -1
  642. package/dist/modules/workflow/recovery-bot.d.ts.map +1 -1
  643. package/dist/modules/workflow/recovery-bot.js +1 -1
  644. package/dist/modules/workflow/recovery-bot.js.map +1 -1
  645. package/dist/modules/workflow/review-workflow/approval-lock.d.ts +1 -1
  646. package/dist/modules/workflow/review-workflow/approval-lock.d.ts.map +1 -1
  647. package/dist/modules/workflow/review-workflow/review-workflow.interface.d.ts +4 -20
  648. package/dist/modules/workflow/review-workflow/review-workflow.interface.d.ts.map +1 -1
  649. package/dist/modules/workflow/review-workflow/review-workflow.service.d.ts +4 -8
  650. package/dist/modules/workflow/review-workflow/review-workflow.service.d.ts.map +1 -1
  651. package/dist/modules/workflow/review-workflow/review-workflow.service.js +3 -138
  652. package/dist/modules/workflow/review-workflow/review-workflow.service.js.map +1 -1
  653. package/dist/modules/workflow/workflow.routes.d.ts +5 -5
  654. package/dist/modules/workflow/workflow.routes.d.ts.map +1 -1
  655. package/dist/modules/workflow/workflow.routes.js +42 -94
  656. package/dist/modules/workflow/workflow.routes.js.map +1 -1
  657. package/dist/modules/workflow/workflow.service.d.ts +41 -50
  658. package/dist/modules/workflow/workflow.service.d.ts.map +1 -1
  659. package/dist/modules/workflow/workflow.service.js +221 -154
  660. package/dist/modules/workflow/workflow.service.js.map +1 -1
  661. package/dist/modules/workspace/agent-access.gate.d.ts +3 -3
  662. package/dist/modules/workspace/agent-access.gate.d.ts.map +1 -1
  663. package/dist/modules/workspace/agent-download.builder.d.ts +1 -1
  664. package/dist/modules/workspace/agent-download.builder.d.ts.map +1 -1
  665. package/dist/modules/workspace/agent-download.builder.js +1 -1
  666. package/dist/modules/workspace/agent-download.builder.js.map +1 -1
  667. package/dist/modules/workspace/agent-upload.routes.d.ts.map +1 -1
  668. package/dist/modules/workspace/agent-upload.routes.js +19 -0
  669. package/dist/modules/workspace/agent-upload.routes.js.map +1 -1
  670. package/dist/modules/workspace/agent-upload.store.d.ts +11 -0
  671. package/dist/modules/workspace/agent-upload.store.d.ts.map +1 -1
  672. package/dist/modules/workspace/agent-upload.store.js +18 -0
  673. package/dist/modules/workspace/agent-upload.store.js.map +1 -1
  674. package/dist/modules/workspace/file-readers/doc-extract.service.d.ts +82 -14
  675. package/dist/modules/workspace/file-readers/doc-extract.service.d.ts.map +1 -1
  676. package/dist/modules/workspace/file-readers/doc-extract.service.js +109 -36
  677. package/dist/modules/workspace/file-readers/doc-extract.service.js.map +1 -1
  678. package/dist/modules/workspace/file-readers/doc-extract.types.d.ts +9 -2
  679. package/dist/modules/workspace/file-readers/doc-extract.types.d.ts.map +1 -1
  680. package/dist/modules/workspace/file-readers/doc-extract.types.js.map +1 -1
  681. package/dist/modules/workspace/file-readers/document-extractor.contract.d.ts +41 -0
  682. package/dist/modules/workspace/file-readers/document-extractor.contract.d.ts.map +1 -0
  683. package/dist/modules/workspace/file-readers/document-extractor.contract.js +5 -0
  684. package/dist/modules/workspace/file-readers/document-extractor.contract.js.map +1 -0
  685. package/dist/modules/workspace/file-readers/document-extractors.d.ts +9 -0
  686. package/dist/modules/workspace/file-readers/document-extractors.d.ts.map +1 -0
  687. package/dist/modules/workspace/file-readers/document-extractors.js +26 -0
  688. package/dist/modules/workspace/file-readers/document-extractors.js.map +1 -0
  689. package/dist/modules/workspace/file-readers/document-formats.d.ts +12 -0
  690. package/dist/modules/workspace/file-readers/document-formats.d.ts.map +1 -0
  691. package/dist/modules/workspace/file-readers/document-formats.js +11 -0
  692. package/dist/modules/workspace/file-readers/document-formats.js.map +1 -0
  693. package/dist/modules/workspace/file-readers/document-reader.d.ts +21 -17
  694. package/dist/modules/workspace/file-readers/document-reader.d.ts.map +1 -1
  695. package/dist/modules/workspace/file-readers/document-reader.js +38 -34
  696. package/dist/modules/workspace/file-readers/document-reader.js.map +1 -1
  697. package/dist/modules/workspace/file-readers/extract-in-worker.d.ts +60 -0
  698. package/dist/modules/workspace/file-readers/extract-in-worker.d.ts.map +1 -0
  699. package/dist/modules/workspace/file-readers/extract-in-worker.js +140 -0
  700. package/dist/modules/workspace/file-readers/extract-in-worker.js.map +1 -0
  701. package/dist/modules/workspace/file-readers/extract-pdf.d.ts +2 -0
  702. package/dist/modules/workspace/file-readers/extract-pdf.d.ts.map +1 -1
  703. package/dist/modules/workspace/file-readers/extract-pdf.js +20 -3
  704. package/dist/modules/workspace/file-readers/extract-pdf.js.map +1 -1
  705. package/dist/modules/workspace/file-readers/extract.worker.d.ts +2 -0
  706. package/dist/modules/workspace/file-readers/extract.worker.d.ts.map +1 -0
  707. package/dist/modules/workspace/file-readers/extract.worker.js +5 -0
  708. package/dist/modules/workspace/file-readers/extract.worker.js.map +1 -0
  709. package/dist/modules/workspace/file-readers/extraction-cache.d.ts +21 -5
  710. package/dist/modules/workspace/file-readers/extraction-cache.d.ts.map +1 -1
  711. package/dist/modules/workspace/file-readers/extraction-cache.js +24 -10
  712. package/dist/modules/workspace/file-readers/extraction-cache.js.map +1 -1
  713. package/dist/modules/workspace/file-readers/extraction-worker.d.ts +42 -0
  714. package/dist/modules/workspace/file-readers/extraction-worker.d.ts.map +1 -0
  715. package/dist/modules/workspace/file-readers/extraction-worker.js +69 -0
  716. package/dist/modules/workspace/file-readers/extraction-worker.js.map +1 -0
  717. package/dist/modules/workspace/file-readers/file-reader.d.ts +13 -4
  718. package/dist/modules/workspace/file-readers/file-reader.d.ts.map +1 -1
  719. package/dist/modules/workspace/file-readers/file-reader.js.map +1 -1
  720. package/dist/modules/workspace/file-readers/file-reader.registry.d.ts +3 -2
  721. package/dist/modules/workspace/file-readers/file-reader.registry.d.ts.map +1 -1
  722. package/dist/modules/workspace/file-readers/file-reader.registry.js +6 -20
  723. package/dist/modules/workspace/file-readers/file-reader.registry.js.map +1 -1
  724. package/dist/modules/workspace/first-run.js +1 -1
  725. package/dist/modules/workspace/first-run.js.map +1 -1
  726. package/dist/modules/workspace/git-internals.middleware.d.ts +1 -1
  727. package/dist/modules/workspace/git-internals.middleware.d.ts.map +1 -1
  728. package/dist/modules/workspace/git-internals.middleware.js +1 -1
  729. package/dist/modules/workspace/git-internals.middleware.js.map +1 -1
  730. package/dist/modules/workspace/index.d.ts +24 -0
  731. package/dist/modules/workspace/index.d.ts.map +1 -1
  732. package/dist/modules/workspace/index.js +21 -0
  733. package/dist/modules/workspace/index.js.map +1 -1
  734. package/dist/modules/workspace/kb-repository.d.ts.map +1 -1
  735. package/dist/modules/workspace/kb-repository.js +1 -1
  736. package/dist/modules/workspace/kb-repository.js.map +1 -1
  737. package/dist/modules/workspace/not-found.d.ts +1 -1
  738. package/dist/modules/workspace/not-found.d.ts.map +1 -1
  739. package/dist/modules/workspace/not-found.js +1 -1
  740. package/dist/modules/workspace/not-found.js.map +1 -1
  741. package/dist/modules/workspace/nul-scan.d.ts +19 -0
  742. package/dist/modules/workspace/nul-scan.d.ts.map +1 -0
  743. package/dist/modules/workspace/nul-scan.js +55 -0
  744. package/dist/modules/workspace/nul-scan.js.map +1 -0
  745. package/dist/modules/workspace/pattern-matcher.contract.d.ts +111 -28
  746. package/dist/modules/workspace/pattern-matcher.contract.d.ts.map +1 -1
  747. package/dist/modules/workspace/pattern-matcher.contract.js +31 -14
  748. package/dist/modules/workspace/pattern-matcher.contract.js.map +1 -1
  749. package/dist/modules/workspace/ripgrep-search.d.ts +54 -0
  750. package/dist/modules/workspace/ripgrep-search.d.ts.map +1 -0
  751. package/dist/modules/workspace/ripgrep-search.js +657 -0
  752. package/dist/modules/workspace/ripgrep-search.js.map +1 -0
  753. package/dist/modules/workspace/ripgrep-version.d.ts +15 -0
  754. package/dist/modules/workspace/ripgrep-version.d.ts.map +1 -0
  755. package/dist/modules/workspace/ripgrep-version.js +31 -0
  756. package/dist/modules/workspace/ripgrep-version.js.map +1 -0
  757. package/dist/modules/workspace/routine-write-policy.js +1 -1
  758. package/dist/modules/workspace/routine-write-policy.js.map +1 -1
  759. package/dist/modules/workspace/startup/beside-checkout.d.ts +8 -5
  760. package/dist/modules/workspace/startup/beside-checkout.d.ts.map +1 -1
  761. package/dist/modules/workspace/startup/beside-checkout.js +14 -5
  762. package/dist/modules/workspace/startup/beside-checkout.js.map +1 -1
  763. package/dist/modules/workspace/startup/kb-git.js +1 -1
  764. package/dist/modules/workspace/startup/kb-git.js.map +1 -1
  765. package/dist/modules/workspace/startup/kb-startup-runner.d.ts.map +1 -1
  766. package/dist/modules/workspace/startup/kb-startup-runner.js +1 -2
  767. package/dist/modules/workspace/startup/kb-startup-runner.js.map +1 -1
  768. package/dist/modules/workspace/startup/steps/groups-to-plugins.step.js +2 -2
  769. package/dist/modules/workspace/startup/steps/groups-to-plugins.step.js.map +1 -1
  770. package/dist/modules/workspace/startup/steps/personal-spaces.step.js +2 -2
  771. package/dist/modules/workspace/startup/steps/personal-spaces.step.js.map +1 -1
  772. package/dist/modules/workspace/startup/steps/plugin-layout.js +1 -1
  773. package/dist/modules/workspace/startup/steps/plugin-layout.js.map +1 -1
  774. package/dist/modules/workspace/startup/steps/roles-yaml.step.js +1 -1
  775. package/dist/modules/workspace/startup/steps/roles-yaml.step.js.map +1 -1
  776. package/dist/modules/workspace/startup/steps/seed-tree.js +2 -2
  777. package/dist/modules/workspace/startup/steps/seed-tree.js.map +1 -1
  778. package/dist/modules/workspace/startup/steps/template-files.step.d.ts +1 -1
  779. package/dist/modules/workspace/startup/steps/template-files.step.d.ts.map +1 -1
  780. package/dist/modules/workspace/startup/steps/template-files.step.js +2 -2
  781. package/dist/modules/workspace/startup/steps/template-files.step.js.map +1 -1
  782. package/dist/modules/workspace/startup/steps/template-source.js +2 -2
  783. package/dist/modules/workspace/startup/steps/template-source.js.map +1 -1
  784. package/dist/modules/workspace/worker-pool.d.ts +99 -0
  785. package/dist/modules/workspace/worker-pool.d.ts.map +1 -0
  786. package/dist/modules/workspace/worker-pool.js +156 -0
  787. package/dist/modules/workspace/worker-pool.js.map +1 -0
  788. package/dist/modules/workspace/workspace-tmp.d.ts +146 -0
  789. package/dist/modules/workspace/workspace-tmp.d.ts.map +1 -0
  790. package/dist/modules/workspace/workspace-tmp.js +435 -0
  791. package/dist/modules/workspace/workspace-tmp.js.map +1 -0
  792. package/dist/modules/workspace/workspace.routes.d.ts +7 -8
  793. package/dist/modules/workspace/workspace.routes.d.ts.map +1 -1
  794. package/dist/modules/workspace/workspace.routes.js +9 -32
  795. package/dist/modules/workspace/workspace.routes.js.map +1 -1
  796. package/dist/modules/workspace/workspace.service.d.ts +48 -7
  797. package/dist/modules/workspace/workspace.service.d.ts.map +1 -1
  798. package/dist/modules/workspace/workspace.service.js +89 -12
  799. package/dist/modules/workspace/workspace.service.js.map +1 -1
  800. package/dist/modules/workspace/workspace.tools.d.ts +7 -7
  801. package/dist/modules/workspace/workspace.tools.d.ts.map +1 -1
  802. package/dist/modules/workspace/workspace.tools.js +502 -140
  803. package/dist/modules/workspace/workspace.tools.js.map +1 -1
  804. package/dist/modules/workspace/write-denial.d.ts +4 -4
  805. package/dist/modules/workspace/write-denial.d.ts.map +1 -1
  806. package/dist/modules/workspace/write-denial.js +2 -3
  807. package/dist/modules/workspace/write-denial.js.map +1 -1
  808. package/dist/modules/write-access/index.d.ts +8 -0
  809. package/dist/modules/write-access/index.d.ts.map +1 -0
  810. package/dist/modules/write-access/index.js +7 -0
  811. package/dist/modules/write-access/index.js.map +1 -0
  812. package/dist/shared/path-order.d.ts +28 -8
  813. package/dist/shared/path-order.d.ts.map +1 -1
  814. package/dist/shared/path-order.js +37 -8
  815. package/dist/shared/path-order.js.map +1 -1
  816. package/migrations/0020_change_request_body_is_the_description.sql +20 -0
  817. package/migrations/0021_data_migrations_ledger.sql +11 -0
  818. package/migrations/0022_session_version.sql +6 -0
  819. package/migrations/0023_agent_path.sql +3 -0
  820. package/migrations/meta/0020_snapshot.json +2321 -0
  821. package/migrations/meta/0021_snapshot.json +2353 -0
  822. package/migrations/meta/0022_snapshot.json +2360 -0
  823. package/migrations/meta/0023_snapshot.json +2378 -0
  824. package/migrations/meta/_journal.json +28 -0
  825. package/package.json +3 -3
  826. package/src/__tests__/pg-scratch.test.ts +69 -0
  827. package/src/__tests__/pg-scratch.ts +31 -0
  828. package/src/__tests__/slow-ripgrep.ts +65 -0
  829. package/src/core/__tests__/boot-without-ripgrep.test.ts +34 -0
  830. package/src/core/__tests__/catalog-revision.test.ts +89 -0
  831. package/src/core/__tests__/damaged-document.tools.test.ts +374 -0
  832. package/src/core/__tests__/gated-boot.test.ts +8 -1
  833. package/src/core/__tests__/lifecycle.test.ts +46 -13
  834. package/src/core/__tests__/public-config.test.ts +5 -0
  835. package/src/core/catalog-revision.ts +24 -2
  836. package/src/core/core-ports.ts +42 -0
  837. package/src/core/create-core-server.ts +45 -3
  838. package/src/core/create-core-services.ts +81 -17
  839. package/src/core/lifecycle.ts +36 -2
  840. package/src/core/public-config.ts +10 -0
  841. package/src/index.ts +1 -1
  842. package/src/modules/access/__tests__/access-control.admin-root-floor.test.ts +12 -0
  843. package/src/modules/access/__tests__/access-control.colliding-name-cases.test.ts +113 -0
  844. package/src/modules/access/__tests__/access-control.frontmatter-head.test.ts +117 -0
  845. package/src/modules/access/__tests__/access-control.group-named-admin.test.ts +122 -0
  846. package/src/modules/access/__tests__/access-control.preview-relocation.test.ts +50 -0
  847. package/src/modules/access/__tests__/access-declarations.test.ts +19 -0
  848. package/src/modules/access/__tests__/access-groups.test.ts +55 -22
  849. package/src/modules/access/__tests__/access-mutation.service.test.ts +85 -59
  850. package/src/modules/access/__tests__/access-requests.routes.test.ts +29 -15
  851. package/src/modules/access/__tests__/access-restrict-here.test.ts +7 -5
  852. package/src/modules/access/__tests__/access.routes.admins.test.ts +1 -0
  853. package/src/modules/access/__tests__/access.routes.batch.test.ts +2 -0
  854. package/src/modules/access/__tests__/access.routes.folder-governs.test.ts +2 -0
  855. package/src/modules/access/__tests__/access.routes.group-grant.test.ts +50 -14
  856. package/src/modules/access/__tests__/access.routes.overrides.test.ts +2 -1
  857. package/src/modules/access/__tests__/access.routes.proposal-branch.test.ts +1 -0
  858. package/src/modules/access/__tests__/access.routes.prospective.test.ts +2 -0
  859. package/src/modules/access/__tests__/access.routes.revoke.test.ts +18 -13
  860. package/src/modules/access/__tests__/access.routes.unknown-email.test.ts +2 -0
  861. package/src/modules/access/__tests__/grant-sources.test.ts +20 -15
  862. package/src/modules/access/__tests__/groups-admin.routes.test.ts +61 -0
  863. package/src/modules/access/__tests__/groups-admin.service.test.ts +211 -18
  864. package/src/modules/access/__tests__/reference-scan.test.ts +366 -14
  865. package/src/modules/access/__tests__/roles-admin.security.test.ts +1 -1
  866. package/src/modules/access/__tests__/roles-admin.service.test.ts +43 -22
  867. package/src/modules/access/__tests__/roles-capabilities.test.ts +6 -2
  868. package/src/modules/access/__tests__/roles.routes.test.ts +1 -1
  869. package/src/modules/access/access-control.interface.ts +17 -10
  870. package/src/modules/access/access-control.service.ts +161 -76
  871. package/src/modules/access/access-declarations.ts +1 -1
  872. package/src/modules/access/access-mutation.service.ts +58 -57
  873. package/src/modules/access/access-requests.contract.ts +1 -1
  874. package/src/modules/access/access-requests.routes.ts +10 -15
  875. package/src/modules/access/access-requests.service.ts +29 -71
  876. package/src/modules/access/access-view.ts +13 -11
  877. package/src/modules/access/access.routes.ts +51 -43
  878. package/src/modules/access/admin-locked-commit.ts +3 -2
  879. package/src/modules/access/capability-registry.ts +1 -1
  880. package/src/modules/access/change-read-gate.ts +3 -5
  881. package/src/modules/access/creator-access.ts +3 -5
  882. package/src/modules/access/directory-sync-bot.ts +2 -2
  883. package/src/modules/access/groups-admin.routes.ts +7 -5
  884. package/src/modules/access/groups-admin.service.ts +116 -47
  885. package/src/modules/access/groups-edit.ts +3 -3
  886. package/src/modules/access/index.ts +17 -0
  887. package/src/modules/access/reference-scan.ts +320 -47
  888. package/src/modules/access/roles-admin.service.ts +45 -31
  889. package/src/modules/access/roles-edit.ts +1 -1
  890. package/src/modules/access/synced-groups-committer.ts +4 -4
  891. package/src/modules/access/synced-groups-writer.ts +3 -3
  892. package/src/modules/access/user-access-removal.service.ts +3 -6
  893. package/src/modules/access-model/__tests__/access-grammar.test.ts +38 -1
  894. package/src/modules/access-model/__tests__/access-splice.test.ts +50 -8
  895. package/src/modules/access-model/access-grammar.ts +65 -20
  896. package/src/modules/access-model/access-splice.ts +31 -23
  897. package/src/modules/access-model/group-files.ts +5 -0
  898. package/src/modules/access-model/index.ts +21 -5
  899. package/src/modules/access-model/roles-yaml-guard.ts +1 -1
  900. package/src/modules/admin/admin-access.routes.ts +1 -1
  901. package/src/modules/admin/admin-access.service.ts +2 -2
  902. package/src/modules/admin/index.ts +7 -0
  903. package/src/modules/agent-guide/__tests__/agent-guide.test.ts +36 -0
  904. package/src/modules/agent-guide/agent-guide.tools.ts +17 -8
  905. package/src/modules/agent-guide/agent-guide.ts +1 -1
  906. package/src/modules/agent-guide/index.ts +1 -1
  907. package/src/modules/agent-instructions/__tests__/shared-file-rules.test.ts +1 -0
  908. package/src/modules/agent-instructions/compose.ts +3 -1
  909. package/src/modules/agent-instructions/read-preamble.ts +1 -1
  910. package/src/modules/agent-instructions/shared-file-rules.ts +17 -1
  911. package/src/modules/agent-scope/__tests__/agent-surfaces.connect-as.test.ts +421 -0
  912. package/src/modules/agent-scope/__tests__/connection-scope.test.ts +46 -0
  913. package/src/modules/agent-scope/__tests__/in-memory-kb.ts +148 -0
  914. package/src/modules/agent-scope/agent-scope.contract.ts +83 -0
  915. package/src/modules/agent-scope/connection-scope.ts +199 -0
  916. package/src/modules/agent-scope/index.ts +15 -0
  917. package/src/modules/audit/agent-audit.service.ts +5 -3
  918. package/src/modules/audit/agent-connection.routes.ts +1 -1
  919. package/src/modules/audit/agent-rest-audit.middleware.ts +1 -1
  920. package/src/modules/audit/audit.contract.ts +6 -0
  921. package/src/modules/audit/audit.routes.ts +4 -4
  922. package/src/modules/auth/__tests__/auth.middleware.test.ts +30 -2
  923. package/src/modules/auth/__tests__/auth.routes.test.ts +71 -5
  924. package/src/modules/auth/__tests__/auth.service.test.ts +90 -9
  925. package/src/modules/auth/__tests__/password-change-sessions.pg.test.ts +269 -0
  926. package/src/modules/auth/account-admission.ts +19 -0
  927. package/src/modules/auth/account-erasure.service.ts +4 -9
  928. package/src/modules/auth/account-switch-lock.ts +2 -2
  929. package/src/modules/auth/account.routes.ts +3 -3
  930. package/src/modules/auth/auth.middleware.ts +45 -4
  931. package/src/modules/auth/auth.routes.ts +46 -29
  932. package/src/modules/auth/auth.service.ts +139 -38
  933. package/src/modules/auth/index.ts +5 -0
  934. package/src/modules/auth/oidc-auth-provider.ts +3 -10
  935. package/src/modules/code-mode/code-mode.tool.ts +1 -1
  936. package/src/modules/connection-probe/connection-probe.service.ts +3 -6
  937. package/src/modules/database/__tests__/legacy-change-request-body.test.ts +118 -0
  938. package/src/modules/database/__tests__/legacy-request-bodies.pg.test.ts +258 -0
  939. package/src/modules/database/__tests__/pii-backfill.pg.test.ts +15 -18
  940. package/src/modules/database/__tests__/session-version-migration.pg.test.ts +133 -0
  941. package/src/modules/database/core-schema.ts +76 -36
  942. package/src/modules/database/index.ts +9 -0
  943. package/src/modules/database/migrate.ts +79 -3
  944. package/src/modules/declared-variables/__tests__/declared-variables.route.test.ts +44 -1
  945. package/src/modules/declared-variables/declared-variables.routes.ts +14 -3
  946. package/src/modules/diff/diff.routes.ts +5 -5
  947. package/src/modules/diff/diff.service.ts +2 -2
  948. package/src/modules/diff/index.ts +6 -0
  949. package/src/modules/embed/__tests__/embed.tools.test.ts +12 -0
  950. package/src/modules/embed/account-link.service.ts +2 -2
  951. package/src/modules/embed/embed.routes.ts +2 -2
  952. package/src/modules/embed/embed.service.ts +1 -1
  953. package/src/modules/embed/embed.tools.ts +11 -9
  954. package/src/modules/github-app/github-app.connection.ts +1 -1
  955. package/src/modules/github-app/github-app.routes.ts +3 -3
  956. package/src/modules/kb-fs/__tests__/locking-filesystem.test.ts +25 -0
  957. package/src/modules/kb-fs/__tests__/repo-path.test.ts +53 -8
  958. package/src/modules/kb-fs/index.ts +13 -0
  959. package/src/modules/kb-fs/locking-filesystem.ts +8 -2
  960. package/src/modules/kb-fs/repo-path.ts +33 -7
  961. package/src/modules/kb-fs/tmp-ref.ts +81 -0
  962. package/src/modules/kb-sync/kb-sync.routes.ts +3 -3
  963. package/src/modules/kb-sync/kb-sync.service.ts +1 -1
  964. package/src/modules/kb-sync/sync-auth.ts +1 -1
  965. package/src/modules/kb-sync/sync-payload.ts +1 -1
  966. package/src/modules/marketplace/git-http.routes.ts +1 -1
  967. package/src/modules/marketplace/github-facade/github-facade-admin.routes.ts +1 -1
  968. package/src/modules/marketplace/github-facade/github-facade-codes.store.ts +2 -2
  969. package/src/modules/marketplace/github-facade/github-facade-credentials.service.ts +2 -2
  970. package/src/modules/marketplace/github-facade/github-facade.routes.ts +2 -2
  971. package/src/modules/marketplace/github-facade/github-facade.service.ts +2 -2
  972. package/src/modules/marketplace/marketplace-repo.service.ts +2 -2
  973. package/src/modules/mcp/__tests__/connect-as.pg.test.ts +137 -0
  974. package/src/modules/mcp/__tests__/mcp-auth.middleware.test.ts +29 -5
  975. package/src/modules/mcp/__tests__/mcp-routes-harness.ts +8 -0
  976. package/src/modules/mcp/__tests__/mcp.connect-as.test.ts +195 -0
  977. package/src/modules/mcp/__tests__/mcp.routes.connect-as.test.ts +192 -0
  978. package/src/modules/mcp/__tests__/oauth-consent.connect-as.test.ts +146 -0
  979. package/src/modules/mcp/__tests__/read-only-hint.e2e.test.ts +213 -0
  980. package/src/modules/mcp/index.ts +7 -0
  981. package/src/modules/mcp/mcp-auth.middleware.ts +25 -9
  982. package/src/modules/mcp/mcp.routes.ts +42 -8
  983. package/src/modules/mcp/mcp.service.ts +136 -29
  984. package/src/modules/mcp/oauth/bevel-oauth-provider.ts +48 -10
  985. package/src/modules/mcp/oauth/oauth-consent.routes.ts +42 -2
  986. package/src/modules/onboarding/onboarding.routes.ts +1 -1
  987. package/src/modules/onboarding/starter-pack.service.ts +5 -6
  988. package/src/modules/plugins/__tests__/bundle-dialect.e2e.test.ts +2 -1
  989. package/src/modules/plugins/__tests__/plugin-links.service.test.ts +2 -1
  990. package/src/modules/plugins/__tests__/plugins.tools.test.ts +38 -2
  991. package/src/modules/plugins/compile/compile-marketplace.ts +2 -2
  992. package/src/modules/plugins/compile/marketplace-compiler.service.ts +3 -3
  993. package/src/modules/plugins/discovery/bundle-dialect/registry.ts +1 -1
  994. package/src/modules/plugins/index.ts +3 -1
  995. package/src/modules/plugins/join-proposals.ts +2 -2
  996. package/src/modules/plugins/join-request-jobs.service.ts +3 -3
  997. package/src/modules/plugins/join-request-records.store.ts +2 -2
  998. package/src/modules/plugins/join-requests.service.ts +4 -4
  999. package/src/modules/plugins/plugin-links.service.ts +10 -11
  1000. package/src/modules/plugins/plugin-links.ts +23 -6
  1001. package/src/modules/plugins/plugin-provision.service.ts +4 -5
  1002. package/src/modules/plugins/plugin-rename.service.ts +3 -3
  1003. package/src/modules/plugins/plugins.contract.ts +1 -1
  1004. package/src/modules/plugins/plugins.routes.ts +39 -8
  1005. package/src/modules/plugins/plugins.service.ts +5 -5
  1006. package/src/modules/plugins/plugins.tools.ts +4 -4
  1007. package/src/modules/plugins/teams.routes.ts +3 -3
  1008. package/src/modules/secrets-vault/__tests__/connect-pending.route.test.ts +113 -0
  1009. package/src/modules/secrets-vault/db-secrets-vault.service.ts +2 -2
  1010. package/src/modules/secrets-vault/index.ts +2 -0
  1011. package/src/modules/secrets-vault/secrets-vault.routes.ts +27 -7
  1012. package/src/modules/settings/__tests__/deployment-settings.service.test.ts +88 -1
  1013. package/src/modules/settings/connection-check.ts +1 -1
  1014. package/src/modules/settings/deployment-settings.service.ts +44 -4
  1015. package/src/modules/settings/git-root-folders.ts +1 -1
  1016. package/src/modules/settings/index.ts +12 -0
  1017. package/src/modules/settings/setup.routes.ts +5 -4
  1018. package/src/modules/skills/__tests__/allowed-tools-warn.tools.test.ts +2 -2
  1019. package/src/modules/skills/__tests__/skill-access-requests.routes.test.ts +6 -3
  1020. package/src/modules/skills/__tests__/skills.service.test.ts +34 -0
  1021. package/src/modules/skills/allowed-tools-check.ts +2 -6
  1022. package/src/modules/skills/index.ts +9 -2
  1023. package/src/modules/skills/pending-skills.service.ts +3 -4
  1024. package/src/modules/skills/skill-access-requests.routes.ts +10 -17
  1025. package/src/modules/skills/skills.contract.ts +17 -0
  1026. package/src/modules/skills/skills.routes.ts +1 -1
  1027. package/src/modules/skills/skills.service.ts +7 -3
  1028. package/src/modules/skills/skills.tools.ts +49 -22
  1029. package/src/modules/tool-auth/__tests__/external-api-key.service.test.ts +4 -0
  1030. package/src/modules/tool-auth/connection-key-rejection.ts +1 -1
  1031. package/src/modules/tool-auth/connection-keys-admin.routes.ts +2 -2
  1032. package/src/modules/tool-auth/external-api-key.interface.ts +11 -1
  1033. package/src/modules/tool-auth/external-api-key.service.ts +7 -4
  1034. package/src/modules/tool-auth/index.ts +14 -0
  1035. package/src/modules/tool-auth/internal-token.service.ts +10 -0
  1036. package/src/modules/tool-auth/tool-auth.middleware.ts +48 -6
  1037. package/src/modules/tool-helpers/__tests__/agent-roles-write.test.ts +2 -2
  1038. package/src/modules/tool-helpers/__tests__/can-write.tools.test.ts +5 -3
  1039. package/src/modules/tool-helpers/__tests__/phase4-tools.test.ts +2 -2
  1040. package/src/modules/tool-helpers/default-branch-write.ts +1 -1
  1041. package/src/modules/tool-helpers/index.ts +5 -1
  1042. package/src/modules/tool-helpers/route-argument-check.ts +1 -1
  1043. package/src/modules/tool-helpers/route-tool-schemas.ts +1 -1
  1044. package/src/modules/tool-helpers/tool-context.ts +18 -10
  1045. package/src/modules/tool-helpers/tool-def.ts +7 -3
  1046. package/src/modules/tool-helpers/tool-handler.ts +36 -2
  1047. package/src/modules/tool-helpers/tool.contract.ts +12 -2
  1048. package/src/modules/tool-helpers/validate-token.ts +5 -4
  1049. package/src/modules/tool-manuals/__tests__/tool-manuals.archive.route.test.ts +80 -4
  1050. package/src/modules/tool-manuals/__tests__/tool-manuals.service.test.ts +42 -0
  1051. package/src/modules/tool-manuals/__tests__/tool-manuals.tools.test.ts +3 -3
  1052. package/src/modules/tool-manuals/index.ts +12 -2
  1053. package/src/modules/tool-manuals/mcp-server-edit.service.ts +2 -2
  1054. package/src/modules/tool-manuals/pending-tools.service.ts +2 -2
  1055. package/src/modules/tool-manuals/tool-delete.service.ts +5 -6
  1056. package/src/modules/tool-manuals/tool-manuals.contract.ts +18 -6
  1057. package/src/modules/tool-manuals/tool-manuals.routes.ts +45 -8
  1058. package/src/modules/tool-manuals/tool-manuals.service.ts +34 -18
  1059. package/src/modules/tool-manuals/tool-manuals.tools.ts +32 -17
  1060. package/src/modules/tool-registry/__tests__/read-only-hints.test.ts +439 -0
  1061. package/src/modules/tool-registry/__tests__/tool-description-length.test.ts +2 -2
  1062. package/src/modules/tool-registry/__tests__/tool-registry.test.ts +9 -2
  1063. package/src/modules/tool-registry/description-length.ts +2 -2
  1064. package/src/modules/tool-registry/index.ts +22 -0
  1065. package/src/modules/tool-registry/manual.routes.ts +38 -11
  1066. package/src/modules/tool-registry/read-only-hints.contract.ts +54 -0
  1067. package/src/modules/tool-registry/read-only-hints.ts +225 -0
  1068. package/src/modules/tool-registry/tool.contract.ts +18 -0
  1069. package/src/modules/update-check/update-check.routes.ts +2 -2
  1070. package/src/modules/workflow/__tests__/event-bus.test.ts +14 -2
  1071. package/src/modules/workflow/__tests__/events-delivery.test.ts +778 -0
  1072. package/src/modules/workflow/__tests__/workflow.service.facade.test.ts +85 -22
  1073. package/src/modules/workflow/__tests__/workflow.service.sync.test.ts +1 -1
  1074. package/src/modules/workflow/__tests__/workflow.service.update-change-request.pg.test.ts +120 -0
  1075. package/src/modules/workflow/__tests__/workflow.service.update-change-request.test.ts +346 -0
  1076. package/src/modules/workflow/agent-tools/__tests__/change-request-read-shape.test.ts +32 -209
  1077. package/src/modules/workflow/agent-tools/__tests__/change-request-read.tools.test.ts +16 -245
  1078. package/src/modules/workflow/agent-tools/__tests__/update-change-request.parity.test.ts +306 -0
  1079. package/src/modules/workflow/agent-tools/__tests__/workflow.tools.test.ts +87 -60
  1080. package/src/modules/workflow/agent-tools/change-request-read-shape.ts +18 -153
  1081. package/src/modules/workflow/agent-tools/change-request-read.tools.ts +24 -96
  1082. package/src/modules/workflow/agent-tools/change-request-summary.ts +16 -2
  1083. package/src/modules/workflow/agent-tools/workflow.tools.ts +63 -84
  1084. package/src/modules/workflow/change-request-hooks.ts +1 -1
  1085. package/src/modules/workflow/event-bus.ts +3 -1
  1086. package/src/modules/workflow/events-delivery.ts +278 -0
  1087. package/src/modules/workflow/events.routes.ts +30 -9
  1088. package/src/modules/workflow/file-lock.service.ts +2 -2
  1089. package/src/modules/workflow/git/__tests__/git.service.list-branches.test.ts +130 -3
  1090. package/src/modules/workflow/git/__tests__/pull-request.service.getPrDetail.test.ts +24 -9
  1091. package/src/modules/workflow/git/git.service.ts +34 -56
  1092. package/src/modules/workflow/git/node-git-runner.ts +1 -1
  1093. package/src/modules/workflow/git/pull-request.service.ts +34 -29
  1094. package/src/modules/workflow/index.ts +15 -2
  1095. package/src/modules/workflow/pending-commits.service.ts +2 -2
  1096. package/src/modules/workflow/read-on-branch.ts +1 -1
  1097. package/src/modules/workflow/recovery-bot.ts +2 -2
  1098. package/src/modules/workflow/review-workflow/approval-lock.ts +1 -1
  1099. package/src/modules/workflow/review-workflow/review-workflow.interface.ts +3 -35
  1100. package/src/modules/workflow/review-workflow/review-workflow.service.ts +6 -165
  1101. package/src/modules/workflow/workflow.routes.ts +46 -100
  1102. package/src/modules/workflow/workflow.service.ts +277 -191
  1103. package/src/modules/workspace/__tests__/agent-downloads.test.ts +2 -1
  1104. package/src/modules/workspace/__tests__/agent-uploads.test.ts +87 -1
  1105. package/src/modules/workspace/__tests__/escape-sequences.routes.test.ts +2 -1
  1106. package/src/modules/workspace/__tests__/file-stat-access.test.ts +2 -1
  1107. package/src/modules/workspace/__tests__/git-internals.security.test.ts +4 -3
  1108. package/src/modules/workspace/__tests__/holds-nul.test.ts +66 -0
  1109. package/src/modules/workspace/__tests__/rest-tool-arguments.test.ts +5 -4
  1110. package/src/modules/workspace/__tests__/ripgrep-search.test.ts +570 -0
  1111. package/src/modules/workspace/__tests__/ripgrep-version.test.ts +29 -0
  1112. package/src/modules/workspace/__tests__/worker-pool.test.ts +118 -0
  1113. package/src/modules/workspace/__tests__/workspace-paths-inside-the-repo.test.ts +3 -2
  1114. package/src/modules/workspace/__tests__/workspace-tmp.tools.test.ts +928 -0
  1115. package/src/modules/workspace/__tests__/workspace.routes.read-gate.test.ts +17 -37
  1116. package/src/modules/workspace/__tests__/workspace.service.ensure-remotes-fetched.test.ts +30 -0
  1117. package/src/modules/workspace/__tests__/workspace.service.read-filter.test.ts +20 -8
  1118. package/src/modules/workspace/__tests__/workspace.tools.agents-file.test.ts +4 -3
  1119. package/src/modules/workspace/__tests__/workspace.tools.branch-errors.test.ts +24 -11
  1120. package/src/modules/workspace/__tests__/workspace.tools.test.ts +423 -117
  1121. package/src/modules/workspace/agent-access.gate.ts +3 -3
  1122. package/src/modules/workspace/agent-download.builder.ts +1 -1
  1123. package/src/modules/workspace/agent-upload.routes.ts +19 -0
  1124. package/src/modules/workspace/agent-upload.store.ts +18 -0
  1125. package/src/modules/workspace/file-readers/README.md +9 -0
  1126. package/src/modules/workspace/file-readers/__tests__/doc-extract.service.test.ts +175 -0
  1127. package/src/modules/workspace/file-readers/__tests__/doc-extract.test.ts +21 -16
  1128. package/src/modules/workspace/file-readers/__tests__/extract-in-worker.test.ts +229 -0
  1129. package/src/modules/workspace/file-readers/__tests__/file-reader.registry.test.ts +2 -1
  1130. package/src/modules/workspace/file-readers/__tests__/fixtures/damaged-pdf.ts +34 -0
  1131. package/src/modules/workspace/file-readers/__tests__/fixtures/misbehaving-extract.worker.ts +57 -0
  1132. package/src/modules/workspace/file-readers/__tests__/fixtures/pdf-in-trouble.worker.ts +20 -0
  1133. package/src/modules/workspace/file-readers/__tests__/fixtures/unloadable-extract.worker.ts +2 -0
  1134. package/src/modules/workspace/file-readers/doc-extract.service.ts +144 -36
  1135. package/src/modules/workspace/file-readers/doc-extract.types.ts +13 -3
  1136. package/src/modules/workspace/file-readers/document-extractor.contract.ts +42 -0
  1137. package/src/modules/workspace/file-readers/document-extractors.ts +28 -0
  1138. package/src/modules/workspace/file-readers/document-formats.ts +13 -0
  1139. package/src/modules/workspace/file-readers/document-reader.ts +40 -36
  1140. package/src/modules/workspace/file-readers/extract-in-worker.ts +183 -0
  1141. package/src/modules/workspace/file-readers/extract-pdf.ts +23 -4
  1142. package/src/modules/workspace/file-readers/extract.worker.ts +5 -0
  1143. package/src/modules/workspace/file-readers/extraction-cache.ts +33 -12
  1144. package/src/modules/workspace/file-readers/extraction-worker.ts +86 -0
  1145. package/src/modules/workspace/file-readers/file-reader.registry.ts +6 -20
  1146. package/src/modules/workspace/file-readers/file-reader.ts +14 -4
  1147. package/src/modules/workspace/first-run.ts +1 -1
  1148. package/src/modules/workspace/git-internals.middleware.ts +1 -1
  1149. package/src/modules/workspace/index.ts +37 -0
  1150. package/src/modules/workspace/kb-repository.ts +3 -2
  1151. package/src/modules/workspace/not-found.ts +1 -1
  1152. package/src/modules/workspace/nul-scan.ts +50 -0
  1153. package/src/modules/workspace/pattern-matcher.contract.ts +124 -33
  1154. package/src/modules/workspace/ripgrep-search.ts +715 -0
  1155. package/src/modules/workspace/ripgrep-version.ts +35 -0
  1156. package/src/modules/workspace/routine-write-policy.ts +1 -1
  1157. package/src/modules/workspace/startup/__tests__/beside-checkout.test.ts +11 -0
  1158. package/src/modules/workspace/startup/beside-checkout.ts +13 -5
  1159. package/src/modules/workspace/startup/kb-git.ts +1 -1
  1160. package/src/modules/workspace/startup/kb-startup-runner.ts +1 -2
  1161. package/src/modules/workspace/startup/steps/groups-to-plugins.step.ts +3 -3
  1162. package/src/modules/workspace/startup/steps/personal-spaces.step.ts +2 -2
  1163. package/src/modules/workspace/startup/steps/plugin-layout.ts +1 -1
  1164. package/src/modules/workspace/startup/steps/roles-yaml.step.ts +1 -1
  1165. package/src/modules/workspace/startup/steps/seed-tree.ts +2 -2
  1166. package/src/modules/workspace/startup/steps/template-files.step.ts +2 -2
  1167. package/src/modules/workspace/startup/steps/template-source.ts +2 -2
  1168. package/src/modules/workspace/worker-pool.ts +192 -0
  1169. package/src/modules/workspace/workspace-tmp.ts +457 -0
  1170. package/src/modules/workspace/workspace.routes.ts +15 -39
  1171. package/src/modules/workspace/workspace.service.ts +96 -22
  1172. package/src/modules/workspace/workspace.tools.ts +550 -186
  1173. package/src/modules/workspace/write-denial.ts +4 -5
  1174. package/src/modules/write-access/index.ts +7 -0
  1175. package/src/shared/__tests__/module-boundaries.lint.test.ts +301 -0
  1176. package/src/shared/path-order.ts +37 -8
  1177. package/starter-packs/engineering/Plugins/engineering-starter/access.md +1 -1
  1178. package/starter-packs/general/Plugins/general-starter/access.md +1 -1
  1179. package/starter-packs/operations/Plugins/operations-starter/access.md +1 -1
  1180. package/starter-packs/sales/Plugins/sales-starter/access.md +1 -1
  1181. package/starter-packs/support/Plugins/support-starter/access.md +1 -1
  1182. package/dist/modules/workspace/bounded-matcher.d.ts +0 -79
  1183. package/dist/modules/workspace/bounded-matcher.d.ts.map +0 -1
  1184. package/dist/modules/workspace/bounded-matcher.js +0 -261
  1185. package/dist/modules/workspace/bounded-matcher.js.map +0 -1
  1186. package/src/modules/workflow/__tests__/format-affected-owners.test.ts +0 -85
  1187. package/src/modules/workspace/__tests__/bounded-matcher.test.ts +0 -213
  1188. package/src/modules/workspace/bounded-matcher.ts +0 -328
@@ -1,36 +1,32 @@
1
1
  import nodeFs from 'node:fs/promises';
2
- import { join } from 'node:path';
2
+ import { isAbsolute, join, relative, sep } from 'node:path';
3
3
  import AdmZip from 'adm-zip';
4
- import { hasHttpStatus, ToolError } from '../tool-helpers/tool.contract.js';
5
- import { BRANCH_INPUT, toolDef } from '../tool-helpers/tool-def.js';
4
+ import { hasHttpStatus, ToolError, BRANCH_INPUT, toolDef, CAN_WRITE_CLAUSE, defaultBranchWriteVerdicts } from '../tool-helpers/index.js';
6
5
  import { notifyAgentRead, assertAgentWriteAllowed, SESSION_ID_INPUT, } from './agent-access.gate.js';
7
- import { CAN_WRITE_CLAUSE, defaultBranchWriteVerdicts } from '../tool-helpers/index.js';
8
- import { requireInternalSource, requireExternalSource } from '../tool-auth/tool-auth.middleware.js';
6
+ import { requireInternalSource, requireExternalSource } from '../tool-auth/index.js';
9
7
  import { workspaceIdForBranch } from '../../shared/workspace-id.js';
10
8
  import { GitInternalsError, WorkflowValidationError } from '../../shared/domain-errors.js';
11
9
  // Leaf-level shared primitive (same exception `workspace.service.ts` already
12
10
  // relies on) — not a workflow service, so this stays inside the module boundary.
13
- import { assertInsideRepo, assertRepoRootNameFree, assertRepoRootNameFreeArgs, isInsideRepo, normalizePathArgs, normalizeWorkspacePath, } from '../kb-fs/repo-path.js';
14
- import { GitGuardedFilesystem } from '../kb-fs/git-guarded-filesystem.js';
11
+ import { assertInsideRepo, assertRepoRootNameFree, assertRepoRootNameFreeArgs, hasControlCharacter, isInsideRepo, isTmpRef, normalizePathArgs, normalizeWorkspacePath, } from '../kb-fs/index.js';
12
+ import { GitGuardedFilesystem, MoveLockedError, MoveRacedError } from '../kb-fs/index.js';
15
13
  import { assertNoGitInternalsSegment, assertNotGitInternals, hasGitInternalsSegment } from '../../shared/git-internals.js';
16
- import { isRolesYamlPath } from '../access-model/roles-yaml-guard.js';
14
+ import { isRolesYamlPath, toKbRelative, resolveReadableMap, AccessDeniedError } from '../access-model/index.js';
17
15
  import { isAbsence } from '../../shared/fs.contract.js';
18
- import { accessRoster, resolveAccessView } from '../access/access-view.js';
19
- import { accessMdPathForFolder, fileCarriesAccessRules, governingFolderOf } from '../access/access-mutation.service.js';
20
- import { toKbRelative, resolveReadableMap } from '../access-model/kb-read-filter.js';
16
+ import { accessRoster, resolveAccessView, accessMdPathForFolder, fileCarriesAccessRules, governingFolderOf } from '../access/index.js';
21
17
  import { displayPath } from './file-readers/file-reader.js';
22
18
  import { fileTypeOf, needsContent } from './file-readers/content-mode.js';
23
19
  import { createFileReaderRegistry } from './file-readers/file-reader.registry.js';
24
20
  import { DocumentReader } from './file-readers/document-reader.js';
21
+ import { TextReader } from './file-readers/text-reader.js';
25
22
  import { mcpImageResult } from '@bevel-software/platform-mcp-core';
26
23
  import { folderPlaceholderPath, isFolderPlaceholder, isPlatformFile, isPlatformFolder, platformFileCreationRefusal, platformFileRefusal, platformFileUploadRefusal, platformFolderRefusal, isRepositoryOwnFile, repositoryOwnFileDeleteRefusal, entryExistsMessage, } from '@bevel-software/platform-shared';
27
- import { AccessDeniedError } from '../access-model/access-errors.js';
28
- import { AGENT_GUIDE_FILE, isAgentGuidePath, isManagedGuide, withPlatformGuideAppended, } from '../agent-guide/agent-guide.js';
24
+ import { AGENT_GUIDE_FILE, isAgentGuidePath, isManagedGuide, withPlatformGuideAppended, } from '../agent-guide/index.js';
29
25
  import { removeEmptyDirs } from './empty-dirs.js';
30
- import { endsTheSearch } from './pattern-matcher.contract.js';
26
+ import { compareSearchPaths, PATTERN_DIALECT, } from './pattern-matcher.contract.js';
27
+ import { holdsNul } from './nul-scan.js';
31
28
  import { FIRST_RUN_SECTION_ID, firstRunNote, knowledgeFolderIsNew } from './first-run.js';
32
29
  import { planMoveLinks } from './move-links.js';
33
- import { MoveLockedError, MoveRacedError } from '../kb-fs/locking-filesystem.js';
34
30
  import { rethrowAsWriteDenial } from './write-denial.js';
35
31
  import { notFound, orDeclaredNotFound, orNotFound } from './not-found.js';
36
32
  import { logger } from '../../shared/logging.js';
@@ -42,6 +38,12 @@ import { isSymlinkZipEntry, isZipNoiseEntry, readZipEntry, zipEntryName, zipEntr
42
38
  const log = logger('workspace-tools');
43
39
  /** Types that run scripts wherever they are opened, sent by `request_file_download` as plain bytes. */
44
40
  const ACTIVE_CONTENT_TYPES = new Set(['image/svg+xml', 'text/html', 'application/xhtml+xml']);
41
+ /**
42
+ * The caller's verdicts on a file you staged in the workspace's tmp folder: it
43
+ * may be read (and copied out), nothing else — the folder is read-only
44
+ * through the ref, and `request_file_download` does not take one.
45
+ */
46
+ const TMP_ACCESS = { read: true, write: false, download: false, owner: false };
45
47
  /** How many files `file_stat` counts under a folder before it stops and says so. */
46
48
  const DESCENDANTS_CAP = 10_000;
47
49
  /** How many of a folder's files a `delete_folder` answer names. */
@@ -73,13 +75,19 @@ async function filterReadableEntries(gate, dir, entries) {
73
75
  }
74
76
  if (fileWsPaths.length === 0)
75
77
  return entries;
76
- const verdict = await resolveReadableMap((wid, email, rels) => gate.accessControl.canReadBatch(wid, email, rels), gate.workspaceId, gate.userEmail, gate.kbDirName, fileWsPaths);
77
- return entries.filter((e) => {
78
- if (e.type === 'directory')
79
- return true;
80
- const wsPath = dir ? `${dir}/${e.name}` : e.name;
81
- return verdict.get(wsPath) === true;
82
- });
78
+ const readable = await readableFiles(gate, fileWsPaths);
79
+ return entries.filter((e) => e.type === 'directory' || readable.has(dir ? `${dir}/${e.name}` : e.name));
80
+ }
81
+ /**
82
+ * The FILES among `wsPaths` the caller may read, judged in one batched ACL
83
+ * load by the FULL `canReadBatch` (per-node frontmatter honoured), via the
84
+ * shared `resolveReadableMap`. A path the verdict does not name is unreadable.
85
+ */
86
+ async function readableFiles(gate, wsPaths) {
87
+ if (wsPaths.length === 0)
88
+ return new Set();
89
+ const verdict = await resolveReadableMap((wid, email, rels) => gate.accessControl.canReadBatch(wid, email, rels), gate.workspaceId, gate.userEmail, gate.kbDirName, wsPaths);
90
+ return new Set(wsPaths.filter((p) => verdict.get(p) === true));
83
91
  }
84
92
  /**
85
93
  * Drop the empty-folder placeholder from a directory listing: it keeps a
@@ -186,6 +194,30 @@ const RESERVED_ROOT_NAME_TARGETS = {
186
194
  // inside the handler — an archive chooses its entry names, not the caller.
187
195
  apply_file_upload: ['destination'],
188
196
  };
197
+ /**
198
+ * The inputs that take a tmp ref (`__tmp__/<path>`, see `workspace-tmp.ts`)
199
+ * beside a repository path — the four reads of the one file it names. Every
200
+ * other tool, and every other input of these four (`copy_file`'s `dest`
201
+ * among them), refuses a ref before anything else runs — in
202
+ * `normalizePathArgs`, through the one admission gate (`kb-fs/tmp-ref.ts`):
203
+ * the folder is read-only through the ref, and `copy_file` to a repository
204
+ * path is how a file is kept.
205
+ */
206
+ const TMP_REF_INPUTS = {
207
+ read_file: ['path'],
208
+ file_stat: ['path'],
209
+ grep: ['path'],
210
+ copy_file: ['src'],
211
+ };
212
+ /**
213
+ * A path input that also takes a tmp ref (see `TMP_REF_INPUTS`): said on the
214
+ * input, because the descriptions of the tools that take one have no room
215
+ * left, and what the ref is is in the shared rules.
216
+ */
217
+ const orTmpRef = (schema) => ({
218
+ ...schema,
219
+ description: `${schema.description ?? ''} Or a \`__tmp__/…\` ref to one file you staged in the workspace's tmp folder.`,
220
+ });
189
221
  function asText(content) {
190
222
  return typeof content === 'string' ? content : content.toString('utf8');
191
223
  }
@@ -473,46 +505,94 @@ function modeOf(a) {
473
505
  return a.mode;
474
506
  throw new ToolError(`"${String(a.mode)}" is not a write mode: use ${WRITE_MODES.map((m) => `\`${m}\``).join(', ')} (default \`create\`).`, 400, { code: 'bad_mode' });
475
507
  }
508
+ /** The longest stretch of a matching line a grep answer carries. */
509
+ const GREP_LINE_CHARS = 300;
510
+ /** {@link searchableText}'s `bytesOf` for a repository path: the workspace filesystem's own read. */
511
+ function fileBytes(fs) {
512
+ return async (path) => asBytes(await fs.readFile(path));
513
+ }
476
514
  /**
477
- * Search ONE file and append its matches to `out`. Shared by the directory
478
- * walk and by a grep whose `path` names a file, so both produce the same match
479
- * shape (that path, 1-based line numbers, 300-char text) under the same cap.
480
- *
481
- * What is searched is the file's reader's business: text content for the text
482
- * reader (null on NUL bytes / invalid UTF-8 — binary is not searchable), the
483
- * EXTRACTION for a document reader (marker line included, so the
484
- * `[slide N]`/`[sheet: …]`/`[page N]` lines are themselves searchable and line
485
- * numbers match what read_file returns), nothing for images.
515
+ * Files the text pass judges, then searches, at a time: first this many, then
516
+ * twice as many each time, up to {@link GREP_MAX_BATCH}. A verdict reads the
517
+ * file's own access rules, so a batch costs one read of each of its files.
518
+ * Its names also go to ripgrep on the command line, so a batch also ends
519
+ * once they reach {@link GREP_BATCH_CHARS}, well inside the system's limit.
520
+ */
521
+ const GREP_FIRST_BATCH = 256;
522
+ const GREP_MAX_BATCH = 2_048;
523
+ const GREP_BATCH_CHARS = 256 * 1024;
524
+ /**
525
+ * The text ONE file holds for `grep`, read through its reader: the text
526
+ * content for a text reader (none on NUL bytes / invalid UTF-8 — binary is not
527
+ * searchable), the EXTRACTION for a document reader (marker line included, so
528
+ * the `[slide N]`/`[sheet: …]`/`[page N]` lines are themselves searchable and
529
+ * line numbers match what read_file returns), nothing for images.
486
530
  *
487
531
  * Throws whatever reading the file throws — the caller decides whether that is
488
- * a file to skip (the walk) or an error to surface (a single-file grep).
532
+ * a file to skip (a tree search) or an error to surface (a single-file grep).
533
+ * `bytesOf` is where the file's bytes come from: the workspace filesystem for
534
+ * a repository path, the tmp resolver for a tmp ref.
489
535
  */
490
- async function grepOneFile(fs, path, matcher, out, max, docs) {
536
+ async function searchableText(bytesOf, path, docs) {
491
537
  const reader = docs.readers.readerFor(path);
492
- const bytes = asBytes(await fs.readFile(path));
493
- let content = reader.greppableText ? await reader.greppableText(bytes, path) : null;
494
- if (content === null && reader instanceof DocumentReader) {
495
- // Cold document (extraction not yet cached): cached ones above are free,
496
- // extracting draws on the per-walk budget (see UNCACHED_DOCS_PER_GREP) —
497
- // beyond it the search skips the document and counts it.
498
- if (docs.uncachedBudget <= 0) {
499
- docs.skippedUncached++;
500
- return 'budget-skipped';
538
+ const bytes = await bytesOf(path);
539
+ let content;
540
+ if (reader instanceof DocumentReader) {
541
+ // What the cache remembers is free — an extraction is searched, a failure
542
+ // (a damaged file, or one that overran its budget within the hour) is
543
+ // skipped without extracting it again. A cold document draws on the
544
+ // per-call budget (see UNCACHED_DOCS_PER_GREP) — beyond it the search
545
+ // skips the document and counts it.
546
+ let res = await reader.cachedRead(bytes, path);
547
+ if (res === undefined) {
548
+ if (docs.uncachedBudget <= 0) {
549
+ docs.skippedUncached++;
550
+ return { kind: 'budget-skipped' };
551
+ }
552
+ docs.uncachedBudget--;
553
+ res = await reader.read(bytes, path, docs.origin);
501
554
  }
502
- docs.uncachedBudget--;
503
- const res = await reader.read(bytes, path);
504
- // A non-text outcome is a corrupt document — nothing searchable.
555
+ // A non-text outcome is a document that could not be read — nothing searchable.
505
556
  content = res.kind === 'text' ? res.text : null;
506
557
  }
507
- if (content === null)
508
- return 'no-text';
509
- const lines = content.split('\n');
510
- // matchingLines posts these to the worker in bounded batches, so no one
511
- // copy of a large file runs on the request thread.
512
- for (const i of await matcher.matchingLines(lines, max - out.length)) {
513
- out.push({ path, line: i + 1, text: lines[i].slice(0, 300) });
558
+ else {
559
+ content = reader.greppableText ? await reader.greppableText(bytes, path) : null;
514
560
  }
515
- return 'searched';
561
+ return content === null ? { kind: 'no-text' } : { kind: 'text', text: content };
562
+ }
563
+ /**
564
+ * grep over the one text file `path`, by ripgrep from the folder holding it,
565
+ * its lines pushed onto `out`, when it is a regular file; `null`, with
566
+ * nothing searched, for anything else (a link, one that loops, a file gone
567
+ * since), which is read as read_file reads it instead. A file that answers no
568
+ * line has no text when ripgrep finds it binary: it holds a NUL, which
569
+ * {@link holdsNul} looks for in the very file that was judged.
570
+ */
571
+ async function grepTextFile(fs, path, search, max, out) {
572
+ const slash = path.lastIndexOf('/');
573
+ const scope = await treeScope(fs, slash < 0 ? '' : path.slice(0, slash));
574
+ const name = path.slice(slash + 1);
575
+ const absolute = join(scope.cwd, scope.root, name);
576
+ const judged = await nodeFs.lstat(absolute).catch(() => null);
577
+ if (judged === null || !judged.isFile())
578
+ return null;
579
+ const from = out.length;
580
+ for await (const file of search.files(scope, { only: [name], maxLinesPerFile: max })) {
581
+ for (const l of file.lines)
582
+ out.push({ path, line: l.line, text: l.text.slice(0, GREP_LINE_CHARS) });
583
+ }
584
+ if (out.length > from)
585
+ return { kind: 'searched' };
586
+ const binary = await orNotFound(path, () => holdsNul(absolute, judged, search), 'Nothing to search');
587
+ return binary ? { kind: 'no-text' } : { kind: 'searched' };
588
+ }
589
+ /** Append the lines `hits` names (0-based indices into `text`'s lines) to `out`, as matches in `path`. */
590
+ function pushMatches(out, path, text, hits) {
591
+ if (hits.length === 0)
592
+ return;
593
+ const lines = text.split('\n');
594
+ for (const i of hits)
595
+ out.push({ path, line: i + 1, text: lines[i].slice(0, GREP_LINE_CHARS) });
516
596
  }
517
597
  /**
518
598
  * What a grep's `path` actually names. The walk starts with `readdir`, which
@@ -546,55 +626,145 @@ async function searchRootKind(fs, path) {
546
626
  return 'file';
547
627
  }
548
628
  }
549
- /** JS grep over the workspace tree (read methods only) — bounded by match + depth caps. */
550
- async function grepWalk(fs, dir, matcher, out, max, depth, gate, notifyRead, docs,
551
- /** A file the walk leaves to its caller: never opened, never counted against `max`. */
552
- skip = () => false) {
553
- if (out.length >= max || depth > 12)
554
- return;
555
- let entries;
556
- try {
557
- entries = (await fs.readdir(dir || '.'));
558
- }
559
- catch {
560
- return;
629
+ /**
630
+ * Where ripgrep searches the directory `root`: from the workspace's canonical
631
+ * directory, with the root's canonical path relative to it. The stat that
632
+ * called `root` a directory already refused one outside the workspace; this
633
+ * refuses it again where the search is started, so ripgrep, which follows the
634
+ * root it is given, is never started on anything outside.
635
+ */
636
+ async function treeScope(fs, root) {
637
+ const cwd = await nodeFs.realpath(fs.basePath);
638
+ const absolute = fs.resolveAbsolutePath(root);
639
+ const rel = absolute === undefined ? '..' : relative(cwd, await nodeFs.realpath(absolute));
640
+ if (rel === '..' || rel.startsWith(`..${sep}`) || isAbsolute(rel)) {
641
+ throw new ToolError(`"${displayPath(root)}" is outside the workspace.`, 403);
561
642
  }
562
- // Filter unreadable KB nodes out of the walk so grep never opens — or leaks
563
- // a line from — a file the caller may not read.
564
- entries = await filterReadableEntries(gate, dir, entries);
565
- for (const e of entries) {
566
- if (out.length >= max)
567
- return;
568
- if (hasGitInternalsSegment(e.name) || e.name === 'node_modules')
569
- continue;
570
- if (e.type !== 'directory' && isFolderPlaceholder(e.name))
571
- continue;
572
- const p = dir ? `${dir}/${e.name}` : e.name;
573
- if (e.type === 'directory') {
574
- await grepWalk(fs, p, matcher, out, max, depth + 1, gate, notifyRead, docs, skip);
643
+ return { cwd, root: rel === '' ? '.' : rel.split(sep).join('/') };
644
+ }
645
+ /**
646
+ * grep over the directory `root`: the tree is listed, then searched in two
647
+ * passes, and no file is opened before it is admitted.
648
+ *
649
+ * The listing opens no file. Admission is the ONE step a file passes before
650
+ * either pass opens it: it is judged readable by the gate, and then — being a
651
+ * file the search will read, as `read_file` reads one — it is told to the
652
+ * read hook, which may refuse it, and with it the search. A file the caller
653
+ * may not read is never opened and never told of (there is no read to tell):
654
+ * what it holds can change neither the answer nor how long the search takes,
655
+ * and so not whether it ends within its budget. Judging and telling are both
656
+ * spent from that budget. A file that was not in the listing (it appeared
657
+ * since) is never admitted, so never searched.
658
+ *
659
+ * The text pass is ripgrep's own: every file whose reader greps its bytes as
660
+ * text (a TextReader) is searched by it, in path order, and read nowhere else.
661
+ * It admits a batch at a time, before ripgrep opens any of it, so the hook
662
+ * hears of each file of a batch whether or not a line of it is answered —
663
+ * and, past the line that fills the cap, of the rest of that batch, which the
664
+ * pass then never opens. Each file is answered as ripgrep finishes it, and
665
+ * the pass stops at the `max`-th line.
666
+ *
667
+ * The document pass reads the files every other reader owns through that
668
+ * reader, as `read_file` does — extractions under the per-call budget — and
669
+ * has their text matched by the same engine. A document that sorts after the
670
+ * text pass's last line cannot be among the first `max`, so it is not read.
671
+ *
672
+ * Answers what both found, unsorted: the caller merges, sorts and caps.
673
+ */
674
+ async function grepTree(fs, root, search, max, gate, notifyRead, docs,
675
+ /** A file the search leaves to its caller: never answered, never counted against `max`. */
676
+ skip = () => false) {
677
+ const scope = await treeScope(fs, root);
678
+ // A folder named with a trailing slash answers the paths it is spelled
679
+ // with everywhere else (`a/b.md`, never `a//b.md`), so the guide's own
680
+ // path and every verdict meet the one spelling.
681
+ const base = root.replace(/\/+$/, '');
682
+ const at = (p) => (base === '' ? p : `${base}/${p}`);
683
+ // ripgrep already stays out of `.git`; the folder's every other spelling,
684
+ // and the folder placeholder, are left out as everywhere else.
685
+ const shown = (p) => !hasGitInternalsSegment(p) && !isFolderPlaceholder(p) && !skip(p);
686
+ // Which reader owns an extension is the registry's answer, asked of a name
687
+ // carrying it; a TextReader greps the bytes themselves, which is ripgrep's
688
+ // pass. Extensions any other reader owns are left out of it.
689
+ const readerOf = (ext) => docs.readers.readerFor(`file${ext}`);
690
+ const notRaw = docs.readers.ownedExtensions().filter((ext) => !(readerOf(ext) instanceof TextReader));
691
+ const ownedBy = (p, exts) => {
692
+ const lower = p.toLowerCase();
693
+ return exts.some((ext) => lower.endsWith(ext));
694
+ };
695
+ const readerOwned = notRaw.filter((ext) => {
696
+ const reader = readerOf(ext);
697
+ return reader instanceof DocumentReader || reader.greppableText !== undefined;
698
+ });
699
+ const out = [];
700
+ // Admission (see above): the gate's verdict on `paths`, then the hook told
701
+ // of each readable one in path order — a refusal ends the search here, as
702
+ // it ends a `read_file`, before anything is opened. Spent from the budget.
703
+ const admit = (paths) => search.charged(async () => {
704
+ const readable = await readableFiles(gate, paths);
705
+ for (const p of paths) {
706
+ if (readable.has(p))
707
+ await notifyRead(p);
575
708
  }
576
- else if (skip(p)) {
577
- continue;
709
+ return readable;
710
+ });
711
+ // Every file the walk covers, in path order. Only what is shown is ever
712
+ // admitted, so what is admitted is what may be answered. A name holding a
713
+ // control character is no file name to the platform — no tool reads or
714
+ // writes one — so it is not searched either.
715
+ const all = (await search.list(scope)).filter((p) => shown(at(p)) && !hasControlCharacter(p));
716
+ const raw = all.filter((p) => !ownedBy(p, notRaw));
717
+ // The text pass: a batch of files is admitted, then its admitted files, and
718
+ // only they, are searched. A batch is admitted before ripgrep opens any of
719
+ // it, and the pass stops at the `max`-th line, so the verdicts asked for are
720
+ // those of the files the answer reached — few for a common word — and the
721
+ // batches double so a rare one still walks the tree in a handful of runs.
722
+ let size = GREP_FIRST_BATCH;
723
+ for (let from = 0; from < raw.length && out.length < max; size = Math.min(size * 2, GREP_MAX_BATCH)) {
724
+ const batch = [];
725
+ for (let chars = 0; from < raw.length && batch.length < size && (batch.length === 0 || chars < GREP_BATCH_CHARS); from++) {
726
+ batch.push(raw[from]);
727
+ chars += raw[from].length;
578
728
  }
579
- else {
580
- // Opening a file is a read of it, even when the walk started at a root
581
- // the read hook was already told about — so every file the walk opens
582
- // reaches the hook by name (closes the read-leak).
583
- await notifyRead(p);
584
- // A file the walk cannot read is silently skipped: one unreadable entry
585
- // must not fail a search over the whole tree.
586
- // A pattern too expensive to finish, or no worker free to run it, is not
587
- // an unreadable file: either ends the whole search.
588
- try {
589
- await grepOneFile(fs, p, matcher, out, max, docs);
590
- }
591
- catch (err) {
592
- if (endsTheSearch(err))
593
- throw err;
729
+ const readable = await admit(batch.map(at));
730
+ const only = batch.filter((p) => readable.has(at(p)));
731
+ for await (const file of search.files(scope, { only, maxLinesPerFile: max - out.length })) {
732
+ const p = at(file.path);
733
+ // Only what was admitted answers, whatever ripgrep printed.
734
+ if (!readable.has(p))
594
735
  continue;
736
+ for (const l of file.lines.slice(0, max - out.length)) {
737
+ out.push({ path: p, line: l.line, text: l.text.slice(0, GREP_LINE_CHARS) });
595
738
  }
739
+ // Enough: leaving the loop kills ripgrep at the file that filled the cap.
740
+ if (out.length >= max)
741
+ break;
742
+ }
743
+ }
744
+ const last = out.length >= max ? out[out.length - 1].path : undefined;
745
+ const candidates = all
746
+ .filter((p) => ownedBy(p, readerOwned))
747
+ .map(at)
748
+ .filter((p) => last === undefined || compareSearchPaths(p, last) <= 0);
749
+ const readable = await admit(candidates);
750
+ const texts = [];
751
+ for (const p of candidates) {
752
+ if (!readable.has(p))
753
+ continue;
754
+ let found;
755
+ try {
756
+ found = await searchableText(fileBytes(fs), p, docs);
757
+ }
758
+ catch {
759
+ // One document that cannot be read must not fail a search over the tree.
760
+ continue;
596
761
  }
762
+ if (found.kind === 'text')
763
+ texts.push({ path: p, text: found.text });
597
764
  }
765
+ const hits = await search.matchingLines(texts.map((t) => t.text));
766
+ texts.forEach((t, i) => pushMatches(out, t.path, t.text, hits[i]));
767
+ return out;
598
768
  }
599
769
  const SAVE_WARNINGS_OUTPUT = {
600
770
  type: 'array',
@@ -840,7 +1010,9 @@ patternMatcher) {
840
1010
  const paths = toolPathArgs(args);
841
1011
  for (const p of paths)
842
1012
  assertNoGitInternalsSegment(p);
843
- const onDisk = paths.filter((p) => !spillStore.isSpillRef(p));
1013
+ // A spill ref belongs to no workspace, and a tmp ref to the folder beside
1014
+ // the checkout: neither is judged against the checkout's git folder.
1015
+ const onDisk = paths.filter((p) => !spillStore.isSpillRef(p) && !isTmpRef(p));
844
1016
  if (onDisk.length === 0)
845
1017
  return;
846
1018
  const root = await gitCheckRootFor(args, ctx);
@@ -894,9 +1066,14 @@ patternMatcher) {
894
1066
  * caller WILL have, never whether they may do it. The write verdicts that
895
1067
  * gate the move are `writeBlocked` and the lock gate, both of which read
896
1068
  * the tree as it is.
1069
+ *
1070
+ * `sourceContent` is the text of a source that is no repository path (a
1071
+ * tmp ref): it carries rules in exactly as a repository file would, so it
1072
+ * is previewed through the same relocation reading, never as "nothing
1073
+ * travels".
897
1074
  */
898
1075
  const accessAfter = async (branch, ctx, src, dest, opts) => {
899
- const from = toKbRelative(src, kbDirName);
1076
+ const from = opts?.sourceContent !== undefined ? src : toKbRelative(src, kbDirName);
900
1077
  const to = toKbRelative(dest, kbDirName);
901
1078
  // Outside the repository there are no rules to carry, and none to land
902
1079
  // among — the same answer `accessAt` gives for such a path.
@@ -904,6 +1081,16 @@ patternMatcher) {
904
1081
  return accessAt(branch, ctx, dest);
905
1082
  return accessControl.previewAccessAfterRelocation(workspaceIdForBranch(branch), ctx.user.email, from, to, opts);
906
1083
  };
1084
+ /**
1085
+ * The text a tmp source carries into the repository, for the preview only:
1086
+ * read as a repository source is read there — a file that cannot be read
1087
+ * carries no rules — so the preview never answers before the write
1088
+ * verdict. Whether the file is there at all is `statTmpFile`'s to say.
1089
+ */
1090
+ const tmpSourceText = (branch, ctx, ref) => ctx.workspaceService
1091
+ .readTmpFile(workspaceIdForBranch(branch), ctx.user.id, ref)
1092
+ .then((bytes) => bytes.toString('utf-8'))
1093
+ .catch(() => '');
907
1094
  /**
908
1095
  * What `copy_file`'s dry run answers: the same impact shape `move_file`
909
1096
  * previews, over a copy's own rules.
@@ -931,10 +1118,16 @@ patternMatcher) {
931
1118
  * them nothing they could not ask `file_stat` for.
932
1119
  */
933
1120
  const copyImpact = async (branch, ctx, src, dest) => {
934
- const [before, after, blocked] = await Promise.all([
935
- accessAt(branch, ctx, src),
936
- accessAfter(branch, ctx, src, dest, { sourceRemains: true }),
937
- writeBlocked(branch, ctx, [dest]),
1121
+ const fromTmp = isTmpRef(src);
1122
+ // The write verdict FIRST, and alone: a staged file's bytes are read only
1123
+ // for a caller who may write the destination. A denied preview carries
1124
+ // no rules from the source ('' — what an unreadable source carries), so
1125
+ // its `access.after` is the destination's own rules for the caller.
1126
+ const blocked = await writeBlocked(branch, ctx, [dest]);
1127
+ const sourceContent = fromTmp ? (blocked.length > 0 ? '' : await tmpSourceText(branch, ctx, src)) : undefined;
1128
+ const [before, after] = await Promise.all([
1129
+ fromTmp ? TMP_ACCESS : accessAt(branch, ctx, src),
1130
+ accessAfter(branch, ctx, src, dest, { sourceRemains: true, sourceContent }),
938
1131
  ]);
939
1132
  const access = { before, after };
940
1133
  const accessChanges = verbsDiffer(before, after);
@@ -951,7 +1144,11 @@ patternMatcher) {
951
1144
  };
952
1145
  }
953
1146
  const fs = await ctx.getFilesystem(branch);
954
- const kind = await kindOf(fs, src);
1147
+ // A tmp ref names one file by rule: resolving it is the whole look, and
1148
+ // a folder or nothing there is refused by the resolver itself.
1149
+ const kind = fromTmp
1150
+ ? (await orNotFound(src, () => ctx.workspaceService.statTmpFile(workspaceIdForBranch(branch), ctx.user.id, src), 'Nothing to copy'), 'file')
1151
+ : await kindOf(fs, src);
955
1152
  if (kind === null)
956
1153
  throw notFound(src, 'Nothing to copy');
957
1154
  const srcFiles = kind === 'folder' ? (await filesUnder(fs, src)).files : [src];
@@ -976,6 +1173,39 @@ patternMatcher) {
976
1173
  copied: false,
977
1174
  };
978
1175
  };
1176
+ /**
1177
+ * `copy_file` out of the workspace's tmp folder: the bytes the ref names
1178
+ * (through the one tmp resolver), landed at `dest` by the ordinary write —
1179
+ * the lock, the pre-disk validation, the creator's read grant for a new
1180
+ * folder and the commit every write to the repository takes — and
1181
+ * exclusively, so a name taken since the handler's look is refused with
1182
+ * the same sentence rather than replaced. From then on the copy is a
1183
+ * repository file like any other; the staged file is left where it was.
1184
+ *
1185
+ * A missing source is the ordinary 404 naming the ref, asked only after
1186
+ * the write verdict (as for any copy); an absence met while landing is the
1187
+ * destination's.
1188
+ */
1189
+ const copyFromTmp = async (fs, branch, ctx, src, dest) => {
1190
+ const bytes = await orNotFound(src, () => ctx.workspaceService.readTmpFile(workspaceIdForBranch(branch), ctx.user.id, src), 'Nothing to copy');
1191
+ try {
1192
+ // Exclusive, under the destination's lock: a name taken since the look
1193
+ // is refused there as `DestinationTakenError` — releasing the lock
1194
+ // untouched, so the winner's queued file stays — and answered as a
1195
+ // repository copy's lost race is (`asEntryExists`).
1196
+ await asEntryExists(() => fs.writeFile(dest, bytes, { overwrite: false }));
1197
+ }
1198
+ catch (err) {
1199
+ if (err instanceof ToolError)
1200
+ throw err;
1201
+ const occupiedBy = await existingAt(await workspaceRoot(branch, ctx), dest);
1202
+ if (occupiedBy !== null)
1203
+ throw new ToolError(entryExistsMessage(occupiedBy, dest), 409);
1204
+ if (isAbsence(err))
1205
+ throw notFound(dest, 'Nowhere to copy to');
1206
+ throw err;
1207
+ }
1208
+ };
979
1209
  /**
980
1210
  * The paths among `paths` the caller may NOT write, judged exactly as the
981
1211
  * lock gate judges them (`WorkflowService.acquireLock`): on a protected
@@ -1340,11 +1570,21 @@ patternMatcher) {
1340
1570
  // spill ref; for any other, `__tool_chain_spill__/x` is an ordinary
1341
1571
  // path, and exempting it there would be a workspace-relative path that
1342
1572
  // never reached the repository — the whole bug, spelled with a prefix.
1573
+ //
1574
+ // The other is a tmp ref (`__tmp__/…`), left as written in exactly the
1575
+ // inputs `TMP_REF_INPUTS` names and refused in every other one first,
1576
+ // so no tool sees one it does not resolve itself.
1343
1577
  toolHandler(async (args, ctx) => {
1344
1578
  // BEFORE the normaliser: see `assertToolPathsNotGitInternals`.
1345
1579
  if (spec.fileTool !== false)
1346
1580
  await assertToolPathsNotGitInternals(args, ctx);
1347
- const normalized = normalizePathArgs(args, kbDirName, spec.name === 'read_file' ? (v) => spillStore.isSpillRef(v) : undefined);
1581
+ // The normaliser admits a tmp ref in exactly the inputs
1582
+ // `TMP_REF_INPUTS` names and refuses it in every other one first.
1583
+ const normalized = normalizePathArgs(args, kbDirName, {
1584
+ tool: spec.name,
1585
+ tmpRefInputs: TMP_REF_INPUTS[spec.name],
1586
+ skip: spec.name === 'read_file' ? (v) => spillStore.isSpillRef(v) : undefined,
1587
+ });
1348
1588
  // The checkout's own name is reserved at the repository root on this
1349
1589
  // surface too. The routes meet that rule inside `WorkspaceService`;
1350
1590
  // these tools write through the locking filesystem, which never
@@ -1495,6 +1735,61 @@ patternMatcher) {
1495
1735
  * copy drifts on the first change to any of them.
1496
1736
  */
1497
1737
  const readForTool = async (branch, p, ctx) => (await readServed(branch, p, ctx)).result;
1738
+ /**
1739
+ * What a tmp ref (see `workspace-tmp.ts`) reads as: the bytes of the one
1740
+ * file it names in the CALLER's own folder of the branch workspace's `tmp/`
1741
+ * — through `readTmpFile`, the resolver a distribution's tool reads it with
1742
+ * — put through the SAME reader a repository file of that name gets. No
1743
+ * access gate and no read hook: the folder is outside the repository, so
1744
+ * no rule governs it and no knowledge-base path is read; what keeps one
1745
+ * person's staged file from another is that the ref resolves inside the
1746
+ * caller's folder alone. A missing file — somebody else's included — is the
1747
+ * ordinary 404, naming the ref.
1748
+ */
1749
+ const readTmp = async (branch, ref, ctx) => {
1750
+ const workspaceId = workspaceIdForBranch(branch);
1751
+ const bytes = await orNotFound(ref, () => ctx.workspaceService.readTmpFile(workspaceId, ctx.user.id, ref));
1752
+ return readers.readerFor(ref).read(bytes, ref, { workspaceId });
1753
+ };
1754
+ /**
1755
+ * `file_stat` on a tmp ref: the shape a repository file's stat has, its
1756
+ * content fields decided by the same reader as {@link readTmp} reads with —
1757
+ * and nothing to DO with it but read and copy out. Not written, moved,
1758
+ * deleted or downloaded through these tools (`managed` is false: the
1759
+ * platform's own files are a repository notion), and so not text-editable
1760
+ * either, whatever its content.
1761
+ */
1762
+ const statTmp = async (branch, ref, ctx) => {
1763
+ const workspaceId = workspaceIdForBranch(branch);
1764
+ const stat = await orNotFound(ref, () => ctx.workspaceService.statTmpFile(workspaceId, ctx.user.id, ref));
1765
+ const reader = readers.readerFor(ref);
1766
+ // One read of the file at most: the type decision and the remembered
1767
+ // extraction below both want the bytes, and a staged document can be large.
1768
+ let bytes;
1769
+ const bytesOf = async () => (bytes ??= await orNotFound(ref, () => ctx.workspaceService.readTmpFile(workspaceId, ctx.user.id, ref)));
1770
+ const type = fileTypeOf(reader, ref, needsContent(reader) ? await bytesOf() : undefined);
1771
+ const out = {
1772
+ ...stat,
1773
+ path: ref,
1774
+ type: 'file',
1775
+ managed: false,
1776
+ movable: false,
1777
+ deletable: false,
1778
+ access: TMP_ACCESS,
1779
+ canWrite: false,
1780
+ ...type,
1781
+ textEditable: false,
1782
+ };
1783
+ // A document whose extraction failed answers that failure's notice, as a
1784
+ // repository document does: from what the cache remembers, never by
1785
+ // extracting.
1786
+ if (reader instanceof DocumentReader) {
1787
+ const remembered = await reader.cachedRead(await bytesOf(), ref);
1788
+ if (remembered?.kind === 'refusal')
1789
+ return { ...out, unreadable: remembered.message };
1790
+ }
1791
+ return out;
1792
+ };
1498
1793
  /**
1499
1794
  * {@link readForTool}, also saying, at the guide's name, whether a file of
1500
1795
  * the knowledge base's own answered first on THIS branch (`guide`: `own`)
@@ -1520,7 +1815,7 @@ patternMatcher) {
1520
1815
  // the access gate and the read hook above — a document read is still a
1521
1816
  // KB read. ONE registry dispatch picks the reader by extension.
1522
1817
  const bytes = await orNotFound(p, async () => asBytes(await fs.readFile(p)));
1523
- return { result: await readers.readerFor(p).read(bytes, p), guide: null };
1818
+ return { result: await readers.readerFor(p).read(bytes, p, { workspaceId: workspaceIdForBranch(branch) }), guide: null };
1524
1819
  };
1525
1820
  /**
1526
1821
  * Whether the DEFAULT branch has a file of the knowledge base's own at the
@@ -1556,7 +1851,7 @@ patternMatcher) {
1556
1851
  type: 'object',
1557
1852
  properties: {
1558
1853
  branch: BRANCH_INPUT,
1559
- path: str(`Path to read, under \`${kbDirName}/\` (e.g. \`${kbDirName}/KnowledgeBase/Foo.md\`), with or without a leading slash — a path without that prefix is placed under \`${kbDirName}/\` — or a \`__tool_chain_spill__/…\` ref from a truncated \`call_tool_chain\`.`),
1854
+ path: str(`Path to read, under \`${kbDirName}/\` (e.g. \`${kbDirName}/KnowledgeBase/Foo.md\`), with or without a leading slash — a path without that prefix is placed under \`${kbDirName}/\` — or a \`__tool_chain_spill__/…\` ref from a truncated \`call_tool_chain\`, or a \`__tmp__/…\` ref to a file you staged in the workspace's tmp folder.`),
1560
1855
  offset: int('Start character index (default 0).'),
1561
1856
  limit: int('Max characters to return from `offset`.'),
1562
1857
  sessionId: SESSION_ID_INPUT,
@@ -1592,7 +1887,11 @@ patternMatcher) {
1592
1887
  : content;
1593
1888
  };
1594
1889
  const branch = a.branch;
1595
- const { result, guide } = await readServed(branch, p, ctx);
1890
+ // A tmp ref is no repository path, so the `canWrite` below is false for
1891
+ // it by the same rule as for any path outside the repository.
1892
+ const { result, guide } = isTmpRef(p)
1893
+ ? { result: await readTmp(branch, p, ctx), guide: null }
1894
+ : await readServed(branch, p, ctx);
1596
1895
  // Judged after the read, so a path the caller may not read is refused
1597
1896
  // before anything is said about writing it. At the guide's name this
1598
1897
  // answers for the knowledge base's own file there, as `file_stat` does:
@@ -1796,7 +2095,7 @@ patternMatcher) {
1796
2095
  type: 'object',
1797
2096
  properties: {
1798
2097
  branch: BRANCH_INPUT,
1799
- path: wsPath(kbDirName, 'Path'),
2098
+ path: orTmpRef(wsPath(kbDirName, 'Path')),
1800
2099
  explainAccess: {
1801
2100
  type: 'boolean',
1802
2101
  description: 'Also explain `access` (default false): `access.why` says what decided each of your verdicts — the folder rules or file frontmatter and whether that is inherited; `access.roster` lists who holds each verb and where each grant is written, given only when you can manage this path\'s access (otherwise null, with `access.rosterReason`).',
@@ -1855,6 +2154,7 @@ patternMatcher) {
1855
2154
  description: 'Files only: where `mime` came from. `fallback` means no type was detected.',
1856
2155
  },
1857
2156
  textEditable: { type: 'boolean', description: 'Files only: whether write_file/write_files/edit_file accept this file as it is now.' },
2157
+ unreadable: str('Documents only, and only when its text could not be extracted: the one-line notice read_file answers for it.'),
1858
2158
  mimeNote: str('Present when `mimeSource` is `fallback`: says the MIME type is a fallback, not a detected type.'),
1859
2159
  platformGuide: {
1860
2160
  type: 'boolean',
@@ -1868,6 +2168,8 @@ patternMatcher) {
1868
2168
  handler: async (a, ctx) => {
1869
2169
  const p = a.path;
1870
2170
  const branch = a.branch;
2171
+ if (isTmpRef(p))
2172
+ return statTmp(branch, p, ctx);
1871
2173
  // The guide's name with no file of the knowledge base's own under it —
1872
2174
  // or one the caller may not read, or a copy of the guide an earlier
1873
2175
  // release wrote, none of which `read_file` serves: what a read answers
@@ -2011,7 +2313,17 @@ patternMatcher) {
2011
2313
  const bytes = needsContent(reader)
2012
2314
  ? await orNotFound(p, async () => asBytes(await fs.readFile(p)))
2013
2315
  : undefined;
2014
- return { ...out, ...fileTypeOf(reader, p, bytes) };
2316
+ // A document whose extraction failed answers that failure's notice here
2317
+ // too, from what the cache remembers — never by extracting, so stat
2318
+ // stays as cheap as it was. The notice quotes the parser, so only a
2319
+ // caller who may read the file hears it.
2320
+ const type = fileTypeOf(reader, p, bytes);
2321
+ if (reader instanceof DocumentReader && verdicts.read) {
2322
+ const remembered = await reader.cachedRead(await orNotFound(p, async () => asBytes(await fs.readFile(p))), p);
2323
+ if (remembered?.kind === 'refusal')
2324
+ return { ...out, ...type, unreadable: remembered.message };
2325
+ }
2326
+ return { ...out, ...type };
2015
2327
  },
2016
2328
  });
2017
2329
  // Mounted only when the composition supplied a matcher — see the
@@ -2021,13 +2333,14 @@ patternMatcher) {
2021
2333
  mount({
2022
2334
  name: 'grep',
2023
2335
  gated: true,
2024
- description: 'Regex search across the workspace. Returns `{ matches: [{ path, line, text }] }` (capped). Use to find where something is defined/referenced. `path` may name a DIRECTORY (searches the subtree) or a single FILE (searches just that file); a path with nothing at it is an error, never an empty result. Searches INSIDE Office and OpenDocument files (.docx/.pptx/.xlsx, .odt/.odp/.ods), PDFs and email files (.eml/.msg) via their extracted text — matches there carry the extraction\'s line numbers, and the `[slide N]`/`[sheet: Name]`/`[page N]`/`[from]`/`[subject]` marker lines locate them; a bounded number of not-yet-extracted documents is extracted per call, and the result notes how many were skipped (re-run to cover them).',
2336
+ description: `Regex search across the workspace. ${PATTERN_DIALECT} Covers hidden and git-ignored files. ` +
2337
+ 'Returns `{ matches: [{ path, line, text }] }`, capped, in path then line order. `path` may name a DIRECTORY (its subtree) or a single FILE; a path with nothing at it is an error. Searches INSIDE Office/OpenDocument, PDF and email files (.eml/.msg) via their extracted text — matches carry the extraction\'s line numbers, and the `[slide N]`/`[sheet: Name]`/`[page N]`/`[from]`/`[subject]` marker lines locate them; a bounded number of not-yet-extracted documents is extracted per call; the result notes the rest (re-run to cover them).',
2025
2338
  inputs: {
2026
2339
  type: 'object',
2027
2340
  properties: {
2028
2341
  branch: BRANCH_INPUT,
2029
- pattern: str('JavaScript regular expression.'),
2030
- path: str(`Subtree to search, or a single file to search on its own, with or without a leading slash — a path without the \`${kbDirName}/\` prefix is placed under \`${kbDirName}/\` (default: the whole repository, \`${kbDirName}/\`).`),
2342
+ pattern: str('Regular expression, RE2-style (ripgrep): no look-around, no backreferences.'),
2343
+ path: str(`Subtree to search, or a single file to search on its own, with or without a leading slash — a path without the \`${kbDirName}/\` prefix is placed under \`${kbDirName}/\` (default: the whole repository, \`${kbDirName}/\`) — or a \`__tmp__/…\` ref to one staged file.`),
2031
2344
  ignore_case: { type: 'boolean', description: 'Case-insensitive match.' },
2032
2345
  max_results: { type: 'integer', minimum: 1, maximum: 1000, description: 'Cap on matches (default 200).' },
2033
2346
  sessionId: SESSION_ID_INPUT,
@@ -2054,9 +2367,14 @@ patternMatcher) {
2054
2367
  },
2055
2368
  write: false,
2056
2369
  handler: async (a, ctx) => {
2057
- // The caller's pattern never runs on the request thread: a backtracking
2058
- // one would hold the event loop for everyone (see IPatternMatcher).
2059
- const matcher = patterns.search(a.pattern, a.ignore_case ? 'i' : '');
2370
+ // The caller's pattern runs in ripgrep, never on the request thread
2371
+ // (see IPatternMatcher); one the engine refuses is answered here,
2372
+ // before anything is searched. A caller that goes away takes the
2373
+ // search's runs with it.
2374
+ const search = await patterns.search(a.pattern, {
2375
+ ignoreCase: Boolean(a.ignore_case),
2376
+ signal: ctx.abortSignal,
2377
+ });
2060
2378
  // No path means the whole REPOSITORY, not the workspace directory above
2061
2379
  // it. The workspace root also holds whatever an older build left beside
2062
2380
  // the checkout, and the read gate has no rules for a path outside the
@@ -2072,16 +2390,27 @@ patternMatcher) {
2072
2390
  const gate = readGateFor(a.branch, ctx);
2073
2391
  const out = [];
2074
2392
  const max = typeof a.max_results === 'number' ? Math.min(a.max_results, 1000) : 200;
2075
- const docs = { readers, uncachedBudget: UNCACHED_DOCS_PER_GREP, skippedUncached: 0 };
2393
+ const docs = {
2394
+ readers,
2395
+ origin: { workspaceId: workspaceIdForBranch(a.branch) },
2396
+ uncachedBudget: UNCACHED_DOCS_PER_GREP,
2397
+ skippedUncached: 0,
2398
+ };
2076
2399
  // The empty root is the workspace itself — always a directory, and never
2077
2400
  // worth a stat.
2078
2401
  // A placeholder named on its own is searched as what it is to every
2079
2402
  // other tool: nothing.
2080
- const kind = searchRoot === ''
2081
- ? 'directory'
2082
- : isFolderPlaceholder(searchRoot)
2083
- ? 'missing'
2084
- : await searchRootKind(fs, searchRoot);
2403
+ // A tmp ref names one file by rule (see `workspace-tmp.ts`), so it is
2404
+ // searched as a single file — never walked, and outside the repository
2405
+ // there is no read gate or read hook for it, as for `read_file`.
2406
+ const tmp = isTmpRef(searchRoot);
2407
+ const kind = tmp
2408
+ ? 'file'
2409
+ : searchRoot === ''
2410
+ ? 'directory'
2411
+ : isFolderPlaceholder(searchRoot)
2412
+ ? 'missing'
2413
+ : await searchRootKind(fs, searchRoot);
2085
2414
  /** Why a single-file search found nothing, when "no matches" would be a lie. */
2086
2415
  let fileNote;
2087
2416
  // The guide is searched where it is read: a search of the repository
@@ -2102,22 +2431,26 @@ patternMatcher) {
2102
2431
  // The guide's own path is not told here, because `guideAt` tells the
2103
2432
  // hook of the organisation's file there exactly as `read_file` does
2104
2433
  // (after the gate), and the platform's guide alone is nobody's file to
2105
- // note. Each file the walk opens goes to the hook per file below, so a
2106
- // hook sees every path a grep reached rather than only its root.
2107
- if (!(coversGuide && kind !== 'directory')) {
2434
+ // note. Each file the search opens goes to the hook per file below,
2435
+ // before it is opened and whether or not a line of it is answered
2436
+ // (`grepTree`'s admission), so a hook sees every file a grep reads
2437
+ // rather than only its root, and may refuse one as it refuses a
2438
+ // read_file. A tmp ref is no repository content, so there is nothing
2439
+ // to tell.
2440
+ if (!tmp && !(coversGuide && kind !== 'directory')) {
2108
2441
  await notifyAgentRead(agentAccessGate, ctx, a.branch, searchRoot);
2109
2442
  }
2443
+ const notifyRead = (p) => notifyAgentRead(agentAccessGate, ctx, a.branch, p);
2110
2444
  if (coversGuide) {
2111
2445
  if (kind === 'directory') {
2112
- await grepWalk(fs, searchRoot, matcher, out, max, 0, gate, (p) => notifyAgentRead(agentAccessGate, ctx, a.branch, p), docs, (p) => p === guidePath);
2113
- }
2114
- const lines = (await guideAt(a.branch, ctx, guidePath)).split('\n');
2115
- for (const i of await matcher.matchingLines(lines, max - out.length)) {
2116
- out.push({ path: guidePath, line: i + 1, text: lines[i].slice(0, 300) });
2446
+ out.push(...(await grepTree(fs, searchRoot, search, max, gate, notifyRead, docs, (p) => p === guidePath)));
2117
2447
  }
2448
+ const guide = await guideAt(a.branch, ctx, guidePath);
2449
+ const [hits] = await search.matchingLines([guide]);
2450
+ pushMatches(out, guidePath, guide, hits);
2118
2451
  }
2119
2452
  else if (kind === 'directory') {
2120
- await grepWalk(fs, searchRoot, matcher, out, max, 0, gate, (p) => notifyAgentRead(agentAccessGate, ctx, a.branch, p), docs);
2453
+ out.push(...(await grepTree(fs, searchRoot, search, max, gate, notifyRead, docs)));
2121
2454
  }
2122
2455
  else {
2123
2456
  // Not a directory: the permission verdict comes BEFORE every other
@@ -2129,11 +2462,28 @@ patternMatcher) {
2129
2462
  await assertCanRead(gate, searchRoot);
2130
2463
  if (kind === 'missing')
2131
2464
  throw notFound(searchRoot, 'Nothing to search');
2132
- // A named FILE is searched directly: routing it through the walk would
2133
- // fail its readdir and answer an empty match list, which the caller
2134
- // cannot tell from "the pattern is not in this file".
2135
- const outcome = await orNotFound(searchRoot, () => grepOneFile(fs, searchRoot, matcher, out, max, docs), 'Nothing to search');
2136
- if (outcome === 'no-text') {
2465
+ // A named text FILE is searched as a tree search searches it: by
2466
+ // ripgrep, from its folder, so it answers the same lines either way
2467
+ // (the valid UTF-8 lines of a file holding some that are not, and
2468
+ // nothing from one ripgrep finds binary). Any other file, and any
2469
+ // path that is not a regular file, is read through its reader,
2470
+ // exactly as read_file reads it, its text searched by the same
2471
+ // engine: a tree search would find nothing to walk and answer an
2472
+ // empty match list, which the caller cannot tell from "the pattern
2473
+ // is not in this file". A tmp ref is not in the checkout ripgrep
2474
+ // searches, so it is always read through its reader, its bytes from
2475
+ // the tmp resolver.
2476
+ const bytesOf = tmp
2477
+ ? (ref) => ctx.workspaceService.readTmpFile(docs.origin.workspaceId, ctx.user.id, ref)
2478
+ : fileBytes(fs);
2479
+ const found = (!tmp && readers.readerFor(searchRoot) instanceof TextReader
2480
+ ? await grepTextFile(fs, searchRoot, search, max, out)
2481
+ : null) ?? (await orNotFound(searchRoot, () => searchableText(bytesOf, searchRoot, docs), 'Nothing to search'));
2482
+ if (found.kind === 'text') {
2483
+ const [hits] = await search.matchingLines([found.text]);
2484
+ pushMatches(out, searchRoot, found.text, hits);
2485
+ }
2486
+ else if (found.kind === 'no-text') {
2137
2487
  fileNote =
2138
2488
  `"${displayPath(searchRoot)}" has no searchable text — it is an image, binary content, or a document ` +
2139
2489
  'whose text could not be extracted. There were no matches because there was nothing to search, not ' +
@@ -2146,8 +2496,11 @@ patternMatcher) {
2146
2496
  `extracted and this call's extraction budget (${UNCACHED_DOCS_PER_GREP}) ran out. Re-run the ` +
2147
2497
  'same grep to extract and search the next batch.'
2148
2498
  : undefined);
2499
+ // One order whatever found the lines, then the cap: the first
2500
+ // `max_results` by path, then line.
2501
+ out.sort((x, y) => compareSearchPaths(x.path, y.path) || x.line - y.line);
2149
2502
  return {
2150
- matches: out,
2503
+ matches: out.slice(0, max),
2151
2504
  truncated: out.length >= max,
2152
2505
  ...(note !== undefined ? { note } : {}),
2153
2506
  };
@@ -2966,14 +3319,14 @@ patternMatcher) {
2966
3319
  mount({
2967
3320
  name: 'copy_file',
2968
3321
  gated: true,
2969
- description: 'Copy a workspace FILE to a new path. The destination must not exist — like a move, a copy never overwrites a file or a folder; to change what is in a file that already exists, write it. Committed + pushed as you. ' +
3322
+ description: 'Copy a workspace FILE to a new path. The destination must not exist — like a move, a copy never overwrites a file or a folder; to change what is in a file that already exists, write it. Committed + pushed as you. `src` may be a `__tmp__/<path>` ref to a file you staged in the workspace\'s tmp folder: the copy is how such a file is kept, as a normal repository file. ' +
2970
3323
  'Preflight first: `dryRun: true` changes nothing and answers `{ src, dest, kind, descendants, access: { before, after }, accessChanges, allowed, reason? }` — `access` is your own `{ read, write, download, owner }` at the source and at the destination AS IT WILL BE once the copy has landed, with every `access.md` inside a copied folder counted at its new place. ' +
2971
3324
  'One exception to that shape: when the destination is one you may not write, the answer is the refusal alone — `allowed: false` with `reason`, and no `kind` and no `descendants`, because nothing about the source is read before that verdict.',
2972
3325
  inputs: {
2973
3326
  type: 'object',
2974
3327
  properties: {
2975
3328
  branch: BRANCH_INPUT,
2976
- src: wsPath(kbDirName, 'Source path'),
3329
+ src: orTmpRef(wsPath(kbDirName, 'Source path')),
2977
3330
  dest: wsPath(kbDirName, 'Destination path — must not exist yet'),
2978
3331
  dryRun: { type: 'boolean', description: 'Answer with the impact and change nothing.' },
2979
3332
  sessionId: SESSION_ID_INPUT,
@@ -3001,11 +3354,16 @@ patternMatcher) {
3001
3354
  proposable: true,
3002
3355
  handler: async (a, ctx) => {
3003
3356
  // A copy CARRIES the source content into the destination, so BOTH ends
3004
- // go to the write hook. Ask about both before touching disk.
3005
- writePolicy.assertPathWritable(ctx.sessionId, a.src);
3357
+ // go to the write hook. Ask about both before touching disk. A tmp ref
3358
+ // is not a knowledge-base path, so only the destination is one to ask
3359
+ // about when the copy is out of the workspace's tmp folder.
3360
+ const fromTmp = isTmpRef(a.src);
3361
+ if (!fromTmp)
3362
+ writePolicy.assertPathWritable(ctx.sessionId, a.src);
3006
3363
  writePolicy.assertPathWritable(ctx.sessionId, a.dest);
3007
3364
  const branch = a.branch;
3008
- await assertAgentWriteAllowed(agentAccessGate, ctx, branch, a.src);
3365
+ if (!fromTmp)
3366
+ await assertAgentWriteAllowed(agentAccessGate, ctx, branch, a.src);
3009
3367
  await assertAgentWriteAllowed(agentAccessGate, ctx, branch, a.dest);
3010
3368
  const src = a.src;
3011
3369
  const dest = a.dest;
@@ -3055,6 +3413,10 @@ patternMatcher) {
3055
3413
  // the server's own absolute path. Anything that is not absence travels
3056
3414
  // on as it always did.
3057
3415
  const fs = await ctx.getFilesystem(branch);
3416
+ if (fromTmp) {
3417
+ await copyFromTmp(fs, branch, ctx, src, dest);
3418
+ return { src, dest, copied: true };
3419
+ }
3058
3420
  try {
3059
3421
  await asEntryExists(() => fs.copyFile(src, dest));
3060
3422
  }