@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
@@ -3,6 +3,7 @@ import { DEFAULT_ISSUE_GRAPH_LIVENESS_AUTO_RECOVERY_LOOKBACK_HOURS, MAX_ISSUE_GR
3
3
  import { agents, agentWakeupRequests, approvals, activityLog, companies, heartbeatRunEvents, heartbeatRunWatchdogDecisions, heartbeatRuns, issueAttachments, issueComments, issueApprovals, issueRecoveryActions, issueRelations, issueThreadInteractions, issues, } from "@penclipai/db";
4
4
  import { parseObject, asBoolean, asNumber } from "../../adapters/utils.js";
5
5
  import { runningProcesses } from "../../adapters/index.js";
6
+ import { visibleIssueCondition } from "../issue-visibility.js";
6
7
  import { forbidden, notFound } from "../../errors.js";
7
8
  import { logger } from "../../middleware/logger.js";
8
9
  import { isPidAlive, isProcessGroupAlive, terminateLocalService } from "../local-service-supervisor.js";
@@ -25,7 +26,7 @@ import { classifyIssueGraphLiveness, } from "./issue-graph-liveness.js";
25
26
  import { recoveryAssigneeAdapterOverrides, withRecoveryModelProfileHint, } from "./model-profile-hint.js";
26
27
  import { isAutomaticRecoverySuppressedByPauseHold } from "./pause-hold-guard.js";
27
28
  const EXECUTION_PATH_HEARTBEAT_RUN_STATUSES = ["queued", "running", "scheduled_retry"];
28
- const UNSUCCESSFUL_HEARTBEAT_RUN_TERMINAL_STATUSES = ["failed", "cancelled", "timed_out"];
29
+ const UNSUCCESSFUL_HEARTBEAT_RUN_TERMINAL_STATUSES = ["interrupted", "failed", "cancelled", "timed_out"];
29
30
  export const ACTIVE_RUN_OUTPUT_SUSPICION_THRESHOLD_MS = 60 * 60 * 1000;
30
31
  export const ACTIVE_RUN_OUTPUT_CRITICAL_THRESHOLD_MS = 4 * 60 * 60 * 1000;
31
32
  export const ACTIVE_RUN_OUTPUT_CONTINUE_REARM_MS = 30 * 60 * 1000;
@@ -102,6 +103,7 @@ const TRANSIENT_INFRA_CONTINUATION_ERROR_CODES = new Set([
102
103
  "adapter_failed",
103
104
  "codex_transient_upstream",
104
105
  "claude_transient_upstream",
106
+ "provider_quota",
105
107
  "timeout",
106
108
  ]);
107
109
  const NON_RETRYABLE_CONTINUATION_ERROR_CODES = new Set([
@@ -426,6 +428,17 @@ export function recoveryService(db, deps) {
426
428
  .limit(1)
427
429
  .then((rows) => Boolean(rows[0]));
428
430
  }
431
+ async function hasPersistedDurableWaitPath(issue) {
432
+ if (issue.monitorNextCheckAt)
433
+ return true;
434
+ return db
435
+ .select({ id: issueRelations.issueId })
436
+ .from(issueRelations)
437
+ .innerJoin(issues, eq(issueRelations.issueId, issues.id))
438
+ .where(and(eq(issueRelations.companyId, issue.companyId), eq(issueRelations.relatedIssueId, issue.id), eq(issueRelations.type, "blocks"), eq(issues.companyId, issue.companyId), notInArray(issues.status, ["done", "cancelled"]), isNull(issues.hiddenAt)))
439
+ .limit(1)
440
+ .then((rows) => Boolean(rows[0]));
441
+ }
429
442
  async function hasQueuedIssueWake(companyId, issueId, agentId) {
430
443
  return db
431
444
  .select({ id: agentWakeupRequests.id })
@@ -434,6 +447,51 @@ export function recoveryService(db, deps) {
434
447
  .limit(1)
435
448
  .then((rows) => Boolean(rows[0]));
436
449
  }
450
+ async function getLatestAcceptedContinuationInteraction(companyId, issueId) {
451
+ return db
452
+ .select({
453
+ id: issueThreadInteractions.id,
454
+ kind: issueThreadInteractions.kind,
455
+ status: issueThreadInteractions.status,
456
+ continuationPolicy: issueThreadInteractions.continuationPolicy,
457
+ sourceRunId: issueThreadInteractions.sourceRunId,
458
+ resolvedAt: issueThreadInteractions.resolvedAt,
459
+ updatedAt: issueThreadInteractions.updatedAt,
460
+ })
461
+ .from(issueThreadInteractions)
462
+ .where(and(eq(issueThreadInteractions.companyId, companyId), eq(issueThreadInteractions.issueId, issueId), eq(issueThreadInteractions.status, "accepted"), inArray(issueThreadInteractions.continuationPolicy, ["wake_assignee", "wake_assignee_on_accept"])))
463
+ .orderBy(desc(sql `coalesce(${issueThreadInteractions.resolvedAt}, ${issueThreadInteractions.updatedAt})`), desc(issueThreadInteractions.id))
464
+ .limit(1)
465
+ .then((rows) => rows[0] ?? null);
466
+ }
467
+ async function hasSuccessfulIssueRunSince(companyId, issueId, agentId, since, interactionId) {
468
+ return db
469
+ .select({ id: heartbeatRuns.id })
470
+ .from(heartbeatRuns)
471
+ .where(and(eq(heartbeatRuns.companyId, companyId), eq(heartbeatRuns.agentId, agentId), eq(heartbeatRuns.status, "succeeded"), sql `${heartbeatRuns.contextSnapshot} ->> 'issueId' = ${issueId}`, interactionId
472
+ ? sql `${heartbeatRuns.contextSnapshot} ->> 'interactionId' = ${interactionId}`
473
+ : sql `true`, or(gte(heartbeatRuns.createdAt, since), gte(heartbeatRuns.finishedAt, since))))
474
+ .limit(1)
475
+ .then((rows) => Boolean(rows[0]));
476
+ }
477
+ async function getLatestIssueRunSince(companyId, issueId, agentId, since) {
478
+ return db
479
+ .select({
480
+ id: heartbeatRuns.id,
481
+ agentId: heartbeatRuns.agentId,
482
+ status: heartbeatRuns.status,
483
+ error: heartbeatRuns.error,
484
+ errorCode: heartbeatRuns.errorCode,
485
+ contextSnapshot: heartbeatRuns.contextSnapshot,
486
+ livenessState: heartbeatRuns.livenessState,
487
+ resultJson: heartbeatRuns.resultJson,
488
+ })
489
+ .from(heartbeatRuns)
490
+ .where(and(eq(heartbeatRuns.companyId, companyId), eq(heartbeatRuns.agentId, agentId), sql `${heartbeatRuns.contextSnapshot} ->> 'issueId' = ${issueId}`, or(gte(heartbeatRuns.createdAt, since), gte(heartbeatRuns.finishedAt, since))))
491
+ .orderBy(desc(heartbeatRuns.createdAt), desc(heartbeatRuns.id))
492
+ .limit(1)
493
+ .then((rows) => rows[0] ?? null);
494
+ }
437
495
  // GGU-809: visible-progress signal for stranded-recovery escalation guard.
438
496
  // Returns true if the assignee posted a comment, OR any attachment was added
439
497
  // to the issue, within `windowMs`. Used to suppress false-positive recovery
@@ -656,7 +714,7 @@ export function recoveryService(db, deps) {
656
714
  updatedAt: issues.updatedAt,
657
715
  })
658
716
  .from(issues)
659
- .where(and(eq(issues.companyId, companyId), eq(issues.originKind, STALE_ACTIVE_RUN_EVALUATION_ORIGIN_KIND), eq(issues.originId, runId), isNull(issues.hiddenAt), notInArray(issues.status, ["done", "cancelled"])))
717
+ .where(and(eq(issues.companyId, companyId), eq(issues.originKind, STALE_ACTIVE_RUN_EVALUATION_ORIGIN_KIND), eq(issues.originId, runId), visibleIssueCondition(), notInArray(issues.status, ["done", "cancelled"])))
660
718
  .limit(1);
661
719
  return row ?? null;
662
720
  }
@@ -673,7 +731,7 @@ export function recoveryService(db, deps) {
673
731
  const [row] = await db
674
732
  .select({ id: issues.id, identifier: issues.identifier, status: issues.status })
675
733
  .from(issues)
676
- .where(and(eq(issues.companyId, companyId), eq(issues.originKind, STALE_ACTIVE_RUN_EVALUATION_ORIGIN_KIND), eq(issues.originId, runId), isNull(issues.hiddenAt), eq(issues.status, "done")))
734
+ .where(and(eq(issues.companyId, companyId), eq(issues.originKind, STALE_ACTIVE_RUN_EVALUATION_ORIGIN_KIND), eq(issues.originId, runId), visibleIssueCondition(), eq(issues.status, "done")))
677
735
  .orderBy(desc(issues.updatedAt))
678
736
  .limit(1);
679
737
  return row ?? null;
@@ -750,7 +808,7 @@ export function recoveryService(db, deps) {
750
808
  const [issue] = await db
751
809
  .select()
752
810
  .from(issues)
753
- .where(and(eq(issues.companyId, run.companyId), eq(issues.id, issueId), isNull(issues.hiddenAt)))
811
+ .where(and(eq(issues.companyId, run.companyId), eq(issues.id, issueId), visibleIssueCondition()))
754
812
  .limit(1);
755
813
  return issue ?? null;
756
814
  }
@@ -1060,7 +1118,7 @@ export function recoveryService(db, deps) {
1060
1118
  ? db
1061
1119
  .select({ id: issues.id, identifier: issues.identifier, title: issues.title, status: issues.status })
1062
1120
  .from(issues)
1063
- .where(and(eq(issues.companyId, input.run.companyId), eq(issues.parentId, input.sourceIssue.id), isNull(issues.hiddenAt)))
1121
+ .where(and(eq(issues.companyId, input.run.companyId), eq(issues.parentId, input.sourceIssue.id), visibleIssueCondition()))
1064
1122
  .orderBy(desc(issues.updatedAt))
1065
1123
  .limit(8)
1066
1124
  : Promise.resolve([]),
@@ -1414,12 +1472,27 @@ export function recoveryService(db, deps) {
1414
1472
  async function scanSilentActiveRuns(opts) {
1415
1473
  const now = opts?.now ?? new Date();
1416
1474
  const suspicionBefore = new Date(now.getTime() - ACTIVE_RUN_OUTPUT_SUSPICION_THRESHOLD_MS);
1417
- const candidates = await db
1475
+ let candidates = await db
1418
1476
  .select()
1419
1477
  .from(heartbeatRuns)
1420
1478
  .where(and(opts?.companyId ? eq(heartbeatRuns.companyId, opts.companyId) : undefined, eq(heartbeatRuns.status, "running"), sql `coalesce(${heartbeatRuns.lastOutputAt}, ${heartbeatRuns.processStartedAt}, ${heartbeatRuns.startedAt}, ${heartbeatRuns.createdAt}) <= ${suspicionBefore.toISOString()}::timestamptz`))
1421
1479
  .orderBy(asc(heartbeatRuns.createdAt))
1422
1480
  .limit(100);
1481
+ if (opts?.issueCreatedAtGte) {
1482
+ const issueIds = [...new Set(candidates.flatMap((run) => {
1483
+ const context = parseObject(run.contextSnapshot);
1484
+ const issueId = context.issueId ?? context.taskId;
1485
+ return typeof issueId === "string" && issueId.length > 0 ? [issueId] : [];
1486
+ }))];
1487
+ const eligibleIssueIds = new Set(issueIds.length > 0
1488
+ ? (await db.select({ id: issues.id }).from(issues).where(and(inArray(issues.id, issueIds), gte(issues.createdAt, opts.issueCreatedAtGte)))).map((issue) => issue.id)
1489
+ : []);
1490
+ candidates = candidates.filter((run) => {
1491
+ const context = parseObject(run.contextSnapshot);
1492
+ const issueId = context.issueId ?? context.taskId;
1493
+ return typeof issueId === "string" && eligibleIssueIds.has(issueId);
1494
+ });
1495
+ }
1423
1496
  const result = {
1424
1497
  scanned: candidates.length,
1425
1498
  created: 0,
@@ -1563,7 +1636,7 @@ export function recoveryService(db, deps) {
1563
1636
  return db
1564
1637
  .select()
1565
1638
  .from(issues)
1566
- .where(and(eq(issues.companyId, companyId), eq(issues.originKind, STRANDED_ISSUE_RECOVERY_ORIGIN_KIND), eq(issues.originId, sourceIssueId), isNull(issues.hiddenAt), notInArray(issues.status, ["done", "cancelled"])))
1639
+ .where(and(eq(issues.companyId, companyId), eq(issues.originKind, STRANDED_ISSUE_RECOVERY_ORIGIN_KIND), eq(issues.originId, sourceIssueId), visibleIssueCondition(), notInArray(issues.status, ["done", "cancelled"])))
1567
1640
  .orderBy(desc(issues.createdAt))
1568
1641
  .limit(1)
1569
1642
  .then((rows) => rows[0] ?? null);
@@ -2008,7 +2081,7 @@ export function recoveryService(db, deps) {
2008
2081
  const openChildren = await db
2009
2082
  .select({ id: issues.id, identifier: issues.identifier })
2010
2083
  .from(issues)
2011
- .where(and(eq(issues.companyId, issue.companyId), eq(issues.parentId, issue.id), isNull(issues.hiddenAt), notInArray(issues.status, ["done", "cancelled"])));
2084
+ .where(and(eq(issues.companyId, issue.companyId), eq(issues.parentId, issue.id), visibleIssueCondition(), notInArray(issues.status, ["done", "cancelled"])));
2012
2085
  const blockedByIssueIds = [...new Set([...existingBlockers.map((row) => row.id), ...openChildren.map((row) => row.id)])];
2013
2086
  if (blockedByIssueIds.length === 0)
2014
2087
  return null;
@@ -2189,11 +2262,11 @@ export function recoveryService(db, deps) {
2189
2262
  }
2190
2263
  return updated;
2191
2264
  }
2192
- async function reconcileStrandedAssignedIssues() {
2265
+ async function reconcileStrandedAssignedIssues(opts) {
2193
2266
  const candidates = await db
2194
2267
  .select()
2195
2268
  .from(issues)
2196
- .where(and(isNull(issues.assigneeUserId), inArray(issues.status, ["todo", "in_progress", "in_review"]), or(sql `${issues.assigneeAgentId} is not null`, eq(issues.status, "in_review"))));
2269
+ .where(and(isNull(issues.assigneeUserId), inArray(issues.status, ["todo", "in_progress", "in_review"]), or(sql `${issues.assigneeAgentId} is not null`, eq(issues.status, "in_review")), opts?.issueCreatedAtGte ? gte(issues.createdAt, opts.issueCreatedAtGte) : undefined));
2197
2270
  const result = {
2198
2271
  assignmentDispatched: 0,
2199
2272
  dispatchRequeued: 0,
@@ -2246,6 +2319,10 @@ export function recoveryService(db, deps) {
2246
2319
  continue;
2247
2320
  }
2248
2321
  const latestRun = await getLatestIssueRun(issue.companyId, issue.id);
2322
+ if (latestRun?.status === "succeeded" && await hasPersistedDurableWaitPath(issue)) {
2323
+ result.skipped += 1;
2324
+ continue;
2325
+ }
2249
2326
  if (isStrandedIssueRecoveryIssue(issue) && isUnsuccessfulTerminalIssueRun(latestRun)) {
2250
2327
  const updated = await escalateStrandedRecoveryIssueInPlace({
2251
2328
  issue,
@@ -2261,6 +2338,52 @@ export function recoveryService(db, deps) {
2261
2338
  }
2262
2339
  continue;
2263
2340
  }
2341
+ const acceptedContinuationInteraction = await getLatestAcceptedContinuationInteraction(issue.companyId, issue.id);
2342
+ const acceptedInteractionResolvedAt = acceptedContinuationInteraction
2343
+ ? acceptedContinuationInteraction.resolvedAt ?? acceptedContinuationInteraction.updatedAt
2344
+ : null;
2345
+ if (acceptedContinuationInteraction && acceptedInteractionResolvedAt && !pendingExecutionState) {
2346
+ const successfulRunSinceResolution = await hasSuccessfulIssueRunSince(issue.companyId, issue.id, agentId, acceptedInteractionResolvedAt, acceptedContinuationInteraction.id);
2347
+ if (!successfulRunSinceResolution) {
2348
+ if (!agentInvokable) {
2349
+ result.skipped += 1;
2350
+ continue;
2351
+ }
2352
+ if (await hasQueuedIssueWake(issue.companyId, issue.id, agentId)) {
2353
+ result.skipped += 1;
2354
+ continue;
2355
+ }
2356
+ if (await isInvocationBudgetBlocked(issue, agentId)) {
2357
+ result.skipped += 1;
2358
+ continue;
2359
+ }
2360
+ const latestPostResolutionRun = await getLatestIssueRunSince(issue.companyId, issue.id, agentId, acceptedInteractionResolvedAt);
2361
+ const queued = await enqueueStrandedIssueRecovery({
2362
+ issueId: issue.id,
2363
+ agentId,
2364
+ reason: "issue_continuation_needed",
2365
+ retryReason: "issue_continuation_needed",
2366
+ source: "issue.interaction_continuation_recovery",
2367
+ retryOfRunId: latestPostResolutionRun?.id ?? acceptedContinuationInteraction.sourceRunId ?? latestRun?.id ?? null,
2368
+ extraContext: {
2369
+ mutation: "interaction",
2370
+ interactionId: acceptedContinuationInteraction.id,
2371
+ interactionKind: acceptedContinuationInteraction.kind,
2372
+ interactionStatus: acceptedContinuationInteraction.status,
2373
+ interactionContinuationPolicy: acceptedContinuationInteraction.continuationPolicy,
2374
+ interactionResolvedAt: acceptedInteractionResolvedAt.toISOString(),
2375
+ },
2376
+ });
2377
+ if (queued) {
2378
+ result.continuationRequeued += 1;
2379
+ result.issueIds.push(issue.id);
2380
+ }
2381
+ else {
2382
+ result.skipped += 1;
2383
+ }
2384
+ continue;
2385
+ }
2386
+ }
2264
2387
  if (issue.status === "in_review") {
2265
2388
  if (!participantAgentId || !pendingExecutionState) {
2266
2389
  result.skipped += 1;
@@ -2611,7 +2734,7 @@ export function recoveryService(db, deps) {
2611
2734
  monitorAttemptCount: issues.monitorAttemptCount,
2612
2735
  })
2613
2736
  .from(issues)
2614
- .where(and(isNull(issues.hiddenAt), notInArray(issues.originKind, [RECOVERY_ORIGIN_KINDS.issueGraphLivenessEscalation]))));
2737
+ .where(and(visibleIssueCondition(), notInArray(issues.originKind, [RECOVERY_ORIGIN_KINDS.issueGraphLivenessEscalation]))));
2615
2738
  const [issueRows, relationRows, agentRows, activeRunRows, activeIssueRunRows, wakeRows, interactionRows, approvalRows, recoveryIssueRows, recoveryActionRows,] = await Promise.all([
2616
2739
  issueRowsPromise,
2617
2740
  db
@@ -2651,7 +2774,7 @@ export function recoveryService(db, deps) {
2651
2774
  })
2652
2775
  .from(issues)
2653
2776
  .innerJoin(heartbeatRuns, eq(issues.executionRunId, heartbeatRuns.id))
2654
- .where(and(isNull(issues.hiddenAt), notInArray(issues.originKind, [RECOVERY_ORIGIN_KINDS.issueGraphLivenessEscalation]), inArray(heartbeatRuns.status, [...EXECUTION_PATH_HEARTBEAT_RUN_STATUSES]))),
2777
+ .where(and(visibleIssueCondition(), notInArray(issues.originKind, [RECOVERY_ORIGIN_KINDS.issueGraphLivenessEscalation]), inArray(heartbeatRuns.status, [...EXECUTION_PATH_HEARTBEAT_RUN_STATUSES]))),
2655
2778
  db
2656
2779
  .select({
2657
2780
  companyId: agentWakeupRequests.companyId,
@@ -2687,7 +2810,7 @@ export function recoveryService(db, deps) {
2687
2810
  originId: issues.originId,
2688
2811
  })
2689
2812
  .from(issues)
2690
- .where(and(isNull(issues.hiddenAt), inArray(issues.originKind, [
2813
+ .where(and(visibleIssueCondition(), inArray(issues.originKind, [
2691
2814
  STRANDED_ISSUE_RECOVERY_ORIGIN_KIND,
2692
2815
  RECOVERY_ORIGIN_KINDS.issueGraphLivenessEscalation,
2693
2816
  ]), notInArray(issues.status, ["done", "cancelled"]))),
@@ -2763,7 +2886,7 @@ export function recoveryService(db, deps) {
2763
2886
  return db
2764
2887
  .select()
2765
2888
  .from(issues)
2766
- .where(and(eq(issues.companyId, companyId), eq(issues.originKind, RECOVERY_ORIGIN_KINDS.issueGraphLivenessEscalation), eq(issues.originId, incidentKey), isNull(issues.hiddenAt), notInArray(issues.status, ["done", "cancelled"])))
2889
+ .where(and(eq(issues.companyId, companyId), eq(issues.originKind, RECOVERY_ORIGIN_KINDS.issueGraphLivenessEscalation), eq(issues.originId, incidentKey), visibleIssueCondition(), notInArray(issues.status, ["done", "cancelled"])))
2767
2890
  .limit(1)
2768
2891
  .then((rows) => rows[0] ?? null);
2769
2892
  }
@@ -2771,7 +2894,7 @@ export function recoveryService(db, deps) {
2771
2894
  const byFingerprint = await db
2772
2895
  .select()
2773
2896
  .from(issues)
2774
- .where(and(eq(issues.companyId, finding.companyId), eq(issues.originKind, RECOVERY_ORIGIN_KINDS.issueGraphLivenessEscalation), eq(issues.originFingerprint, livenessRecoveryLeafFingerprint(finding)), isNull(issues.hiddenAt), notInArray(issues.status, ["done", "cancelled"])))
2897
+ .where(and(eq(issues.companyId, finding.companyId), eq(issues.originKind, RECOVERY_ORIGIN_KINDS.issueGraphLivenessEscalation), eq(issues.originFingerprint, livenessRecoveryLeafFingerprint(finding)), visibleIssueCondition(), notInArray(issues.status, ["done", "cancelled"])))
2775
2898
  .limit(1)
2776
2899
  .then((rows) => rows[0] ?? null);
2777
2900
  if (byFingerprint)
@@ -2780,7 +2903,7 @@ export function recoveryService(db, deps) {
2780
2903
  const openRecoveries = await db
2781
2904
  .select()
2782
2905
  .from(issues)
2783
- .where(and(eq(issues.companyId, finding.companyId), eq(issues.originKind, RECOVERY_ORIGIN_KINDS.issueGraphLivenessEscalation), isNull(issues.hiddenAt), notInArray(issues.status, ["done", "cancelled"])));
2906
+ .where(and(eq(issues.companyId, finding.companyId), eq(issues.originKind, RECOVERY_ORIGIN_KINDS.issueGraphLivenessEscalation), visibleIssueCondition(), notInArray(issues.status, ["done", "cancelled"])));
2784
2907
  return openRecoveries.find((row) => {
2785
2908
  const parsed = parseLivenessIncidentKey(row.originId);
2786
2909
  return parsed?.state === finding.state && parsed.leafIssueId === leafIssueId;
@@ -2830,7 +2953,7 @@ export function recoveryService(db, deps) {
2830
2953
  const openRecoveries = await db
2831
2954
  .select()
2832
2955
  .from(issues)
2833
- .where(and(eq(issues.originKind, RECOVERY_ORIGIN_KINDS.issueGraphLivenessEscalation), isNull(issues.hiddenAt), notInArray(issues.status, ["done", "cancelled"])));
2956
+ .where(and(eq(issues.originKind, RECOVERY_ORIGIN_KINDS.issueGraphLivenessEscalation), visibleIssueCondition(), notInArray(issues.status, ["done", "cancelled"])));
2834
2957
  const result = {
2835
2958
  retired: 0,
2836
2959
  activeSkipped: 0,
@@ -2878,7 +3001,7 @@ export function recoveryService(db, deps) {
2878
3001
  const closedRecoveries = await db
2879
3002
  .select()
2880
3003
  .from(issues)
2881
- .where(and(eq(issues.originKind, RECOVERY_ORIGIN_KINDS.issueGraphLivenessEscalation), isNull(issues.hiddenAt), inArray(issues.status, ["done", "cancelled"])));
3004
+ .where(and(eq(issues.originKind, RECOVERY_ORIGIN_KINDS.issueGraphLivenessEscalation), visibleIssueCondition(), inArray(issues.status, ["done", "cancelled"])));
2882
3005
  let blockerRelationsRemoved = 0;
2883
3006
  for (const recovery of closedRecoveries) {
2884
3007
  if (await removeRecoveryBlockerFromSource(recovery)) {
@@ -3221,14 +3344,40 @@ export function recoveryService(db, deps) {
3221
3344
  enqueueFailed: 0,
3222
3345
  issueIds: [],
3223
3346
  };
3347
+ const source = opts?.source ?? "issue_graph_liveness.backstop";
3348
+ const requestedByActorId = source === "workspace.finalize"
3349
+ ? "heartbeat_finalize"
3350
+ : "issue_graph_liveness_backstop";
3351
+ const payloadBackstop = source === "workspace.finalize"
3352
+ ? "workspace_finalize_reconciliation"
3353
+ : "issue_graph_liveness_reconciliation";
3354
+ const useCursor = !opts?.blockerIssueId;
3224
3355
  const queryCandidates = (afterIssueId) => {
3225
3356
  const filters = [
3226
3357
  eq(issues.status, "blocked"),
3227
- isNull(issues.hiddenAt),
3358
+ visibleIssueCondition(),
3228
3359
  sql `${issues.assigneeAgentId} is not null`,
3229
3360
  ];
3361
+ if (opts?.companyId)
3362
+ filters.push(eq(issues.companyId, opts.companyId));
3230
3363
  if (afterIssueId)
3231
3364
  filters.push(gt(issues.id, afterIssueId));
3365
+ if (opts?.blockerIssueId) {
3366
+ filters.push(eq(issueRelations.companyId, issues.companyId), eq(issueRelations.type, "blocks"), eq(issueRelations.issueId, opts.blockerIssueId), eq(issueRelations.relatedIssueId, issues.id));
3367
+ return db
3368
+ .select({
3369
+ id: issues.id,
3370
+ companyId: issues.companyId,
3371
+ identifier: issues.identifier,
3372
+ assigneeAgentId: issues.assigneeAgentId,
3373
+ totalCount: sql `count(*) over()::int`,
3374
+ })
3375
+ .from(issueRelations)
3376
+ .innerJoin(issues, eq(issueRelations.relatedIssueId, issues.id))
3377
+ .where(and(...filters))
3378
+ .orderBy(asc(issues.id))
3379
+ .limit(RESOLVED_DEPENDENCY_WAKE_BACKSTOP_CANDIDATE_LIMIT);
3380
+ }
3232
3381
  return db
3233
3382
  .select({
3234
3383
  id: issues.id,
@@ -3242,8 +3391,8 @@ export function recoveryService(db, deps) {
3242
3391
  .orderBy(asc(issues.id))
3243
3392
  .limit(RESOLVED_DEPENDENCY_WAKE_BACKSTOP_CANDIDATE_LIMIT);
3244
3393
  };
3245
- let candidateRows = await queryCandidates(resolvedDependencyWakeBackstopCandidateCursor);
3246
- if (candidateRows.length === 0 && resolvedDependencyWakeBackstopCandidateCursor) {
3394
+ let candidateRows = await queryCandidates(useCursor ? resolvedDependencyWakeBackstopCandidateCursor : null);
3395
+ if (useCursor && candidateRows.length === 0 && resolvedDependencyWakeBackstopCandidateCursor) {
3247
3396
  resolvedDependencyWakeBackstopCandidateCursor = null;
3248
3397
  candidateRows = await queryCandidates(null);
3249
3398
  }
@@ -3252,14 +3401,18 @@ export function recoveryService(db, deps) {
3252
3401
  result.checked = candidates.length;
3253
3402
  result.candidateLimitSkipped = Math.max(0, totalCandidateCount - candidates.length);
3254
3403
  const lastCandidate = candidates[candidates.length - 1] ?? null;
3255
- resolvedDependencyWakeBackstopCandidateCursor =
3256
- result.candidateLimitSkipped > 0 && lastCandidate ? lastCandidate.id : null;
3404
+ if (useCursor) {
3405
+ resolvedDependencyWakeBackstopCandidateCursor =
3406
+ result.candidateLimitSkipped > 0 && lastCandidate ? lastCandidate.id : null;
3407
+ }
3257
3408
  if (result.candidateLimitSkipped > 0) {
3258
3409
  logger.warn({
3259
3410
  processed: candidates.length,
3260
3411
  skipped: result.candidateLimitSkipped,
3261
3412
  limit: RESOLVED_DEPENDENCY_WAKE_BACKSTOP_CANDIDATE_LIMIT,
3262
- nextCursor: resolvedDependencyWakeBackstopCandidateCursor,
3413
+ nextCursor: useCursor ? resolvedDependencyWakeBackstopCandidateCursor : null,
3414
+ source,
3415
+ blockerIssueId: opts?.blockerIssueId ?? null,
3263
3416
  }, "issue graph liveness backstop deferred resolved dependency wake candidates past page limit");
3264
3417
  }
3265
3418
  const candidatesByCompany = new Map();
@@ -3321,16 +3474,16 @@ export function recoveryService(db, deps) {
3321
3474
  issueId: candidate.id,
3322
3475
  resolvedBlockerIssueId,
3323
3476
  blockerIssueIds: readiness.blockerIssueIds,
3324
- backstop: "issue_graph_liveness_reconciliation",
3477
+ backstop: payloadBackstop,
3325
3478
  },
3326
3479
  idempotencyKey,
3327
3480
  requestedByActorType: "system",
3328
- requestedByActorId: "issue_graph_liveness_backstop",
3481
+ requestedByActorId,
3329
3482
  contextSnapshot: {
3330
3483
  issueId: candidate.id,
3331
3484
  taskId: candidate.id,
3332
3485
  wakeReason: ISSUE_BLOCKERS_RESOLVED_WAKE_REASON,
3333
- source: "issue_graph_liveness.backstop",
3486
+ source,
3334
3487
  resolvedBlockerIssueId,
3335
3488
  blockerIssueIds: readiness.blockerIssueIds,
3336
3489
  },
@@ -3354,7 +3507,7 @@ export function recoveryService(db, deps) {
3354
3507
  entityType: "issue",
3355
3508
  entityId: candidate.id,
3356
3509
  details: {
3357
- source: "issue_graph_liveness.backstop",
3510
+ source,
3358
3511
  wakeupRunId: wake.id,
3359
3512
  idempotencyKey,
3360
3513
  resolvedBlockerIssueId,
@@ -3365,17 +3518,28 @@ export function recoveryService(db, deps) {
3365
3518
  catch (err) {
3366
3519
  result.deferredOrFailed += 1;
3367
3520
  result.enqueueFailed += 1;
3368
- logger.warn({ err, issueId: candidate.id, agentId, idempotencyKey }, "failed to enqueue dependency wake from issue graph liveness backstop");
3521
+ logger.warn({ err, issueId: candidate.id, agentId, idempotencyKey, source }, "failed to enqueue dependency wake from issue graph liveness backstop");
3369
3522
  }
3370
3523
  }
3371
3524
  }
3372
3525
  if (result.healed > 0) {
3373
- logger.warn({ healed: result.healed, issueIds: result.issueIds }, "issue graph liveness backstop healed resolved blocked dependency wakes");
3526
+ logger.warn({ healed: result.healed, issueIds: result.issueIds, source, blockerIssueId: opts?.blockerIssueId ?? null }, "issue graph liveness backstop healed resolved blocked dependency wakes");
3374
3527
  }
3375
3528
  return result;
3376
3529
  }
3377
3530
  async function reconcileIssueGraphLiveness(opts) {
3378
- const findings = await collectIssueGraphLivenessFindings();
3531
+ let findings = await collectIssueGraphLivenessFindings();
3532
+ if (opts?.issueCreatedAtGte) {
3533
+ const findingIssueIds = [...new Set(findings.map((finding) => finding.recoveryIssueId))];
3534
+ const eligibleIssueIds = new Set(findingIssueIds.length === 0
3535
+ ? []
3536
+ : (await db
3537
+ .select({ id: issues.id })
3538
+ .from(issues)
3539
+ .where(and(inArray(issues.id, findingIssueIds), gte(issues.createdAt, opts.issueCreatedAtGte))))
3540
+ .map((issue) => issue.id));
3541
+ findings = findings.filter((finding) => eligibleIssueIds.has(finding.recoveryIssueId));
3542
+ }
3379
3543
  const experimentalSettings = await instanceSettings.getExperimental();
3380
3544
  const autoRecoveryEnabled = asBoolean(experimentalSettings.enableIssueGraphLivenessAutoRecovery, true) || opts?.force === true;
3381
3545
  const lookbackHours = normalizeIssueGraphLivenessAutoRecoveryLookbackHours(opts?.lookbackHours ?? experimentalSettings.issueGraphLivenessAutoRecoveryLookbackHours);
@@ -3413,10 +3577,6 @@ export function recoveryService(db, deps) {
3413
3577
  escalationIssueIds: [],
3414
3578
  retiredRecoveryIssueIds: obsoleteRecoveryCleanup.retiredIssueIds,
3415
3579
  };
3416
- if (!autoRecoveryEnabled) {
3417
- result.skippedAutoRecoveryDisabled = findings.length;
3418
- return result;
3419
- }
3420
3580
  const dependencyWakeBackstop = await reconcileResolvedDependencyWakeBackstop({
3421
3581
  runId: opts?.runId ?? null,
3422
3582
  });
@@ -3431,6 +3591,10 @@ export function recoveryService(db, deps) {
3431
3591
  result.dependencyWakeDeferredOrFailed = dependencyWakeBackstop.deferredOrFailed;
3432
3592
  result.dependencyWakeEnqueueFailed = dependencyWakeBackstop.enqueueFailed;
3433
3593
  result.dependencyWakeIssueIds = dependencyWakeBackstop.issueIds;
3594
+ if (!autoRecoveryEnabled) {
3595
+ result.skippedAutoRecoveryDisabled = findings.length;
3596
+ return result;
3597
+ }
3434
3598
  for (const finding of findings) {
3435
3599
  if (!isLivenessFindingInsideAutoRecoveryLookback(finding, cutoff, updatedAtByIssueKey)) {
3436
3600
  result.skippedOutsideLookback += 1;
@@ -3557,6 +3721,7 @@ export function recoveryService(db, deps) {
3557
3721
  reconcileStrandedAssignedIssues,
3558
3722
  sweepStaleIssueLocks,
3559
3723
  buildIssueGraphLivenessAutoRecoveryPreview,
3724
+ reconcileResolvedDependencyWakeBackstop,
3560
3725
  reconcileIssueGraphLiveness,
3561
3726
  readRecoveryTimerIntervalMs,
3562
3727
  };