@paperclipai/server 2026.824.0 → 2026.825.0-beta.1

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 (519) hide show
  1. package/dist/adapters/builtin-adapter-types.d.ts.map +1 -1
  2. package/dist/adapters/builtin-adapter-types.js +1 -0
  3. package/dist/adapters/builtin-adapter-types.js.map +1 -1
  4. package/dist/adapters/plugin-loader.d.ts +1 -0
  5. package/dist/adapters/plugin-loader.d.ts.map +1 -1
  6. package/dist/adapters/plugin-loader.js +12 -1
  7. package/dist/adapters/plugin-loader.js.map +1 -1
  8. package/dist/adapters/plugin-loader.test.d.ts +2 -0
  9. package/dist/adapters/plugin-loader.test.d.ts.map +1 -0
  10. package/dist/adapters/plugin-loader.test.js +37 -0
  11. package/dist/adapters/plugin-loader.test.js.map +1 -0
  12. package/dist/adapters/registry.d.ts.map +1 -1
  13. package/dist/adapters/registry.js +68 -5
  14. package/dist/adapters/registry.js.map +1 -1
  15. package/dist/adapters/registry.test.d.ts +2 -0
  16. package/dist/adapters/registry.test.d.ts.map +1 -0
  17. package/dist/adapters/registry.test.js +35 -0
  18. package/dist/adapters/registry.test.js.map +1 -0
  19. package/dist/app.d.ts.map +1 -1
  20. package/dist/app.js +5 -7
  21. package/dist/app.js.map +1 -1
  22. package/dist/auth/better-auth.d.ts +10 -0
  23. package/dist/auth/better-auth.d.ts.map +1 -1
  24. package/dist/auth/better-auth.js +47 -0
  25. package/dist/auth/better-auth.js.map +1 -1
  26. package/dist/auth/workspace-login-handoff-exchange.d.ts +75 -0
  27. package/dist/auth/workspace-login-handoff-exchange.d.ts.map +1 -0
  28. package/dist/auth/workspace-login-handoff-exchange.js +73 -0
  29. package/dist/auth/workspace-login-handoff-exchange.js.map +1 -0
  30. package/dist/auth/workspace-login-handoff-plugin.d.ts +40 -0
  31. package/dist/auth/workspace-login-handoff-plugin.d.ts.map +1 -0
  32. package/dist/auth/workspace-login-handoff-plugin.js +140 -0
  33. package/dist/auth/workspace-login-handoff-plugin.js.map +1 -0
  34. package/dist/auth/workspace-login-handoff.d.ts +189 -0
  35. package/dist/auth/workspace-login-handoff.d.ts.map +1 -0
  36. package/dist/auth/workspace-login-handoff.js +319 -0
  37. package/dist/auth/workspace-login-handoff.js.map +1 -0
  38. package/dist/build-info.json +3 -0
  39. package/dist/config.d.ts +1 -0
  40. package/dist/config.d.ts.map +1 -1
  41. package/dist/config.js +14 -0
  42. package/dist/config.js.map +1 -1
  43. package/dist/dev-runner-worktree.d.ts.map +1 -1
  44. package/dist/dev-runner-worktree.js +5 -0
  45. package/dist/dev-runner-worktree.js.map +1 -1
  46. package/dist/duplex-aggregate-ceiling-env.d.ts +21 -0
  47. package/dist/duplex-aggregate-ceiling-env.d.ts.map +1 -0
  48. package/dist/duplex-aggregate-ceiling-env.js +23 -0
  49. package/dist/duplex-aggregate-ceiling-env.js.map +1 -0
  50. package/dist/embedded-postgres-supervisor.d.ts +27 -0
  51. package/dist/embedded-postgres-supervisor.d.ts.map +1 -0
  52. package/dist/embedded-postgres-supervisor.js +72 -0
  53. package/dist/embedded-postgres-supervisor.js.map +1 -0
  54. package/dist/errors.d.ts +2 -0
  55. package/dist/errors.d.ts.map +1 -1
  56. package/dist/errors.js +6 -0
  57. package/dist/errors.js.map +1 -1
  58. package/dist/index.d.ts.map +1 -1
  59. package/dist/index.js +115 -7
  60. package/dist/index.js.map +1 -1
  61. package/dist/instrumentation.d.ts +33 -0
  62. package/dist/instrumentation.d.ts.map +1 -1
  63. package/dist/instrumentation.js +68 -1
  64. package/dist/instrumentation.js.map +1 -1
  65. package/dist/middleware/auth.d.ts.map +1 -1
  66. package/dist/middleware/auth.js +35 -10
  67. package/dist/middleware/auth.js.map +1 -1
  68. package/dist/middleware/error-handler.d.ts.map +1 -1
  69. package/dist/middleware/error-handler.js +8 -1
  70. package/dist/middleware/error-handler.js.map +1 -1
  71. package/dist/middleware/logger.d.ts.map +1 -1
  72. package/dist/middleware/logger.js +5 -2
  73. package/dist/middleware/logger.js.map +1 -1
  74. package/dist/middleware/redact-sensitive.d.ts.map +1 -1
  75. package/dist/middleware/redact-sensitive.js +4 -0
  76. package/dist/middleware/redact-sensitive.js.map +1 -1
  77. package/dist/middleware/validate.d.ts +3 -1
  78. package/dist/middleware/validate.d.ts.map +1 -1
  79. package/dist/middleware/validate.js +37 -0
  80. package/dist/middleware/validate.js.map +1 -1
  81. package/dist/routes/access.d.ts.map +1 -1
  82. package/dist/routes/access.js +20 -0
  83. package/dist/routes/access.js.map +1 -1
  84. package/dist/routes/activity.js +4 -4
  85. package/dist/routes/activity.js.map +1 -1
  86. package/dist/routes/adapter-login-route-spine.d.ts +81 -0
  87. package/dist/routes/adapter-login-route-spine.d.ts.map +1 -0
  88. package/dist/routes/adapter-login-route-spine.js +40 -0
  89. package/dist/routes/adapter-login-route-spine.js.map +1 -0
  90. package/dist/routes/adapters.d.ts +33 -0
  91. package/dist/routes/adapters.d.ts.map +1 -1
  92. package/dist/routes/adapters.js +35 -1
  93. package/dist/routes/adapters.js.map +1 -1
  94. package/dist/routes/adapters.test.d.ts +2 -0
  95. package/dist/routes/adapters.test.d.ts.map +1 -0
  96. package/dist/routes/adapters.test.js +58 -0
  97. package/dist/routes/adapters.test.js.map +1 -0
  98. package/dist/routes/agents.d.ts.map +1 -1
  99. package/dist/routes/agents.js +281 -91
  100. package/dist/routes/agents.js.map +1 -1
  101. package/dist/routes/cases.d.ts +11 -22
  102. package/dist/routes/cases.d.ts.map +1 -1
  103. package/dist/routes/cases.js +13 -13
  104. package/dist/routes/companies.js +3 -3
  105. package/dist/routes/decision-training.js +6 -6
  106. package/dist/routes/decisions.js +4 -4
  107. package/dist/routes/decisions.js.map +1 -1
  108. package/dist/routes/environments.d.ts.map +1 -1
  109. package/dist/routes/environments.js +79 -6
  110. package/dist/routes/environments.js.map +1 -1
  111. package/dist/routes/execution-workspaces.d.ts.map +1 -1
  112. package/dist/routes/execution-workspaces.js +384 -16
  113. package/dist/routes/execution-workspaces.js.map +1 -1
  114. package/dist/routes/file-resources.js +2 -2
  115. package/dist/routes/health.d.ts.map +1 -1
  116. package/dist/routes/health.js +58 -4
  117. package/dist/routes/health.js.map +1 -1
  118. package/dist/routes/instance-settings.d.ts.map +1 -1
  119. package/dist/routes/instance-settings.js +40 -0
  120. package/dist/routes/instance-settings.js.map +1 -1
  121. package/dist/routes/issues.d.ts +10 -0
  122. package/dist/routes/issues.d.ts.map +1 -1
  123. package/dist/routes/issues.js +495 -65
  124. package/dist/routes/issues.js.map +1 -1
  125. package/dist/routes/openapi.d.ts.map +1 -1
  126. package/dist/routes/openapi.js +241 -122
  127. package/dist/routes/openapi.js.map +1 -1
  128. package/dist/routes/pipelines.js +19 -19
  129. package/dist/routes/plugins.d.ts.map +1 -1
  130. package/dist/routes/plugins.js +22 -0
  131. package/dist/routes/plugins.js.map +1 -1
  132. package/dist/routes/projects.d.ts.map +1 -1
  133. package/dist/routes/projects.js +2 -0
  134. package/dist/routes/projects.js.map +1 -1
  135. package/dist/routes/routines.js +2 -2
  136. package/dist/routes/routines.js.map +1 -1
  137. package/dist/routes/secrets.d.ts +1 -1
  138. package/dist/routes/secrets.d.ts.map +1 -1
  139. package/dist/routes/secrets.js +39 -50
  140. package/dist/routes/secrets.js.map +1 -1
  141. package/dist/routes/setup-token-route.test.js +50 -3
  142. package/dist/routes/setup-token-route.test.js.map +1 -1
  143. package/dist/services/adapter-login-lease.d.ts +50 -0
  144. package/dist/services/adapter-login-lease.d.ts.map +1 -0
  145. package/dist/services/adapter-login-lease.js +26 -0
  146. package/dist/services/adapter-login-lease.js.map +1 -0
  147. package/dist/services/adapter-login-lease.test.d.ts +2 -0
  148. package/dist/services/adapter-login-lease.test.d.ts.map +1 -0
  149. package/dist/services/adapter-login-lease.test.js +68 -0
  150. package/dist/services/adapter-login-lease.test.js.map +1 -0
  151. package/dist/services/agent-action-audit.js +1 -1
  152. package/dist/services/agent-secret-bindings.d.ts +15 -0
  153. package/dist/services/agent-secret-bindings.d.ts.map +1 -1
  154. package/dist/services/agent-secret-bindings.js +2 -2
  155. package/dist/services/agent-secret-bindings.js.map +1 -1
  156. package/dist/services/agents.d.ts +13 -13
  157. package/dist/services/agents.d.ts.map +1 -1
  158. package/dist/services/agents.js +46 -5
  159. package/dist/services/agents.js.map +1 -1
  160. package/dist/services/artifact-review-documents.d.ts +34 -0
  161. package/dist/services/artifact-review-documents.d.ts.map +1 -0
  162. package/dist/services/artifact-review-documents.js +196 -0
  163. package/dist/services/artifact-review-documents.js.map +1 -0
  164. package/dist/services/assets.d.ts +1 -1
  165. package/dist/services/codex-device-login-credential-read.d.ts +58 -0
  166. package/dist/services/codex-device-login-credential-read.d.ts.map +1 -0
  167. package/dist/services/codex-device-login-credential-read.js +118 -0
  168. package/dist/services/codex-device-login-credential-read.js.map +1 -0
  169. package/dist/services/codex-device-login-reaper.d.ts.map +1 -1
  170. package/dist/services/codex-device-login-reaper.js +8 -5
  171. package/dist/services/codex-device-login-reaper.js.map +1 -1
  172. package/dist/services/codex-device-login-service.d.ts +127 -36
  173. package/dist/services/codex-device-login-service.d.ts.map +1 -1
  174. package/dist/services/codex-device-login-service.js +204 -84
  175. package/dist/services/codex-device-login-service.js.map +1 -1
  176. package/dist/services/company-portability.d.ts +3 -1
  177. package/dist/services/company-portability.d.ts.map +1 -1
  178. package/dist/services/company-portability.js +76 -20
  179. package/dist/services/company-portability.js.map +1 -1
  180. package/dist/services/company-skill-policy.d.ts +1 -1
  181. package/dist/services/costs.d.ts +1 -1
  182. package/dist/services/decisions.d.ts +6 -6
  183. package/dist/services/duplex-observability-recorder.d.ts +62 -0
  184. package/dist/services/duplex-observability-recorder.d.ts.map +1 -0
  185. package/dist/services/duplex-observability-recorder.js +54 -0
  186. package/dist/services/duplex-observability-recorder.js.map +1 -0
  187. package/dist/services/environment-config.js +5 -5
  188. package/dist/services/environment-config.js.map +1 -1
  189. package/dist/services/environment-custom-image-runtime.d.ts +116 -0
  190. package/dist/services/environment-custom-image-runtime.d.ts.map +1 -1
  191. package/dist/services/environment-custom-image-runtime.js +255 -1
  192. package/dist/services/environment-custom-image-runtime.js.map +1 -1
  193. package/dist/services/environment-custom-images.d.ts +39 -0
  194. package/dist/services/environment-custom-images.d.ts.map +1 -1
  195. package/dist/services/environment-custom-images.js +219 -17
  196. package/dist/services/environment-custom-images.js.map +1 -1
  197. package/dist/services/environment-driver-traits.d.ts +109 -0
  198. package/dist/services/environment-driver-traits.d.ts.map +1 -0
  199. package/dist/services/environment-driver-traits.js +102 -0
  200. package/dist/services/environment-driver-traits.js.map +1 -0
  201. package/dist/services/environment-execution-target.d.ts +4 -0
  202. package/dist/services/environment-execution-target.d.ts.map +1 -1
  203. package/dist/services/environment-execution-target.js +63 -7
  204. package/dist/services/environment-execution-target.js.map +1 -1
  205. package/dist/services/environment-run-orchestrator.d.ts +27 -1
  206. package/dist/services/environment-run-orchestrator.d.ts.map +1 -1
  207. package/dist/services/environment-run-orchestrator.js +24 -4
  208. package/dist/services/environment-run-orchestrator.js.map +1 -1
  209. package/dist/services/environment-runtime.d.ts +118 -20
  210. package/dist/services/environment-runtime.d.ts.map +1 -1
  211. package/dist/services/environment-runtime.js +436 -91
  212. package/dist/services/environment-runtime.js.map +1 -1
  213. package/dist/services/environments.d.ts.map +1 -1
  214. package/dist/services/environments.js +20 -2
  215. package/dist/services/environments.js.map +1 -1
  216. package/dist/services/execution-workspace-branch-ownership.d.ts +4 -0
  217. package/dist/services/execution-workspace-branch-ownership.d.ts.map +1 -0
  218. package/dist/services/execution-workspace-branch-ownership.js +9 -0
  219. package/dist/services/execution-workspace-branch-ownership.js.map +1 -0
  220. package/dist/services/execution-workspace-policy.d.ts.map +1 -1
  221. package/dist/services/execution-workspace-policy.js +3 -0
  222. package/dist/services/execution-workspace-policy.js.map +1 -1
  223. package/dist/services/execution-workspaces.d.ts +2 -0
  224. package/dist/services/execution-workspaces.d.ts.map +1 -1
  225. package/dist/services/execution-workspaces.js +90 -2
  226. package/dist/services/execution-workspaces.js.map +1 -1
  227. package/dist/services/external-objects.d.ts +19 -19
  228. package/dist/services/finance.d.ts +1 -1
  229. package/dist/services/goals.d.ts +2 -2
  230. package/dist/services/heartbeat-policy.d.ts +3 -0
  231. package/dist/services/heartbeat-policy.d.ts.map +1 -0
  232. package/dist/services/heartbeat-policy.js +10 -0
  233. package/dist/services/heartbeat-policy.js.map +1 -0
  234. package/dist/services/heartbeat-run-runtime-status.test.js +1 -1
  235. package/dist/services/heartbeat-run-runtime-status.test.js.map +1 -1
  236. package/dist/services/heartbeat.d.ts +23 -1
  237. package/dist/services/heartbeat.d.ts.map +1 -1
  238. package/dist/services/heartbeat.js +192 -11
  239. package/dist/services/heartbeat.js.map +1 -1
  240. package/dist/services/index.d.ts +1 -0
  241. package/dist/services/index.d.ts.map +1 -1
  242. package/dist/services/index.js +1 -0
  243. package/dist/services/index.js.map +1 -1
  244. package/dist/services/instance-settings.d.ts.map +1 -1
  245. package/dist/services/instance-settings.js +2 -0
  246. package/dist/services/instance-settings.js.map +1 -1
  247. package/dist/services/issue-dependency-wakeups.d.ts +57 -9
  248. package/dist/services/issue-dependency-wakeups.d.ts.map +1 -1
  249. package/dist/services/issue-dependency-wakeups.js +146 -14
  250. package/dist/services/issue-dependency-wakeups.js.map +1 -1
  251. package/dist/services/issue-dependency-wakeups.test.d.ts +2 -0
  252. package/dist/services/issue-dependency-wakeups.test.d.ts.map +1 -0
  253. package/dist/services/issue-dependency-wakeups.test.js +183 -0
  254. package/dist/services/issue-dependency-wakeups.test.js.map +1 -0
  255. package/dist/services/issue-recovery-actions.d.ts +6 -1
  256. package/dist/services/issue-recovery-actions.d.ts.map +1 -1
  257. package/dist/services/issue-recovery-actions.js +123 -44
  258. package/dist/services/issue-recovery-actions.js.map +1 -1
  259. package/dist/services/issue-thread-interactions.d.ts +8 -0
  260. package/dist/services/issue-thread-interactions.d.ts.map +1 -1
  261. package/dist/services/issue-thread-interactions.js +220 -10
  262. package/dist/services/issue-thread-interactions.js.map +1 -1
  263. package/dist/services/issues.d.ts +8 -7
  264. package/dist/services/issues.d.ts.map +1 -1
  265. package/dist/services/issues.js +84 -12
  266. package/dist/services/issues.js.map +1 -1
  267. package/dist/services/local-service-supervisor.d.ts +61 -1
  268. package/dist/services/local-service-supervisor.d.ts.map +1 -1
  269. package/dist/services/local-service-supervisor.js +221 -25
  270. package/dist/services/local-service-supervisor.js.map +1 -1
  271. package/dist/services/login-command.d.ts +46 -0
  272. package/dist/services/login-command.d.ts.map +1 -0
  273. package/dist/services/login-command.js +87 -0
  274. package/dist/services/login-command.js.map +1 -0
  275. package/dist/services/login-command.test.d.ts +2 -0
  276. package/dist/services/login-command.test.d.ts.map +1 -0
  277. package/dist/services/login-command.test.js +71 -0
  278. package/dist/services/login-command.test.js.map +1 -0
  279. package/dist/services/managed-workspace-identity.d.ts +140 -0
  280. package/dist/services/managed-workspace-identity.d.ts.map +1 -0
  281. package/dist/services/managed-workspace-identity.js +277 -0
  282. package/dist/services/managed-workspace-identity.js.map +1 -0
  283. package/dist/services/plugin-environment-driver.d.ts +15 -1
  284. package/dist/services/plugin-environment-driver.d.ts.map +1 -1
  285. package/dist/services/plugin-environment-driver.js +23 -1
  286. package/dist/services/plugin-environment-driver.js.map +1 -1
  287. package/dist/services/plugin-host-services.d.ts +3 -2
  288. package/dist/services/plugin-host-services.d.ts.map +1 -1
  289. package/dist/services/plugin-host-services.js +11 -2
  290. package/dist/services/plugin-host-services.js.map +1 -1
  291. package/dist/services/plugin-loader.d.ts.map +1 -1
  292. package/dist/services/plugin-loader.js +39 -8
  293. package/dist/services/plugin-loader.js.map +1 -1
  294. package/dist/services/plugin-managed-agents.d.ts.map +1 -1
  295. package/dist/services/plugin-managed-agents.js +50 -5
  296. package/dist/services/plugin-managed-agents.js.map +1 -1
  297. package/dist/services/plugin-manifest-validator.d.ts.map +1 -1
  298. package/dist/services/plugin-manifest-validator.js +5 -2
  299. package/dist/services/plugin-manifest-validator.js.map +1 -1
  300. package/dist/services/plugin-registry.d.ts +5 -5
  301. package/dist/services/plugin-worker-manager.d.ts +158 -11
  302. package/dist/services/plugin-worker-manager.d.ts.map +1 -1
  303. package/dist/services/plugin-worker-manager.js +1139 -79
  304. package/dist/services/plugin-worker-manager.js.map +1 -1
  305. package/dist/services/projects.d.ts +1 -1
  306. package/dist/services/recovery/disposition-repair.d.ts +24 -0
  307. package/dist/services/recovery/disposition-repair.d.ts.map +1 -0
  308. package/dist/services/recovery/disposition-repair.js +125 -0
  309. package/dist/services/recovery/disposition-repair.js.map +1 -0
  310. package/dist/services/recovery/service.d.ts +6 -6
  311. package/dist/services/recovery/service.d.ts.map +1 -1
  312. package/dist/services/recovery/service.js +856 -384
  313. package/dist/services/recovery/service.js.map +1 -1
  314. package/dist/services/recovery/stranded-notice.js +4 -4
  315. package/dist/services/recovery/stranded-notice.js.map +1 -1
  316. package/dist/services/recovery/stranded-notice.test.js +1 -1
  317. package/dist/services/recovery/stranded-notice.test.js.map +1 -1
  318. package/dist/services/recovery/successful-run-handoff.d.ts +1 -1
  319. package/dist/services/recovery/successful-run-handoff.d.ts.map +1 -1
  320. package/dist/services/recovery/successful-run-handoff.js +6 -4
  321. package/dist/services/recovery/successful-run-handoff.js.map +1 -1
  322. package/dist/services/recovery/successful-run-handoff.test.js +1 -1
  323. package/dist/services/recovery/successful-run-handoff.test.js.map +1 -1
  324. package/dist/services/recovery-observability.d.ts +1 -1
  325. package/dist/services/recovery-observability.d.ts.map +1 -1
  326. package/dist/services/recovery-observability.js +4 -1
  327. package/dist/services/recovery-observability.js.map +1 -1
  328. package/dist/services/routines.d.ts.map +1 -1
  329. package/dist/services/routines.js +86 -1
  330. package/dist/services/routines.js.map +1 -1
  331. package/dist/services/runtime-exposure/loopback-listener.js +1 -1
  332. package/dist/services/runtime-exposure/loopback-listener.js.map +1 -1
  333. package/dist/services/runtime-exposure/loopback-listener.test.js +1 -1
  334. package/dist/services/runtime-exposure/loopback-listener.test.js.map +1 -1
  335. package/dist/services/scripts/codex-auth-read.cjs +93 -0
  336. package/dist/services/secret-proposal-authorization.d.ts +15 -0
  337. package/dist/services/secret-proposal-authorization.d.ts.map +1 -0
  338. package/dist/services/secret-proposal-authorization.js +29 -0
  339. package/dist/services/secret-proposal-authorization.js.map +1 -0
  340. package/dist/services/secret-proposal-notifications.d.ts +18 -0
  341. package/dist/services/secret-proposal-notifications.d.ts.map +1 -0
  342. package/dist/services/secret-proposal-notifications.js +37 -0
  343. package/dist/services/secret-proposal-notifications.js.map +1 -0
  344. package/dist/services/secret-proposals.d.ts +20 -10
  345. package/dist/services/secret-proposals.d.ts.map +1 -1
  346. package/dist/services/secret-proposals.js +205 -14
  347. package/dist/services/secret-proposals.js.map +1 -1
  348. package/dist/services/secrets.d.ts +3 -3
  349. package/dist/services/settings-visibility.d.ts +17 -0
  350. package/dist/services/settings-visibility.d.ts.map +1 -0
  351. package/dist/services/settings-visibility.js +29 -0
  352. package/dist/services/settings-visibility.js.map +1 -0
  353. package/dist/services/setup-token-reaper.d.ts +36 -0
  354. package/dist/services/setup-token-reaper.d.ts.map +1 -0
  355. package/dist/services/setup-token-reaper.js +38 -0
  356. package/dist/services/setup-token-reaper.js.map +1 -0
  357. package/dist/services/setup-token-reaper.test.d.ts +2 -0
  358. package/dist/services/setup-token-reaper.test.d.ts.map +1 -0
  359. package/dist/services/setup-token-reaper.test.js +123 -0
  360. package/dist/services/setup-token-reaper.test.js.map +1 -0
  361. package/dist/services/setup-token-session.d.ts +57 -45
  362. package/dist/services/setup-token-session.d.ts.map +1 -1
  363. package/dist/services/setup-token-session.js +118 -110
  364. package/dist/services/setup-token-session.js.map +1 -1
  365. package/dist/services/setup-token-session.test.js +88 -47
  366. package/dist/services/setup-token-session.test.js.map +1 -1
  367. package/dist/services/setup-token-transport-binding.d.ts +20 -12
  368. package/dist/services/setup-token-transport-binding.d.ts.map +1 -1
  369. package/dist/services/setup-token-transport-binding.js +59 -32
  370. package/dist/services/setup-token-transport-binding.js.map +1 -1
  371. package/dist/services/setup-token-transport-binding.test.js +50 -17
  372. package/dist/services/setup-token-transport-binding.test.js.map +1 -1
  373. package/dist/services/smoke-lab.d.ts +1 -1
  374. package/dist/services/stalled-review-decisions.d.ts +1 -1
  375. package/dist/services/status-cards.d.ts +168 -168
  376. package/dist/services/tool-access-policy.d.ts +2 -2
  377. package/dist/services/tool-gateway.d.ts +1 -1
  378. package/dist/services/work-products.d.ts +19 -0
  379. package/dist/services/work-products.d.ts.map +1 -1
  380. package/dist/services/work-products.js +50 -3
  381. package/dist/services/work-products.js.map +1 -1
  382. package/dist/services/workspace-git-operation-scheduler.test.js +10 -3
  383. package/dist/services/workspace-git-operation-scheduler.test.js.map +1 -1
  384. package/dist/services/workspace-instance-cleanup.d.ts +9 -0
  385. package/dist/services/workspace-instance-cleanup.d.ts.map +1 -1
  386. package/dist/services/workspace-instance-cleanup.js +29 -3
  387. package/dist/services/workspace-instance-cleanup.js.map +1 -1
  388. package/dist/services/workspace-login-handoff-issuer.d.ts +95 -0
  389. package/dist/services/workspace-login-handoff-issuer.d.ts.map +1 -0
  390. package/dist/services/workspace-login-handoff-issuer.js +147 -0
  391. package/dist/services/workspace-login-handoff-issuer.js.map +1 -0
  392. package/dist/services/workspace-operations.d.ts +4 -1
  393. package/dist/services/workspace-operations.d.ts.map +1 -1
  394. package/dist/services/workspace-operations.js +29 -15
  395. package/dist/services/workspace-operations.js.map +1 -1
  396. package/dist/services/workspace-readiness.d.ts +56 -0
  397. package/dist/services/workspace-readiness.d.ts.map +1 -0
  398. package/dist/services/workspace-readiness.js +250 -0
  399. package/dist/services/workspace-readiness.js.map +1 -0
  400. package/dist/services/workspace-realization.d.ts.map +1 -1
  401. package/dist/services/workspace-realization.js +5 -33
  402. package/dist/services/workspace-realization.js.map +1 -1
  403. package/dist/services/workspace-runtime-exposure.test.js +321 -12
  404. package/dist/services/workspace-runtime-exposure.test.js.map +1 -1
  405. package/dist/services/workspace-runtime-leases.d.ts.map +1 -1
  406. package/dist/services/workspace-runtime-leases.js +1 -1
  407. package/dist/services/workspace-runtime-leases.js.map +1 -1
  408. package/dist/services/workspace-runtime-read-model.d.ts +8 -8
  409. package/dist/services/workspace-runtime-read-model.test.js +20 -0
  410. package/dist/services/workspace-runtime-read-model.test.js.map +1 -1
  411. package/dist/services/workspace-runtime-ready-comment.test.js +1 -0
  412. package/dist/services/workspace-runtime-ready-comment.test.js.map +1 -1
  413. package/dist/services/workspace-runtime.d.ts +77 -4
  414. package/dist/services/workspace-runtime.d.ts.map +1 -1
  415. package/dist/services/workspace-runtime.js +1020 -126
  416. package/dist/services/workspace-runtime.js.map +1 -1
  417. package/dist/worktree-config.d.ts.map +1 -1
  418. package/dist/worktree-config.js +3 -76
  419. package/dist/worktree-config.js.map +1 -1
  420. package/dist/worktree-seed-manifest.d.ts +8 -0
  421. package/dist/worktree-seed-manifest.d.ts.map +1 -0
  422. package/dist/worktree-seed-manifest.js +47 -0
  423. package/dist/worktree-seed-manifest.js.map +1 -0
  424. package/package.json +34 -30
  425. package/skills/paperclip/SKILL.md +2 -0
  426. package/skills/paperclip/references/api-reference.md +44 -2
  427. package/ui-dist/assets/CompanyExport-DnEsO-St.js +4 -0
  428. package/ui-dist/assets/{abnfDiagram-N423BO3Z-BvgoV-u5.js → abnfDiagram-N423BO3Z-2ff8TsQ0.js} +1 -1
  429. package/ui-dist/assets/{arc-BInnUBUU.js → arc-B2AXsH34.js} +1 -1
  430. package/ui-dist/assets/architectureDiagram-T3A2C74G-BDxtKMxk.js +36 -0
  431. package/ui-dist/assets/{blockDiagram-VBNYF7ZC-D9kzAkLN.js → blockDiagram-VBNYF7ZC-BB8T5Mj5.js} +1 -1
  432. package/ui-dist/assets/{c4Diagram-5PPSVZJV-BwzsgV_0.js → c4Diagram-5PPSVZJV-lMo8qk-x.js} +1 -1
  433. package/ui-dist/assets/channel-DCTVZpyq.js +1 -0
  434. package/ui-dist/assets/{chunk-2GRJ4B5K-D2EQ9vrl.js → chunk-2GRJ4B5K-CsS7EB3G.js} +1 -1
  435. package/ui-dist/assets/{chunk-2Q5K7J3B-DOA_8fSd.js → chunk-2Q5K7J3B-DFyQPjoR.js} +1 -1
  436. package/ui-dist/assets/{chunk-5RXB4S5H-CT5ukRiT.js → chunk-5RXB4S5H-No2SHOQR.js} +1 -1
  437. package/ui-dist/assets/{chunk-5VM5RSS4-D2gOlkyB.js → chunk-5VM5RSS4-DdxQO7V9.js} +1 -1
  438. package/ui-dist/assets/{chunk-6Q2QTUOP-DUb6aG8c.js → chunk-6Q2QTUOP-gbHjh-aK.js} +1 -1
  439. package/ui-dist/assets/{chunk-GF5L2VYU-BPabG3Cx.js → chunk-GF5L2VYU-h-BBl6NY.js} +1 -1
  440. package/ui-dist/assets/{chunk-JWPE2WC7-scNfhlZz.js → chunk-JWPE2WC7-Q3pJdTz5.js} +1 -1
  441. package/ui-dist/assets/{chunk-KBJHAD2P-BcRAzRpq.js → chunk-KBJHAD2P-Ba8LGLSx.js} +1 -1
  442. package/ui-dist/assets/{chunk-RYQCIY6F-BiZ0-EGh.js → chunk-RYQCIY6F-9VcvykBo.js} +1 -1
  443. package/ui-dist/assets/{chunk-XXDRQBXY-lJULxFIE.js → chunk-XXDRQBXY-NVbjDH4W.js} +1 -1
  444. package/ui-dist/assets/classDiagram-JCYQIIEL-CzJ88u6h.js +1 -0
  445. package/ui-dist/assets/classDiagram-v2-OCEON4UE-CzJ88u6h.js +1 -0
  446. package/ui-dist/assets/cose-bilkent-JH36ORCC-Cdz4wtUh.js +1 -0
  447. package/ui-dist/assets/{cynefin-VYW2F7L2-B34jJY1x.js → cynefin-VYW2F7L2-MpzJkW5s.js} +1 -1
  448. package/ui-dist/assets/{cynefinDiagram-MW4NZA55-DQ8QK8JK.js → cynefinDiagram-MW4NZA55-_Nx8av7i.js} +1 -1
  449. package/ui-dist/assets/{dagre-VZM6K2ZE-B7lSKgxH.js → dagre-VZM6K2ZE-DcZTQ4Oh.js} +1 -1
  450. package/ui-dist/assets/{diagram-7IWD3JNH-B3hLAFGE.js → diagram-7IWD3JNH-UyLi2mee.js} +1 -1
  451. package/ui-dist/assets/{diagram-B4RE2ZJO-CH9Ro9e0.js → diagram-B4RE2ZJO-B6p0Ivqg.js} +1 -1
  452. package/ui-dist/assets/{diagram-LBJQPF4R-DdPVMii7.js → diagram-LBJQPF4R-C8u6pa97.js} +1 -1
  453. package/ui-dist/assets/{diagram-Q27KOJAE-f5VXswjc.js → diagram-Q27KOJAE-DbwyagW0.js} +1 -1
  454. package/ui-dist/assets/{diagram-UB23O5K3-DGqxixsR.js → diagram-UB23O5K3-Cn5BMEH7.js} +1 -1
  455. package/ui-dist/assets/{ebnfDiagram-BXEA7PRR-C-1klg_w.js → ebnfDiagram-BXEA7PRR-vE0IZma9.js} +1 -1
  456. package/ui-dist/assets/{erDiagram-JOGREHBK-Dt4qK4gv.js → erDiagram-JOGREHBK-3OZVIlVG.js} +1 -1
  457. package/ui-dist/assets/{flowDiagram-UKHOOZJN-9ZlrTuET.js → flowDiagram-UKHOOZJN-C94FiPyr.js} +1 -1
  458. package/ui-dist/assets/ganttDiagram-PKOTCBZU-DMVaPmF-.js +292 -0
  459. package/ui-dist/assets/{gitGraphDiagram-DS77QQ5N-HH2fSgad.js → gitGraphDiagram-DS77QQ5N-yeFtJ689.js} +1 -1
  460. package/ui-dist/assets/{index-Cm6iEYPt.js → index-B4ZF3vY8.js} +288 -224
  461. package/ui-dist/assets/{index-CHXG4GPL.js → index-Bi_vqkcQ.js} +1 -1
  462. package/ui-dist/assets/{index-Bc9g6q63.js → index-BjDGQg9-.js} +1 -1
  463. package/ui-dist/assets/{index-FHzrJ7iQ.js → index-BnpyUMTb.js} +1 -1
  464. package/ui-dist/assets/{index-C1mpWCcn.js → index-BoqQTVMA.js} +1 -1
  465. package/ui-dist/assets/index-Bq-Mr-4x.js +1 -0
  466. package/ui-dist/assets/{index-DceuCrr8.js → index-Brb2U7N4.js} +1 -1
  467. package/ui-dist/assets/{index-DQIrrn2L.js → index-BsBybVwH.js} +1 -1
  468. package/ui-dist/assets/{index-CQhaM6qd.js → index-C2iv4Wgu.js} +1 -1
  469. package/ui-dist/assets/{index-DV2FOgyD.js → index-CKxIu7uO.js} +1 -1
  470. package/ui-dist/assets/{index-DU4U1fuv.js → index-Cb4VGIwp.js} +1 -1
  471. package/ui-dist/assets/{index-B61ORkIb.js → index-ChpszwcO.js} +1 -1
  472. package/ui-dist/assets/{index-DlVBBF8o.js → index-CoQFdT8N.js} +1 -1
  473. package/ui-dist/assets/index-D6P8_f0W.css +1 -0
  474. package/ui-dist/assets/index-DKdmghUG.js +1 -0
  475. package/ui-dist/assets/{index-CVTL3aAL.js → index-DaBci7Bx.js} +1 -1
  476. package/ui-dist/assets/{index-diFs0CNC.js → index-DjYaNiXZ.js} +1 -1
  477. package/ui-dist/assets/{index-Bf7tyGxE.js → index-DxTBJl4h.js} +1 -1
  478. package/ui-dist/assets/{index-DsdVneqe.js → index-Dz3E8nn0.js} +1 -1
  479. package/ui-dist/assets/{index-DvFUXI-Q.js → index-J7dz_hap.js} +1 -1
  480. package/ui-dist/assets/{index-CLu3Tfpv.js → index-JMp2Gpnz.js} +1 -1
  481. package/ui-dist/assets/{index-CcRTJ93J.js → index-Kp6wavQt.js} +1 -1
  482. package/ui-dist/assets/{index-BvFx-4KW.js → index-LBhYZ0L4.js} +1 -1
  483. package/ui-dist/assets/{index-BbAhzCq8.js → index-c3C0P6l8.js} +4 -4
  484. package/ui-dist/assets/{index-BY5ITKmG.js → index-pBEPheTW.js} +1 -1
  485. package/ui-dist/assets/{infoDiagram-6WML65LV-2jai2fw-.js → infoDiagram-6WML65LV-BiL7jKLA.js} +1 -1
  486. package/ui-dist/assets/{ishikawaDiagram-WSZJBQD7-CUmGhmEb.js → ishikawaDiagram-WSZJBQD7-DYcQy41D.js} +1 -1
  487. package/ui-dist/assets/{journeyDiagram-NVQOT4AX-CGQuPDO1.js → journeyDiagram-NVQOT4AX-Bxva6JgA.js} +1 -1
  488. package/ui-dist/assets/{kanban-definition-27J2QSJJ-zgEPcbHl.js → kanban-definition-27J2QSJJ-B2HpN34Q.js} +1 -1
  489. package/ui-dist/assets/{linear-BVf5VtLS.js → linear-Dq8qSESw.js} +1 -1
  490. package/ui-dist/assets/{mermaid.core-D2TFkGfI.js → mermaid.core-Ikay8Cpl.js} +35 -35
  491. package/ui-dist/assets/{mindmap-definition-FAOFIHXS-xoAQ0Lb_.js → mindmap-definition-FAOFIHXS-C-SIdYSY.js} +1 -1
  492. package/ui-dist/assets/{pegDiagram-VL7TDLO6-CBR1PWLr.js → pegDiagram-VL7TDLO6-C7rIJ_13.js} +1 -1
  493. package/ui-dist/assets/{pieDiagram-7S7Q4E2Y-BMPnzK_e.js → pieDiagram-7S7Q4E2Y-3gx0a0ve.js} +1 -1
  494. package/ui-dist/assets/{quadrantDiagram-CIZ2JOQS-CPtVUPkR.js → quadrantDiagram-CIZ2JOQS-BiwM9QGv.js} +1 -1
  495. package/ui-dist/assets/{railroadDiagram-AXF67PYL-DC0lsZV1.js → railroadDiagram-AXF67PYL-rFS8XcFA.js} +1 -1
  496. package/ui-dist/assets/{requirementDiagram-LRYGKXZP-BF6k05SB.js → requirementDiagram-LRYGKXZP-CEAUDUTQ.js} +1 -1
  497. package/ui-dist/assets/{sankeyDiagram-W5VNT64P-CRN0ibiP.js → sankeyDiagram-W5VNT64P-B7anpjlM.js} +1 -1
  498. package/ui-dist/assets/{sequenceDiagram-SI44F4Z6-CQtTiPWm.js → sequenceDiagram-SI44F4Z6-CJEdJvm_.js} +1 -1
  499. package/ui-dist/assets/{sizeCapture-X5ZJPWSS-BdjuGZd1.js → sizeCapture-X5ZJPWSS-CU1Vm6c1.js} +1 -1
  500. package/ui-dist/assets/{stateDiagram-OKZ733FA-B99onxyh.js → stateDiagram-OKZ733FA-wxVV9WIi.js} +1 -1
  501. package/ui-dist/assets/stateDiagram-v2-UEYNNEHI-BIFLqlqR.js +1 -0
  502. package/ui-dist/assets/{swimlanes-SLNWSIFB-BIByPbrL.js → swimlanes-SLNWSIFB-Cd-C1Z_k.js} +2 -2
  503. package/ui-dist/assets/swimlanesDiagram-ULZ7WXOC-CoBROkkd.js +8 -0
  504. package/ui-dist/assets/{timeline-definition-Z64GVDOM-I1NgOcn9.js → timeline-definition-Z64GVDOM-SWngk4aR.js} +1 -1
  505. package/ui-dist/assets/{vennDiagram-T6HMQDX7-D6t2Njcl.js → vennDiagram-T6HMQDX7-DFdPUr36.js} +1 -1
  506. package/ui-dist/assets/{wardleyDiagram-T6FBY63Y-BiYKm9gh.js → wardleyDiagram-T6FBY63Y-C6IlrZ7t.js} +1 -1
  507. package/ui-dist/assets/{xychartDiagram-ELKLHX3M-BhwXKWIa.js → xychartDiagram-ELKLHX3M-BNm6hHGl.js} +1 -1
  508. package/ui-dist/index.html +2 -2
  509. package/ui-dist/assets/architectureDiagram-T3A2C74G-Dg4MziOm.js +0 -36
  510. package/ui-dist/assets/channel-qoSYbCn0.js +0 -1
  511. package/ui-dist/assets/classDiagram-JCYQIIEL-B24u1REs.js +0 -1
  512. package/ui-dist/assets/classDiagram-v2-OCEON4UE-B24u1REs.js +0 -1
  513. package/ui-dist/assets/cose-bilkent-JH36ORCC-Do8pe8JB.js +0 -1
  514. package/ui-dist/assets/ganttDiagram-PKOTCBZU-CE3lyvFq.js +0 -292
  515. package/ui-dist/assets/index-BHiUiToL.css +0 -1
  516. package/ui-dist/assets/index-hkanj4t6.js +0 -1
  517. package/ui-dist/assets/index-yRJnh4vx.js +0 -1
  518. package/ui-dist/assets/stateDiagram-v2-UEYNNEHI-bzFlYBZ1.js +0 -1
  519. package/ui-dist/assets/swimlanesDiagram-ULZ7WXOC-DgdkBnuK.js +0 -8
@@ -1,7 +1,12 @@
1
+ import { spawn } from "node:child_process";
2
+ import { accessSync, constants as fsConstants, existsSync, readFileSync } from "node:fs";
3
+ import path from "node:path";
1
4
  import { and, eq } from "drizzle-orm";
2
5
  import { Router } from "express";
3
6
  import { issues, projects, projectWorkspaces } from "@paperclipai/db";
4
7
  import { findWorkspaceCommandDefinition, matchWorkspaceRuntimeServiceToCommand, reconcileExecutionWorkspaceBranchSchema, updateExecutionWorkspaceSchema, workspaceOverviewQuerySchema, workspaceRuntimeControlTargetSchema, } from "@paperclipai/shared";
8
+ import { baseWorkspaceDeclaresInstanceConfig, resolveCanonicalWorktreeSeedSource, } from "@paperclipai/shared/worktree-seed-source";
9
+ import { resolvePaperclipConfigPath } from "../paths.js";
5
10
  import { validate } from "../middleware/validate.js";
6
11
  import { accessService, executionWorkspaceService, heartbeatService, logActivity, workspaceOperationService, workspaceRuntimeLeaseService, LEASED_WORKSPACE_RUNTIME_ACTIONS, } from "../services/index.js";
7
12
  import { mergeExecutionWorkspaceConfig, readExecutionWorkspaceConfig } from "../services/execution-workspaces.js";
@@ -15,7 +20,29 @@ import { assertCanManageExecutionWorkspaceRuntimeServices } from "./workspace-ru
15
20
  import { appendWithCap } from "../adapters/utils.js";
16
21
  import { environmentRuntimeService } from "../services/environment-runtime.js";
17
22
  import { runExclusiveWorkspaceRuntimeControl } from "../services/workspace-operations.js";
23
+ import { resolveManagedWorkspaceInstanceId } from "../services/managed-workspace-identity.js";
24
+ import { isVerifiedWorktreeSeedManifest } from "../worktree-seed-manifest.js";
25
+ import { issueWorkspaceLoginHandoff, workspaceLoginHandoffFailureStatus, } from "../services/workspace-login-handoff-issuer.js";
26
+ import { conflict, unprocessable } from "../errors.js";
18
27
  const WORKSPACE_CONTROL_OUTPUT_MAX_CHARS = 256 * 1024;
28
+ function isReadableFile(filePath) {
29
+ try {
30
+ accessSync(filePath, fsConstants.R_OK);
31
+ return true;
32
+ }
33
+ catch {
34
+ return false;
35
+ }
36
+ }
37
+ /**
38
+ * The control plane's own instance config, named as the seed source only when the base
39
+ * project workspace is a plain checkout carrying no instance config of its own. A base
40
+ * workspace that has one stays authoritative, so an operator's mismatched source is
41
+ * still rejected.
42
+ */
43
+ function resolveFallbackSeedSourceConfigPath(baseWorkspaceCwd) {
44
+ return baseWorkspaceDeclaresInstanceConfig(baseWorkspaceCwd) ? null : resolvePaperclipConfigPath();
45
+ }
19
46
  export function executionWorkspaceRoutes(db, opts = {}) {
20
47
  const router = Router();
21
48
  const svc = executionWorkspaceService(db);
@@ -106,6 +133,81 @@ export function executionWorkspaceRoutes(db, opts = {}) {
106
133
  }
107
134
  res.json(readiness);
108
135
  });
136
+ /**
137
+ * Mint a single-use workspace login handoff for the calling board user.
138
+ *
139
+ * Board-only: the ticket carries a user identity, so an agent key — which has
140
+ * no user to sign in — must never be able to mint one. Nothing in the request
141
+ * body influences what the ticket is bound to; only the landing path is taken
142
+ * from the caller, and it is reduced to a same-origin path before signing.
143
+ */
144
+ router.post("/execution-workspaces/:id/login-handoff", async (req, res) => {
145
+ const id = req.params.id;
146
+ assertBoard(req);
147
+ const workspace = await getAccessibleResource(req, res, svc.getById(id), "Execution workspace not found");
148
+ if (!workspace)
149
+ return;
150
+ // Opening a workspace board is a runtime-control-grade action: it hands the
151
+ // caller an authenticated session inside the cloned instance.
152
+ if (!(await assertRuntimeManageAllowed(req, res, workspace.companyId)))
153
+ return;
154
+ const requestedNext = typeof req.body?.next === "string"
155
+ ? req.body.next
156
+ : null;
157
+ const result = await issueWorkspaceLoginHandoff({
158
+ db,
159
+ companyId: workspace.companyId,
160
+ executionWorkspace: { id: workspace.id, cwd: workspace.cwd },
161
+ actor: {
162
+ userId: req.actor.userId ?? null,
163
+ userEmail: req.actor.userEmail ?? null,
164
+ source: req.actor.source ?? null,
165
+ },
166
+ next: requestedNext,
167
+ });
168
+ if (!result.ok) {
169
+ logger.warn({
170
+ executionWorkspaceId: workspace.id,
171
+ reason: result.failure.reason,
172
+ detail: "detail" in result.failure ? result.failure.detail : null,
173
+ }, "workspace login handoff was not issued");
174
+ res.status(workspaceLoginHandoffFailureStatus(result.failure)).json({
175
+ error: "workspace_login_handoff_unavailable",
176
+ // The UI turns this into the labeled snapshot-local credential fallback
177
+ // or a repair prompt, so the machine reason has to survive the boundary.
178
+ reason: result.failure.reason,
179
+ mode: "credentials",
180
+ ...("detail" in result.failure ? { detail: result.failure.detail } : {}),
181
+ ...("readiness" in result.failure ? { readiness: result.failure.readiness } : {}),
182
+ });
183
+ return;
184
+ }
185
+ await logActivity(db, {
186
+ companyId: workspace.companyId,
187
+ // Auditing issuance is a requirement of the handoff design: the nonce ties
188
+ // this record to the guest's own accept/reject record. The ticket itself is
189
+ // never recorded.
190
+ action: "workspace_login_handoff_issued",
191
+ entityType: "execution_workspace",
192
+ entityId: workspace.id,
193
+ actorType: "user",
194
+ actorId: result.issuance.userId,
195
+ details: {
196
+ nonce: result.issuance.nonce,
197
+ instanceId: result.issuance.instanceId,
198
+ origin: result.issuance.origin,
199
+ expiresAt: result.issuance.expiresAt,
200
+ },
201
+ }).catch((error) => {
202
+ logger.warn({ err: error, executionWorkspaceId: workspace.id }, "failed to audit workspace login handoff");
203
+ });
204
+ res.setHeader("Cache-Control", "no-store");
205
+ res.status(201).json({
206
+ url: result.issuance.url,
207
+ expiresAt: result.issuance.expiresAt,
208
+ mode: "handoff",
209
+ });
210
+ });
109
211
  router.get("/execution-workspaces/:id/workspace-operations", async (req, res) => {
110
212
  const id = req.params.id;
111
213
  const workspace = await getAccessibleResource(req, res, svc.getById(id), "Execution workspace not found");
@@ -119,7 +221,7 @@ export function executionWorkspaceRoutes(db, opts = {}) {
119
221
  async function handleExecutionWorkspaceRuntimeCommand(req, res) {
120
222
  const id = req.params.id;
121
223
  const action = String(req.params.action ?? "").trim().toLowerCase();
122
- if (action !== "start" && action !== "stop" && action !== "restart" && action !== "run") {
224
+ if (action !== "start" && action !== "stop" && action !== "restart" && action !== "repair" && action !== "run") {
123
225
  res.status(404).json({ error: "Workspace command action not found" });
124
226
  return;
125
227
  }
@@ -133,13 +235,6 @@ export function executionWorkspaceRoutes(db, opts = {}) {
133
235
  executionWorkspaceId: existing.id,
134
236
  sourceIssueId: existing.sourceIssueId,
135
237
  });
136
- // Recover any managed runtime-control operation this workspace was stranded with, then
137
- // refuse only if one is genuinely still live. Authorization above still gates the caller,
138
- // so recovery never widens who may control the workspace.
139
- await workspaceOperationsSvc.assertRuntimeControlAvailable({
140
- executionWorkspaceId: existing.id,
141
- action,
142
- });
143
238
  const workspaceCwd = existing.cwd;
144
239
  if (!workspaceCwd) {
145
240
  res.status(422).json({ error: "Execution workspace needs a local path before Paperclip can run workspace commands" });
@@ -156,7 +251,7 @@ export function executionWorkspaceRoutes(db, opts = {}) {
156
251
  metadata: projectWorkspaces.metadata,
157
252
  })
158
253
  .from(projectWorkspaces)
159
- .where(and(eq(projectWorkspaces.id, existing.projectWorkspaceId), eq(projectWorkspaces.companyId, existing.companyId)))
254
+ .where(and(eq(projectWorkspaces.id, existing.projectWorkspaceId), eq(projectWorkspaces.companyId, existing.companyId), eq(projectWorkspaces.projectId, existing.projectId)))
160
255
  .then((rows) => rows[0] ?? null)
161
256
  : null;
162
257
  const projectWorkspaceRuntime = readProjectWorkspaceRuntimeConfig(projectWorkspace?.metadata ?? null)?.workspaceRuntime ?? null;
@@ -174,6 +269,7 @@ export function executionWorkspaceRoutes(db, opts = {}) {
174
269
  const configuredServices = effectiveRuntimeConfig
175
270
  ? listConfiguredRuntimeServiceEntries({ workspaceRuntime: effectiveRuntimeConfig })
176
271
  : [];
272
+ const repairRestartsRuntimeServices = action === "repair" && configuredServices.length > 0;
177
273
  const workspaceCommand = effectiveRuntimeConfig
178
274
  ? findWorkspaceCommandDefinition(effectiveRuntimeConfig, target.workspaceCommandId ?? null)
179
275
  : null;
@@ -214,6 +310,70 @@ export function executionWorkspaceRoutes(db, opts = {}) {
214
310
  res.status(422).json({ error: "Execution workspace has no workspace command configuration or inherited project workspace default" });
215
311
  return;
216
312
  }
313
+ let repairSeedSource = null;
314
+ let repairPreviousAttemptId = null;
315
+ let repairCliArgs = null;
316
+ if (action === "repair") {
317
+ const manifestPath = path.join(workspaceCwd, ".paperclip", "seed-manifest.json");
318
+ let manifest;
319
+ try {
320
+ manifest = JSON.parse(readFileSync(manifestPath, "utf8"));
321
+ }
322
+ catch {
323
+ throw unprocessable("Workspace seed manifest is malformed; repair source identity cannot be trusted.", {
324
+ code: "workspace_repair_precondition_failed",
325
+ reason: "seed_manifest_malformed",
326
+ repairPhase: "precondition_validation",
327
+ });
328
+ }
329
+ try {
330
+ if (!projectWorkspace?.cwd) {
331
+ throw new Error("Workspace repair requires a registered base project workspace.");
332
+ }
333
+ const expectedTargetInstanceId = resolveManagedWorkspaceInstanceId(workspaceCwd);
334
+ if (!expectedTargetInstanceId) {
335
+ throw new Error("Workspace repair cannot resolve the registered target instance.");
336
+ }
337
+ repairSeedSource = resolveCanonicalWorktreeSeedSource({
338
+ registeredBaseWorkspaceCwd: projectWorkspace.cwd,
339
+ explicitSourceConfigPath: resolveFallbackSeedSourceConfigPath(projectWorkspace.cwd),
340
+ targetConfigPath: path.join(workspaceCwd, ".paperclip", "config.json"),
341
+ expectedTargetInstanceId,
342
+ manifestSource: manifest.source,
343
+ manifestTargetInstanceId: manifest.targetInstanceId,
344
+ });
345
+ repairPreviousAttemptId = typeof manifest.attemptId === "string" ? manifest.attemptId : null;
346
+ const baseWorkspaceCwd = repairSeedSource.baseWorkspaceCwd;
347
+ if (!baseWorkspaceCwd) {
348
+ throw new Error("Workspace repair source is not bound to a registered base project workspace.");
349
+ }
350
+ const cliRunner = path.join(baseWorkspaceCwd, "cli", "node_modules", "tsx", "dist", "cli.mjs");
351
+ const cliEntry = path.join(baseWorkspaceCwd, "cli", "src", "index.ts");
352
+ const cliDist = path.join(baseWorkspaceCwd, "cli", "dist", "index.js");
353
+ repairCliArgs = isReadableFile(cliRunner) && isReadableFile(cliEntry)
354
+ ? [cliRunner, cliEntry]
355
+ : isReadableFile(cliDist)
356
+ ? [cliDist]
357
+ : null;
358
+ if (!repairCliArgs) {
359
+ throw new Error("Workspace repair cannot find a runnable Paperclip CLI in the base workspace.");
360
+ }
361
+ }
362
+ catch (error) {
363
+ throw unprocessable(error instanceof Error ? error.message : "Workspace repair source validation failed.", {
364
+ code: "workspace_repair_precondition_failed",
365
+ reason: "source_registration_invalid",
366
+ repairPhase: "precondition_validation",
367
+ });
368
+ }
369
+ }
370
+ // This check can reconcile a stale operation row, so repair source validation must
371
+ // precede it. Invalid manifest diagnostics must fail before any operation or service
372
+ // mutation, not merely before the reseed child process is spawned.
373
+ await workspaceOperationsSvc.assertRuntimeControlAvailable({
374
+ executionWorkspaceId: existing.id,
375
+ action,
376
+ });
217
377
  const actor = getActorInfo(req);
218
378
  const recorder = workspaceOperationsSvc.createRecorder({
219
379
  companyId: existing.companyId,
@@ -268,7 +428,11 @@ export function executionWorkspaceRoutes(db, opts = {}) {
268
428
  }
269
429
  }
270
430
  const recordRuntimeControlOperation = () => recorder.recordOperation({
271
- phase: action === "stop" ? "workspace_teardown" : "workspace_provision",
431
+ phase: action === "stop"
432
+ ? "workspace_teardown"
433
+ : action === "repair"
434
+ ? "workspace_repair"
435
+ : "workspace_provision",
272
436
  command: workspaceCommand?.command ?? `workspace command ${action}`,
273
437
  cwd: existing.cwd,
274
438
  metadata: {
@@ -280,7 +444,7 @@ export function executionWorkspaceRoutes(db, opts = {}) {
280
444
  runtimeServiceId: selectedRuntimeServiceId,
281
445
  serviceIndex: selectedServiceIndex,
282
446
  },
283
- run: async () => {
447
+ run: async (reportProgress) => {
284
448
  const ensureWorkspaceAvailable = async () => await ensurePersistedExecutionWorkspaceAvailable({
285
449
  base: {
286
450
  baseCwd: projectWorkspace?.cwd ?? workspaceCwd,
@@ -367,7 +531,203 @@ export function executionWorkspaceRoutes(db, opts = {}) {
367
531
  else
368
532
  stderr = appendWithCap(stderr, chunk, WORKSPACE_CONTROL_OUTPUT_MAX_CHARS);
369
533
  };
370
- if (action === "stop" || action === "restart") {
534
+ if (action === "repair") {
535
+ const repairDiagnostics = [];
536
+ let repairPhase = "managed_stop";
537
+ const repairPreconditionError = (status, reason, message) => {
538
+ const details = {
539
+ code: "workspace_repair_precondition_failed",
540
+ reason,
541
+ repairPhase,
542
+ };
543
+ return status === 409
544
+ ? conflict(message, details)
545
+ : unprocessable(message, details);
546
+ };
547
+ const reportRepairPhase = async (phase, status) => {
548
+ repairPhase = phase;
549
+ repairDiagnostics.push({ phase, status, at: new Date().toISOString() });
550
+ if (repairDiagnostics.length > 32)
551
+ repairDiagnostics.splice(0, repairDiagnostics.length - 32);
552
+ await reportProgress({
553
+ metadata: {
554
+ repairPhase,
555
+ repairDiagnostics: [...repairDiagnostics],
556
+ databaseOnly: true,
557
+ worktreePreserved: true,
558
+ },
559
+ system: `Workspace repair ${phase}: ${status}.\n`,
560
+ });
561
+ };
562
+ try {
563
+ await reportRepairPhase("managed_stop", "started");
564
+ await stopRuntimeServicesForExecutionWorkspace({
565
+ db,
566
+ executionWorkspaceId: existing.id,
567
+ workspaceCwd,
568
+ });
569
+ await reportRepairPhase("managed_stop", "succeeded");
570
+ if (!repairSeedSource?.baseWorkspaceCwd || !repairCliArgs) {
571
+ throw new Error("Workspace repair source preflight did not complete.");
572
+ }
573
+ const manifestPath = path.join(workspaceCwd, ".paperclip", "seed-manifest.json");
574
+ const sourceConfigPath = repairSeedSource.configPath;
575
+ const baseWorkspaceCwd = repairSeedSource.baseWorkspaceCwd;
576
+ await reportRepairPhase("target_backup", "started");
577
+ const child = spawn(process.execPath, [
578
+ ...repairCliArgs,
579
+ "worktree",
580
+ "reseed",
581
+ "--from-config",
582
+ sourceConfigPath,
583
+ "--to",
584
+ workspaceCwd,
585
+ "--seed-mode",
586
+ "full",
587
+ "--yes",
588
+ "--backup-target",
589
+ ], {
590
+ cwd: baseWorkspaceCwd,
591
+ env: {
592
+ ...process.env,
593
+ PAPERCLIP_SEED_EXPECTED_COMPANY_ID: existing.companyId,
594
+ PAPERCLIP_WORKSPACE_BASE_CWD: baseWorkspaceCwd,
595
+ PAPERCLIP_PROJECT_WORKSPACE_ID: existing.projectWorkspaceId ?? "",
596
+ },
597
+ stdio: ["ignore", "pipe", "pipe"],
598
+ });
599
+ child.stdout?.on("data", (chunk) => {
600
+ void onLog("stdout", chunk.toString("utf8"));
601
+ });
602
+ child.stderr?.on("data", (chunk) => {
603
+ void onLog("stderr", chunk.toString("utf8"));
604
+ });
605
+ let repairCommandTimedOut = false;
606
+ let repairCommandForceTimeout = null;
607
+ const repairCommandTimeout = setTimeout(() => {
608
+ repairCommandTimedOut = true;
609
+ child.kill("SIGTERM");
610
+ repairCommandForceTimeout = setTimeout(() => child.kill("SIGKILL"), 5_000);
611
+ repairCommandForceTimeout.unref?.();
612
+ }, 20 * 60_000);
613
+ repairCommandTimeout.unref?.();
614
+ let reseedObserved = false;
615
+ const manifestPoll = setInterval(() => {
616
+ if (reseedObserved || !existsSync(manifestPath))
617
+ return;
618
+ try {
619
+ const current = JSON.parse(readFileSync(manifestPath, "utf8"));
620
+ if (typeof current.attemptId === "string"
621
+ && current.attemptId !== repairPreviousAttemptId
622
+ && (current.state === "pending" || current.state === "running" || current.state === "failed")) {
623
+ reseedObserved = true;
624
+ }
625
+ }
626
+ catch {
627
+ // The atomic manifest writer makes this unlikely; the terminal
628
+ // read below remains authoritative.
629
+ }
630
+ }, 100);
631
+ manifestPoll.unref?.();
632
+ const exitCode = await new Promise((resolve, reject) => {
633
+ child.once("error", reject);
634
+ child.once("exit", (code) => resolve(code ?? 1));
635
+ }).finally(() => {
636
+ clearInterval(manifestPoll);
637
+ clearTimeout(repairCommandTimeout);
638
+ if (repairCommandForceTimeout)
639
+ clearTimeout(repairCommandForceTimeout);
640
+ });
641
+ if (reseedObserved) {
642
+ await reportRepairPhase("target_backup", "succeeded");
643
+ await reportRepairPhase("full_reseed", "started");
644
+ }
645
+ if (exitCode !== 0) {
646
+ let seedFailurePhase = null;
647
+ try {
648
+ const failedManifest = JSON.parse(readFileSync(manifestPath, "utf8"));
649
+ seedFailurePhase = failedManifest.state === "failed" && typeof failedManifest.phase === "string"
650
+ ? failedManifest.phase
651
+ : null;
652
+ }
653
+ catch {
654
+ // The outer repair phase remains exact when no seed phase was persisted.
655
+ }
656
+ await reportProgress({
657
+ metadata: { seedFailurePhase },
658
+ system: seedFailurePhase ? `Workspace seed failed during ${seedFailurePhase}.\n` : null,
659
+ });
660
+ throw new Error(repairCommandTimedOut
661
+ ? `Workspace database repair command timed out during ${repairPhase}.`
662
+ : `Workspace database repair command failed during ${repairPhase}.`);
663
+ }
664
+ if (!reseedObserved) {
665
+ await reportRepairPhase("target_backup", "succeeded");
666
+ await reportRepairPhase("full_reseed", "started");
667
+ }
668
+ const manifest = JSON.parse(readFileSync(manifestPath, "utf8"));
669
+ if (!isVerifiedWorktreeSeedManifest(manifest)) {
670
+ throw new Error("Workspace reseed returned without a verified terminal manifest.");
671
+ }
672
+ const expectedInstanceId = resolveManagedWorkspaceInstanceId(workspaceCwd);
673
+ if (manifest.targetInstanceId !== expectedInstanceId) {
674
+ throw repairPreconditionError(422, "seed_manifest_instance_mismatch", "Verified seed manifest belongs to a different workspace instance.");
675
+ }
676
+ resolveCanonicalWorktreeSeedSource({
677
+ registeredBaseWorkspaceCwd: baseWorkspaceCwd,
678
+ explicitSourceConfigPath: resolveFallbackSeedSourceConfigPath(baseWorkspaceCwd),
679
+ targetConfigPath: path.join(workspaceCwd, ".paperclip", "config.json"),
680
+ expectedTargetInstanceId: repairSeedSource.targetInstanceId,
681
+ manifestSource: manifest.source,
682
+ manifestTargetInstanceId: manifest.targetInstanceId,
683
+ });
684
+ await reportRepairPhase("full_reseed", "succeeded");
685
+ await reportRepairPhase("managed_restart", "started");
686
+ let startedServices = [];
687
+ if (repairRestartsRuntimeServices) {
688
+ const availableWorkspace = await ensureWorkspaceAvailable();
689
+ if (!availableWorkspace) {
690
+ throw new Error("Execution workspace needs a local path before Paperclip can restart it.");
691
+ }
692
+ startedServices = await startRuntimeServicesForWorkspaceControl({
693
+ db,
694
+ actor: {
695
+ id: actor.agentId ?? null,
696
+ name: actor.actorType === "user" ? "Board" : "Agent",
697
+ companyId: existing.companyId,
698
+ },
699
+ issue: existing.sourceIssueId
700
+ ? { id: existing.sourceIssueId, identifier: null, title: existing.name }
701
+ : null,
702
+ workspace: availableWorkspace,
703
+ executionWorkspaceId: existing.id,
704
+ config: {
705
+ workspaceRuntime: effectiveRuntimeConfig,
706
+ runtimeProvisionCommand: existing.config?.runtimeProvisionCommand
707
+ ?? projectPolicy?.workspaceStrategy?.runtimeProvisionCommand
708
+ ?? null,
709
+ },
710
+ adapterEnv: {},
711
+ onLog,
712
+ recorder,
713
+ });
714
+ }
715
+ runtimeServiceCount = startedServices.length;
716
+ await reportRepairPhase("managed_restart", "succeeded");
717
+ await reportRepairPhase("readiness_validation", "started");
718
+ if (repairRestartsRuntimeServices
719
+ && (startedServices.length === 0
720
+ || startedServices.some((service) => service.status !== "running" || service.healthStatus !== "healthy"))) {
721
+ throw new Error("Managed restart did not produce healthy runtime services.");
722
+ }
723
+ await reportRepairPhase("readiness_validation", "succeeded");
724
+ }
725
+ catch (error) {
726
+ await reportRepairPhase(repairPhase, "failed");
727
+ throw error;
728
+ }
729
+ }
730
+ else if (action === "stop" || action === "restart") {
371
731
  await stopRuntimeServicesForExecutionWorkspace({
372
732
  db,
373
733
  executionWorkspaceId: existing.id,
@@ -419,7 +779,7 @@ export function executionWorkspaceRoutes(db, opts = {}) {
419
779
  }
420
780
  runtimeServiceCount = startedServices.length;
421
781
  }
422
- else {
782
+ else if (action !== "repair") {
423
783
  runtimeServiceCount = selectedRuntimeServiceId ? Math.max(0, (existing.runtimeServices?.length ?? 1) - 1) : 0;
424
784
  }
425
785
  const currentDesiredState = existing.config?.desiredState
@@ -435,7 +795,9 @@ export function executionWorkspaceRoutes(db, opts = {}) {
435
795
  config: { workspaceRuntime: effectiveRuntimeConfig },
436
796
  currentDesiredState,
437
797
  currentServiceStates: existing.config?.serviceStates ?? null,
438
- action,
798
+ action: action === "repair"
799
+ ? repairRestartsRuntimeServices ? "start" : "stop"
800
+ : action,
439
801
  serviceIndex: selectedServiceIndex,
440
802
  });
441
803
  const metadata = mergeExecutionWorkspaceConfig(existing.metadata, {
@@ -451,12 +813,17 @@ export function executionWorkspaceRoutes(db, opts = {}) {
451
813
  ? "Stopped execution workspace runtime services.\n"
452
814
  : action === "restart"
453
815
  ? "Restarted execution workspace runtime services.\n"
454
- : "Started execution workspace runtime services.\n",
816
+ : action === "repair"
817
+ ? repairRestartsRuntimeServices
818
+ ? "Repaired the isolated workspace database and restarted healthy runtime services.\n"
819
+ : "Repaired the isolated workspace database; no managed runtime services were configured to restart.\n"
820
+ : "Started execution workspace runtime services.\n",
455
821
  metadata: {
456
822
  runtimeServiceCount,
457
823
  workspaceCommandId: workspaceCommand?.id ?? target.workspaceCommandId ?? null,
458
824
  runtimeServiceId: selectedRuntimeServiceId,
459
825
  serviceIndex: selectedServiceIndex,
826
+ runtimeRestarted: action === "repair" ? repairRestartsRuntimeServices : undefined,
460
827
  },
461
828
  };
462
829
  },
@@ -494,8 +861,9 @@ export function executionWorkspaceRoutes(db, opts = {}) {
494
861
  // The operation is already terminal here. This also catches the recorder's own time
495
862
  // budget expiring on a start that never settles, which is the one failure the inner
496
863
  // handler cannot see — reconcile there too so no listener or desired state is left over.
497
- if (action === "start" || action === "restart")
864
+ if (action === "start" || action === "restart" || action === "repair") {
498
865
  await reconcileFailedRuntimeStart(error);
866
+ }
499
867
  throw error;
500
868
  }
501
869
  },