neondeck 1.0.0-beta.4

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 (760) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/DEVELOPMENT.md +310 -0
  3. package/LICENSE +21 -0
  4. package/README.md +128 -0
  5. package/SOUL.md +8 -0
  6. package/bin/neondeck.mjs +27 -0
  7. package/config/dashboard.json +208 -0
  8. package/config/dashboard.schema.json +207 -0
  9. package/dist/SOUL.md +8 -0
  10. package/dist/assets/app-BuuvLo98.js +3620 -0
  11. package/dist/assets/app-BuuvLo98.js.map +1 -0
  12. package/dist/assets/autopilot-CKgEx8yQ.js +68025 -0
  13. package/dist/assets/autopilot-CKgEx8yQ.js.map +1 -0
  14. package/dist/assets/briefing-DYVbJaqk.js +2 -0
  15. package/dist/assets/briefing-DoO-fJr1.js +22 -0
  16. package/dist/assets/briefing-DoO-fJr1.js.map +1 -0
  17. package/dist/assets/command-run-B2TWLpLL.js +20 -0
  18. package/dist/assets/command-run-B2TWLpLL.js.map +1 -0
  19. package/dist/assets/command-run-CzQra_Y7.js +2 -0
  20. package/dist/assets/display-assistant-CbCRBSYM.js +389 -0
  21. package/dist/assets/display-assistant-CbCRBSYM.js.map +1 -0
  22. package/dist/assets/fix-pr-ci-BlUl-2ht.js +46 -0
  23. package/dist/assets/fix-pr-ci-BlUl-2ht.js.map +1 -0
  24. package/dist/assets/fix-pr-ci-Dl1wpKXp.js +2 -0
  25. package/dist/assets/migrations/20260710061339_neondeck_pre_1_0_baseline/migration.sql +748 -0
  26. package/dist/assets/migrations/20260710061339_neondeck_pre_1_0_baseline/snapshot.json +7240 -0
  27. package/dist/assets/prepare-pr-worktree-CLzccRYh.js +2 -0
  28. package/dist/assets/prepare-pr-worktree-DxyTygiU.js +17 -0
  29. package/dist/assets/prepare-pr-worktree-DxyTygiU.js.map +1 -0
  30. package/dist/assets/push-pr-autofix-BFNSEASU.js +2 -0
  31. package/dist/assets/push-pr-autofix-DlVjw1IN.js +17 -0
  32. package/dist/assets/push-pr-autofix-DlVjw1IN.js.map +1 -0
  33. package/dist/assets/review-pr-for-human-B2j8wz2L.js +2 -0
  34. package/dist/assets/review-pr-for-human-DcGE-7wb.js +708 -0
  35. package/dist/assets/review-pr-for-human-DcGE-7wb.js.map +1 -0
  36. package/dist/assets/safety-CawD9GxD.js +2499 -0
  37. package/dist/assets/safety-CawD9GxD.js.map +1 -0
  38. package/dist/assets/scheduled-agent-instruction-CQgogBv3.js +22 -0
  39. package/dist/assets/scheduled-agent-instruction-CQgogBv3.js.map +1 -0
  40. package/dist/assets/scheduled-agent-instruction-Dr2ebZRD.js +2 -0
  41. package/dist/assets/scheduler-tick-Cy26qBld.js +105 -0
  42. package/dist/assets/scheduler-tick-Cy26qBld.js.map +1 -0
  43. package/dist/assets/skills/github-gh/SKILL.md +56 -0
  44. package/dist/assets/skills/neon-ci-fix/SKILL.md +15 -0
  45. package/dist/assets/skills/neon-docs-fix/SKILL.md +15 -0
  46. package/dist/assets/skills/neon-issue-triage/SKILL.md +13 -0
  47. package/dist/assets/skills/neon-pr-review/SKILL.md +19 -0
  48. package/dist/assets/skills/neondeck/SKILL.md +123 -0
  49. package/dist/assets/skills/neondeck-handoff/SKILL.md +31 -0
  50. package/dist/assets/triage-pr-event-BlE3GKNR.js +17 -0
  51. package/dist/assets/triage-pr-event-BlE3GKNR.js.map +1 -0
  52. package/dist/assets/triage-pr-event-hxUP587F.js +2 -0
  53. package/dist/assets/verify-then-push-pr-autofix-CIl5ZwZm.js +2 -0
  54. package/dist/assets/verify-then-push-pr-autofix-Djy0UFUv.js +75 -0
  55. package/dist/assets/verify-then-push-pr-autofix-Djy0UFUv.js.map +1 -0
  56. package/dist/config/dashboard.json +208 -0
  57. package/dist/config/dashboard.schema.json +207 -0
  58. package/dist/server.mjs +582 -0
  59. package/dist/server.mjs.map +1 -0
  60. package/dist/skills/github-gh/SKILL.md +56 -0
  61. package/dist/skills/neon-ci-fix/SKILL.md +15 -0
  62. package/dist/skills/neon-docs-fix/SKILL.md +15 -0
  63. package/dist/skills/neon-issue-triage/SKILL.md +13 -0
  64. package/dist/skills/neon-pr-review/SKILL.md +19 -0
  65. package/dist/skills/neondeck/SKILL.md +123 -0
  66. package/dist/skills/neondeck-handoff/SKILL.md +31 -0
  67. package/drizzle.config.ts +7 -0
  68. package/package.json +155 -0
  69. package/shared/patch-anchors.ts +78 -0
  70. package/src/agents/busywork-workflow.ts +24 -0
  71. package/src/agents/display-assistant.ts +134 -0
  72. package/src/agents/pr-review-assistant.ts +25 -0
  73. package/src/agents/scheduler-workflow.ts +20 -0
  74. package/src/agents/support/tools.ts +346 -0
  75. package/src/app.ts +1 -0
  76. package/src/cli/index.ts +560 -0
  77. package/src/cli/learning.ts +44 -0
  78. package/src/cli/mcp.ts +496 -0
  79. package/src/cli/modules.ts +107 -0
  80. package/src/cli/onboarding.ts +667 -0
  81. package/src/cli/options.ts +103 -0
  82. package/src/cli/output.ts +399 -0
  83. package/src/cli/preapprovals.ts +204 -0
  84. package/src/cli/prompts.ts +108 -0
  85. package/src/cli/types.ts +59 -0
  86. package/src/db.ts +41 -0
  87. package/src/desktop/open.ts +698 -0
  88. package/src/desktop/service.ts +863 -0
  89. package/src/domains/mcp/actions.ts +420 -0
  90. package/src/domains/mcp/config.ts +501 -0
  91. package/src/domains/mcp/format.ts +35 -0
  92. package/src/domains/mcp/gate.ts +188 -0
  93. package/src/domains/mcp/index.ts +9 -0
  94. package/src/domains/mcp/instructions.ts +18 -0
  95. package/src/domains/mcp/oauth.ts +1063 -0
  96. package/src/domains/mcp/policy.ts +15 -0
  97. package/src/domains/mcp/registry.ts +461 -0
  98. package/src/domains/mcp/schemas.ts +171 -0
  99. package/src/domains/mcp/stdio.ts +451 -0
  100. package/src/domains/mcp/store.ts +905 -0
  101. package/src/domains/mcp/tools.ts +119 -0
  102. package/src/lib/action-result.ts +51 -0
  103. package/src/lib/exec.ts +118 -0
  104. package/src/lib/git.ts +20 -0
  105. package/src/lib/report-html.ts +193 -0
  106. package/src/lib/sqlite.ts +51 -0
  107. package/src/lib/valibot.ts +33 -0
  108. package/src/modules/app-state/index.ts +5 -0
  109. package/src/modules/app-state/native-notifications.ts +76 -0
  110. package/src/modules/app-state/notification-events.ts +45 -0
  111. package/src/modules/app-state/notifications.ts +276 -0
  112. package/src/modules/app-state/types.ts +42 -0
  113. package/src/modules/app-state/workflow-summaries.ts +201 -0
  114. package/src/modules/autonomous-audit/index.ts +225 -0
  115. package/src/modules/autopilot/actions.ts +165 -0
  116. package/src/modules/autopilot/admissions.ts +865 -0
  117. package/src/modules/autopilot/approvals.ts +59 -0
  118. package/src/modules/autopilot/ci-fix-run.ts +1332 -0
  119. package/src/modules/autopilot/ci-fix.ts +692 -0
  120. package/src/modules/autopilot/comments.ts +426 -0
  121. package/src/modules/autopilot/fixtures.ts +344 -0
  122. package/src/modules/autopilot/github-facts.ts +303 -0
  123. package/src/modules/autopilot/index.ts +64 -0
  124. package/src/modules/autopilot/notifications.ts +271 -0
  125. package/src/modules/autopilot/push-support.ts +288 -0
  126. package/src/modules/autopilot/push.ts +661 -0
  127. package/src/modules/autopilot/recovery.ts +656 -0
  128. package/src/modules/autopilot/review-feedback.ts +651 -0
  129. package/src/modules/autopilot/review-support.ts +524 -0
  130. package/src/modules/autopilot/revision-run.ts +445 -0
  131. package/src/modules/autopilot/schemas.ts +485 -0
  132. package/src/modules/autopilot/state-mappers.ts +512 -0
  133. package/src/modules/autopilot/state-schemas.ts +451 -0
  134. package/src/modules/autopilot/state-store.ts +183 -0
  135. package/src/modules/autopilot/state.ts +255 -0
  136. package/src/modules/autopilot/triage-support.ts +234 -0
  137. package/src/modules/autopilot/triage.ts +156 -0
  138. package/src/modules/autopilot/utils.ts +145 -0
  139. package/src/modules/autopilot/worktree.ts +622 -0
  140. package/src/modules/autopilot-policy/config.ts +110 -0
  141. package/src/modules/autopilot-policy/index.ts +4 -0
  142. package/src/modules/autopilot-policy/risk.ts +359 -0
  143. package/src/modules/autopilot-policy/schemas.ts +284 -0
  144. package/src/modules/autopilot-policy/service.ts +304 -0
  145. package/src/modules/commands/actions.ts +112 -0
  146. package/src/modules/commands/handlers/index.ts +3 -0
  147. package/src/modules/commands/handlers/misc.ts +441 -0
  148. package/src/modules/commands/handlers/queue.ts +694 -0
  149. package/src/modules/commands/handlers/repo.ts +339 -0
  150. package/src/modules/commands/index.ts +5 -0
  151. package/src/modules/commands/registry.ts +157 -0
  152. package/src/modules/commands/runner.ts +152 -0
  153. package/src/modules/commands/schemas.ts +107 -0
  154. package/src/modules/commands/summaries.ts +92 -0
  155. package/src/modules/commands/utils.ts +113 -0
  156. package/src/modules/config/actions.ts +253 -0
  157. package/src/modules/config/events.ts +80 -0
  158. package/src/modules/config/files.ts +9 -0
  159. package/src/modules/config/history.ts +74 -0
  160. package/src/modules/config/index.ts +9 -0
  161. package/src/modules/config/mutations/dashboard.ts +319 -0
  162. package/src/modules/config/mutations/execution.ts +89 -0
  163. package/src/modules/config/mutations/models.ts +467 -0
  164. package/src/modules/config/mutations/providers.ts +163 -0
  165. package/src/modules/config/mutations/repos.ts +620 -0
  166. package/src/modules/config/read.ts +135 -0
  167. package/src/modules/config/result.ts +66 -0
  168. package/src/modules/config/schemas.ts +181 -0
  169. package/src/modules/docs-drift/index.ts +1 -0
  170. package/src/modules/docs-drift/service.ts +863 -0
  171. package/src/modules/execution/actions.ts +35 -0
  172. package/src/modules/execution/approvals.ts +322 -0
  173. package/src/modules/execution/exedev/checkouts.ts +356 -0
  174. package/src/modules/execution/exedev/context.ts +286 -0
  175. package/src/modules/execution/index.ts +7 -0
  176. package/src/modules/execution/policy.ts +102 -0
  177. package/src/modules/execution/run.ts +589 -0
  178. package/src/modules/execution/schemas.ts +116 -0
  179. package/src/modules/execution/scope.ts +137 -0
  180. package/src/modules/execution/store.ts +320 -0
  181. package/src/modules/execution/utils.ts +105 -0
  182. package/src/modules/execution-policy/index.ts +424 -0
  183. package/src/modules/flue/execution-context.ts +41 -0
  184. package/src/modules/github/actions.ts +334 -0
  185. package/src/modules/github/checks.ts +484 -0
  186. package/src/modules/github/client.ts +110 -0
  187. package/src/modules/github/comments.ts +204 -0
  188. package/src/modules/github/errors.ts +50 -0
  189. package/src/modules/github/index.ts +92 -0
  190. package/src/modules/github/issues.ts +116 -0
  191. package/src/modules/github/pr-file-cache.ts +264 -0
  192. package/src/modules/github/pull-requests.ts +384 -0
  193. package/src/modules/github/queue.ts +342 -0
  194. package/src/modules/github/reviews.ts +1421 -0
  195. package/src/modules/github/schemas.ts +794 -0
  196. package/src/modules/github/state-truncation.ts +31 -0
  197. package/src/modules/handoff/index.ts +2 -0
  198. package/src/modules/handoff/schemas.ts +61 -0
  199. package/src/modules/handoff/service.ts +587 -0
  200. package/src/modules/hygiene/index.ts +1 -0
  201. package/src/modules/hygiene/service.ts +513 -0
  202. package/src/modules/kilo/actions.ts +229 -0
  203. package/src/modules/kilo/ci-fix-run-reconcile.ts +299 -0
  204. package/src/modules/kilo/docs-drift-boundary.ts +178 -0
  205. package/src/modules/kilo/index.ts +8 -0
  206. package/src/modules/kilo/notifications.ts +295 -0
  207. package/src/modules/kilo/process.ts +637 -0
  208. package/src/modules/kilo/results/actions.ts +66 -0
  209. package/src/modules/kilo/results/gates.ts +227 -0
  210. package/src/modules/kilo/results/index.ts +23 -0
  211. package/src/modules/kilo/results/schemas.ts +112 -0
  212. package/src/modules/kilo/results/service.ts +512 -0
  213. package/src/modules/kilo/results/state.ts +508 -0
  214. package/src/modules/kilo/results/verify.ts +328 -0
  215. package/src/modules/kilo/revision-reconcile.ts +187 -0
  216. package/src/modules/kilo/runtime-facts.ts +128 -0
  217. package/src/modules/kilo/schemas.ts +265 -0
  218. package/src/modules/kilo/service.ts +714 -0
  219. package/src/modules/kilo/sessions-adapters.ts +343 -0
  220. package/src/modules/kilo/sessions.ts +446 -0
  221. package/src/modules/kilo/store.ts +689 -0
  222. package/src/modules/kilo/utils.ts +166 -0
  223. package/src/modules/learning/automation-health.ts +441 -0
  224. package/src/modules/learning/automation-memory.ts +179 -0
  225. package/src/modules/learning/index.ts +6 -0
  226. package/src/modules/learning/observability.ts +616 -0
  227. package/src/modules/learning/operator.ts +404 -0
  228. package/src/modules/learning/reviews/agents.ts +33 -0
  229. package/src/modules/learning/reviews/complete.ts +321 -0
  230. package/src/modules/learning/reviews/context.ts +145 -0
  231. package/src/modules/learning/reviews/events.ts +306 -0
  232. package/src/modules/learning/reviews/index.ts +6 -0
  233. package/src/modules/learning/reviews/pr-cadence.ts +157 -0
  234. package/src/modules/learning/reviews/pr-context.ts +749 -0
  235. package/src/modules/learning/reviews/prepare.ts +387 -0
  236. package/src/modules/learning/reviews/schemas.ts +184 -0
  237. package/src/modules/learning/reviews/store.ts +405 -0
  238. package/src/modules/learning/skill-patches/actions.ts +86 -0
  239. package/src/modules/learning/skill-patches/index.ts +3 -0
  240. package/src/modules/learning/skill-patches/schemas.ts +60 -0
  241. package/src/modules/learning/skill-patches/service.ts +571 -0
  242. package/src/modules/learning/skill-patches/support.ts +417 -0
  243. package/src/modules/memory/actions.ts +183 -0
  244. package/src/modules/memory/candidates.ts +525 -0
  245. package/src/modules/memory/events.ts +2 -0
  246. package/src/modules/memory/index.ts +6 -0
  247. package/src/modules/memory/prompt.ts +214 -0
  248. package/src/modules/memory/schemas.ts +170 -0
  249. package/src/modules/memory/service.ts +578 -0
  250. package/src/modules/memory/store.ts +489 -0
  251. package/src/modules/pr-events/actions.ts +191 -0
  252. package/src/modules/pr-events/index.ts +45 -0
  253. package/src/modules/pr-events/schemas.ts +186 -0
  254. package/src/modules/pr-events/service.ts +1414 -0
  255. package/src/modules/pr-events/target.ts +222 -0
  256. package/src/modules/pr-events/utils.ts +85 -0
  257. package/src/modules/pr-events/watermarks.ts +308 -0
  258. package/src/modules/pr-local-diffs/index.ts +334 -0
  259. package/src/modules/pr-review-assist/actions.ts +199 -0
  260. package/src/modules/pr-review-assist/index.ts +3 -0
  261. package/src/modules/pr-review-assist/schemas.ts +74 -0
  262. package/src/modules/pr-review-assist/service.ts +656 -0
  263. package/src/modules/prepared-diffs/actions.ts +132 -0
  264. package/src/modules/prepared-diffs/index.ts +53 -0
  265. package/src/modules/prepared-diffs/schemas.ts +255 -0
  266. package/src/modules/prepared-diffs/service.ts +777 -0
  267. package/src/modules/prepared-diffs/store.ts +606 -0
  268. package/src/modules/reports/index.ts +1 -0
  269. package/src/modules/reports/service.ts +322 -0
  270. package/src/modules/repos/index.ts +3 -0
  271. package/src/modules/repos/model-discovery.ts +233 -0
  272. package/src/modules/repos/providers.ts +194 -0
  273. package/src/modules/repos/registry.ts +232 -0
  274. package/src/modules/runtime/agent-config.ts +167 -0
  275. package/src/modules/runtime/doctor.ts +528 -0
  276. package/src/modules/runtime/env.ts +123 -0
  277. package/src/modules/runtime/index.ts +12 -0
  278. package/src/modules/runtime/local-api-auth.ts +43 -0
  279. package/src/modules/runtime/metrics.ts +211 -0
  280. package/src/modules/runtime/skills-actions.ts +141 -0
  281. package/src/modules/runtime/skills.ts +689 -0
  282. package/src/modules/runtime/soul.ts +68 -0
  283. package/src/modules/runtime/status-database.ts +252 -0
  284. package/src/modules/runtime/status-schema.ts +149 -0
  285. package/src/modules/runtime/status.ts +482 -0
  286. package/src/modules/runtime/subagents.ts +37 -0
  287. package/src/modules/runtime/utility-model.ts +47 -0
  288. package/src/modules/safety/index.ts +3 -0
  289. package/src/modules/safety/policy-entries.ts +2432 -0
  290. package/src/modules/safety/schemas.ts +63 -0
  291. package/src/modules/safety/service.ts +58 -0
  292. package/src/modules/safety/tools.ts +15 -0
  293. package/src/modules/scheduled-tasks/actions.ts +113 -0
  294. package/src/modules/scheduled-tasks/dispatch.ts +105 -0
  295. package/src/modules/scheduled-tasks/index.ts +6 -0
  296. package/src/modules/scheduled-tasks/schemas.ts +91 -0
  297. package/src/modules/scheduled-tasks/service.ts +296 -0
  298. package/src/modules/scheduled-tasks/store.ts +814 -0
  299. package/src/modules/scheduled-tasks/triggers.ts +87 -0
  300. package/src/modules/scheduler/actions.ts +37 -0
  301. package/src/modules/scheduler/dispatch.ts +126 -0
  302. package/src/modules/scheduler/index.ts +4 -0
  303. package/src/modules/scheduler/lease.ts +247 -0
  304. package/src/modules/scheduler/pr-watch-event-deltas.ts +367 -0
  305. package/src/modules/scheduler/pr-watch-events.ts +834 -0
  306. package/src/modules/scheduler/schemas.ts +79 -0
  307. package/src/modules/scheduler/service.ts +228 -0
  308. package/src/modules/scheduler/utils.ts +106 -0
  309. package/src/modules/scheduler/workflow-invocation.ts +40 -0
  310. package/src/modules/sessions/actions.ts +213 -0
  311. package/src/modules/sessions/active-session.ts +46 -0
  312. package/src/modules/sessions/agent-context.ts +146 -0
  313. package/src/modules/sessions/approval-nudges.ts +156 -0
  314. package/src/modules/sessions/events.ts +58 -0
  315. package/src/modules/sessions/index.ts +10 -0
  316. package/src/modules/sessions/queries.ts +252 -0
  317. package/src/modules/sessions/references.ts +113 -0
  318. package/src/modules/sessions/schemas.ts +263 -0
  319. package/src/modules/sessions/service.ts +845 -0
  320. package/src/modules/sessions/store.ts +559 -0
  321. package/src/modules/sessions/summaries.ts +129 -0
  322. package/src/modules/sessions/utils.ts +18 -0
  323. package/src/modules/watches/actions.ts +115 -0
  324. package/src/modules/watches/index.ts +6 -0
  325. package/src/modules/watches/polling.ts +245 -0
  326. package/src/modules/watches/references.ts +293 -0
  327. package/src/modules/watches/schemas.ts +156 -0
  328. package/src/modules/watches/service.ts +558 -0
  329. package/src/modules/watches/store.ts +398 -0
  330. package/src/modules/watches/utils.ts +51 -0
  331. package/src/modules/worktree-verification/index.ts +256 -0
  332. package/src/modules/worktrees/access.ts +129 -0
  333. package/src/modules/worktrees/actions.ts +108 -0
  334. package/src/modules/worktrees/cleanup.ts +98 -0
  335. package/src/modules/worktrees/errors.ts +38 -0
  336. package/src/modules/worktrees/git.ts +48 -0
  337. package/src/modules/worktrees/index.ts +5 -0
  338. package/src/modules/worktrees/locks.ts +192 -0
  339. package/src/modules/worktrees/paths.ts +209 -0
  340. package/src/modules/worktrees/queries.ts +31 -0
  341. package/src/modules/worktrees/schemas.ts +234 -0
  342. package/src/modules/worktrees/service.ts +657 -0
  343. package/src/modules/worktrees/store.ts +414 -0
  344. package/src/repo-edit/actions.ts +129 -0
  345. package/src/repo-edit/audit.ts +180 -0
  346. package/src/repo-edit/fuzzy-replace.ts +256 -0
  347. package/src/repo-edit/git.ts +784 -0
  348. package/src/repo-edit/index.ts +4 -0
  349. package/src/repo-edit/locks.ts +27 -0
  350. package/src/repo-edit/patch-parser.ts +212 -0
  351. package/src/repo-edit/patch-service.ts +572 -0
  352. package/src/repo-edit/path-safety.ts +294 -0
  353. package/src/repo-edit/schemas.ts +220 -0
  354. package/src/repo-edit/service.ts +488 -0
  355. package/src/repo-edit/support.ts +459 -0
  356. package/src/runtime-home/app-db/index.ts +73 -0
  357. package/src/runtime-home/app-db/migrate.ts +491 -0
  358. package/src/runtime-home/app-db/migrations/20260710061339_neondeck_pre_1_0_baseline/migration.sql +748 -0
  359. package/src/runtime-home/app-db/migrations/20260710061339_neondeck_pre_1_0_baseline/snapshot.json +7240 -0
  360. package/src/runtime-home/app-db/reconcile.ts +155 -0
  361. package/src/runtime-home/app-db/schema.ts +1118 -0
  362. package/src/runtime-home/bootstrap.ts +171 -0
  363. package/src/runtime-home/defaults.ts +42 -0
  364. package/src/runtime-home/files.ts +193 -0
  365. package/src/runtime-home/index.ts +68 -0
  366. package/src/runtime-home/paths.ts +75 -0
  367. package/src/runtime-home/schemas.ts +485 -0
  368. package/src/sandboxes/exedev.ts +676 -0
  369. package/src/server/app.ts +5 -0
  370. package/src/server/autopilot-push-dispatch.ts +326 -0
  371. package/src/server/create-app.ts +160 -0
  372. package/src/server/events/config-stream.ts +67 -0
  373. package/src/server/events/notification-stream.ts +49 -0
  374. package/src/server/events/session-stream.ts +49 -0
  375. package/src/server/http.ts +56 -0
  376. package/src/server/learning-hooks.ts +430 -0
  377. package/src/server/middleware.ts +81 -0
  378. package/src/server/routes/autopilot.ts +318 -0
  379. package/src/server/routes/commands.ts +12 -0
  380. package/src/server/routes/config.ts +124 -0
  381. package/src/server/routes/execution.ts +71 -0
  382. package/src/server/routes/github.ts +372 -0
  383. package/src/server/routes/handoff.ts +69 -0
  384. package/src/server/routes/kilo.ts +179 -0
  385. package/src/server/routes/learning.ts +384 -0
  386. package/src/server/routes/mcp.ts +301 -0
  387. package/src/server/routes/memory.ts +99 -0
  388. package/src/server/routes/metrics.ts +12 -0
  389. package/src/server/routes/notifications.ts +48 -0
  390. package/src/server/routes/repo-edit.ts +115 -0
  391. package/src/server/routes/reports.ts +127 -0
  392. package/src/server/routes/repos.ts +50 -0
  393. package/src/server/routes/runtime.ts +48 -0
  394. package/src/server/routes/safety.ts +13 -0
  395. package/src/server/routes/scheduled-tasks.ts +58 -0
  396. package/src/server/routes/scheduler.ts +13 -0
  397. package/src/server/routes/sessions.ts +216 -0
  398. package/src/server/routes/skills.ts +103 -0
  399. package/src/server/routes/watches.ts +81 -0
  400. package/src/server/routes/workflows.ts +21 -0
  401. package/src/server/routes/worktrees.ts +64 -0
  402. package/src/server/scheduler-workflow.ts +541 -0
  403. package/src/server/serve.ts +100 -0
  404. package/src/setup.ts +162 -0
  405. package/src/skills/github-gh/SKILL.md +56 -0
  406. package/src/skills/neon-ci-fix/SKILL.md +15 -0
  407. package/src/skills/neon-docs-fix/SKILL.md +15 -0
  408. package/src/skills/neon-issue-triage/SKILL.md +13 -0
  409. package/src/skills/neon-pr-review/SKILL.md +19 -0
  410. package/src/skills/neondeck/SKILL.md +123 -0
  411. package/src/skills/neondeck-handoff/SKILL.md +31 -0
  412. package/src/workflows/briefing.ts +14 -0
  413. package/src/workflows/command-run.ts +15 -0
  414. package/src/workflows/comment-pr-autofix-result.ts +10 -0
  415. package/src/workflows/curate_learning_store.ts +37 -0
  416. package/src/workflows/dev-doctor.ts +10 -0
  417. package/src/workflows/fix-pr-ci-failure.ts +10 -0
  418. package/src/workflows/fix-pr-ci.ts +15 -0
  419. package/src/workflows/fix-pr-review-feedback.ts +10 -0
  420. package/src/workflows/handoff_to_kilo.ts +10 -0
  421. package/src/workflows/prepare-pr-worktree.ts +10 -0
  422. package/src/workflows/promote_kilo_result.ts +10 -0
  423. package/src/workflows/push-pr-autofix.ts +10 -0
  424. package/src/workflows/reconcile_kilo_task.ts +10 -0
  425. package/src/workflows/review-pr-for-human.ts +15 -0
  426. package/src/workflows/review_conversation_for_learning.ts +37 -0
  427. package/src/workflows/review_kilo_result.ts +10 -0
  428. package/src/workflows/review_pr_batch_for_learning.ts +37 -0
  429. package/src/workflows/scheduled-agent-instruction.ts +16 -0
  430. package/src/workflows/scheduler-tick.ts +10 -0
  431. package/src/workflows/summarize_kilo_session.ts +25 -0
  432. package/src/workflows/triage-pr-event.ts +10 -0
  433. package/src/workflows/verify-pr-worktree.ts +10 -0
  434. package/src/workflows/verify-then-push-pr-autofix.ts +82 -0
  435. package/src/workflows/verify_kilo_result.ts +10 -0
  436. package/src/workflows/watch-pr.ts +10 -0
  437. package/web/dist/assets/GitHubPrReview-QK9oqeDs.js +2 -0
  438. package/web/dist/assets/MultiFileView-CMm6tA9f.js +2970 -0
  439. package/web/dist/assets/abap-CLvhMVsD.js +1 -0
  440. package/web/dist/assets/actionscript-3--17pq3dv.js +1 -0
  441. package/web/dist/assets/ada-C5qYipkI.js +1 -0
  442. package/web/dist/assets/andromeeda-vGVdxbeo.js +1 -0
  443. package/web/dist/assets/angular-html-BVBpGdXr.js +1 -0
  444. package/web/dist/assets/angular-ts-BfdufMKP.js +1 -0
  445. package/web/dist/assets/apache-U0d_L8uA.js +1 -0
  446. package/web/dist/assets/apex-VAyPSnFM.js +1 -0
  447. package/web/dist/assets/apl-DWBSSoBH.js +1 -0
  448. package/web/dist/assets/applescript-CCn79oCD.js +1 -0
  449. package/web/dist/assets/ara-4CJ0cIlV.js +1 -0
  450. package/web/dist/assets/asciidoc-DE70LPWp.js +1 -0
  451. package/web/dist/assets/asm-Cmm7eHzH.js +1 -0
  452. package/web/dist/assets/astro-3LtMP0Sq.js +1 -0
  453. package/web/dist/assets/aurora-x-CDeNXAV0.js +1 -0
  454. package/web/dist/assets/awk-BWXHIvNe.js +1 -0
  455. package/web/dist/assets/ayu-dark-DluEY0Gj.js +1 -0
  456. package/web/dist/assets/ayu-light-C3h-C4tm.js +1 -0
  457. package/web/dist/assets/ayu-mirage-Bqwy1Gya.js +1 -0
  458. package/web/dist/assets/ballerina-B7ZEbQpA.js +1 -0
  459. package/web/dist/assets/bat-Bo4NYOV-.js +1 -0
  460. package/web/dist/assets/beancount-D-usSTwE.js +1 -0
  461. package/web/dist/assets/berry-DKpUyyne.js +1 -0
  462. package/web/dist/assets/bibtex-Ci_nEsc7.js +1 -0
  463. package/web/dist/assets/bicep-CUHmPFLl.js +1 -0
  464. package/web/dist/assets/bird2-C6vDhewU.js +1 -0
  465. package/web/dist/assets/blade-llJRbbtR.js +1 -0
  466. package/web/dist/assets/bsl-BkkzgIyY.js +1 -0
  467. package/web/dist/assets/c-Wt1voDr2.js +1 -0
  468. package/web/dist/assets/c3-BFHwR3_K.js +1 -0
  469. package/web/dist/assets/cadence-CQ2zXKGN.js +1 -0
  470. package/web/dist/assets/cairo-DLTphjLi.js +1 -0
  471. package/web/dist/assets/catppuccin-frappe-3VR1Za6u.js +1 -0
  472. package/web/dist/assets/catppuccin-latte-DwIHMF0Q.js +1 -0
  473. package/web/dist/assets/catppuccin-macchiato-DYnBP6_5.js +1 -0
  474. package/web/dist/assets/catppuccin-mocha-DYhrFGRu.js +1 -0
  475. package/web/dist/assets/clarity-SemFz856.js +1 -0
  476. package/web/dist/assets/clojure-DqKBuwfJ.js +1 -0
  477. package/web/dist/assets/cmake-Bj61d0ZC.js +1 -0
  478. package/web/dist/assets/cobol-x_HIyl2P.js +1 -0
  479. package/web/dist/assets/codeowners-C8r90Shi.js +1 -0
  480. package/web/dist/assets/codeql-oeQT6MSM.js +1 -0
  481. package/web/dist/assets/coffee-CThvmt4R.js +1 -0
  482. package/web/dist/assets/common-lisp-Cv5bFMCO.js +1 -0
  483. package/web/dist/assets/coq-BrsZFFmf.js +1 -0
  484. package/web/dist/assets/cpp-NtAeskI3.js +1 -0
  485. package/web/dist/assets/crystal-DNu_sX0G.js +1 -0
  486. package/web/dist/assets/csharp-oqKa8noW.js +1 -0
  487. package/web/dist/assets/css-DJp_X0uY.js +1 -0
  488. package/web/dist/assets/csv-Dx-8-gkx.js +1 -0
  489. package/web/dist/assets/cue-CE9AQfxI.js +1 -0
  490. package/web/dist/assets/cypher-ClKdZ_lG.js +1 -0
  491. package/web/dist/assets/d-qD-0Kul2.js +1 -0
  492. package/web/dist/assets/dark-plus-Cs2F2srj.js +1 -0
  493. package/web/dist/assets/dart-CnvKMtbv.js +1 -0
  494. package/web/dist/assets/dax-BkyTk9wS.js +1 -0
  495. package/web/dist/assets/desktop-Dlh5hvp9.js +1 -0
  496. package/web/dist/assets/diff-woXpYk--.js +1 -0
  497. package/web/dist/assets/docker-IyjqRm3v.js +1 -0
  498. package/web/dist/assets/dotenv-_5a1GRtc.js +1 -0
  499. package/web/dist/assets/dracula-BHWKrbxM.js +1 -0
  500. package/web/dist/assets/dracula-soft-5eyTD99u.js +1 -0
  501. package/web/dist/assets/dream-maker-DW3nJb8Q.js +1 -0
  502. package/web/dist/assets/edge-ozw5tpLl.js +1 -0
  503. package/web/dist/assets/elixir-VhA6FeZt.js +1 -0
  504. package/web/dist/assets/elm-dREJmIFz.js +1 -0
  505. package/web/dist/assets/emacs-lisp-B4R74twV.js +1 -0
  506. package/web/dist/assets/erb-CIg6G69l.js +1 -0
  507. package/web/dist/assets/erlang-Cphh6RMH.js +1 -0
  508. package/web/dist/assets/everforest-dark-sB-x3p7T.js +1 -0
  509. package/web/dist/assets/everforest-light-Df2xbC6M.js +1 -0
  510. package/web/dist/assets/fennel-DQxkIbk2.js +1 -0
  511. package/web/dist/assets/fish-BJitypiv.js +1 -0
  512. package/web/dist/assets/fluent-C03EYrpw.js +1 -0
  513. package/web/dist/assets/fortran-fixed-form-DEKoE2YW.js +1 -0
  514. package/web/dist/assets/fortran-free-form-CYNrtFtB.js +1 -0
  515. package/web/dist/assets/fsharp-D13ZGOAj.js +1 -0
  516. package/web/dist/assets/gdresource-C0sCabJj.js +1 -0
  517. package/web/dist/assets/gdscript-Cp2uCuqX.js +1 -0
  518. package/web/dist/assets/gdshader-CBce3t8t.js +1 -0
  519. package/web/dist/assets/genie-CV2tkWYe.js +1 -0
  520. package/web/dist/assets/gherkin-DExj1W_8.js +1 -0
  521. package/web/dist/assets/git-commit-BSykSTBG.js +1 -0
  522. package/web/dist/assets/git-rebase-B44mJPta.js +1 -0
  523. package/web/dist/assets/github-dark-C-LZuMrd.js +1 -0
  524. package/web/dist/assets/github-dark-default-DXG-b-1a.js +1 -0
  525. package/web/dist/assets/github-dark-dimmed-Bx1FflLF.js +1 -0
  526. package/web/dist/assets/github-dark-high-contrast-B_tTalzw.js +1 -0
  527. package/web/dist/assets/github-light-EUqPIrTm.js +1 -0
  528. package/web/dist/assets/github-light-default-BXViO-2h.js +1 -0
  529. package/web/dist/assets/github-light-high-contrast-B68TUdTA.js +1 -0
  530. package/web/dist/assets/gleam-CSRkHgEL.js +1 -0
  531. package/web/dist/assets/glimmer-js-vH_gHG0-.js +1 -0
  532. package/web/dist/assets/glimmer-ts--abOzSAQ.js +1 -0
  533. package/web/dist/assets/glsl-Dv5r7kPw.js +1 -0
  534. package/web/dist/assets/gn-ilITqXS6.js +1 -0
  535. package/web/dist/assets/gnuplot-7GGW24-e.js +1 -0
  536. package/web/dist/assets/go-rLFTqkRN.js +1 -0
  537. package/web/dist/assets/graphql-CB4jsw2E.js +1 -0
  538. package/web/dist/assets/groovy-CacY0gHj.js +1 -0
  539. package/web/dist/assets/gruvbox-dark-hard-C820rvS2.js +1 -0
  540. package/web/dist/assets/gruvbox-dark-medium-BPjhmG05.js +1 -0
  541. package/web/dist/assets/gruvbox-dark-soft-MrdJrrXF.js +1 -0
  542. package/web/dist/assets/gruvbox-light-hard-BC_s9l72.js +1 -0
  543. package/web/dist/assets/gruvbox-light-medium-BAWPOn9u.js +1 -0
  544. package/web/dist/assets/gruvbox-light-soft-BSMLrYjP.js +1 -0
  545. package/web/dist/assets/hack-DvEYX148.js +1 -0
  546. package/web/dist/assets/haml-zE6W3STP.js +1 -0
  547. package/web/dist/assets/handlebars-CzBR2SDs.js +1 -0
  548. package/web/dist/assets/haskell-D8IpX4py.js +1 -0
  549. package/web/dist/assets/haxe-OTjmBuCE.js +1 -0
  550. package/web/dist/assets/hcl-Dh228itO.js +1 -0
  551. package/web/dist/assets/hjson-CxZEssPk.js +1 -0
  552. package/web/dist/assets/hlsl-Cvrh5tZx.js +1 -0
  553. package/web/dist/assets/horizon-CE9ld1lL.js +1 -0
  554. package/web/dist/assets/horizon-bright-DSNQnXHK.js +1 -0
  555. package/web/dist/assets/houston-CsvMBhTu.js +1 -0
  556. package/web/dist/assets/html-C8UlPnhE.js +1 -0
  557. package/web/dist/assets/html-derivative-CY6NRz-J.js +1 -0
  558. package/web/dist/assets/http-Cyd7bS_S.js +1 -0
  559. package/web/dist/assets/hurl-CWPsiEpf.js +1 -0
  560. package/web/dist/assets/hxml-B0Qn7Nwc.js +1 -0
  561. package/web/dist/assets/hy-CZbG8q4J.js +1 -0
  562. package/web/dist/assets/imba-DsUTQ-LC.js +1 -0
  563. package/web/dist/assets/index-DqZpo0Jd.js +44 -0
  564. package/web/dist/assets/index-_jKCE4ks.css +2 -0
  565. package/web/dist/assets/ini-B5eOa1yu.js +1 -0
  566. package/web/dist/assets/java-CGc3VwQr.js +1 -0
  567. package/web/dist/assets/javascript-CUt1pgmJ.js +1 -0
  568. package/web/dist/assets/jinja-CD-Z-FLd.js +1 -0
  569. package/web/dist/assets/jison-imPNup1l.js +1 -0
  570. package/web/dist/assets/json-Bg9ijW3F.js +1 -0
  571. package/web/dist/assets/json5-BR5RXkoi.js +1 -0
  572. package/web/dist/assets/jsonc-CYpm1nAK.js +1 -0
  573. package/web/dist/assets/jsonl-CmCQp5Yx.js +1 -0
  574. package/web/dist/assets/jsonnet-CJTPZ8u_.js +1 -0
  575. package/web/dist/assets/jssm-DXw9l8Rf.js +1 -0
  576. package/web/dist/assets/jsx-CY6oMTks.js +1 -0
  577. package/web/dist/assets/julia-Dc3O-irA.js +1 -0
  578. package/web/dist/assets/just-BhOq_Kbv.js +1 -0
  579. package/web/dist/assets/kanagawa-dragon-CXtmUGW6.js +1 -0
  580. package/web/dist/assets/kanagawa-lotus-BN08jTvb.js +1 -0
  581. package/web/dist/assets/kanagawa-wave-CTweb8Dz.js +1 -0
  582. package/web/dist/assets/kdl-CsD5j6eV.js +1 -0
  583. package/web/dist/assets/kotlin-DhhofPvG.js +1 -0
  584. package/web/dist/assets/kusto-C7mF5XQf.js +1 -0
  585. package/web/dist/assets/laserwave-C_8bwKvT.js +1 -0
  586. package/web/dist/assets/latex-Cu4Y1d5w.js +1 -0
  587. package/web/dist/assets/lean-CewbzKMR.js +1 -0
  588. package/web/dist/assets/less-DVTAwKKz.js +1 -0
  589. package/web/dist/assets/light-plus-DVQuIRkW.js +1 -0
  590. package/web/dist/assets/liquid-CvXMrjlQ.js +1 -0
  591. package/web/dist/assets/llvm-Cm23YOpf.js +1 -0
  592. package/web/dist/assets/log-BNLmms1o.js +1 -0
  593. package/web/dist/assets/logo-Cluzi2Zq.js +1 -0
  594. package/web/dist/assets/lua-BjLEUjKY.js +1 -0
  595. package/web/dist/assets/luau-FMPmPwt6.js +1 -0
  596. package/web/dist/assets/make-Dixweg8N.js +1 -0
  597. package/web/dist/assets/markdown-BYOwaDjH.js +1 -0
  598. package/web/dist/assets/marko-DvhNOisQ.js +1 -0
  599. package/web/dist/assets/material-theme-Bm3Qr25_.js +1 -0
  600. package/web/dist/assets/material-theme-darker-2IIEA8gg.js +1 -0
  601. package/web/dist/assets/material-theme-lighter-uhdI0v04.js +1 -0
  602. package/web/dist/assets/material-theme-ocean-CHQ94UKr.js +1 -0
  603. package/web/dist/assets/material-theme-palenight-B5W6OYN7.js +1 -0
  604. package/web/dist/assets/matlab-D7qyCx1q.js +1 -0
  605. package/web/dist/assets/mdc-Bm9TpL1X.js +1 -0
  606. package/web/dist/assets/mdx-DQZ5AkYe.js +1 -0
  607. package/web/dist/assets/mermaid-Bk4SNUv9.js +1 -0
  608. package/web/dist/assets/min-dark-BSWPekZh.js +1 -0
  609. package/web/dist/assets/min-light-DDpmG2fV.js +1 -0
  610. package/web/dist/assets/mipsasm-BMqwQI7S.js +1 -0
  611. package/web/dist/assets/mojo-BgCJLMeH.js +1 -0
  612. package/web/dist/assets/monokai-CdkpiU2Y.js +1 -0
  613. package/web/dist/assets/moonbit-CaWjb8XO.js +1 -0
  614. package/web/dist/assets/move-B1IS1UjX.js +1 -0
  615. package/web/dist/assets/narrat-_X_XdTYD.js +1 -0
  616. package/web/dist/assets/nextflow-BJtWHP5T.js +1 -0
  617. package/web/dist/assets/nextflow-groovy-DJMQeKeT.js +1 -0
  618. package/web/dist/assets/nginx-Bhc82uuv.js +1 -0
  619. package/web/dist/assets/night-owl-DhmEMT88.js +1 -0
  620. package/web/dist/assets/night-owl-light-eJ-hLW7d.js +1 -0
  621. package/web/dist/assets/nim-DXTVBFnF.js +1 -0
  622. package/web/dist/assets/nix-IvuFDN5E.js +1 -0
  623. package/web/dist/assets/nord-Cb4Vim4T.js +1 -0
  624. package/web/dist/assets/nushell-DcLAeLz5.js +1 -0
  625. package/web/dist/assets/objective-c-D1A_Heim.js +1 -0
  626. package/web/dist/assets/objective-cpp-BsSzOQcm.js +1 -0
  627. package/web/dist/assets/ocaml-O90oeIOV.js +1 -0
  628. package/web/dist/assets/odin-B1RWQWA5.js +1 -0
  629. package/web/dist/assets/one-dark-pro-CLwyXe_n.js +1 -0
  630. package/web/dist/assets/one-light-D7Lr4KcI.js +1 -0
  631. package/web/dist/assets/openscad-BUDT5pXO.js +1 -0
  632. package/web/dist/assets/pascal-4ZHwLPI5.js +1 -0
  633. package/web/dist/assets/perl-C7veXV9z.js +1 -0
  634. package/web/dist/assets/php-BRiuMnnr.js +1 -0
  635. package/web/dist/assets/pierre-dark-CpLgRqie.js +1 -0
  636. package/web/dist/assets/pierre-dark-protanopia-deuteranopia-B35FxJx-.js +1 -0
  637. package/web/dist/assets/pierre-dark-soft-kZQmAZld.js +1 -0
  638. package/web/dist/assets/pierre-dark-tritanopia-CpjhbsIL.js +1 -0
  639. package/web/dist/assets/pierre-dark-vibrant-CpQYzh95.js +1 -0
  640. package/web/dist/assets/pierre-light-CoaEpmwp.js +1 -0
  641. package/web/dist/assets/pierre-light-protanopia-deuteranopia-0fSaH845.js +1 -0
  642. package/web/dist/assets/pierre-light-soft-lWLdNTOI.js +1 -0
  643. package/web/dist/assets/pierre-light-tritanopia-CEbqgOJL.js +1 -0
  644. package/web/dist/assets/pierre-light-vibrant-D80Fkn33.js +1 -0
  645. package/web/dist/assets/pkl-ot-7Btpt.js +1 -0
  646. package/web/dist/assets/plastic-DQwYfKfQ.js +1 -0
  647. package/web/dist/assets/plsql-DGHpHOYJ.js +1 -0
  648. package/web/dist/assets/po-BiJDBrnU.js +1 -0
  649. package/web/dist/assets/poimandres-DRFjx7u4.js +1 -0
  650. package/web/dist/assets/polar-C7UOKdEL.js +1 -0
  651. package/web/dist/assets/postcss-BXeXVLqQ.js +1 -0
  652. package/web/dist/assets/powerquery-DNMTfnFr.js +1 -0
  653. package/web/dist/assets/powershell-DshXNtvi.js +1 -0
  654. package/web/dist/assets/prisma-BsRQq5mF.js +1 -0
  655. package/web/dist/assets/prolog-iXnhIJG7.js +1 -0
  656. package/web/dist/assets/proto-DB4EqR-F.js +1 -0
  657. package/web/dist/assets/pug-C5hz5LQ7.js +1 -0
  658. package/web/dist/assets/puppet-CDv2pdJW.js +1 -0
  659. package/web/dist/assets/purescript-9MfHhQsQ.js +1 -0
  660. package/web/dist/assets/python-gzcpVVnB.js +1 -0
  661. package/web/dist/assets/qml-BdUV3aTS.js +1 -0
  662. package/web/dist/assets/qmldir-DCQb3MpD.js +1 -0
  663. package/web/dist/assets/qss-Fe1Jh2GI.js +1 -0
  664. package/web/dist/assets/r-8R7vtdQc.js +1 -0
  665. package/web/dist/assets/racket-DcIDlBhZ.js +1 -0
  666. package/web/dist/assets/raku-B3gFvitq.js +1 -0
  667. package/web/dist/assets/razor-DRL52XO2.js +1 -0
  668. package/web/dist/assets/red-CJ3rzSJv.js +1 -0
  669. package/web/dist/assets/reg-CRGYupPL.js +1 -0
  670. package/web/dist/assets/regexp-Omp9DhTb.js +1 -0
  671. package/web/dist/assets/rel-BtDbiS_P.js +1 -0
  672. package/web/dist/assets/riscv-Ckw8ddFX.js +1 -0
  673. package/web/dist/assets/rolldown-runtime-QTnfLwEv.js +1 -0
  674. package/web/dist/assets/ron-VUp2lXgN.js +1 -0
  675. package/web/dist/assets/rose-pine-BthvhNj6.js +1 -0
  676. package/web/dist/assets/rose-pine-dawn-Dg85fqjY.js +1 -0
  677. package/web/dist/assets/rose-pine-moon-hon4tzzS.js +1 -0
  678. package/web/dist/assets/rosmsg-CAekHB0j.js +1 -0
  679. package/web/dist/assets/rst-BHX71KW9.js +1 -0
  680. package/web/dist/assets/ruby-B--HzjGU.js +1 -0
  681. package/web/dist/assets/rust-Cfkwpbl8.js +1 -0
  682. package/web/dist/assets/sas-DrLaYOK_.js +1 -0
  683. package/web/dist/assets/sass-DXrisJhu.js +1 -0
  684. package/web/dist/assets/scala-DKOlJaKm.js +1 -0
  685. package/web/dist/assets/scheme-DQCgrYNe.js +1 -0
  686. package/web/dist/assets/scss-DdSxiZKl.js +1 -0
  687. package/web/dist/assets/sdbl-bTVj8UrX.js +1 -0
  688. package/web/dist/assets/shaderlab-TOUzSsQk.js +1 -0
  689. package/web/dist/assets/shellscript-DwcUjJBL.js +1 -0
  690. package/web/dist/assets/shellsession-CPZkydE6.js +1 -0
  691. package/web/dist/assets/slack-dark-DnToyrRv.js +1 -0
  692. package/web/dist/assets/slack-ochin-B2OO5cIa.js +1 -0
  693. package/web/dist/assets/smalltalk-B16xEiuN.js +1 -0
  694. package/web/dist/assets/snazzy-light-4G7pJPwS.js +1 -0
  695. package/web/dist/assets/solarized-dark-DV17i1UV.js +1 -0
  696. package/web/dist/assets/solarized-light-DSh2HLQt.js +1 -0
  697. package/web/dist/assets/solidity-CKzVLygQ.js +1 -0
  698. package/web/dist/assets/soy-Br5FhD7c.js +1 -0
  699. package/web/dist/assets/sparql-D_iOobhT.js +1 -0
  700. package/web/dist/assets/splunk-BC2Px7Mm.js +1 -0
  701. package/web/dist/assets/sql-DNssxck8.js +1 -0
  702. package/web/dist/assets/ssh-config-BgfXC-Er.js +1 -0
  703. package/web/dist/assets/stata-DXn1tqOr.js +1 -0
  704. package/web/dist/assets/stylus-B6D30XZt.js +1 -0
  705. package/web/dist/assets/surfaces-B8Ko8AJ3.js +1 -0
  706. package/web/dist/assets/surrealql-IeLNQw0f.js +1 -0
  707. package/web/dist/assets/svelte-DOdLCIlh.js +1 -0
  708. package/web/dist/assets/swift-DonLKvLd.js +1 -0
  709. package/web/dist/assets/synthwave-84-nFMaYfgc.js +1 -0
  710. package/web/dist/assets/system-verilog-DJ5XKQeo.js +1 -0
  711. package/web/dist/assets/systemd-BxMlprV5.js +1 -0
  712. package/web/dist/assets/talonscript-CohzipZa.js +1 -0
  713. package/web/dist/assets/tasl-DMoTqEGO.js +1 -0
  714. package/web/dist/assets/tcl-CZd0xW_V.js +1 -0
  715. package/web/dist/assets/templ-CIwIngms.js +1 -0
  716. package/web/dist/assets/terraform-DswuEJGm.js +1 -0
  717. package/web/dist/assets/tex-D8QMumu5.js +1 -0
  718. package/web/dist/assets/tokyo-night-oM2G3aXe.js +1 -0
  719. package/web/dist/assets/toml-CcmNWLt0.js +1 -0
  720. package/web/dist/assets/ts-tags-BMVY4q-l.js +1 -0
  721. package/web/dist/assets/tsv-sltzmVWM.js +1 -0
  722. package/web/dist/assets/tsx-5Eka4NBX.js +1 -0
  723. package/web/dist/assets/turtle-ByJddavk.js +1 -0
  724. package/web/dist/assets/twig-C8o_5mgw.js +1 -0
  725. package/web/dist/assets/typescript-DOu2WMV5.js +1 -0
  726. package/web/dist/assets/typespec-BRdr0IET.js +1 -0
  727. package/web/dist/assets/typst-DI99ib-x.js +1 -0
  728. package/web/dist/assets/v-DETTlOr0.js +1 -0
  729. package/web/dist/assets/vala-zf12oZj6.js +1 -0
  730. package/web/dist/assets/vb-Djn5o6TS.js +1 -0
  731. package/web/dist/assets/verilog-CiiDBU1e.js +1 -0
  732. package/web/dist/assets/vesper-DdrHHSXu.js +1 -0
  733. package/web/dist/assets/vhdl-BroJfC0k.js +1 -0
  734. package/web/dist/assets/viml-DvXPmvsu.js +1 -0
  735. package/web/dist/assets/vitesse-black-fwtXNY1n.js +1 -0
  736. package/web/dist/assets/vitesse-dark-BZCL-v6S.js +1 -0
  737. package/web/dist/assets/vitesse-light-VbXTXTou.js +1 -0
  738. package/web/dist/assets/vue-BU18DNDL.js +1 -0
  739. package/web/dist/assets/vue-html-BeluIYX0.js +1 -0
  740. package/web/dist/assets/vue-vine-DGUAbOCX.js +1 -0
  741. package/web/dist/assets/vyper-CgoNMtux.js +1 -0
  742. package/web/dist/assets/wasm-BnjxR4X6.js +1 -0
  743. package/web/dist/assets/wasm-ByWQv1Qj.js +1 -0
  744. package/web/dist/assets/wenyan-C8pVoKbM.js +1 -0
  745. package/web/dist/assets/wgsl-BsKzXJz4.js +1 -0
  746. package/web/dist/assets/wikitext-ClFFjSW2.js +1 -0
  747. package/web/dist/assets/wit-DdvCle-K.js +1 -0
  748. package/web/dist/assets/wolfram-DLL8P-h_.js +1 -0
  749. package/web/dist/assets/worker-CBKQOXEl.js +160 -0
  750. package/web/dist/assets/xml-DIqSwXR3.js +1 -0
  751. package/web/dist/assets/xsl-Ct_-YIAy.js +1 -0
  752. package/web/dist/assets/yaml-DTtCYNlS.js +1 -0
  753. package/web/dist/assets/zenscript-BnlCZFoB.js +1 -0
  754. package/web/dist/assets/zig-CMLA9XwU.js +1 -0
  755. package/web/dist/icons/neondeck-icon-192.png +0 -0
  756. package/web/dist/icons/neondeck-icon-512.png +0 -0
  757. package/web/dist/icons/neondeck-icon.svg +41 -0
  758. package/web/dist/icons/neondeck-maskable-512.png +0 -0
  759. package/web/dist/index.html +24 -0
  760. package/web/dist/manifest.webmanifest +28 -0
@@ -0,0 +1,814 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ import { asJsonValue } from '../../lib/action-result';
3
+ import { openDb } from '../../lib/sqlite';
4
+ import { ensureRuntimeHome, runtimePaths } from '../../runtime-home';
5
+ import {
6
+ scheduledTaskSpecSchema,
7
+ type AutomationTrigger,
8
+ type ScheduledTaskRecord,
9
+ type ScheduledTaskRunRecord,
10
+ } from './schemas';
11
+ import { nextOccurrence, validateAutomationTrigger } from './triggers';
12
+ import * as v from 'valibot';
13
+
14
+ const defaultClaimTtlMs = 5 * 60 * 1_000;
15
+ export const maxActiveScheduledWorkflowRuns = 10;
16
+
17
+ export async function listScheduledTasks(paths = runtimePaths()) {
18
+ await ensureRuntimeHome(paths);
19
+ const database = openDb(paths.neondeckDatabase);
20
+ try {
21
+ return database
22
+ .prepare(
23
+ `
24
+ SELECT *
25
+ FROM scheduled_tasks
26
+ ORDER BY next_run_at ASC, updated_at DESC;
27
+ `,
28
+ )
29
+ .all()
30
+ .map(readScheduledTaskRow);
31
+ } finally {
32
+ database.close();
33
+ }
34
+ }
35
+
36
+ export async function readScheduledTask(id: string, paths = runtimePaths()) {
37
+ await ensureRuntimeHome(paths);
38
+ const database = openDb(paths.neondeckDatabase);
39
+ try {
40
+ const row = database
41
+ .prepare('SELECT * FROM scheduled_tasks WHERE id = ?;')
42
+ .get(id);
43
+ return row ? readScheduledTaskRow(row) : undefined;
44
+ } finally {
45
+ database.close();
46
+ }
47
+ }
48
+
49
+ export async function readLatestScheduledTaskRun(
50
+ taskId: string,
51
+ paths = runtimePaths(),
52
+ ) {
53
+ await ensureRuntimeHome(paths);
54
+ const database = openDb(paths.neondeckDatabase);
55
+ try {
56
+ const row = database
57
+ .prepare(
58
+ `
59
+ SELECT *
60
+ FROM scheduled_task_runs
61
+ WHERE task_id = ? AND status IN ('completed', 'failed')
62
+ ORDER BY created_at DESC
63
+ LIMIT 1;
64
+ `,
65
+ )
66
+ .get(taskId);
67
+ return row ? readScheduledTaskRunRow(row) : undefined;
68
+ } finally {
69
+ database.close();
70
+ }
71
+ }
72
+
73
+ export async function upsertScheduledTask(
74
+ input: {
75
+ id: string;
76
+ spec: unknown;
77
+ trigger: unknown;
78
+ enabled?: boolean;
79
+ nextRunAt?: string | null;
80
+ },
81
+ paths = runtimePaths(),
82
+ ) {
83
+ await ensureRuntimeHome(paths);
84
+ const spec = v.parse(scheduledTaskSpecSchema, input.spec);
85
+ const triggerResult = validateAutomationTrigger(input.trigger);
86
+ if (!triggerResult.ok) throw new Error(triggerResult.message);
87
+ const trigger = triggerResult.trigger;
88
+ const now = new Date();
89
+ const existing = await readScheduledTask(input.id, paths);
90
+ if (existing && existing.spec.kind !== spec.kind) {
91
+ throw new Error(
92
+ `Scheduled task "${input.id}" is a ${existing.spec.kind} task and cannot be replaced with ${spec.kind}.`,
93
+ );
94
+ }
95
+ const record: ScheduledTaskRecord = {
96
+ id: input.id,
97
+ spec,
98
+ trigger,
99
+ enabled: input.enabled ?? existing?.enabled ?? true,
100
+ nextRunAt:
101
+ input.nextRunAt ??
102
+ (existing && sameTrigger(existing.trigger, trigger)
103
+ ? existing.nextRunAt
104
+ : nextOccurrence(trigger, now)),
105
+ claimId: existing?.claimId ?? null,
106
+ claimExpiresAt: existing?.claimExpiresAt ?? null,
107
+ lastRunAt: existing?.lastRunAt ?? null,
108
+ createdAt: existing?.createdAt ?? now.toISOString(),
109
+ updatedAt: now.toISOString(),
110
+ };
111
+ const database = openDb(paths.neondeckDatabase);
112
+ try {
113
+ database
114
+ .prepare(
115
+ `
116
+ INSERT INTO scheduled_tasks (
117
+ id, kind, trigger_json, payload_json, enabled, next_run_at,
118
+ claim_id, claim_expires_at, last_run_at, created_at, updated_at
119
+ )
120
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
121
+ ON CONFLICT(id) DO UPDATE SET
122
+ kind = excluded.kind,
123
+ trigger_json = excluded.trigger_json,
124
+ payload_json = excluded.payload_json,
125
+ enabled = excluded.enabled,
126
+ next_run_at = excluded.next_run_at,
127
+ updated_at = excluded.updated_at;
128
+ `,
129
+ )
130
+ .run(
131
+ record.id,
132
+ record.spec.kind,
133
+ JSON.stringify(asJsonValue(record.trigger)),
134
+ JSON.stringify(asJsonValue(record.spec)),
135
+ record.enabled ? 1 : 0,
136
+ record.nextRunAt,
137
+ record.claimId,
138
+ record.claimExpiresAt,
139
+ record.lastRunAt,
140
+ record.createdAt,
141
+ record.updatedAt,
142
+ );
143
+ } finally {
144
+ database.close();
145
+ }
146
+ return record;
147
+ }
148
+
149
+ export async function deleteScheduledTask(id: string, paths = runtimePaths()) {
150
+ await ensureRuntimeHome(paths);
151
+ const database = openDb(paths.neondeckDatabase);
152
+ try {
153
+ database.exec('BEGIN IMMEDIATE;');
154
+ database
155
+ .prepare('DELETE FROM scheduled_task_runs WHERE task_id = ?;')
156
+ .run(id);
157
+ database.prepare('DELETE FROM scheduled_tasks WHERE id = ?;').run(id);
158
+ database.exec('COMMIT;');
159
+ } catch (error) {
160
+ database.exec('ROLLBACK;');
161
+ throw error;
162
+ } finally {
163
+ database.close();
164
+ }
165
+ }
166
+
167
+ export async function setScheduledTaskEnabled(
168
+ id: string,
169
+ enabled: boolean,
170
+ paths = runtimePaths(),
171
+ ) {
172
+ await ensureRuntimeHome(paths);
173
+ const database = openDb(paths.neondeckDatabase);
174
+ try {
175
+ database.exec('BEGIN IMMEDIATE;');
176
+ const current = database
177
+ .prepare('SELECT * FROM scheduled_tasks WHERE id = ?;')
178
+ .get(id);
179
+ if (!current) {
180
+ database.exec('COMMIT;');
181
+ return undefined;
182
+ }
183
+ const task = readScheduledTaskRow(current);
184
+ const now = new Date();
185
+ const resumeAt =
186
+ enabled &&
187
+ !task.enabled &&
188
+ (!task.nextRunAt || Date.parse(task.nextRunAt) <= now.getTime())
189
+ ? nextOccurrence(task.trigger, now)
190
+ : task.nextRunAt;
191
+ const nextEnabled = enabled && (task.trigger.kind !== 'once' || resumeAt);
192
+ const result = database
193
+ .prepare(
194
+ `
195
+ UPDATE scheduled_tasks
196
+ SET enabled = ?, next_run_at = ?, updated_at = ?
197
+ WHERE id = ?;
198
+ `,
199
+ )
200
+ .run(nextEnabled ? 1 : 0, resumeAt, now.toISOString(), id);
201
+ database.exec('COMMIT;');
202
+ if (result.changes !== 1) return undefined;
203
+ } catch (error) {
204
+ database.exec('ROLLBACK;');
205
+ throw error;
206
+ } finally {
207
+ database.close();
208
+ }
209
+ return readScheduledTask(id, paths);
210
+ }
211
+
212
+ export async function claimDueScheduledTasks(
213
+ paths = runtimePaths(),
214
+ now = new Date(),
215
+ limit = 10,
216
+ claimTtlMs = defaultClaimTtlMs,
217
+ ) {
218
+ await ensureRuntimeHome(paths);
219
+ const database = openDb(paths.neondeckDatabase);
220
+ const claimed: Array<{
221
+ task: ScheduledTaskRecord;
222
+ previous: ScheduledTaskRecord;
223
+ run: ScheduledTaskRunRecord;
224
+ }> = [];
225
+ const nowIso = now.toISOString();
226
+ const expiresAt = new Date(now.getTime() + claimTtlMs).toISOString();
227
+ const staleUnattachedRunAt = new Date(
228
+ now.getTime() - claimTtlMs,
229
+ ).toISOString();
230
+ try {
231
+ database.exec('BEGIN IMMEDIATE;');
232
+ database
233
+ .prepare(
234
+ `
235
+ UPDATE scheduled_tasks
236
+ SET enabled = 1, next_run_at = ?, updated_at = ?
237
+ WHERE json_extract(trigger_json, '$.kind') = 'once'
238
+ AND EXISTS (
239
+ SELECT 1 FROM scheduled_task_runs
240
+ WHERE scheduled_task_runs.task_id = scheduled_tasks.id
241
+ AND scheduled_task_runs.status = 'active'
242
+ AND scheduled_task_runs.workflow_run_id IS NULL
243
+ AND scheduled_task_runs.started_at <= ?
244
+ );
245
+ `,
246
+ )
247
+ .run(nowIso, nowIso, staleUnattachedRunAt);
248
+ database
249
+ .prepare(
250
+ `
251
+ UPDATE scheduled_task_runs
252
+ SET status = 'failed', outcome = 'failed',
253
+ message = 'Scheduled workflow admission was not durably attached before recovery.',
254
+ error = 'Scheduled workflow run id was not attached before the recovery deadline.',
255
+ completed_at = ?, updated_at = ?
256
+ WHERE status = 'active'
257
+ AND workflow_run_id IS NULL
258
+ AND started_at <= ?;
259
+ `,
260
+ )
261
+ .run(nowIso, nowIso, staleUnattachedRunAt);
262
+ database
263
+ .prepare(
264
+ `
265
+ UPDATE scheduled_tasks
266
+ SET enabled = 1, next_run_at = ?, updated_at = ?
267
+ WHERE json_extract(trigger_json, '$.kind') = 'once'
268
+ AND claim_id IS NOT NULL
269
+ AND claim_expires_at <= ?;
270
+ `,
271
+ )
272
+ .run(nowIso, nowIso, nowIso);
273
+ database
274
+ .prepare(
275
+ `
276
+ UPDATE scheduled_task_runs
277
+ SET status = 'failed', outcome = 'failed',
278
+ message = 'Scheduled task claim expired before execution completed.',
279
+ error = 'Scheduled task claim expired before execution completed.',
280
+ completed_at = ?, updated_at = ?
281
+ WHERE status = 'claimed'
282
+ AND EXISTS (
283
+ SELECT 1
284
+ FROM scheduled_tasks
285
+ WHERE scheduled_tasks.id = scheduled_task_runs.task_id
286
+ AND scheduled_tasks.claim_id IS NOT NULL
287
+ AND scheduled_tasks.claim_expires_at <= ?
288
+ );
289
+ `,
290
+ )
291
+ .run(nowIso, nowIso, nowIso);
292
+ database
293
+ .prepare(
294
+ `
295
+ UPDATE scheduled_tasks
296
+ SET claim_id = NULL, claim_expires_at = NULL, updated_at = ?
297
+ WHERE claim_id IS NOT NULL AND claim_expires_at <= ?;
298
+ `,
299
+ )
300
+ .run(nowIso, nowIso);
301
+ const due = database
302
+ .prepare(
303
+ `
304
+ SELECT *
305
+ FROM scheduled_tasks
306
+ WHERE enabled = 1
307
+ AND next_run_at IS NOT NULL
308
+ AND next_run_at <= ?
309
+ AND (claim_expires_at IS NULL OR claim_expires_at <= ?)
310
+ AND NOT EXISTS (
311
+ SELECT 1
312
+ FROM scheduled_task_runs
313
+ WHERE scheduled_task_runs.task_id = scheduled_tasks.id
314
+ AND scheduled_task_runs.status = 'active'
315
+ )
316
+ ORDER BY next_run_at ASC, id ASC
317
+ LIMIT ?;
318
+ `,
319
+ )
320
+ .all(nowIso, nowIso, limit)
321
+ .map(readScheduledTaskRow);
322
+
323
+ for (const task of due) {
324
+ const claimId = `scheduled-task-claim:${randomUUID()}`;
325
+ const runId = `scheduled-task-run:${randomUUID()}`;
326
+ const nextRunAt = nextOccurrence(task.trigger, now);
327
+ const enabled = task.trigger.kind === 'once' ? false : task.enabled;
328
+ const updated = database
329
+ .prepare(
330
+ `
331
+ UPDATE scheduled_tasks
332
+ SET claim_id = ?, claim_expires_at = ?, next_run_at = ?,
333
+ enabled = ?, last_run_at = ?, updated_at = ?
334
+ WHERE id = ?
335
+ AND enabled = 1
336
+ AND (claim_expires_at IS NULL OR claim_expires_at <= ?);
337
+ `,
338
+ )
339
+ .run(
340
+ claimId,
341
+ expiresAt,
342
+ nextRunAt,
343
+ enabled ? 1 : 0,
344
+ nowIso,
345
+ nowIso,
346
+ task.id,
347
+ nowIso,
348
+ );
349
+ if (updated.changes !== 1) continue;
350
+ const run: ScheduledTaskRunRecord = {
351
+ id: runId,
352
+ taskId: task.id,
353
+ status: 'claimed',
354
+ outcome: 'recorded',
355
+ message: 'Scheduled task claimed.',
356
+ workflowRunId: null,
357
+ sessionId: null,
358
+ result: null,
359
+ error: null,
360
+ startedAt: nowIso,
361
+ completedAt: null,
362
+ createdAt: nowIso,
363
+ updatedAt: nowIso,
364
+ };
365
+ database
366
+ .prepare(
367
+ `
368
+ INSERT INTO scheduled_task_runs (
369
+ id, task_id, status, outcome, message, workflow_run_id, session_id,
370
+ result_json, error, started_at, completed_at, created_at, updated_at
371
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);
372
+ `,
373
+ )
374
+ .run(
375
+ run.id,
376
+ run.taskId,
377
+ run.status,
378
+ run.outcome,
379
+ run.message,
380
+ null,
381
+ null,
382
+ null,
383
+ null,
384
+ run.startedAt,
385
+ null,
386
+ run.createdAt,
387
+ run.updatedAt,
388
+ );
389
+ claimed.push({
390
+ task: {
391
+ ...task,
392
+ enabled,
393
+ nextRunAt,
394
+ claimId,
395
+ claimExpiresAt: expiresAt,
396
+ lastRunAt: nowIso,
397
+ updatedAt: nowIso,
398
+ },
399
+ previous: task,
400
+ run,
401
+ });
402
+ }
403
+ database.exec('COMMIT;');
404
+ return claimed;
405
+ } catch (error) {
406
+ database.exec('ROLLBACK;');
407
+ throw error;
408
+ } finally {
409
+ database.close();
410
+ }
411
+ }
412
+
413
+ export async function releaseUnstartedScheduledTaskClaim(
414
+ input: {
415
+ task: ScheduledTaskRecord;
416
+ previous: ScheduledTaskRecord;
417
+ run: ScheduledTaskRunRecord;
418
+ message: string;
419
+ },
420
+ paths = runtimePaths(),
421
+ ) {
422
+ await ensureRuntimeHome(paths);
423
+ const now = new Date().toISOString();
424
+ const database = openDb(paths.neondeckDatabase);
425
+ try {
426
+ database.exec('BEGIN IMMEDIATE;');
427
+ database
428
+ .prepare(
429
+ `
430
+ UPDATE scheduled_task_runs
431
+ SET status = 'failed', outcome = 'failed', message = ?, error = ?,
432
+ completed_at = ?, updated_at = ?
433
+ WHERE id = ? AND task_id = ? AND status IN ('claimed', 'active');
434
+ `,
435
+ )
436
+ .run(input.message, input.message, now, now, input.run.id, input.task.id);
437
+ database
438
+ .prepare(
439
+ `
440
+ UPDATE scheduled_tasks
441
+ SET enabled = ?, next_run_at = ?, claim_id = NULL, claim_expires_at = NULL,
442
+ last_run_at = ?, updated_at = ?
443
+ WHERE id = ? AND claim_id = ?;
444
+ `,
445
+ )
446
+ .run(
447
+ input.previous.enabled ? 1 : 0,
448
+ input.previous.nextRunAt,
449
+ input.previous.lastRunAt,
450
+ now,
451
+ input.task.id,
452
+ input.task.claimId,
453
+ );
454
+ database.exec('COMMIT;');
455
+ } catch (error) {
456
+ database.exec('ROLLBACK;');
457
+ throw error;
458
+ } finally {
459
+ database.close();
460
+ }
461
+ }
462
+
463
+ export async function deferUnstartedScheduledTaskClaim(
464
+ input: {
465
+ task: ScheduledTaskRecord;
466
+ previous: ScheduledTaskRecord;
467
+ run: ScheduledTaskRunRecord;
468
+ message: string;
469
+ },
470
+ paths = runtimePaths(),
471
+ ) {
472
+ await ensureRuntimeHome(paths);
473
+ const now = new Date();
474
+ const nowIso = now.toISOString();
475
+ const retryAt = new Date(now.getTime() + 60_000).toISOString();
476
+ const nextRunAt =
477
+ input.task.trigger.kind === 'once'
478
+ ? retryAt
479
+ : nextOccurrence(input.task.trigger, now);
480
+ const enabled =
481
+ input.task.trigger.kind === 'once'
482
+ ? input.previous.enabled
483
+ : input.task.enabled;
484
+ const database = openDb(paths.neondeckDatabase);
485
+ try {
486
+ database.exec('BEGIN IMMEDIATE;');
487
+ database
488
+ .prepare(
489
+ `
490
+ UPDATE scheduled_task_runs
491
+ SET status = 'completed', outcome = 'silent', message = ?, error = NULL,
492
+ completed_at = ?, updated_at = ?
493
+ WHERE id = ? AND task_id = ? AND status IN ('claimed', 'active');
494
+ `,
495
+ )
496
+ .run(input.message, nowIso, nowIso, input.run.id, input.task.id);
497
+ database
498
+ .prepare(
499
+ `
500
+ UPDATE scheduled_tasks
501
+ SET enabled = ?, next_run_at = ?, claim_id = NULL, claim_expires_at = NULL,
502
+ updated_at = ?
503
+ WHERE id = ? AND claim_id = ?;
504
+ `,
505
+ )
506
+ .run(
507
+ enabled ? 1 : 0,
508
+ nextRunAt,
509
+ nowIso,
510
+ input.task.id,
511
+ input.task.claimId,
512
+ );
513
+ database.exec('COMMIT;');
514
+ } catch (error) {
515
+ database.exec('ROLLBACK;');
516
+ throw error;
517
+ } finally {
518
+ database.close();
519
+ }
520
+ }
521
+
522
+ export async function canAdmitScheduledWorkflow(
523
+ taskId: string,
524
+ paths = runtimePaths(),
525
+ maximumActiveRuns = maxActiveScheduledWorkflowRuns,
526
+ ) {
527
+ await ensureRuntimeHome(paths);
528
+ const database = openDb(paths.neondeckDatabase);
529
+ try {
530
+ const activeForTask = database
531
+ .prepare(
532
+ `
533
+ SELECT 1
534
+ FROM scheduled_task_runs
535
+ WHERE task_id = ? AND status = 'active'
536
+ LIMIT 1;
537
+ `,
538
+ )
539
+ .get(taskId);
540
+ if (activeForTask) return false;
541
+ const row = database
542
+ .prepare(
543
+ `
544
+ SELECT COUNT(*) AS count
545
+ FROM scheduled_task_runs
546
+ WHERE status = 'active';
547
+ `,
548
+ )
549
+ .get() as { count?: unknown } | undefined;
550
+ return Number(row?.count ?? 0) < maximumActiveRuns;
551
+ } finally {
552
+ database.close();
553
+ }
554
+ }
555
+
556
+ export async function activateScheduledTaskWorkflowRun(
557
+ input: { taskId: string; runId: string; claimId: string },
558
+ paths = runtimePaths(),
559
+ ) {
560
+ await ensureRuntimeHome(paths);
561
+ const now = new Date().toISOString();
562
+ const database = openDb(paths.neondeckDatabase);
563
+ try {
564
+ database.exec('BEGIN IMMEDIATE;');
565
+ const run = database
566
+ .prepare(
567
+ `
568
+ UPDATE scheduled_task_runs
569
+ SET status = 'active', message = ?, updated_at = ?
570
+ WHERE id = ? AND task_id = ? AND status = 'claimed';
571
+ `,
572
+ )
573
+ .run(
574
+ 'Scheduled workflow admitted and awaiting terminal observation.',
575
+ now,
576
+ input.runId,
577
+ input.taskId,
578
+ );
579
+ if (run.changes !== 1)
580
+ throw new Error('Scheduled task run is not claimable.');
581
+ database
582
+ .prepare(
583
+ `
584
+ UPDATE scheduled_tasks
585
+ SET claim_id = NULL, claim_expires_at = NULL, updated_at = ?
586
+ WHERE id = ? AND claim_id = ?;
587
+ `,
588
+ )
589
+ .run(now, input.taskId, input.claimId);
590
+ database.exec('COMMIT;');
591
+ } catch (error) {
592
+ database.exec('ROLLBACK;');
593
+ throw error;
594
+ } finally {
595
+ database.close();
596
+ }
597
+ }
598
+
599
+ export async function attachScheduledTaskWorkflowRunId(
600
+ input: { runId: string; workflowRunId: string },
601
+ paths = runtimePaths(),
602
+ ) {
603
+ await ensureRuntimeHome(paths);
604
+ const database = openDb(paths.neondeckDatabase);
605
+ try {
606
+ database.exec('BEGIN IMMEDIATE;');
607
+ const terminal = database
608
+ .prepare(
609
+ `
610
+ SELECT status, ended_at
611
+ FROM workflow_run_observations
612
+ WHERE run_id = ? AND status IN ('completed', 'failed');
613
+ `,
614
+ )
615
+ .get(input.workflowRunId) as
616
+ { status?: unknown; ended_at?: unknown } | undefined;
617
+ database
618
+ .prepare(
619
+ `
620
+ UPDATE scheduled_task_runs
621
+ SET workflow_run_id = ?, status = ?, outcome = ?, message = ?, error = ?,
622
+ completed_at = ?, updated_at = ?
623
+ WHERE id = ? AND status = 'active';
624
+ `,
625
+ )
626
+ .run(
627
+ input.workflowRunId,
628
+ terminal?.status === 'failed'
629
+ ? 'failed'
630
+ : terminal
631
+ ? 'completed'
632
+ : 'active',
633
+ terminal?.status === 'failed' ? 'failed' : 'recorded',
634
+ terminal
635
+ ? terminal.status === 'failed'
636
+ ? 'Scheduled workflow failed; see Flue run details.'
637
+ : 'Scheduled workflow completed.'
638
+ : 'Scheduled workflow admitted and awaiting terminal observation.',
639
+ terminal?.status === 'failed' ? 'See Flue run details.' : null,
640
+ terminal
641
+ ? typeof terminal.ended_at === 'string'
642
+ ? terminal.ended_at
643
+ : new Date().toISOString()
644
+ : null,
645
+ new Date().toISOString(),
646
+ input.runId,
647
+ );
648
+ database.exec('COMMIT;');
649
+ } catch (error) {
650
+ database.exec('ROLLBACK;');
651
+ throw error;
652
+ } finally {
653
+ database.close();
654
+ }
655
+ }
656
+
657
+ export async function settleScheduledTaskWorkflowRun(
658
+ input: { workflowRunId: string; failed: boolean },
659
+ paths = runtimePaths(),
660
+ ) {
661
+ await ensureRuntimeHome(paths);
662
+ const now = new Date().toISOString();
663
+ const database = openDb(paths.neondeckDatabase);
664
+ try {
665
+ database
666
+ .prepare(
667
+ `
668
+ UPDATE scheduled_task_runs
669
+ SET status = ?, outcome = ?, message = ?, error = ?, completed_at = ?, updated_at = ?
670
+ WHERE workflow_run_id = ? AND status = 'active';
671
+ `,
672
+ )
673
+ .run(
674
+ input.failed ? 'failed' : 'completed',
675
+ input.failed ? 'failed' : 'recorded',
676
+ input.failed
677
+ ? 'Scheduled workflow failed; see Flue run details.'
678
+ : 'Scheduled workflow completed.',
679
+ input.failed ? 'See Flue run details.' : null,
680
+ now,
681
+ now,
682
+ input.workflowRunId,
683
+ );
684
+ } finally {
685
+ database.close();
686
+ }
687
+ }
688
+
689
+ export async function settleScheduledTaskRun(
690
+ input: {
691
+ taskId: string;
692
+ runId: string;
693
+ claimId: string;
694
+ status: 'completed' | 'failed';
695
+ outcome: 'recorded' | 'silent' | 'failed';
696
+ message: string;
697
+ workflowRunId?: string | null;
698
+ sessionId?: string | null;
699
+ result?: unknown;
700
+ error?: string | null;
701
+ },
702
+ paths = runtimePaths(),
703
+ ) {
704
+ await ensureRuntimeHome(paths);
705
+ const now = new Date().toISOString();
706
+ const database = openDb(paths.neondeckDatabase);
707
+ try {
708
+ database.exec('BEGIN IMMEDIATE;');
709
+ database
710
+ .prepare(
711
+ `
712
+ UPDATE scheduled_task_runs
713
+ SET status = ?, outcome = ?, message = ?, workflow_run_id = ?, session_id = ?,
714
+ result_json = ?, error = ?, completed_at = ?, updated_at = ?
715
+ WHERE id = ? AND task_id = ?;
716
+ `,
717
+ )
718
+ .run(
719
+ input.status,
720
+ input.outcome,
721
+ input.message,
722
+ input.workflowRunId ?? null,
723
+ input.sessionId ?? null,
724
+ input.result === undefined
725
+ ? null
726
+ : JSON.stringify(asJsonValue(input.result)),
727
+ input.error ?? null,
728
+ now,
729
+ now,
730
+ input.runId,
731
+ input.taskId,
732
+ );
733
+ database
734
+ .prepare(
735
+ `
736
+ UPDATE scheduled_tasks
737
+ SET claim_id = NULL, claim_expires_at = NULL, updated_at = ?
738
+ WHERE id = ? AND claim_id = ?;
739
+ `,
740
+ )
741
+ .run(now, input.taskId, input.claimId);
742
+ database.exec('COMMIT;');
743
+ } catch (error) {
744
+ database.exec('ROLLBACK;');
745
+ throw error;
746
+ } finally {
747
+ database.close();
748
+ }
749
+ }
750
+
751
+ function readScheduledTaskRow(row: unknown): ScheduledTaskRecord {
752
+ const record = row as Record<string, unknown>;
753
+ const spec = v.parse(
754
+ scheduledTaskSpecSchema,
755
+ JSON.parse(String(record.payload_json)),
756
+ );
757
+ const triggerResult = validateAutomationTrigger(
758
+ JSON.parse(String(record.trigger_json)),
759
+ );
760
+ if (!triggerResult.ok) throw new Error(triggerResult.message);
761
+ return {
762
+ id: String(record.id),
763
+ spec,
764
+ trigger: triggerResult.trigger,
765
+ enabled: Boolean(record.enabled),
766
+ nextRunAt:
767
+ typeof record.next_run_at === 'string' ? record.next_run_at : null,
768
+ claimId: typeof record.claim_id === 'string' ? record.claim_id : null,
769
+ claimExpiresAt:
770
+ typeof record.claim_expires_at === 'string'
771
+ ? record.claim_expires_at
772
+ : null,
773
+ lastRunAt:
774
+ typeof record.last_run_at === 'string' ? record.last_run_at : null,
775
+ createdAt: String(record.created_at),
776
+ updatedAt: String(record.updated_at),
777
+ };
778
+ }
779
+
780
+ function readScheduledTaskRunRow(row: unknown): ScheduledTaskRunRecord {
781
+ const record = row as Record<string, unknown>;
782
+ return {
783
+ id: String(record.id),
784
+ taskId: String(record.task_id),
785
+ status: v.parse(
786
+ v.picklist(['claimed', 'active', 'completed', 'failed']),
787
+ record.status,
788
+ ),
789
+ outcome: v.parse(
790
+ v.picklist(['recorded', 'silent', 'failed']),
791
+ record.outcome,
792
+ ),
793
+ message: String(record.message),
794
+ workflowRunId:
795
+ typeof record.workflow_run_id === 'string'
796
+ ? record.workflow_run_id
797
+ : null,
798
+ sessionId: typeof record.session_id === 'string' ? record.session_id : null,
799
+ result:
800
+ typeof record.result_json === 'string'
801
+ ? (JSON.parse(record.result_json) as ScheduledTaskRunRecord['result'])
802
+ : null,
803
+ error: typeof record.error === 'string' ? record.error : null,
804
+ startedAt: String(record.started_at),
805
+ completedAt:
806
+ typeof record.completed_at === 'string' ? record.completed_at : null,
807
+ createdAt: String(record.created_at),
808
+ updatedAt: String(record.updated_at),
809
+ };
810
+ }
811
+
812
+ function sameTrigger(left: AutomationTrigger, right: AutomationTrigger) {
813
+ return JSON.stringify(left) === JSON.stringify(right);
814
+ }