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,865 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ import { openDb } from '../../lib/sqlite';
3
+ import {
4
+ ensureRuntimeHome,
5
+ parseAppConfig,
6
+ readRuntimeJson,
7
+ runtimePaths,
8
+ } from '../../runtime-home';
9
+ import { readRepoRegistrySnapshot } from '../repos';
10
+ import { listPrWatchRecords } from '../watches';
11
+ import type {
12
+ AutopilotConcurrencyPolicy,
13
+ AutopilotMode,
14
+ } from '../autopilot-policy';
15
+ import { repoAutopilotPolicyForWatch } from '../autopilot-policy';
16
+
17
+ export type AutopilotAdmissionState =
18
+ | 'triage-admitted'
19
+ | 'triaged'
20
+ | 'prepare-admitted'
21
+ | 'prepared'
22
+ | 'blocked'
23
+ | 'manual-review'
24
+ | 'failed'
25
+ | 'superseded';
26
+
27
+ export type AutopilotAdmission = {
28
+ id: string;
29
+ watchId: string;
30
+ eventFingerprint: string;
31
+ repoId: string;
32
+ prNumber: number;
33
+ mode: AutopilotMode;
34
+ input: Record<string, unknown>;
35
+ state: AutopilotAdmissionState;
36
+ currentWorkflow: string | null;
37
+ currentRunId: string | null;
38
+ worktreeId: string | null;
39
+ attemptCount: number;
40
+ nextAttemptAt: string | null;
41
+ lastError: string | null;
42
+ createdAt: string;
43
+ updatedAt: string;
44
+ };
45
+
46
+ export type AutopilotAdmissionTerminalFact = {
47
+ workflow: 'triage-pr-event' | 'prepare-pr-worktree';
48
+ failed: boolean;
49
+ shouldPrepare?: boolean;
50
+ worktreeId?: string;
51
+ };
52
+
53
+ const terminalFactKeyPrefix = 'autopilot.admission.terminal:';
54
+ const staleAdmissionMs = 5 * 60 * 1000;
55
+ const terminalFactRetentionMs = 60 * 60 * 1000;
56
+
57
+ export async function reconcileAutopilotAdmissions(
58
+ paths = runtimePaths(),
59
+ now = new Date(),
60
+ ) {
61
+ await ensureRuntimeHome(paths);
62
+ const database = openDb(paths.neondeckDatabase);
63
+ const nowIso = now.toISOString();
64
+ const staleBefore = new Date(now.getTime() - staleAdmissionMs).toISOString();
65
+ const factBefore = new Date(
66
+ now.getTime() - terminalFactRetentionMs,
67
+ ).toISOString();
68
+ try {
69
+ database.exec('BEGIN IMMEDIATE;');
70
+ database
71
+ .prepare(
72
+ `UPDATE autopilot_admissions
73
+ SET state = 'failed', current_workflow = NULL, last_error = ?,
74
+ next_attempt_at = ?, updated_at = ?
75
+ WHERE state IN ('triage-admitted', 'prepare-admitted')
76
+ AND current_run_id IS NULL
77
+ AND updated_at <= ?;`,
78
+ )
79
+ .run(
80
+ 'Autopilot admission became stale before its workflow completed.',
81
+ nowIso,
82
+ nowIso,
83
+ staleBefore,
84
+ );
85
+ const terminalRuns = database
86
+ .prepare(
87
+ `SELECT a.*, observation.status AS observation_status,
88
+ observation.last_event_at AS observation_last_event_at
89
+ FROM autopilot_admissions AS a
90
+ JOIN workflow_run_observations AS observation
91
+ ON observation.run_id = a.current_run_id
92
+ WHERE a.state IN ('triage-admitted', 'prepare-admitted')
93
+ AND observation.status IN ('completed', 'failed');`,
94
+ )
95
+ .all();
96
+ for (const run of terminalRuns) {
97
+ const admission = readAdmission(run);
98
+ if (!admission) continue;
99
+ const terminal = readTerminalFact(
100
+ database
101
+ .prepare('SELECT value FROM app_metadata WHERE key = ?;')
102
+ .get(terminalFactKey(admission.currentRunId ?? '')),
103
+ );
104
+ if (
105
+ !terminal &&
106
+ (run as { observation_status?: unknown }).observation_status ===
107
+ 'completed' &&
108
+ Date.parse(
109
+ String(
110
+ (run as { observation_last_event_at?: unknown })
111
+ .observation_last_event_at ?? '',
112
+ ),
113
+ ) > Date.parse(staleBefore)
114
+ ) {
115
+ continue;
116
+ }
117
+ const settled = settledAdmissionState(
118
+ admission,
119
+ terminal,
120
+ (run as { observation_status?: unknown }).observation_status ===
121
+ 'failed',
122
+ );
123
+ const preserveTriageDecision =
124
+ terminal?.workflow === 'triage-pr-event' &&
125
+ !terminal.failed &&
126
+ terminal.shouldPrepare === true;
127
+ const uncertainPrepare =
128
+ !terminal &&
129
+ admission.currentWorkflow === 'prepare-pr-worktree' &&
130
+ (run as { observation_status?: unknown }).observation_status ===
131
+ 'completed';
132
+ database
133
+ .prepare(
134
+ `UPDATE autopilot_admissions
135
+ SET state = ?, current_workflow = NULL, worktree_id = ?, last_error = ?,
136
+ next_attempt_at = ?, updated_at = ?
137
+ WHERE id = ?;`,
138
+ )
139
+ .run(
140
+ terminal
141
+ ? settled.state
142
+ : uncertainPrepare
143
+ ? 'manual-review'
144
+ : 'failed',
145
+ settled.worktreeId ?? admission.worktreeId,
146
+ uncertainPrepare
147
+ ? 'Prepare run completed before its durable result was recorded; inspect before retrying.'
148
+ : settled.failed
149
+ ? 'Attached Flue run ended before its durable result was recorded.'
150
+ : null,
151
+ uncertainPrepare || !settled.failed ? null : nowIso,
152
+ nowIso,
153
+ admission.id,
154
+ );
155
+ if (terminal && !preserveTriageDecision) {
156
+ database
157
+ .prepare('DELETE FROM app_metadata WHERE key = ?;')
158
+ .run(terminalFactKey(admission.currentRunId ?? ''));
159
+ }
160
+ }
161
+ const due = database
162
+ .prepare(
163
+ `SELECT * FROM autopilot_admissions
164
+ WHERE state IN ('blocked', 'failed')
165
+ AND (next_attempt_at IS NULL OR next_attempt_at <= ?)
166
+ ORDER BY priority DESC, updated_at ASC;`,
167
+ )
168
+ .all(nowIso)
169
+ .map(readAdmission);
170
+ const retries = due.filter((admission): admission is AutopilotAdmission =>
171
+ Boolean(admission),
172
+ );
173
+ database
174
+ .prepare(
175
+ `DELETE FROM app_metadata
176
+ WHERE key LIKE ? AND updated_at <= ?
177
+ AND NOT EXISTS (
178
+ SELECT 1
179
+ FROM autopilot_admissions AS admission
180
+ WHERE admission.state = 'triaged'
181
+ AND app_metadata.key = ? || admission.current_run_id
182
+ );`,
183
+ )
184
+ .run(`${terminalFactKeyPrefix}%`, factBefore, terminalFactKeyPrefix);
185
+ database.exec('COMMIT;');
186
+ return retries;
187
+ } catch (error) {
188
+ database.exec('ROLLBACK;');
189
+ throw error;
190
+ } finally {
191
+ database.close();
192
+ }
193
+ }
194
+
195
+ export async function listAutopilotAdmissions(paths = runtimePaths()) {
196
+ await ensureRuntimeHome(paths);
197
+ const database = openDb(paths.neondeckDatabase);
198
+ try {
199
+ return database
200
+ .prepare('SELECT * FROM autopilot_admissions ORDER BY updated_at DESC;')
201
+ .all()
202
+ .map(readAdmission)
203
+ .filter((admission): admission is AutopilotAdmission =>
204
+ Boolean(admission),
205
+ );
206
+ } finally {
207
+ database.close();
208
+ }
209
+ }
210
+
211
+ export async function listAutopilotAdmissionsAwaitingPreparation(
212
+ paths = runtimePaths(),
213
+ ) {
214
+ await ensureRuntimeHome(paths);
215
+ const database = openDb(paths.neondeckDatabase);
216
+ try {
217
+ const admissions = database
218
+ .prepare(
219
+ `SELECT * FROM autopilot_admissions
220
+ WHERE state = 'triaged' AND current_run_id IS NOT NULL
221
+ ORDER BY updated_at ASC;`,
222
+ )
223
+ .all()
224
+ .map(readAdmission)
225
+ .filter((admission): admission is AutopilotAdmission =>
226
+ Boolean(admission),
227
+ );
228
+ return admissions.filter((admission) => {
229
+ const fact = readTerminalFact(
230
+ database
231
+ .prepare('SELECT value FROM app_metadata WHERE key = ?;')
232
+ .get(terminalFactKey(admission.currentRunId ?? '')),
233
+ );
234
+ return (
235
+ fact?.workflow === 'triage-pr-event' &&
236
+ !fact.failed &&
237
+ fact.shouldPrepare === true
238
+ );
239
+ });
240
+ } finally {
241
+ database.close();
242
+ }
243
+ }
244
+
245
+ export async function claimAutopilotTriageAdmission(
246
+ input: {
247
+ watchId: string;
248
+ eventFingerprint: string;
249
+ repoId: string;
250
+ prNumber: number;
251
+ mode: AutopilotMode;
252
+ input: Record<string, unknown>;
253
+ limits: AutopilotConcurrencyPolicy;
254
+ },
255
+ paths = runtimePaths(),
256
+ ) {
257
+ await ensureRuntimeHome(paths);
258
+ const now = new Date().toISOString();
259
+ const database = openDb(paths.neondeckDatabase);
260
+ try {
261
+ database.exec('BEGIN IMMEDIATE;');
262
+ const existing = readAdmission(
263
+ database
264
+ .prepare(
265
+ 'SELECT * FROM autopilot_admissions WHERE watch_id = ? AND event_fingerprint = ?;',
266
+ )
267
+ .get(input.watchId, input.eventFingerprint),
268
+ );
269
+ if (existing) {
270
+ const due =
271
+ (existing.state === 'blocked' || existing.state === 'failed') &&
272
+ (!existing.nextAttemptAt ||
273
+ Date.parse(existing.nextAttemptAt) <= Date.parse(now));
274
+ const capped = admissionUsageExceedsLimits(
275
+ readAdmissionUsage(database, input.repoId, input.prNumber),
276
+ input.limits,
277
+ );
278
+ if (due && !capped) {
279
+ database
280
+ .prepare(
281
+ `UPDATE autopilot_admissions
282
+ SET state = 'triage-admitted', current_workflow = 'triage-pr-event',
283
+ current_run_id = NULL, attempt_count = attempt_count + 1,
284
+ next_attempt_at = NULL, last_error = NULL, updated_at = ?
285
+ WHERE id = ?;`,
286
+ )
287
+ .run(now, existing.id);
288
+ database.exec('COMMIT;');
289
+ return {
290
+ claimed: true,
291
+ admission: {
292
+ ...existing,
293
+ state: 'triage-admitted' as const,
294
+ currentWorkflow: 'triage-pr-event',
295
+ currentRunId: null,
296
+ attemptCount: existing.attemptCount + 1,
297
+ nextAttemptAt: null,
298
+ lastError: null,
299
+ updatedAt: now,
300
+ },
301
+ reason: 'retry' as const,
302
+ };
303
+ }
304
+ database.exec('COMMIT;');
305
+ return {
306
+ claimed: false,
307
+ admission: existing,
308
+ reason: 'duplicate' as const,
309
+ };
310
+ }
311
+ const capped = admissionUsageExceedsLimits(
312
+ readAdmissionUsage(database, input.repoId, input.prNumber),
313
+ input.limits,
314
+ );
315
+ const state: AutopilotAdmissionState = capped
316
+ ? 'blocked'
317
+ : 'triage-admitted';
318
+ const admission: AutopilotAdmission = {
319
+ id: `autopilot-admission:${randomUUID()}`,
320
+ watchId: input.watchId,
321
+ eventFingerprint: input.eventFingerprint,
322
+ repoId: input.repoId,
323
+ prNumber: input.prNumber,
324
+ mode: input.mode,
325
+ input: input.input,
326
+ state,
327
+ currentWorkflow: capped ? null : 'triage-pr-event',
328
+ currentRunId: null,
329
+ worktreeId: null,
330
+ attemptCount: capped ? 0 : 1,
331
+ nextAttemptAt: capped ? now : null,
332
+ lastError: capped ? 'Autopilot admission limit reached.' : null,
333
+ createdAt: now,
334
+ updatedAt: now,
335
+ };
336
+ database
337
+ .prepare(
338
+ `INSERT INTO autopilot_admissions (
339
+ id, watch_id, event_fingerprint, repo_id, pr_number, mode, input_json, state,
340
+ current_workflow, current_run_id, attempt_count, next_attempt_at,
341
+ last_error, created_at, updated_at
342
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);`,
343
+ )
344
+ .run(
345
+ admission.id,
346
+ admission.watchId,
347
+ admission.eventFingerprint,
348
+ admission.repoId,
349
+ admission.prNumber,
350
+ admission.mode,
351
+ JSON.stringify(input.input),
352
+ admission.state,
353
+ admission.currentWorkflow,
354
+ null,
355
+ admission.attemptCount,
356
+ admission.nextAttemptAt,
357
+ admission.lastError,
358
+ now,
359
+ now,
360
+ );
361
+ database.exec('COMMIT;');
362
+ return {
363
+ claimed: !capped,
364
+ admission,
365
+ reason: capped ? ('limited' as const) : null,
366
+ };
367
+ } catch (error) {
368
+ database.exec('ROLLBACK;');
369
+ throw error;
370
+ } finally {
371
+ database.close();
372
+ }
373
+ }
374
+
375
+ export async function recordAutopilotAdmissionRun(
376
+ input: { id: string; runId: string },
377
+ paths = runtimePaths(),
378
+ ) {
379
+ await ensureRuntimeHome(paths);
380
+ const now = new Date().toISOString();
381
+ const database = openDb(paths.neondeckDatabase);
382
+ try {
383
+ database.exec('BEGIN IMMEDIATE;');
384
+ const admission = readAdmission(
385
+ database
386
+ .prepare('SELECT * FROM autopilot_admissions WHERE id = ?;')
387
+ .get(input.id),
388
+ );
389
+ if (!admission) {
390
+ database.exec('COMMIT;');
391
+ return;
392
+ }
393
+ const observation = database
394
+ .prepare(
395
+ `SELECT status FROM workflow_run_observations
396
+ WHERE run_id = ? AND status IN ('completed', 'failed');`,
397
+ )
398
+ .get(input.runId) as { status?: unknown } | undefined;
399
+ const terminal = readTerminalFact(
400
+ database
401
+ .prepare('SELECT value FROM app_metadata WHERE key = ?;')
402
+ .get(terminalFactKey(input.runId)),
403
+ );
404
+ const observationFailed = observation?.status === 'failed';
405
+ const settles = Boolean(observation || terminal);
406
+ const workflowMatches =
407
+ !terminal || terminal.workflow === admission.currentWorkflow;
408
+ const awaitsPrepareFact =
409
+ observation?.status === 'completed' &&
410
+ admission.currentWorkflow === 'prepare-pr-worktree' &&
411
+ !terminal;
412
+ const settled =
413
+ settles && workflowMatches && !awaitsPrepareFact
414
+ ? settledAdmissionState(admission, terminal, observationFailed)
415
+ : undefined;
416
+ const update = database
417
+ .prepare(
418
+ `UPDATE autopilot_admissions
419
+ SET current_run_id = ?, state = ?, current_workflow = ?, worktree_id = ?,
420
+ last_error = ?, next_attempt_at = ?, updated_at = ?
421
+ WHERE id = ? AND state IN ('triage-admitted', 'prepare-admitted');`,
422
+ )
423
+ .run(
424
+ input.runId,
425
+ settled?.state ?? admission.state,
426
+ settled ? null : admission.currentWorkflow,
427
+ settled?.worktreeId ?? null,
428
+ settled?.failed
429
+ ? 'Workflow ended before its admission run id was attached.'
430
+ : null,
431
+ settled?.failed ? now : null,
432
+ now,
433
+ input.id,
434
+ );
435
+ if (
436
+ settled &&
437
+ workflowMatches &&
438
+ update.changes > 0 &&
439
+ !(
440
+ terminal?.workflow === 'triage-pr-event' &&
441
+ !terminal.failed &&
442
+ terminal.shouldPrepare
443
+ )
444
+ ) {
445
+ database
446
+ .prepare('DELETE FROM app_metadata WHERE key = ?;')
447
+ .run(terminalFactKey(input.runId));
448
+ }
449
+ database.exec('COMMIT;');
450
+ return {
451
+ admission: {
452
+ ...admission,
453
+ currentRunId: input.runId,
454
+ state: settled?.state ?? admission.state,
455
+ currentWorkflow: settled ? null : admission.currentWorkflow,
456
+ nextAttemptAt: settled?.failed ? now : null,
457
+ lastError: settled?.failed
458
+ ? 'Workflow ended before its admission run id was attached.'
459
+ : null,
460
+ updatedAt: now,
461
+ },
462
+ terminal: settles && workflowMatches ? terminal : undefined,
463
+ };
464
+ } catch (error) {
465
+ database.exec('ROLLBACK;');
466
+ throw error;
467
+ } finally {
468
+ database.close();
469
+ }
470
+ }
471
+
472
+ export async function failAutopilotAdmission(
473
+ input: { id: string; error: string },
474
+ paths = runtimePaths(),
475
+ ) {
476
+ await ensureRuntimeHome(paths);
477
+ const database = openDb(paths.neondeckDatabase);
478
+ try {
479
+ database
480
+ .prepare(
481
+ `UPDATE autopilot_admissions
482
+ SET state = 'failed', last_error = ?, next_attempt_at = ?, updated_at = ?
483
+ WHERE id = ? AND state IN ('triage-admitted', 'prepare-admitted');`,
484
+ )
485
+ .run(
486
+ input.error,
487
+ new Date().toISOString(),
488
+ new Date().toISOString(),
489
+ input.id,
490
+ );
491
+ } finally {
492
+ database.close();
493
+ }
494
+ }
495
+
496
+ export async function settleAutopilotAdmissionTriage(
497
+ input: { runId: string; failed: boolean; shouldPrepare?: boolean },
498
+ paths = runtimePaths(),
499
+ ) {
500
+ await ensureRuntimeHome(paths);
501
+ const now = new Date().toISOString();
502
+ const database = openDb(paths.neondeckDatabase);
503
+ try {
504
+ const update = database
505
+ .prepare(
506
+ `UPDATE autopilot_admissions
507
+ SET state = ?, current_workflow = NULL, last_error = ?,
508
+ next_attempt_at = ?, updated_at = ?
509
+ WHERE current_run_id = ? AND state = 'triage-admitted';`,
510
+ )
511
+ .run(
512
+ input.failed ? 'failed' : 'triaged',
513
+ input.failed ? 'Triage workflow failed; see Flue run details.' : null,
514
+ input.failed ? now : null,
515
+ now,
516
+ input.runId,
517
+ );
518
+ if (update.changes > 0 && (input.failed || !input.shouldPrepare)) {
519
+ database
520
+ .prepare('DELETE FROM app_metadata WHERE key = ?;')
521
+ .run(terminalFactKey(input.runId));
522
+ }
523
+ } finally {
524
+ database.close();
525
+ }
526
+ }
527
+
528
+ export async function beginAutopilotAdmissionPrepare(
529
+ input: { triageRunId: string; limits?: AutopilotConcurrencyPolicy },
530
+ paths = runtimePaths(),
531
+ ) {
532
+ await ensureRuntimeHome(paths);
533
+ const configuredLimits = await readAdmissionLimits(input.triageRunId, paths);
534
+ if (configuredLimits === 'disabled') return undefined;
535
+ const limits = configuredLimits ?? input.limits;
536
+ const now = new Date().toISOString();
537
+ const database = openDb(paths.neondeckDatabase);
538
+ try {
539
+ database.exec('BEGIN IMMEDIATE;');
540
+ const admission = readAdmission(
541
+ database
542
+ .prepare(
543
+ `SELECT * FROM autopilot_admissions
544
+ WHERE current_run_id = ? AND state = 'triaged';`,
545
+ )
546
+ .get(input.triageRunId),
547
+ );
548
+ if (!admission) {
549
+ database.exec('COMMIT;');
550
+ return undefined;
551
+ }
552
+ if (
553
+ !limits ||
554
+ admissionUsageExceedsLimits(
555
+ readAdmissionUsage(database, admission.repoId, admission.prNumber),
556
+ limits,
557
+ )
558
+ ) {
559
+ database.exec('COMMIT;');
560
+ return undefined;
561
+ }
562
+ database
563
+ .prepare(
564
+ `UPDATE autopilot_admissions
565
+ SET state = 'prepare-admitted', current_workflow = 'prepare-pr-worktree',
566
+ current_run_id = NULL, attempt_count = attempt_count + 1, updated_at = ?
567
+ WHERE id = ?;`,
568
+ )
569
+ .run(now, admission.id);
570
+ database
571
+ .prepare('DELETE FROM app_metadata WHERE key = ?;')
572
+ .run(terminalFactKey(input.triageRunId));
573
+ database.exec('COMMIT;');
574
+ return {
575
+ ...admission,
576
+ state: 'prepare-admitted' as const,
577
+ currentWorkflow: 'prepare-pr-worktree',
578
+ currentRunId: null,
579
+ attemptCount: admission.attemptCount + 1,
580
+ updatedAt: now,
581
+ };
582
+ } catch (error) {
583
+ database.exec('ROLLBACK;');
584
+ throw error;
585
+ } finally {
586
+ database.close();
587
+ }
588
+ }
589
+
590
+ export async function recordAutopilotAdmissionTerminalFact(
591
+ input: { runId: string; fact: AutopilotAdmissionTerminalFact },
592
+ paths = runtimePaths(),
593
+ ) {
594
+ await ensureRuntimeHome(paths);
595
+ const database = openDb(paths.neondeckDatabase);
596
+ try {
597
+ database
598
+ .prepare(
599
+ `INSERT INTO app_metadata (key, value, updated_at) VALUES (?, ?, ?)
600
+ ON CONFLICT(key) DO UPDATE SET value = excluded.value, updated_at = excluded.updated_at;`,
601
+ )
602
+ .run(
603
+ terminalFactKey(input.runId),
604
+ JSON.stringify(input.fact),
605
+ new Date().toISOString(),
606
+ );
607
+ } finally {
608
+ database.close();
609
+ }
610
+ }
611
+
612
+ export async function settleAutopilotAdmissionPrepare(
613
+ input: { runId: string; failed: boolean; worktreeId?: string },
614
+ paths = runtimePaths(),
615
+ ) {
616
+ await ensureRuntimeHome(paths);
617
+ const now = new Date().toISOString();
618
+ const database = openDb(paths.neondeckDatabase);
619
+ try {
620
+ const update = database
621
+ .prepare(
622
+ `UPDATE autopilot_admissions
623
+ SET state = ?, current_workflow = NULL, worktree_id = ?, last_error = ?,
624
+ next_attempt_at = ?, updated_at = ?
625
+ WHERE current_run_id = ? AND state = 'prepare-admitted';`,
626
+ )
627
+ .run(
628
+ input.failed || !input.worktreeId ? 'failed' : 'prepared',
629
+ input.worktreeId ?? null,
630
+ input.failed || !input.worktreeId
631
+ ? 'Prepare workflow failed or did not produce a worktree.'
632
+ : null,
633
+ input.failed || !input.worktreeId ? now : null,
634
+ now,
635
+ input.runId,
636
+ );
637
+ if (update.changes > 0) {
638
+ database
639
+ .prepare('DELETE FROM app_metadata WHERE key = ?;')
640
+ .run(terminalFactKey(input.runId));
641
+ }
642
+ } finally {
643
+ database.close();
644
+ }
645
+ }
646
+
647
+ function terminalFactKey(runId: string) {
648
+ return `${terminalFactKeyPrefix}${runId}`;
649
+ }
650
+
651
+ function readTerminalFact(
652
+ row: unknown,
653
+ ): AutopilotAdmissionTerminalFact | undefined {
654
+ if (!row || typeof row !== 'object') return undefined;
655
+ const value = (row as { value?: unknown }).value;
656
+ if (typeof value !== 'string') return undefined;
657
+ try {
658
+ const parsed = JSON.parse(value) as Record<string, unknown>;
659
+ if (
660
+ (parsed.workflow !== 'triage-pr-event' &&
661
+ parsed.workflow !== 'prepare-pr-worktree') ||
662
+ typeof parsed.failed !== 'boolean'
663
+ ) {
664
+ return undefined;
665
+ }
666
+ return {
667
+ workflow: parsed.workflow,
668
+ failed: parsed.failed,
669
+ shouldPrepare:
670
+ typeof parsed.shouldPrepare === 'boolean'
671
+ ? parsed.shouldPrepare
672
+ : undefined,
673
+ worktreeId:
674
+ typeof parsed.worktreeId === 'string' ? parsed.worktreeId : undefined,
675
+ };
676
+ } catch {
677
+ return undefined;
678
+ }
679
+ }
680
+
681
+ function settledAdmissionState(
682
+ admission: AutopilotAdmission,
683
+ terminal: AutopilotAdmissionTerminalFact | undefined,
684
+ observationFailed: boolean,
685
+ ) {
686
+ const failed = terminal?.failed ?? observationFailed;
687
+ if (failed) return { state: 'failed' as const, failed: true };
688
+ if (admission.currentWorkflow === 'triage-pr-event') {
689
+ return { state: 'triaged' as const, failed: false };
690
+ }
691
+ if (terminal?.worktreeId) {
692
+ return {
693
+ state: 'prepared' as const,
694
+ failed: false,
695
+ worktreeId: terminal.worktreeId,
696
+ };
697
+ }
698
+ return { state: 'failed' as const, failed: true };
699
+ }
700
+
701
+ function readAdmissionUsage(
702
+ database: ReturnType<typeof openDb>,
703
+ repoId: string,
704
+ prNumber: number,
705
+ ) {
706
+ const workflows = [
707
+ 'triage-pr-event',
708
+ 'triage_pr_event',
709
+ 'prepare-pr-worktree',
710
+ 'prepare_pr_worktree',
711
+ 'fix-pr-review-feedback',
712
+ 'fix_pr_review_feedback',
713
+ 'fix-pr-ci',
714
+ 'fix_pr_ci',
715
+ 'ci-fix-run',
716
+ 'ci_fix_run',
717
+ 'fix-pr-ci-failure',
718
+ 'fix_pr_ci_failure',
719
+ 'verify-pr-worktree',
720
+ 'verify_pr_worktree',
721
+ 'push-pr-autofix',
722
+ 'push_pr_autofix',
723
+ 'verify-then-push-pr-autofix',
724
+ 'verify_then_push_pr_autofix',
725
+ 'comment-pr-autofix-result',
726
+ 'comment_pr_autofix_result',
727
+ 'cleanup-autopilot-worktree',
728
+ 'cleanup_autopilot_worktree',
729
+ ];
730
+ const workflowPlaceholders = workflows.map(() => '?').join(', ');
731
+ return database
732
+ .prepare(
733
+ `WITH active_admissions AS (
734
+ SELECT * FROM autopilot_admissions
735
+ WHERE state IN ('triage-admitted', 'prepare-admitted')
736
+ ), manual_runs AS (
737
+ SELECT run_id FROM workflow_run_observations
738
+ WHERE status = 'active' AND workflow IN (${workflowPlaceholders})
739
+ AND NOT EXISTS (
740
+ SELECT 1 FROM active_admissions
741
+ WHERE active_admissions.current_run_id = workflow_run_observations.run_id
742
+ )
743
+ ), manual_worktrees AS (
744
+ SELECT * FROM worktrees
745
+ WHERE lifecycle_status = 'busy'
746
+ AND (
747
+ owning_workflow_run_id IS NULL OR NOT EXISTS (
748
+ SELECT 1 FROM active_admissions
749
+ WHERE active_admissions.current_run_id = worktrees.owning_workflow_run_id
750
+ )
751
+ )
752
+ )
753
+ SELECT
754
+ (SELECT COUNT(*) FROM active_admissions) +
755
+ (SELECT COUNT(*) FROM manual_runs) +
756
+ (SELECT COUNT(*) FROM manual_worktrees
757
+ WHERE owning_workflow_run_id IS NULL
758
+ OR owning_workflow_run_id NOT IN (SELECT run_id FROM manual_runs))
759
+ AS global_count,
760
+ (SELECT COUNT(*) FROM active_admissions WHERE repo_id = ?) +
761
+ (SELECT COUNT(*) FROM manual_worktrees WHERE repo_id = ?) AS repo_count,
762
+ (SELECT COUNT(*) FROM active_admissions WHERE repo_id = ? AND pr_number = ?) +
763
+ (SELECT COUNT(*) FROM manual_worktrees WHERE repo_id = ? AND pr_number = ?) AS pr_count;`,
764
+ )
765
+ .get(...workflows, repoId, repoId, repoId, prNumber, repoId, prNumber) as {
766
+ global_count?: unknown;
767
+ repo_count?: unknown;
768
+ pr_count?: unknown;
769
+ };
770
+ }
771
+
772
+ function admissionUsageExceedsLimits(
773
+ usage: { global_count?: unknown; repo_count?: unknown; pr_count?: unknown },
774
+ limits: AutopilotConcurrencyPolicy,
775
+ ) {
776
+ const globalCount = Number(usage.global_count ?? 0);
777
+ const repoCount = Number(usage.repo_count ?? 0);
778
+ const prCount = Number(usage.pr_count ?? 0);
779
+ return (
780
+ globalCount >= limits.maxAutonomousJobs ||
781
+ globalCount >= limits.maxActiveWorkflowRuns ||
782
+ repoCount >= limits.maxPerRepoAutonomousJobs ||
783
+ (limits.singleMutationPerPr && prCount > 0)
784
+ );
785
+ }
786
+
787
+ async function readAdmissionLimits(
788
+ triageRunId: string,
789
+ paths: ReturnType<typeof runtimePaths>,
790
+ ) {
791
+ const database = openDb(paths.neondeckDatabase);
792
+ let admission: AutopilotAdmission | undefined;
793
+ try {
794
+ admission = readAdmission(
795
+ database
796
+ .prepare(
797
+ `SELECT * FROM autopilot_admissions
798
+ WHERE current_run_id = ? AND state = 'triaged';`,
799
+ )
800
+ .get(triageRunId),
801
+ );
802
+ } finally {
803
+ database.close();
804
+ }
805
+ if (!admission) return undefined;
806
+ const [registry, appConfig, watches] = await Promise.all([
807
+ readRepoRegistrySnapshot(paths),
808
+ readRuntimeJson(paths.config, parseAppConfig),
809
+ listPrWatchRecords(paths),
810
+ ]);
811
+ const repo = registry.repos.find(
812
+ (candidate) => candidate.id === admission.repoId,
813
+ );
814
+ const watch = watches.find((candidate) => candidate.id === admission.watchId);
815
+ if (!repo || !watch) return undefined;
816
+ const policy = repoAutopilotPolicyForWatch(repo, appConfig, {
817
+ id: watch.id,
818
+ prNumber: watch.prNumber,
819
+ });
820
+ if (!('concurrency' in policy) || policy.mode === 'notify-only') {
821
+ return 'disabled';
822
+ }
823
+ return policy.concurrency;
824
+ }
825
+
826
+ function readAdmission(row: unknown): AutopilotAdmission | undefined {
827
+ if (!row) return undefined;
828
+ const value = row as Record<string, unknown>;
829
+ return {
830
+ id: String(value.id),
831
+ watchId: String(value.watch_id),
832
+ eventFingerprint: String(value.event_fingerprint),
833
+ repoId: String(value.repo_id),
834
+ prNumber: Number(value.pr_number),
835
+ mode: value.mode as AutopilotMode,
836
+ input: readAdmissionInput(value.input_json),
837
+ state: value.state as AutopilotAdmissionState,
838
+ currentWorkflow:
839
+ typeof value.current_workflow === 'string'
840
+ ? value.current_workflow
841
+ : null,
842
+ currentRunId:
843
+ typeof value.current_run_id === 'string' ? value.current_run_id : null,
844
+ worktreeId:
845
+ typeof value.worktree_id === 'string' ? value.worktree_id : null,
846
+ attemptCount: Number(value.attempt_count),
847
+ nextAttemptAt:
848
+ typeof value.next_attempt_at === 'string' ? value.next_attempt_at : null,
849
+ lastError: typeof value.last_error === 'string' ? value.last_error : null,
850
+ createdAt: String(value.created_at),
851
+ updatedAt: String(value.updated_at),
852
+ };
853
+ }
854
+
855
+ function readAdmissionInput(value: unknown) {
856
+ if (typeof value !== 'string') return {};
857
+ try {
858
+ const parsed = JSON.parse(value);
859
+ return parsed && typeof parsed === 'object' && !Array.isArray(parsed)
860
+ ? (parsed as Record<string, unknown>)
861
+ : {};
862
+ } catch {
863
+ return {};
864
+ }
865
+ }