@penclipai/server 2026.704.0 → 2026.714.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 (485) hide show
  1. package/dist/adapters/index.d.ts +1 -1
  2. package/dist/adapters/index.d.ts.map +1 -1
  3. package/dist/adapters/index.js.map +1 -1
  4. package/dist/adapters/process/execute.d.ts.map +1 -1
  5. package/dist/adapters/process/execute.js +1 -0
  6. package/dist/adapters/process/execute.js.map +1 -1
  7. package/dist/adapters/registry.d.ts.map +1 -1
  8. package/dist/adapters/registry.js +79 -51
  9. package/dist/adapters/registry.js.map +1 -1
  10. package/dist/adapters/utils.d.ts +5 -0
  11. package/dist/adapters/utils.d.ts.map +1 -1
  12. package/dist/adapters/utils.js.map +1 -1
  13. package/dist/agent-auth-jwt.d.ts +5 -1
  14. package/dist/agent-auth-jwt.d.ts.map +1 -1
  15. package/dist/agent-auth-jwt.js +72 -20
  16. package/dist/agent-auth-jwt.js.map +1 -1
  17. package/dist/app.d.ts +2 -0
  18. package/dist/app.d.ts.map +1 -1
  19. package/dist/app.js +10 -0
  20. package/dist/app.js.map +1 -1
  21. package/dist/built-ins/agents/reflection-coach/AGENTS.md +47 -0
  22. package/dist/built-ins/agents/reflection-coach/routines/recent-agent-reflection.md +77 -0
  23. package/dist/errors.d.ts +1 -1
  24. package/dist/errors.d.ts.map +1 -1
  25. package/dist/errors.js +2 -2
  26. package/dist/errors.js.map +1 -1
  27. package/dist/index.d.ts.map +1 -1
  28. package/dist/index.js +208 -116
  29. package/dist/index.js.map +1 -1
  30. package/dist/middleware/api-compression.d.ts +8 -0
  31. package/dist/middleware/api-compression.d.ts.map +1 -0
  32. package/dist/middleware/api-compression.js +207 -0
  33. package/dist/middleware/api-compression.js.map +1 -0
  34. package/dist/middleware/auth.d.ts.map +1 -1
  35. package/dist/middleware/auth.js +130 -3
  36. package/dist/middleware/auth.js.map +1 -1
  37. package/dist/middleware/error-handler.d.ts.map +1 -1
  38. package/dist/middleware/error-handler.js +27 -0
  39. package/dist/middleware/error-handler.js.map +1 -1
  40. package/dist/onboarding-assets/default/AGENTS.md +1 -0
  41. package/dist/redaction.d.ts.map +1 -1
  42. package/dist/redaction.js +11 -0
  43. package/dist/redaction.js.map +1 -1
  44. package/dist/routes/access.d.ts.map +1 -1
  45. package/dist/routes/access.js +4 -3
  46. package/dist/routes/access.js.map +1 -1
  47. package/dist/routes/adapters.d.ts.map +1 -1
  48. package/dist/routes/adapters.js +2 -0
  49. package/dist/routes/adapters.js.map +1 -1
  50. package/dist/routes/agents.d.ts.map +1 -1
  51. package/dist/routes/agents.js +222 -87
  52. package/dist/routes/agents.js.map +1 -1
  53. package/dist/routes/attention.d.ts +3 -0
  54. package/dist/routes/attention.d.ts.map +1 -0
  55. package/dist/routes/attention.js +24 -0
  56. package/dist/routes/attention.js.map +1 -0
  57. package/dist/routes/authz.d.ts.map +1 -1
  58. package/dist/routes/authz.js +29 -1
  59. package/dist/routes/authz.js.map +1 -1
  60. package/dist/routes/board-chat.d.ts.map +1 -1
  61. package/dist/routes/board-chat.js +4 -1
  62. package/dist/routes/board-chat.js.map +1 -1
  63. package/dist/routes/built-in-agents.d.ts +3 -0
  64. package/dist/routes/built-in-agents.d.ts.map +1 -0
  65. package/dist/routes/built-in-agents.js +267 -0
  66. package/dist/routes/built-in-agents.js.map +1 -0
  67. package/dist/routes/cases.d.ts +46 -0
  68. package/dist/routes/cases.d.ts.map +1 -0
  69. package/dist/routes/cases.js +1395 -0
  70. package/dist/routes/cases.js.map +1 -0
  71. package/dist/routes/companies.d.ts.map +1 -1
  72. package/dist/routes/companies.js +4 -1
  73. package/dist/routes/companies.js.map +1 -1
  74. package/dist/routes/company-skills.d.ts.map +1 -1
  75. package/dist/routes/company-skills.js +453 -33
  76. package/dist/routes/company-skills.js.map +1 -1
  77. package/dist/routes/environments.d.ts.map +1 -1
  78. package/dist/routes/environments.js +71 -8
  79. package/dist/routes/environments.js.map +1 -1
  80. package/dist/routes/execution-workspaces.d.ts.map +1 -1
  81. package/dist/routes/execution-workspaces.js +89 -3
  82. package/dist/routes/execution-workspaces.js.map +1 -1
  83. package/dist/routes/health.d.ts +2 -0
  84. package/dist/routes/health.d.ts.map +1 -1
  85. package/dist/routes/health.js +30 -0
  86. package/dist/routes/health.js.map +1 -1
  87. package/dist/routes/inbox-dismissals.d.ts.map +1 -1
  88. package/dist/routes/inbox-dismissals.js +80 -19
  89. package/dist/routes/inbox-dismissals.js.map +1 -1
  90. package/dist/routes/index.d.ts +2 -0
  91. package/dist/routes/index.d.ts.map +1 -1
  92. package/dist/routes/index.js +2 -0
  93. package/dist/routes/index.js.map +1 -1
  94. package/dist/routes/issues.d.ts +25 -0
  95. package/dist/routes/issues.d.ts.map +1 -1
  96. package/dist/routes/issues.js +1455 -46
  97. package/dist/routes/issues.js.map +1 -1
  98. package/dist/routes/openapi.d.ts.map +1 -1
  99. package/dist/routes/openapi.js +448 -11
  100. package/dist/routes/openapi.js.map +1 -1
  101. package/dist/routes/pipelines.js +2 -2
  102. package/dist/routes/pipelines.js.map +1 -1
  103. package/dist/routes/resource-memberships.d.ts.map +1 -1
  104. package/dist/routes/resource-memberships.js +13 -5
  105. package/dist/routes/resource-memberships.js.map +1 -1
  106. package/dist/routes/secrets.d.ts.map +1 -1
  107. package/dist/routes/secrets.js +261 -1
  108. package/dist/routes/secrets.js.map +1 -1
  109. package/dist/routes/sidebar-badges.d.ts.map +1 -1
  110. package/dist/routes/sidebar-badges.js +18 -2
  111. package/dist/routes/sidebar-badges.js.map +1 -1
  112. package/dist/routes/user-profiles.d.ts.map +1 -1
  113. package/dist/routes/user-profiles.js +5 -4
  114. package/dist/routes/user-profiles.js.map +1 -1
  115. package/dist/server-info.d.ts +2 -0
  116. package/dist/server-info.d.ts.map +1 -1
  117. package/dist/server-info.js +20 -5
  118. package/dist/server-info.js.map +1 -1
  119. package/dist/services/access.d.ts +4 -4
  120. package/dist/services/access.d.ts.map +1 -1
  121. package/dist/services/activity.d.ts +3 -3
  122. package/dist/services/activity.d.ts.map +1 -1
  123. package/dist/services/activity.js +5 -4
  124. package/dist/services/activity.js.map +1 -1
  125. package/dist/services/adapter-registry-bootstrap.reconcile.test.js +1 -0
  126. package/dist/services/adapter-registry-bootstrap.reconcile.test.js.map +1 -1
  127. package/dist/services/agent-secret-bindings.d.ts +15 -0
  128. package/dist/services/agent-secret-bindings.d.ts.map +1 -1
  129. package/dist/services/agent-secret-bindings.js +43 -0
  130. package/dist/services/agent-secret-bindings.js.map +1 -1
  131. package/dist/services/agents.d.ts +194 -133
  132. package/dist/services/agents.d.ts.map +1 -1
  133. package/dist/services/agents.js +107 -4
  134. package/dist/services/agents.js.map +1 -1
  135. package/dist/services/approvals.d.ts +10 -10
  136. package/dist/services/approvals.d.ts.map +1 -1
  137. package/dist/services/approvals.js +9 -1
  138. package/dist/services/approvals.js.map +1 -1
  139. package/dist/services/assets.d.ts +5 -5
  140. package/dist/services/attention.d.ts +11 -0
  141. package/dist/services/attention.d.ts.map +1 -0
  142. package/dist/services/attention.js +1024 -0
  143. package/dist/services/attention.js.map +1 -0
  144. package/dist/services/authorization.d.ts +15 -2
  145. package/dist/services/authorization.d.ts.map +1 -1
  146. package/dist/services/authorization.js +324 -8
  147. package/dist/services/authorization.js.map +1 -1
  148. package/dist/services/board-auth.d.ts +2 -2
  149. package/dist/services/budgets.d.ts.map +1 -1
  150. package/dist/services/budgets.js +8 -7
  151. package/dist/services/budgets.js.map +1 -1
  152. package/dist/services/built-in-agent-metadata.d.ts +9 -0
  153. package/dist/services/built-in-agent-metadata.d.ts.map +1 -0
  154. package/dist/services/built-in-agent-metadata.js +39 -0
  155. package/dist/services/built-in-agent-metadata.js.map +1 -0
  156. package/dist/services/built-in-agents.d.ts +394 -0
  157. package/dist/services/built-in-agents.d.ts.map +1 -0
  158. package/dist/services/built-in-agents.js +1426 -0
  159. package/dist/services/built-in-agents.js.map +1 -0
  160. package/dist/services/change-consent-gate.d.ts +18 -0
  161. package/dist/services/change-consent-gate.d.ts.map +1 -0
  162. package/dist/services/change-consent-gate.js +170 -0
  163. package/dist/services/change-consent-gate.js.map +1 -0
  164. package/dist/services/companies.d.ts +14 -8
  165. package/dist/services/companies.d.ts.map +1 -1
  166. package/dist/services/companies.js +6 -1
  167. package/dist/services/companies.js.map +1 -1
  168. package/dist/services/company-artifacts.d.ts +4 -1
  169. package/dist/services/company-artifacts.d.ts.map +1 -1
  170. package/dist/services/company-artifacts.js +9 -1
  171. package/dist/services/company-artifacts.js.map +1 -1
  172. package/dist/services/company-member-roles.d.ts.map +1 -1
  173. package/dist/services/company-member-roles.js +2 -0
  174. package/dist/services/company-member-roles.js.map +1 -1
  175. package/dist/services/company-portability.d.ts +1 -1
  176. package/dist/services/company-portability.d.ts.map +1 -1
  177. package/dist/services/company-portability.js +113 -8
  178. package/dist/services/company-portability.js.map +1 -1
  179. package/dist/services/company-search.d.ts.map +1 -1
  180. package/dist/services/company-search.js +843 -294
  181. package/dist/services/company-search.js.map +1 -1
  182. package/dist/services/company-skills.d.ts +64 -3
  183. package/dist/services/company-skills.d.ts.map +1 -1
  184. package/dist/services/company-skills.js +1205 -20
  185. package/dist/services/company-skills.js.map +1 -1
  186. package/dist/services/costs.d.ts +9 -8
  187. package/dist/services/costs.d.ts.map +1 -1
  188. package/dist/services/costs.js +9 -2
  189. package/dist/services/costs.js.map +1 -1
  190. package/dist/services/dashboard.d.ts +2 -0
  191. package/dist/services/dashboard.d.ts.map +1 -1
  192. package/dist/services/dashboard.js +60 -17
  193. package/dist/services/dashboard.js.map +1 -1
  194. package/dist/services/database-backup-health.d.ts +34 -0
  195. package/dist/services/database-backup-health.d.ts.map +1 -0
  196. package/dist/services/database-backup-health.js +104 -0
  197. package/dist/services/database-backup-health.js.map +1 -0
  198. package/dist/services/document-annotations.d.ts +169 -1
  199. package/dist/services/document-annotations.d.ts.map +1 -1
  200. package/dist/services/document-annotations.js +272 -1
  201. package/dist/services/document-annotations.js.map +1 -1
  202. package/dist/services/documents.d.ts +368 -0
  203. package/dist/services/documents.d.ts.map +1 -1
  204. package/dist/services/documents.js +2 -2
  205. package/dist/services/documents.js.map +1 -1
  206. package/dist/services/environment-config.d.ts.map +1 -1
  207. package/dist/services/environment-config.js +6 -0
  208. package/dist/services/environment-config.js.map +1 -1
  209. package/dist/services/environment-custom-image-runtime.d.ts +28 -0
  210. package/dist/services/environment-custom-image-runtime.d.ts.map +1 -1
  211. package/dist/services/environment-custom-image-runtime.js +106 -7
  212. package/dist/services/environment-custom-image-runtime.js.map +1 -1
  213. package/dist/services/environment-custom-images.d.ts +31 -1
  214. package/dist/services/environment-custom-images.d.ts.map +1 -1
  215. package/dist/services/environment-custom-images.js +110 -4
  216. package/dist/services/environment-custom-images.js.map +1 -1
  217. package/dist/services/environment-execution-target.d.ts.map +1 -1
  218. package/dist/services/environment-execution-target.js +1 -3
  219. package/dist/services/environment-execution-target.js.map +1 -1
  220. package/dist/services/environment-probe.d.ts +1 -0
  221. package/dist/services/environment-probe.d.ts.map +1 -1
  222. package/dist/services/environment-probe.js +99 -5
  223. package/dist/services/environment-probe.js.map +1 -1
  224. package/dist/services/environments.d.ts +3 -1
  225. package/dist/services/environments.d.ts.map +1 -1
  226. package/dist/services/environments.js +98 -3
  227. package/dist/services/environments.js.map +1 -1
  228. package/dist/services/execution-workspace-policy.d.ts +29 -3
  229. package/dist/services/execution-workspace-policy.d.ts.map +1 -1
  230. package/dist/services/execution-workspace-policy.js +44 -1
  231. package/dist/services/execution-workspace-policy.js.map +1 -1
  232. package/dist/services/execution-workspaces.d.ts +64 -1
  233. package/dist/services/execution-workspaces.d.ts.map +1 -1
  234. package/dist/services/execution-workspaces.js +634 -3
  235. package/dist/services/execution-workspaces.js.map +1 -1
  236. package/dist/services/external-objects.d.ts +26 -26
  237. package/dist/services/feedback.d.ts +2 -2
  238. package/dist/services/finance.d.ts +5 -5
  239. package/dist/services/goals.d.ts +8 -8
  240. package/dist/services/heartbeat-stop-metadata.d.ts +2 -2
  241. package/dist/services/heartbeat-stop-metadata.d.ts.map +1 -1
  242. package/dist/services/heartbeat-stop-metadata.js +4 -0
  243. package/dist/services/heartbeat-stop-metadata.js.map +1 -1
  244. package/dist/services/heartbeat-stop-metadata.test.js +9 -0
  245. package/dist/services/heartbeat-stop-metadata.test.js.map +1 -1
  246. package/dist/services/heartbeat.d.ts +133 -28
  247. package/dist/services/heartbeat.d.ts.map +1 -1
  248. package/dist/services/heartbeat.js +1963 -239
  249. package/dist/services/heartbeat.js.map +1 -1
  250. package/dist/services/inbox-dismissals.d.ts +26 -0
  251. package/dist/services/inbox-dismissals.d.ts.map +1 -1
  252. package/dist/services/inbox-dismissals.js +33 -18
  253. package/dist/services/inbox-dismissals.js.map +1 -1
  254. package/dist/services/index.d.ts +3 -1
  255. package/dist/services/index.d.ts.map +1 -1
  256. package/dist/services/index.js +3 -1
  257. package/dist/services/index.js.map +1 -1
  258. package/dist/services/instance-settings.d.ts +25 -1
  259. package/dist/services/instance-settings.d.ts.map +1 -1
  260. package/dist/services/instance-settings.js +103 -5
  261. package/dist/services/instance-settings.js.map +1 -1
  262. package/dist/services/issue-continuation-summary.js +1 -1
  263. package/dist/services/issue-continuation-summary.js.map +1 -1
  264. package/dist/services/issue-recovery-actions.d.ts +3 -0
  265. package/dist/services/issue-recovery-actions.d.ts.map +1 -1
  266. package/dist/services/issue-recovery-actions.js +9 -0
  267. package/dist/services/issue-recovery-actions.js.map +1 -1
  268. package/dist/services/issue-rewake-throttle.d.ts +92 -0
  269. package/dist/services/issue-rewake-throttle.d.ts.map +1 -0
  270. package/dist/services/issue-rewake-throttle.js +139 -0
  271. package/dist/services/issue-rewake-throttle.js.map +1 -0
  272. package/dist/services/issue-thread-interactions.d.ts +8 -1
  273. package/dist/services/issue-thread-interactions.d.ts.map +1 -1
  274. package/dist/services/issue-thread-interactions.js +231 -16
  275. package/dist/services/issue-thread-interactions.js.map +1 -1
  276. package/dist/services/issue-visibility.d.ts +4 -0
  277. package/dist/services/issue-visibility.d.ts.map +1 -0
  278. package/dist/services/issue-visibility.js +9 -0
  279. package/dist/services/issue-visibility.js.map +1 -0
  280. package/dist/services/issues.d.ts +225 -105
  281. package/dist/services/issues.d.ts.map +1 -1
  282. package/dist/services/issues.js +540 -18
  283. package/dist/services/issues.js.map +1 -1
  284. package/dist/services/local-service-supervisor.d.ts +3 -0
  285. package/dist/services/local-service-supervisor.d.ts.map +1 -1
  286. package/dist/services/local-service-supervisor.js +51 -0
  287. package/dist/services/local-service-supervisor.js.map +1 -1
  288. package/dist/services/pipeline-case-outputs.d.ts.map +1 -1
  289. package/dist/services/pipeline-case-outputs.js +2 -1
  290. package/dist/services/pipeline-case-outputs.js.map +1 -1
  291. package/dist/services/pipelines-aggregation.d.ts.map +1 -1
  292. package/dist/services/pipelines-aggregation.js +3 -2
  293. package/dist/services/pipelines-aggregation.js.map +1 -1
  294. package/dist/services/pipelines.d.ts +165 -165
  295. package/dist/services/pipelines.d.ts.map +1 -1
  296. package/dist/services/pipelines.js +6 -4
  297. package/dist/services/pipelines.js.map +1 -1
  298. package/dist/services/plugin-database.d.ts +2 -2
  299. package/dist/services/plugin-environment-driver.d.ts +1 -1
  300. package/dist/services/plugin-host-services.d.ts.map +1 -1
  301. package/dist/services/plugin-host-services.js +3 -1
  302. package/dist/services/plugin-host-services.js.map +1 -1
  303. package/dist/services/plugin-managed-routines.d.ts +1 -0
  304. package/dist/services/plugin-managed-routines.d.ts.map +1 -1
  305. package/dist/services/plugin-registry.d.ts +21 -21
  306. package/dist/services/productivity-review.d.ts +1 -0
  307. package/dist/services/productivity-review.d.ts.map +1 -1
  308. package/dist/services/productivity-review.js +6 -5
  309. package/dist/services/productivity-review.js.map +1 -1
  310. package/dist/services/projects.d.ts +9 -9
  311. package/dist/services/recovery/service.d.ts +82 -54
  312. package/dist/services/recovery/service.d.ts.map +1 -1
  313. package/dist/services/recovery/service.js +200 -35
  314. package/dist/services/recovery/service.js.map +1 -1
  315. package/dist/services/recovery/successful-run-handoff.d.ts +1 -0
  316. package/dist/services/recovery/successful-run-handoff.d.ts.map +1 -1
  317. package/dist/services/recovery/successful-run-handoff.js +2 -0
  318. package/dist/services/recovery/successful-run-handoff.js.map +1 -1
  319. package/dist/services/recovery/successful-run-handoff.test.js +20 -0
  320. package/dist/services/recovery/successful-run-handoff.test.js.map +1 -1
  321. package/dist/services/resource-memberships.d.ts +13 -10
  322. package/dist/services/resource-memberships.d.ts.map +1 -1
  323. package/dist/services/resource-memberships.js +89 -20
  324. package/dist/services/resource-memberships.js.map +1 -1
  325. package/dist/services/responsible-user-denial-run-outcomes.d.ts +60 -0
  326. package/dist/services/responsible-user-denial-run-outcomes.d.ts.map +1 -0
  327. package/dist/services/responsible-user-denial-run-outcomes.js +56 -0
  328. package/dist/services/responsible-user-denial-run-outcomes.js.map +1 -0
  329. package/dist/services/responsible-user-denial-run-outcomes.test.d.ts +2 -0
  330. package/dist/services/responsible-user-denial-run-outcomes.test.d.ts.map +1 -0
  331. package/dist/services/responsible-user-denial-run-outcomes.test.js +75 -0
  332. package/dist/services/responsible-user-denial-run-outcomes.test.js.map +1 -0
  333. package/dist/services/routines.d.ts +30 -8
  334. package/dist/services/routines.d.ts.map +1 -1
  335. package/dist/services/routines.js +241 -18
  336. package/dist/services/routines.js.map +1 -1
  337. package/dist/services/run-liveness.d.ts.map +1 -1
  338. package/dist/services/run-liveness.js +21 -0
  339. package/dist/services/run-liveness.js.map +1 -1
  340. package/dist/services/run-log-store.d.ts +1 -0
  341. package/dist/services/run-log-store.d.ts.map +1 -1
  342. package/dist/services/run-log-store.js +4 -0
  343. package/dist/services/run-log-store.js.map +1 -1
  344. package/dist/services/run-scratch.d.ts +42 -0
  345. package/dist/services/run-scratch.d.ts.map +1 -0
  346. package/dist/services/run-scratch.js +111 -0
  347. package/dist/services/run-scratch.js.map +1 -0
  348. package/dist/services/run-scratch.test.d.ts +2 -0
  349. package/dist/services/run-scratch.test.d.ts.map +1 -0
  350. package/dist/services/run-scratch.test.js +98 -0
  351. package/dist/services/run-scratch.test.js.map +1 -0
  352. package/dist/services/secrets.d.ts +1261 -64
  353. package/dist/services/secrets.d.ts.map +1 -1
  354. package/dist/services/secrets.js +1089 -96
  355. package/dist/services/secrets.js.map +1 -1
  356. package/dist/services/task-watchdogs.d.ts +1 -0
  357. package/dist/services/task-watchdogs.d.ts.map +1 -1
  358. package/dist/services/task-watchdogs.js +78 -9
  359. package/dist/services/task-watchdogs.js.map +1 -1
  360. package/dist/services/work-timeline.d.ts.map +1 -1
  361. package/dist/services/work-timeline.js +34 -2
  362. package/dist/services/work-timeline.js.map +1 -1
  363. package/dist/services/workspace-runtime-read-model.d.ts +30 -29
  364. package/dist/services/workspace-runtime-read-model.d.ts.map +1 -1
  365. package/dist/services/workspace-runtime-read-model.js.map +1 -1
  366. package/dist/services/workspace-runtime.d.ts +59 -13
  367. package/dist/services/workspace-runtime.d.ts.map +1 -1
  368. package/dist/services/workspace-runtime.js +1121 -102
  369. package/dist/services/workspace-runtime.js.map +1 -1
  370. package/dist/skills-catalog/catalog/bundled/paperclip-operations/reflection-coach/SKILL.md +202 -0
  371. package/dist/skills-catalog/catalog/bundled/product/paperclip-capsules/SKILL.md +1 -1
  372. package/dist/skills-catalog/catalog/bundled/product/wireframe/SKILL.md +1 -1
  373. package/dist/skills-catalog/catalog/optional/content/release-announcement/SKILL.md +90 -0
  374. package/dist/skills-catalog/catalog/optional/finance/ramp/SKILL.md +98 -0
  375. package/dist/skills-catalog/generated/catalog.json +84 -12
  376. package/dist/ui-branding.d.ts +7 -0
  377. package/dist/ui-branding.d.ts.map +1 -1
  378. package/dist/ui-branding.js +8 -2
  379. package/dist/ui-branding.js.map +1 -1
  380. package/dist/version.d.ts +14 -0
  381. package/dist/version.d.ts.map +1 -1
  382. package/dist/version.js +114 -3
  383. package/dist/version.js.map +1 -1
  384. package/package.json +19 -20
  385. package/skills/paperclip/SKILL.md +45 -10
  386. package/skills/paperclip/references/api-reference.md +246 -1
  387. package/skills/paperclip/references/cases.md +295 -0
  388. package/skills/paperclip/references/company-skills.md +1 -1
  389. package/skills/paperclip-board/SKILL.md +3 -4
  390. package/skills/paperclip-converting-plans-to-tasks/SKILL.md +3 -7
  391. package/skills/para-memory-files/SKILL.md +3 -7
  392. package/ui-dist/assets/{abnfDiagram-VRR7QNED-BsFz2IiG.js → abnfDiagram-VRR7QNED-Dtgfy1PK.js} +1 -1
  393. package/ui-dist/assets/{arc-HZhAwbOs.js → arc-BGdvNvs8.js} +1 -1
  394. package/ui-dist/assets/{architectureDiagram-ZJ3FMSHR-BteMjuOn.js → architectureDiagram-ZJ3FMSHR-CK19SQDx.js} +1 -1
  395. package/ui-dist/assets/{blockDiagram-677ZJIJ3-Iq66uZjf.js → blockDiagram-677ZJIJ3-Kh4N3XG4.js} +1 -1
  396. package/ui-dist/assets/{browser-ponyfill-BBsuyZJt.js → browser-ponyfill-B3hXtEFW.js} +1 -1
  397. package/ui-dist/assets/{c4Diagram-LMCZKHZV-_nlglj7I.js → c4Diagram-LMCZKHZV-CBHpGrgU.js} +1 -1
  398. package/ui-dist/assets/channel-4fjB8e8N.js +1 -0
  399. package/ui-dist/assets/{chunk-2Q5K7J3B-Cvz7WwSQ.js → chunk-2Q5K7J3B-BdHbqi7k.js} +1 -1
  400. package/ui-dist/assets/{chunk-32BRIVSS-LLubniCS.js → chunk-32BRIVSS-DxtzZzpt.js} +1 -1
  401. package/ui-dist/assets/{chunk-5VM5RSS4-BOst5hcr.js → chunk-5VM5RSS4-DMKxBbgu.js} +1 -1
  402. package/ui-dist/assets/{chunk-EX3LRPZG-D5WNShVm.js → chunk-EX3LRPZG-BaIOPi4v.js} +1 -1
  403. package/ui-dist/assets/{chunk-JWPE2WC7-CA07x4av.js → chunk-JWPE2WC7-DGo3MPmr.js} +1 -1
  404. package/ui-dist/assets/{chunk-MOJQB5TN-Clfi83rK.js → chunk-MOJQB5TN-BEhQg0uD.js} +1 -1
  405. package/ui-dist/assets/{chunk-RYQCIY6F-BhZ6p7YJ.js → chunk-RYQCIY6F-HPJ6zRpJ.js} +1 -1
  406. package/ui-dist/assets/{chunk-V7JOEXUC-CdexJGoV.js → chunk-V7JOEXUC-Bl_6cAJD.js} +1 -1
  407. package/ui-dist/assets/{chunk-VR4S4FIN-8vjmBhr1.js → chunk-VR4S4FIN-KMjgGCsw.js} +1 -1
  408. package/ui-dist/assets/{chunk-XXDRQBXY-CqmCaplj.js → chunk-XXDRQBXY-oWGAIKjr.js} +1 -1
  409. package/ui-dist/assets/classDiagram-OUVF2IWQ-CTXxO5l9.js +1 -0
  410. package/ui-dist/assets/classDiagram-v2-EOCWNBFH-CTXxO5l9.js +1 -0
  411. package/ui-dist/assets/{cose-bilkent-JH36ORCC-CY-zAygY.js → cose-bilkent-JH36ORCC-Ckqse1pH.js} +1 -1
  412. package/ui-dist/assets/{cynefin-VYW2F7L2-BQSQ1HKr.js → cynefin-VYW2F7L2-DfZ8Hzqi.js} +1 -1
  413. package/ui-dist/assets/{cynefinDiagram-TSTJHNR4-NJCuFrZL.js → cynefinDiagram-TSTJHNR4-BkDQo9oi.js} +1 -1
  414. package/ui-dist/assets/{dagre-VKFMJZFB-DAUPIc8g.js → dagre-VKFMJZFB-ClghXQ6E.js} +1 -1
  415. package/ui-dist/assets/{diagram-FQU43EPY-DvMwJlCi.js → diagram-FQU43EPY-D5a0CwpV.js} +1 -1
  416. package/ui-dist/assets/{diagram-G47NLZAW-DPY0Jz_y.js → diagram-G47NLZAW-hVjYR_xl.js} +1 -1
  417. package/ui-dist/assets/{diagram-NH7WQ7WH-BpopeEhp.js → diagram-NH7WQ7WH-BlDPgD5Z.js} +1 -1
  418. package/ui-dist/assets/{diagram-OA4YK3LP-Qpu05z9X.js → diagram-OA4YK3LP-D0iZKIS3.js} +1 -1
  419. package/ui-dist/assets/{diagram-WEI45ONY-DHnvw9XU.js → diagram-WEI45ONY-m6hrfD0J.js} +1 -1
  420. package/ui-dist/assets/{ebnfDiagram-CCIWWBDH-D61S54_7.js → ebnfDiagram-CCIWWBDH-D4SQYLod.js} +1 -1
  421. package/ui-dist/assets/{erDiagram-Q63AITRT-pplAN_x2.js → erDiagram-Q63AITRT-Byzb6-I5.js} +1 -1
  422. package/ui-dist/assets/{flowDiagram-23GEKE2U-BaBcbyDq.js → flowDiagram-23GEKE2U-CaTUkFO6.js} +1 -1
  423. package/ui-dist/assets/{ganttDiagram-NO4QXBWP-BOJSII2b.js → ganttDiagram-NO4QXBWP-DmdMQ3ES.js} +1 -1
  424. package/ui-dist/assets/{gitGraphDiagram-IHSO6WYX-aYAaO4a2.js → gitGraphDiagram-IHSO6WYX-Bt-1g2CS.js} +1 -1
  425. package/ui-dist/assets/{index-CZxYajxF.js → index-2Dk9yO0W.js} +1 -1
  426. package/ui-dist/assets/{index-B8H0SHw1.js → index-8jLpgFNU.js} +1 -1
  427. package/ui-dist/assets/{index-3EKATXgc.js → index-AP_iimxs.js} +1 -1
  428. package/ui-dist/assets/{index-C2JgdjPa.js → index-BNJasQY9.js} +1 -1
  429. package/ui-dist/assets/{index-BaiskB3o.js → index-BO-aNmyX.js} +1 -1
  430. package/ui-dist/assets/{index-B5YenxAQ.js → index-BPCzCn1Y.js} +1 -1
  431. package/ui-dist/assets/{index-Da2kqT1M.js → index-BSLnLTb2.js} +1 -1
  432. package/ui-dist/assets/{index-By0oeEvz.js → index-CCZ2qgHN.js} +1 -1
  433. package/ui-dist/assets/{index-bUFCSEgv.js → index-CLZXR1k9.js} +1 -1
  434. package/ui-dist/assets/{index-CJlw4l9L.js → index-CTNfrE1s.js} +1 -1
  435. package/ui-dist/assets/{index-TmpY6Xh_.js → index-ChNd25s7.js} +1 -1
  436. package/ui-dist/assets/{index-BRgdHUNR.js → index-CjHiMOEO.js} +1 -1
  437. package/ui-dist/assets/{index-DrL6pHSJ.js → index-CmeJQpXZ.js} +1 -1
  438. package/ui-dist/assets/index-CyuYtn7U.css +1 -0
  439. package/ui-dist/assets/{index-CKKytnOd.js → index-CzZjM8eh.js} +1 -1
  440. package/ui-dist/assets/{index-Dceamza_.js → index-D-6T0Aft.js} +1 -1
  441. package/ui-dist/assets/{index-CjDqB1SX.js → index-DG_7V1pG.js} +1 -1
  442. package/ui-dist/assets/index-DIKcgxCt.js +676 -0
  443. package/ui-dist/assets/{index-BKVeJ3Jh.js → index-DiUerHmi.js} +1 -1
  444. package/ui-dist/assets/{index-C-nKjFZh.js → index-NZ7v5Fc2.js} +1 -1
  445. package/ui-dist/assets/{index-CvPPuNs1.js → index-Py70EvBg.js} +1 -1
  446. package/ui-dist/assets/{index-LHkZdu0h.js → index-R3aYn0qM.js} +1 -1
  447. package/ui-dist/assets/{index-BT8b79Bd.js → index-YXpm7gW-.js} +1 -1
  448. package/ui-dist/assets/{index-CemenVOf.js → index-n4q3gzki.js} +1 -1
  449. package/ui-dist/assets/{index-D3ODiUup.js → index-vlZ3GoYY.js} +1 -1
  450. package/ui-dist/assets/{infoDiagram-FWYZ7A6U-C7_90qGq.js → infoDiagram-FWYZ7A6U-jdi5ciVg.js} +1 -1
  451. package/ui-dist/assets/{ishikawaDiagram-FXEZZL3T-T-nPPdTt.js → ishikawaDiagram-FXEZZL3T-CMz5VvYp.js} +1 -1
  452. package/ui-dist/assets/{journeyDiagram-5HDEW3XC-C3hqQN0R.js → journeyDiagram-5HDEW3XC-DK6dk2R-.js} +1 -1
  453. package/ui-dist/assets/{kanban-definition-HUTT4EX6-CPoD9DUm.js → kanban-definition-HUTT4EX6-DX5cZL-D.js} +1 -1
  454. package/ui-dist/assets/{linear-D-S8yr3Z.js → linear-CI96ABKp.js} +1 -1
  455. package/ui-dist/assets/{mermaid.core-DhvH8shK.js → mermaid.core-DnsEVfbd.js} +4 -4
  456. package/ui-dist/assets/{mindmap-definition-LN4V7U3C-CxCIKrKo.js → mindmap-definition-LN4V7U3C-BdDCY7hf.js} +1 -1
  457. package/ui-dist/assets/{pegDiagram-2B236MQR-D4G-PC6N.js → pegDiagram-2B236MQR-DuY4TF-f.js} +1 -1
  458. package/ui-dist/assets/{pieDiagram-ENE6RG2P-N4X8UvqY.js → pieDiagram-ENE6RG2P-bgFw7dm3.js} +1 -1
  459. package/ui-dist/assets/{quadrantDiagram-ABIIQ3AL-CZohoDln.js → quadrantDiagram-ABIIQ3AL-BCZVWyWS.js} +1 -1
  460. package/ui-dist/assets/{railroadDiagram-RFXS5EU6-fMGQVhwF.js → railroadDiagram-RFXS5EU6-D9V5_Cgc.js} +1 -1
  461. package/ui-dist/assets/{requirementDiagram-TGXJPOKE-CK0IuUmk.js → requirementDiagram-TGXJPOKE-CItsya2r.js} +1 -1
  462. package/ui-dist/assets/{sankeyDiagram-HTMAVEWB-pSfb3CqG.js → sankeyDiagram-HTMAVEWB-Cz9IHsZO.js} +1 -1
  463. package/ui-dist/assets/{sequenceDiagram-DBY2YBRQ-CbhkqIeq.js → sequenceDiagram-DBY2YBRQ-hMSqTiwK.js} +1 -1
  464. package/ui-dist/assets/{sizeCapture-X5ZJPWSS-B6vqqPx-.js → sizeCapture-X5ZJPWSS-0g9M5wMf.js} +1 -1
  465. package/ui-dist/assets/{stateDiagram-2N3HPSRC-DIJf9h5C.js → stateDiagram-2N3HPSRC-F8_YhgWl.js} +1 -1
  466. package/ui-dist/assets/stateDiagram-v2-6OUMAXLB-fZImUBtq.js +1 -0
  467. package/ui-dist/assets/{swimlanes-5IMT3BWC-DIX_LV8O.js → swimlanes-5IMT3BWC-CCZqPbpE.js} +2 -2
  468. package/ui-dist/assets/swimlanesDiagram-G3AALYLV-9C1UT51R.js +8 -0
  469. package/ui-dist/assets/{timeline-definition-FHXFAJF6-CD-Pxb_g.js → timeline-definition-FHXFAJF6-BeUIr18x.js} +1 -1
  470. package/ui-dist/assets/{vennDiagram-L72KCM5P-BAZsWL0R.js → vennDiagram-L72KCM5P-D3d5h_G4.js} +1 -1
  471. package/ui-dist/assets/{wardleyDiagram-EHGQE667-CnNyfwX5.js → wardleyDiagram-EHGQE667-Bzt-As9A.js} +1 -1
  472. package/ui-dist/assets/{xychartDiagram-FW5EYKEG-j9YgsD3Y.js → xychartDiagram-FW5EYKEG-C2mly0xf.js} +1 -1
  473. package/ui-dist/fonts/InterVariable-Italic.woff2 +0 -0
  474. package/ui-dist/fonts/InterVariable.woff2 +0 -0
  475. package/ui-dist/fonts/NOTICE.md +17 -0
  476. package/ui-dist/index.html +2 -2
  477. package/ui-dist/locales/en/common.json +1142 -5
  478. package/ui-dist/locales/zh-CN/common.json +1140 -3
  479. package/ui-dist/assets/channel-CsiI2LYw.js +0 -1
  480. package/ui-dist/assets/classDiagram-OUVF2IWQ-CBn1Jqo8.js +0 -1
  481. package/ui-dist/assets/classDiagram-v2-EOCWNBFH-CBn1Jqo8.js +0 -1
  482. package/ui-dist/assets/index-BsL8K1vL.css +0 -1
  483. package/ui-dist/assets/index-D__fTsb2.js +0 -643
  484. package/ui-dist/assets/stateDiagram-v2-6OUMAXLB-DpwLD7YL.js +0 -1
  485. package/ui-dist/assets/swimlanesDiagram-G3AALYLV-Cklauutg.js +0 -8
@@ -1,6 +1,6 @@
1
1
  import crypto from "node:crypto";
2
- import { and, asc, desc, eq, inArray, isNotNull, isNull, lte, not, or, sql } from "drizzle-orm";
3
- import { agents, companySecretBindings, companySecretVersions, companySecrets, documentRevisions, documents, executionWorkspaces, goals, heartbeatRuns, issueInboxArchives, issueReadStates, issues, pluginManagedResources, plugins, projects, routineRevisions, routineRuns, routineDocuments, routines, routineTriggers, } from "@penclipai/db";
2
+ import { and, asc, desc, eq, gt, inArray, isNotNull, isNull, lte, not, or, sql } from "drizzle-orm";
3
+ import { agents, activityLog, companies, companyMemberships, companySecretBindings, companySecretVersions, companySecrets, documentRevisions, documents, executionWorkspaces, goals, heartbeatRuns, issueInboxArchives, issueReadStates, issues, pluginManagedResources, plugins, projects, routineRevisions, routineRuns, routineDocuments, routines, routineTriggers, } from "@penclipai/db";
4
4
  import { WORKSPACE_BRANCH_ROUTINE_VARIABLE, getBuiltinRoutineVariableValues, extractRoutineVariableNames, interpolateRoutineTemplate, isValidRoutineDateString, pluginOperationIssueOriginKind, stringifyRoutineVariableValue, syncRoutineVariablesWithTemplate, } from "@penclipai/shared";
5
5
  import { trackRoutineRun } from "@penclipai/shared/telemetry";
6
6
  import { conflict, forbidden, notFound, unauthorized, unprocessable } from "../errors.js";
@@ -9,11 +9,13 @@ import { getTelemetryClient } from "../telemetry.js";
9
9
  import { getConfiguredSecretProvider } from "../secrets/configured-provider.js";
10
10
  import { issueService } from "./issues.js";
11
11
  import { assertAssignableAgent } from "./agent-assignability.js";
12
+ import { visibleIssueCondition } from "./issue-visibility.js";
12
13
  import { secretService } from "./secrets.js";
13
14
  import { getSecretProvider } from "../secrets/provider-registry.js";
14
15
  import { parseCron, validateCron } from "./cron.js";
15
16
  import { isUniqueViolation } from "./db-errors.js";
16
17
  import { heartbeatService } from "./heartbeat.js";
18
+ import { instanceSettingsService, isTruthyRuntimeEnvValue, resolveWorktreeRunExecutionActivationState, } from "./instance-settings.js";
17
19
  import { queueIssueAssignmentWakeup } from "./issue-assignment-wakeup.js";
18
20
  import { logActivity } from "./activity-log.js";
19
21
  const OPEN_ISSUE_STATUSES = ["backlog", "todo", "in_progress", "in_review", "blocked"];
@@ -21,6 +23,12 @@ const LIVE_HEARTBEAT_RUN_STATUSES = ["queued", "running", "scheduled_retry"];
21
23
  const TERMINAL_ISSUE_STATUSES = new Set(["done", "cancelled"]);
22
24
  const MAX_CATCH_UP_RUNS = 25;
23
25
  const MAX_ROUTINE_REVISIONS = 100;
26
+ const ACTIVITY_GATE_IGNORED_ACTIONS = [
27
+ "issue.read_marked",
28
+ "issue.read_unmarked",
29
+ "issue.inbox_archived",
30
+ "issue.inbox_unarchived",
31
+ ];
24
32
  const WEEKDAY_INDEX = {
25
33
  Sun: 0,
26
34
  Mon: 1,
@@ -30,6 +38,39 @@ const WEEKDAY_INDEX = {
30
38
  Fri: 5,
31
39
  Sat: 6,
32
40
  };
41
+ async function resolveCompanyDefaultResponsibleUserId(db, companyId) {
42
+ const company = await db
43
+ .select({ defaultResponsibleUserId: companies.defaultResponsibleUserId })
44
+ .from(companies)
45
+ .where(eq(companies.id, companyId))
46
+ .then((rows) => rows[0] ?? null);
47
+ if (company?.defaultResponsibleUserId)
48
+ return company.defaultResponsibleUserId;
49
+ const owner = await db
50
+ .select({ userId: companyMemberships.principalId })
51
+ .from(companyMemberships)
52
+ .where(and(eq(companyMemberships.companyId, companyId), eq(companyMemberships.principalType, "user"), eq(companyMemberships.status, "active"), eq(companyMemberships.membershipRole, "owner")))
53
+ .orderBy(asc(companyMemberships.createdAt), asc(companyMemberships.id))
54
+ .limit(1)
55
+ .then((rows) => rows[0] ?? null);
56
+ return owner?.userId ?? null;
57
+ }
58
+ async function resolveRoutineResponsibleUserId(db, companyId, actorUserId, parentIssueId) {
59
+ if (actorUserId)
60
+ return actorUserId;
61
+ if (parentIssueId) {
62
+ const parent = await db
63
+ .select({ responsibleUserId: issues.responsibleUserId, createdByUserId: issues.createdByUserId })
64
+ .from(issues)
65
+ .where(and(eq(issues.companyId, companyId), eq(issues.id, parentIssueId)))
66
+ .then((rows) => rows[0] ?? null);
67
+ if (parent?.responsibleUserId)
68
+ return parent.responsibleUserId;
69
+ if (parent?.createdByUserId)
70
+ return parent.createdByUserId;
71
+ }
72
+ return resolveCompanyDefaultResponsibleUserId(db, companyId);
73
+ }
33
74
  const ROUTINE_DESCRIPTION_DOCUMENT_KEY = "description";
34
75
  function routineWebhookSecretConfigPath(secretId) {
35
76
  return `webhookSecret:${secretId}`;
@@ -349,6 +390,7 @@ function routineRevisionSnapshotRoutine(routine) {
349
390
  catchUpPolicy: routine.catchUpPolicy,
350
391
  variables: routine.variables ?? [],
351
392
  env: routine.env ?? null,
393
+ responsibleUserId: routine.responsibleUserId ?? null,
352
394
  };
353
395
  }
354
396
  function routineRevisionSnapshotTrigger(trigger) {
@@ -413,6 +455,8 @@ function mapRoutineDescriptionDocument(row) {
413
455
  export function routineService(db, deps = {}) {
414
456
  const issueSvc = issueService(db);
415
457
  const secretsSvc = secretService(db);
458
+ const instanceSettings = instanceSettingsService(db);
459
+ const runtimeEnv = deps.runtimeEnv ?? process.env;
416
460
  const heartbeat = deps.heartbeat ?? heartbeatService(db, {
417
461
  pluginWorkerManager: deps.pluginWorkerManager,
418
462
  });
@@ -636,6 +680,7 @@ export function routineService(db, deps = {}) {
636
680
  createdByAgentId: actor.agentId ?? null,
637
681
  createdByUserId: actor.userId ?? null,
638
682
  createdByRunId: actor.runId ?? null,
683
+ responsibleUserId: snapshot.routine.responsibleUserId ?? null,
639
684
  createdAt: now,
640
685
  })
641
686
  .returning();
@@ -818,7 +863,7 @@ export function routineService(db, deps = {}) {
818
863
  })
819
864
  .from(issues)
820
865
  .innerJoin(heartbeatRuns, and(eq(heartbeatRuns.id, issues.executionRunId), inArray(heartbeatRuns.status, LIVE_HEARTBEAT_RUN_STATUSES)))
821
- .where(and(eq(issues.companyId, companyId), eq(issues.originKind, "routine_execution"), inArray(issues.originId, routineIds), inArray(issues.status, OPEN_ISSUE_STATUSES), isNull(issues.hiddenAt)))
866
+ .where(and(eq(issues.companyId, companyId), eq(issues.originKind, "routine_execution"), inArray(issues.originId, routineIds), inArray(issues.status, OPEN_ISSUE_STATUSES), visibleIssueCondition()))
822
867
  .orderBy(issues.originId, desc(issues.updatedAt), desc(issues.createdAt));
823
868
  const rowsByOriginId = new Map();
824
869
  for (const row of executionBoundRows) {
@@ -840,7 +885,7 @@ export function routineService(db, deps = {}) {
840
885
  })
841
886
  .from(issues)
842
887
  .innerJoin(heartbeatRuns, and(eq(heartbeatRuns.companyId, issues.companyId), inArray(heartbeatRuns.status, LIVE_HEARTBEAT_RUN_STATUSES), sql `${heartbeatRuns.contextSnapshot} ->> 'issueId' = cast(${issues.id} as text)`))
843
- .where(and(eq(issues.companyId, companyId), eq(issues.originKind, "routine_execution"), inArray(issues.originId, missingRoutineIds), inArray(issues.status, OPEN_ISSUE_STATUSES), isNull(issues.hiddenAt)))
888
+ .where(and(eq(issues.companyId, companyId), eq(issues.originKind, "routine_execution"), inArray(issues.originId, missingRoutineIds), inArray(issues.status, OPEN_ISSUE_STATUSES), visibleIssueCondition()))
844
889
  .orderBy(issues.originId, desc(issues.updatedAt), desc(issues.createdAt));
845
890
  for (const row of legacyRows) {
846
891
  if (!row.originId)
@@ -884,10 +929,113 @@ export function routineService(db, deps = {}) {
884
929
  .where(eq(routineTriggers.id, input.triggerId));
885
930
  }
886
931
  }
887
- // Records a skipped scheduled firing without creating an execution issue. Used when the
888
- // routine's project is paused: the tick is still claimed/advanced upstream (no backfill),
889
- // and run history + trigger audit reflect the pause-specific skip.
890
- async function recordSuppressedScheduleRun(input) {
932
+ async function getAutomaticRoutineDispatchEligibility(routine, activation) {
933
+ if (!isTruthyRuntimeEnvValue(runtimeEnv.PAPERCLIP_IN_WORKTREE))
934
+ return { eligible: true };
935
+ const resolvedActivation = activation ?? await resolveWorktreeRunExecutionActivationState({
936
+ getExperimental: instanceSettings.getExperimental,
937
+ runtimeEnv,
938
+ });
939
+ if (!resolvedActivation.armed)
940
+ return { eligible: false };
941
+ const cutoff = new Date(resolvedActivation.cutoff);
942
+ if (Number.isNaN(cutoff.getTime()) || routine.createdAt < cutoff)
943
+ return { eligible: false };
944
+ return { eligible: true };
945
+ }
946
+ async function evaluateActivityGate(routine, now) {
947
+ const lastDispatchedRun = await db
948
+ .select({ triggeredAt: routineRuns.triggeredAt })
949
+ .from(routineRuns)
950
+ .where(and(eq(routineRuns.companyId, routine.companyId), eq(routineRuns.routineId, routine.id), sql `${routineRuns.status} not in ('skipped', 'coalesced')`))
951
+ .orderBy(desc(routineRuns.triggeredAt), desc(routineRuns.id))
952
+ .limit(1)
953
+ .then((rows) => rows[0] ?? null);
954
+ if (!lastDispatchedRun) {
955
+ return { fire: true, windowStart: null, matchedActivity: null };
956
+ }
957
+ const projectScopeCondition = routine.activityGateScope === "project"
958
+ ? routine.projectId
959
+ ? sql `(
960
+ (${activityLog.entityType} = 'project' and ${activityLog.entityId} = ${routine.projectId})
961
+ or (${activityLog.details} ->> 'projectId') = ${routine.projectId}
962
+ or exists (
963
+ select 1
964
+ from ${issues} activity_issue
965
+ where activity_issue.company_id = ${routine.companyId}
966
+ and activity_issue.project_id = ${routine.projectId}
967
+ and activity_issue.id::text = ${activityLog.entityId}
968
+ and ${activityLog.entityType} = 'issue'
969
+ )
970
+ or exists (
971
+ select 1
972
+ from ${heartbeatRuns} activity_run
973
+ inner join ${issues} run_issue
974
+ on run_issue.company_id = ${routine.companyId}
975
+ and run_issue.id::text = activity_run.context_snapshot ->> 'issueId'
976
+ where activity_run.company_id = ${routine.companyId}
977
+ and activity_run.id = ${activityLog.runId}
978
+ and run_issue.project_id = ${routine.projectId}
979
+ )
980
+ or exists (
981
+ select 1
982
+ from ${routines} activity_routine
983
+ where activity_routine.company_id = ${routine.companyId}
984
+ and activity_routine.project_id = ${routine.projectId}
985
+ and activity_routine.id::text = ${activityLog.entityId}
986
+ and ${activityLog.entityType} = 'routine'
987
+ )
988
+ or exists (
989
+ select 1
990
+ from ${routineRuns} activity_routine_run
991
+ inner join ${routines} activity_routine
992
+ on activity_routine.company_id = ${routine.companyId}
993
+ and activity_routine.id = activity_routine_run.routine_id
994
+ where activity_routine_run.company_id = ${routine.companyId}
995
+ and activity_routine_run.id::text = ${activityLog.entityId}
996
+ and activity_routine.project_id = ${routine.projectId}
997
+ and ${activityLog.entityType} = 'routine_run'
998
+ )
999
+ )`
1000
+ : sql `false`
1001
+ : undefined;
1002
+ const matchedActivity = await db
1003
+ .select({
1004
+ id: activityLog.id,
1005
+ action: activityLog.action,
1006
+ createdAt: activityLog.createdAt,
1007
+ })
1008
+ .from(activityLog)
1009
+ .where(and(eq(activityLog.companyId, routine.companyId), gt(activityLog.createdAt, lastDispatchedRun.triggeredAt), lte(activityLog.createdAt, now), sql `${activityLog.action} not in (${sql.join(ACTIVITY_GATE_IGNORED_ACTIONS.map((action) => sql `${action}`), sql `, `)})`, sql `not (
1010
+ ${activityLog.actorId} = 'routine-scheduler'
1011
+ and (
1012
+ (${activityLog.details} ->> 'routineId') = ${routine.id}
1013
+ or (${activityLog.entityType} = 'routine' and ${activityLog.entityId} = ${routine.id})
1014
+ )
1015
+ )`, sql `not exists (
1016
+ select 1
1017
+ from ${heartbeatRuns} own_run
1018
+ inner join ${issues} own_issue
1019
+ on own_issue.company_id = ${routine.companyId}
1020
+ and own_issue.id::text = own_run.context_snapshot ->> 'issueId'
1021
+ where own_run.company_id = ${routine.companyId}
1022
+ and own_run.id = ${activityLog.runId}
1023
+ and own_issue.origin_kind = 'routine_execution'
1024
+ and own_issue.origin_id = ${routine.id}
1025
+ )`, projectScopeCondition))
1026
+ .orderBy(asc(activityLog.createdAt), asc(activityLog.id))
1027
+ .limit(1)
1028
+ .then((rows) => rows[0] ?? null);
1029
+ return {
1030
+ fire: matchedActivity !== null,
1031
+ windowStart: lastDispatchedRun.triggeredAt,
1032
+ matchedActivity,
1033
+ };
1034
+ }
1035
+ // Records an automatic firing that was claimed but intentionally not dispatched. The
1036
+ // scheduler advances its tick before calling this helper, so suppressed work is never
1037
+ // replayed after a setting or project state changes.
1038
+ async function recordSuppressedAutomaticRun(input) {
891
1039
  const triggeredAt = new Date();
892
1040
  const run = await db.transaction(async (tx) => {
893
1041
  const txDb = tx;
@@ -897,20 +1045,26 @@ export function routineService(db, deps = {}) {
897
1045
  companyId: input.routine.companyId,
898
1046
  routineId: input.routine.id,
899
1047
  triggerId: input.trigger.id,
900
- source: "schedule",
1048
+ source: input.source,
901
1049
  status: "skipped",
902
1050
  triggeredAt,
903
1051
  failureReason: input.reason,
904
1052
  completedAt: triggeredAt,
905
1053
  linkedIssueId: null,
906
1054
  routineRevisionId: input.routine.latestRevisionId,
1055
+ responsibleUserId: input.routine.responsibleUserId ?? null,
1056
+ triggerPayload: input.details ?? null,
907
1057
  })
908
1058
  .returning();
909
1059
  await updateRoutineTouchedState({
910
1060
  routineId: input.routine.id,
911
1061
  triggerId: input.trigger.id,
912
1062
  triggeredAt,
913
- status: "skipped_paused",
1063
+ status: input.reason === "paused"
1064
+ ? "skipped_paused"
1065
+ : input.reason === "no_external_activity"
1066
+ ? "skipped_no_activity"
1067
+ : "skipped_worktree_execution_cutoff",
914
1068
  nextRunAt: input.nextRunAt,
915
1069
  }, txDb);
916
1070
  return createdRun;
@@ -919,16 +1073,17 @@ export function routineService(db, deps = {}) {
919
1073
  await logActivity(db, {
920
1074
  companyId: input.routine.companyId,
921
1075
  actorType: "system",
922
- actorId: "routine-scheduler",
1076
+ actorId: input.source === "schedule" ? "routine-scheduler" : "routine-webhook",
923
1077
  action: "routine.run_skipped",
924
1078
  entityType: "routine_run",
925
1079
  entityId: run.id,
926
1080
  details: {
927
1081
  routineId: input.routine.id,
928
1082
  triggerId: input.trigger.id,
929
- source: "schedule",
1083
+ source: input.source,
930
1084
  status: "skipped",
931
1085
  reason: input.reason,
1086
+ ...(input.details ?? {}),
932
1087
  },
933
1088
  });
934
1089
  }
@@ -952,7 +1107,7 @@ export function routineService(db, deps = {}) {
952
1107
  .select()
953
1108
  .from(issues)
954
1109
  .innerJoin(heartbeatRuns, and(eq(heartbeatRuns.id, issues.executionRunId), inArray(heartbeatRuns.status, LIVE_HEARTBEAT_RUN_STATUSES)))
955
- .where(and(eq(issues.companyId, routine.companyId), eq(issues.originKind, originKind), eq(issues.originId, originId), inArray(issues.status, OPEN_ISSUE_STATUSES), isNull(issues.hiddenAt), ...(fingerprintCondition ? [fingerprintCondition] : [])))
1110
+ .where(and(eq(issues.companyId, routine.companyId), eq(issues.originKind, originKind), eq(issues.originId, originId), inArray(issues.status, OPEN_ISSUE_STATUSES), visibleIssueCondition(), ...(fingerprintCondition ? [fingerprintCondition] : [])))
956
1111
  .orderBy(desc(issues.updatedAt), desc(issues.createdAt))
957
1112
  .limit(1)
958
1113
  .then((rows) => rows[0]?.issues ?? null);
@@ -962,7 +1117,7 @@ export function routineService(db, deps = {}) {
962
1117
  .select()
963
1118
  .from(issues)
964
1119
  .innerJoin(heartbeatRuns, and(eq(heartbeatRuns.companyId, issues.companyId), inArray(heartbeatRuns.status, LIVE_HEARTBEAT_RUN_STATUSES), sql `${heartbeatRuns.contextSnapshot} ->> 'issueId' = cast(${issues.id} as text)`))
965
- .where(and(eq(issues.companyId, routine.companyId), eq(issues.originKind, originKind), eq(issues.originId, originId), inArray(issues.status, OPEN_ISSUE_STATUSES), isNull(issues.hiddenAt), ...(fingerprintCondition ? [fingerprintCondition] : [])))
1120
+ .where(and(eq(issues.companyId, routine.companyId), eq(issues.originKind, originKind), eq(issues.originId, originId), inArray(issues.status, OPEN_ISSUE_STATUSES), visibleIssueCondition(), ...(fingerprintCondition ? [fingerprintCondition] : [])))
966
1121
  .orderBy(desc(issues.updatedAt), desc(issues.createdAt))
967
1122
  .limit(1)
968
1123
  .then((rows) => rows[0]?.issues ?? null);
@@ -1153,6 +1308,21 @@ export function routineService(db, deps = {}) {
1153
1308
  }
1154
1309
  const triggeredAt = new Date();
1155
1310
  const manualRunnerUserId = input.source === "manual" ? input.actor?.userId ?? null : null;
1311
+ const latestRevisionResponsibleUserId = input.routine.latestRevisionId
1312
+ ? await txDb
1313
+ .select({
1314
+ responsibleUserId: routineRevisions.responsibleUserId,
1315
+ snapshot: routineRevisions.snapshot,
1316
+ })
1317
+ .from(routineRevisions)
1318
+ .where(and(eq(routineRevisions.companyId, input.routine.companyId), eq(routineRevisions.routineId, input.routine.id), eq(routineRevisions.id, input.routine.latestRevisionId)))
1319
+ .then((rows) => {
1320
+ const row = rows[0] ?? null;
1321
+ const snapshot = row?.snapshot;
1322
+ return row?.responsibleUserId ?? snapshot?.routine.responsibleUserId ?? null;
1323
+ })
1324
+ : null;
1325
+ const responsibleUserId = manualRunnerUserId ?? latestRevisionResponsibleUserId ?? input.routine.responsibleUserId ?? null;
1156
1326
  const [createdRun] = await txDb
1157
1327
  .insert(routineRuns)
1158
1328
  .values({
@@ -1166,6 +1336,7 @@ export function routineService(db, deps = {}) {
1166
1336
  triggerPayload,
1167
1337
  dispatchFingerprint,
1168
1338
  routineRevisionId: input.routine.latestRevisionId,
1339
+ responsibleUserId,
1169
1340
  })
1170
1341
  .returning();
1171
1342
  const nextRunAt = input.trigger?.kind === "schedule" && input.trigger.cronExpression && input.trigger.timezone
@@ -1216,6 +1387,8 @@ export function routineService(db, deps = {}) {
1216
1387
  assigneeAgentId,
1217
1388
  createdByAgentId: input.source === "manual" ? input.actor?.agentId ?? null : null,
1218
1389
  createdByUserId: manualRunnerUserId,
1390
+ responsibleUserId,
1391
+ trustExplicitResponsibleUserId: true,
1219
1392
  originKind: issueOriginKind,
1220
1393
  originId: issueOriginId,
1221
1394
  originRunId: createdRun.id,
@@ -1339,6 +1512,7 @@ export function routineService(db, deps = {}) {
1339
1512
  return run;
1340
1513
  }
1341
1514
  return {
1515
+ evaluateActivityGate,
1342
1516
  get: getRoutineById,
1343
1517
  getTrigger: getTriggerById,
1344
1518
  list: async (companyId, filters) => {
@@ -1490,6 +1664,10 @@ export function routineService(db, deps = {}) {
1490
1664
  const variables = syncRoutineVariablesWithTemplate([input.title, input.description], sanitizeRoutineVariableInputs(input.variables));
1491
1665
  assertRoutineVariableDefinitions(variables);
1492
1666
  const status = normalizeDraftRoutineStatus(input.status, input.assigneeAgentId);
1667
+ const responsibleUserId = await resolveRoutineResponsibleUserId(db, companyId, actor.userId, input.parentIssueId ?? null);
1668
+ if (!responsibleUserId) {
1669
+ throw unprocessable("Routine requires a responsible user");
1670
+ }
1493
1671
  const createdRoutine = await db.transaction(async (tx) => {
1494
1672
  const txDb = tx;
1495
1673
  const [created] = await txDb
@@ -1508,6 +1686,7 @@ export function routineService(db, deps = {}) {
1508
1686
  catchUpPolicy: input.catchUpPolicy,
1509
1687
  variables,
1510
1688
  env,
1689
+ responsibleUserId,
1511
1690
  createdByAgentId: actor.agentId ?? null,
1512
1691
  createdByUserId: actor.userId ?? null,
1513
1692
  updatedByAgentId: actor.agentId ?? null,
@@ -1567,6 +1746,10 @@ export function routineService(db, deps = {}) {
1567
1746
  if (enabledScheduleTriggers) {
1568
1747
  assertScheduleCompatibleVariables(nextVariables);
1569
1748
  }
1749
+ const responsibleUserId = await resolveRoutineResponsibleUserId(db, existing.companyId, actor.userId, patch.parentIssueId === undefined ? existing.parentIssueId : patch.parentIssueId);
1750
+ if (!responsibleUserId) {
1751
+ throw unprocessable("Routine requires a responsible user");
1752
+ }
1570
1753
  const updatedRoutine = await db.transaction(async (tx) => {
1571
1754
  const txDb = tx;
1572
1755
  await tx.execute(sql `select id from ${routines} where ${routines.id} = ${id} for update`);
@@ -1596,6 +1779,7 @@ export function routineService(db, deps = {}) {
1596
1779
  catchUpPolicy: patch.catchUpPolicy ?? locked.catchUpPolicy,
1597
1780
  variables: nextVariables,
1598
1781
  env: nextEnv,
1782
+ responsibleUserId: locked.responsibleUserId ?? responsibleUserId,
1599
1783
  updatedByAgentId: actor.agentId ?? null,
1600
1784
  updatedByUserId: actor.userId ?? null,
1601
1785
  };
@@ -1631,6 +1815,7 @@ export function routineService(db, deps = {}) {
1631
1815
  catchUpPolicy: candidate.catchUpPolicy,
1632
1816
  variables: candidate.variables,
1633
1817
  env: candidate.env,
1818
+ responsibleUserId: candidate.responsibleUserId,
1634
1819
  updatedByAgentId: actor.agentId ?? null,
1635
1820
  updatedByUserId: actor.userId ?? null,
1636
1821
  updatedAt: new Date(),
@@ -2135,6 +2320,15 @@ export function routineService(db, deps = {}) {
2135
2320
  if (!valid)
2136
2321
  throw unauthorized();
2137
2322
  }
2323
+ const eligibility = await getAutomaticRoutineDispatchEligibility(routine);
2324
+ if (!eligibility.eligible) {
2325
+ return recordSuppressedAutomaticRun({
2326
+ routine,
2327
+ trigger,
2328
+ source: "webhook",
2329
+ reason: "worktree_execution_cutoff",
2330
+ });
2331
+ }
2138
2332
  return dispatchRoutineRun({
2139
2333
  routine,
2140
2334
  trigger,
@@ -2219,6 +2413,12 @@ export function routineService(db, deps = {}) {
2219
2413
  }));
2220
2414
  },
2221
2415
  tickScheduledTriggers: async (now = new Date()) => {
2416
+ const worktreeActivation = isTruthyRuntimeEnvValue(runtimeEnv.PAPERCLIP_IN_WORKTREE)
2417
+ ? await resolveWorktreeRunExecutionActivationState({
2418
+ getExperimental: instanceSettings.getExperimental,
2419
+ runtimeEnv,
2420
+ })
2421
+ : undefined;
2222
2422
  const due = await db
2223
2423
  .select({
2224
2424
  trigger: routineTriggers,
@@ -2239,9 +2439,11 @@ export function routineService(db, deps = {}) {
2239
2439
  // at the next cron boundary instead of replaying missed firings. Routines with no
2240
2440
  // project are never suppressed here.
2241
2441
  const projectPaused = !!(row.routine.projectId && row.projectPausedAt);
2442
+ const automaticEligibility = await getAutomaticRoutineDispatchEligibility(row.routine, worktreeActivation);
2443
+ const worktreeSuppressed = !automaticEligibility.eligible;
2242
2444
  let runCount = 1;
2243
2445
  let claimedNextRunAt = nextCronTickInTimeZone(row.trigger.cronExpression, row.trigger.timezone, now);
2244
- if (!projectPaused && row.routine.catchUpPolicy === "enqueue_missed_with_cap") {
2446
+ if (!projectPaused && !worktreeSuppressed && row.routine.catchUpPolicy === "enqueue_missed_with_cap") {
2245
2447
  let cursor = row.trigger.nextRunAt;
2246
2448
  runCount = 0;
2247
2449
  while (cursor && cursor <= now && runCount < MAX_CATCH_UP_RUNS) {
@@ -2261,15 +2463,36 @@ export function routineService(db, deps = {}) {
2261
2463
  .then((rows) => rows[0] ?? null);
2262
2464
  if (!claimed)
2263
2465
  continue;
2264
- if (projectPaused) {
2265
- await recordSuppressedScheduleRun({
2466
+ if (projectPaused || worktreeSuppressed) {
2467
+ await recordSuppressedAutomaticRun({
2266
2468
  routine: row.routine,
2267
2469
  trigger: row.trigger,
2268
- reason: "paused",
2470
+ source: "schedule",
2471
+ reason: worktreeSuppressed ? "worktree_execution_cutoff" : "paused",
2269
2472
  nextRunAt: claimedNextRunAt,
2270
2473
  });
2271
2474
  continue;
2272
2475
  }
2476
+ const activityGate = row.routine.activityGatePolicy === "require_external_activity"
2477
+ ? await evaluateActivityGate(row.routine, now)
2478
+ : null;
2479
+ if (activityGate && !activityGate.fire) {
2480
+ await recordSuppressedAutomaticRun({
2481
+ routine: row.routine,
2482
+ trigger: row.trigger,
2483
+ source: "schedule",
2484
+ reason: "no_external_activity",
2485
+ nextRunAt: claimedNextRunAt,
2486
+ details: {
2487
+ activityGate: {
2488
+ verdict: "quiet",
2489
+ windowStart: activityGate.windowStart?.toISOString() ?? null,
2490
+ matchedActivityId: null,
2491
+ },
2492
+ },
2493
+ });
2494
+ continue;
2495
+ }
2273
2496
  for (let i = 0; i < runCount; i += 1) {
2274
2497
  await dispatchRoutineRun({
2275
2498
  routine: row.routine,