neondeck 1.0.0-beta.10

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 (804) hide show
  1. package/CHANGELOG.md +76 -0
  2. package/DEVELOPMENT.md +304 -0
  3. package/LICENSE +21 -0
  4. package/README.md +129 -0
  5. package/SOUL.md +8 -0
  6. package/bin/neondeck.mjs +27 -0
  7. package/config/dashboard.json +224 -0
  8. package/config/dashboard.schema.json +247 -0
  9. package/dist/SOUL.md +8 -0
  10. package/dist/assets/app-CnXGMuTl.js +3878 -0
  11. package/dist/assets/app-CnXGMuTl.js.map +1 -0
  12. package/dist/assets/autopilot-B8lfWyA1.js +68813 -0
  13. package/dist/assets/autopilot-B8lfWyA1.js.map +1 -0
  14. package/dist/assets/briefing-BT8h9XXT.js +52 -0
  15. package/dist/assets/briefing-BT8h9XXT.js.map +1 -0
  16. package/dist/assets/briefing-VMdQPEGc.js +2 -0
  17. package/dist/assets/briefings-DuApznpN.js +1596 -0
  18. package/dist/assets/briefings-DuApznpN.js.map +1 -0
  19. package/dist/assets/command-run-CnPOA8iY.js +20 -0
  20. package/dist/assets/command-run-CnPOA8iY.js.map +1 -0
  21. package/dist/assets/command-run-Smpq7waT.js +2 -0
  22. package/dist/assets/display-assistant-CKU4YJlc.js +392 -0
  23. package/dist/assets/display-assistant-CKU4YJlc.js.map +1 -0
  24. package/dist/assets/fix-pr-ci-Ce2SIcyf.js +46 -0
  25. package/dist/assets/fix-pr-ci-Ce2SIcyf.js.map +1 -0
  26. package/dist/assets/fix-pr-ci-P3dLxmbx.js +2 -0
  27. package/dist/assets/migrations/20260710061339_neondeck_pre_1_0_baseline/migration.sql +748 -0
  28. package/dist/assets/migrations/20260710061339_neondeck_pre_1_0_baseline/snapshot.json +7126 -0
  29. package/dist/assets/migrations/20260711171708_conversational_briefings/migration.sql +35 -0
  30. package/dist/assets/migrations/20260711171708_conversational_briefings/snapshot.json +7458 -0
  31. package/dist/assets/migrations/20260714191624_worktree_lock_revocation/migration.sql +1 -0
  32. package/dist/assets/migrations/20260714191624_worktree_lock_revocation/snapshot.json +7468 -0
  33. package/dist/assets/migrations/20260714213018_pr_reviews/migration.sql +34 -0
  34. package/dist/assets/migrations/20260714213018_pr_reviews/snapshot.json +7809 -0
  35. package/dist/assets/pr-reviews-BtJ5cm5P.js +521 -0
  36. package/dist/assets/pr-reviews-BtJ5cm5P.js.map +1 -0
  37. package/dist/assets/prepare-pr-worktree-B0qMZMRP.js +2 -0
  38. package/dist/assets/prepare-pr-worktree-C7SmiaTp.js +17 -0
  39. package/dist/assets/prepare-pr-worktree-C7SmiaTp.js.map +1 -0
  40. package/dist/assets/push-pr-autofix-CsMbrnXR.js +17 -0
  41. package/dist/assets/push-pr-autofix-CsMbrnXR.js.map +1 -0
  42. package/dist/assets/push-pr-autofix-njuM6ej2.js +2 -0
  43. package/dist/assets/review-pr-for-human-CEciM46A.js +2 -0
  44. package/dist/assets/review-pr-for-human-TPiQNRWV.js +790 -0
  45. package/dist/assets/review-pr-for-human-TPiQNRWV.js.map +1 -0
  46. package/dist/assets/safety-BQC7exnI.js +1931 -0
  47. package/dist/assets/safety-BQC7exnI.js.map +1 -0
  48. package/dist/assets/scheduled-agent-instruction-BbxwCKbU.js +2 -0
  49. package/dist/assets/scheduled-agent-instruction-C58itQyU.js +22 -0
  50. package/dist/assets/scheduled-agent-instruction-C58itQyU.js.map +1 -0
  51. package/dist/assets/scheduler-tick-B2S9jCYS.js +90 -0
  52. package/dist/assets/scheduler-tick-B2S9jCYS.js.map +1 -0
  53. package/dist/assets/scheduler-workflow-CnI0tWbg.js +21 -0
  54. package/dist/assets/scheduler-workflow-CnI0tWbg.js.map +1 -0
  55. package/dist/assets/skills/github-gh/SKILL.md +56 -0
  56. package/dist/assets/skills/neon-ci-fix/SKILL.md +15 -0
  57. package/dist/assets/skills/neon-docs-fix/SKILL.md +15 -0
  58. package/dist/assets/skills/neon-issue-triage/SKILL.md +13 -0
  59. package/dist/assets/skills/neon-pr-review/SKILL.md +19 -0
  60. package/dist/assets/skills/neondeck/SKILL.md +127 -0
  61. package/dist/assets/skills/neondeck-handoff/SKILL.md +31 -0
  62. package/dist/assets/triage-pr-event-CBje6df5.js +2 -0
  63. package/dist/assets/triage-pr-event-IgC-IrNs.js +17 -0
  64. package/dist/assets/triage-pr-event-IgC-IrNs.js.map +1 -0
  65. package/dist/assets/verify-then-push-pr-autofix-C5Dpomtd.js +75 -0
  66. package/dist/assets/verify-then-push-pr-autofix-C5Dpomtd.js.map +1 -0
  67. package/dist/assets/verify-then-push-pr-autofix-oZ0-wa7L.js +2 -0
  68. package/dist/config/dashboard.json +224 -0
  69. package/dist/config/dashboard.schema.json +247 -0
  70. package/dist/server.mjs +583 -0
  71. package/dist/server.mjs.map +1 -0
  72. package/dist/skills/github-gh/SKILL.md +56 -0
  73. package/dist/skills/neon-ci-fix/SKILL.md +15 -0
  74. package/dist/skills/neon-docs-fix/SKILL.md +15 -0
  75. package/dist/skills/neon-issue-triage/SKILL.md +13 -0
  76. package/dist/skills/neon-pr-review/SKILL.md +19 -0
  77. package/dist/skills/neondeck/SKILL.md +127 -0
  78. package/dist/skills/neondeck-handoff/SKILL.md +31 -0
  79. package/drizzle.config.ts +7 -0
  80. package/package.json +156 -0
  81. package/shared/patch-anchors.ts +78 -0
  82. package/shared/report-document.ts +91 -0
  83. package/src/agents/busywork-workflow.ts +24 -0
  84. package/src/agents/display-assistant.ts +137 -0
  85. package/src/agents/pr-review-assistant.ts +25 -0
  86. package/src/agents/scheduler-workflow.ts +20 -0
  87. package/src/agents/support/tools.ts +346 -0
  88. package/src/app.ts +1 -0
  89. package/src/cli/index.ts +560 -0
  90. package/src/cli/learning.ts +44 -0
  91. package/src/cli/mcp.ts +496 -0
  92. package/src/cli/modules.ts +107 -0
  93. package/src/cli/onboarding.ts +666 -0
  94. package/src/cli/options.ts +102 -0
  95. package/src/cli/output.ts +399 -0
  96. package/src/cli/preapprovals.ts +204 -0
  97. package/src/cli/prompts.ts +108 -0
  98. package/src/cli/types.ts +59 -0
  99. package/src/db.ts +41 -0
  100. package/src/desktop/open.ts +698 -0
  101. package/src/desktop/service.ts +863 -0
  102. package/src/domains/mcp/actions.ts +420 -0
  103. package/src/domains/mcp/config.ts +501 -0
  104. package/src/domains/mcp/format.ts +35 -0
  105. package/src/domains/mcp/gate.ts +188 -0
  106. package/src/domains/mcp/index.ts +9 -0
  107. package/src/domains/mcp/instructions.ts +18 -0
  108. package/src/domains/mcp/oauth.ts +1063 -0
  109. package/src/domains/mcp/policy.ts +15 -0
  110. package/src/domains/mcp/registry.ts +461 -0
  111. package/src/domains/mcp/schemas.ts +171 -0
  112. package/src/domains/mcp/stdio.ts +451 -0
  113. package/src/domains/mcp/store.ts +905 -0
  114. package/src/domains/mcp/tools.ts +119 -0
  115. package/src/lib/action-result.ts +51 -0
  116. package/src/lib/exec.ts +118 -0
  117. package/src/lib/git.ts +20 -0
  118. package/src/lib/report-html.ts +193 -0
  119. package/src/lib/sqlite.ts +51 -0
  120. package/src/lib/valibot.ts +33 -0
  121. package/src/modules/app-state/index.ts +4 -0
  122. package/src/modules/app-state/notification-events.ts +44 -0
  123. package/src/modules/app-state/notifications.ts +259 -0
  124. package/src/modules/app-state/types.ts +42 -0
  125. package/src/modules/app-state/workflow-summaries.ts +201 -0
  126. package/src/modules/autonomous-audit/index.ts +225 -0
  127. package/src/modules/autopilot/actions.ts +186 -0
  128. package/src/modules/autopilot/admissions.ts +865 -0
  129. package/src/modules/autopilot/approvals.ts +59 -0
  130. package/src/modules/autopilot/ci-fix-run.ts +1332 -0
  131. package/src/modules/autopilot/ci-fix.ts +718 -0
  132. package/src/modules/autopilot/comments.ts +426 -0
  133. package/src/modules/autopilot/fixtures.ts +344 -0
  134. package/src/modules/autopilot/github-facts.ts +306 -0
  135. package/src/modules/autopilot/index.ts +64 -0
  136. package/src/modules/autopilot/notifications.ts +271 -0
  137. package/src/modules/autopilot/push-support.ts +260 -0
  138. package/src/modules/autopilot/push.ts +670 -0
  139. package/src/modules/autopilot/recovery.ts +656 -0
  140. package/src/modules/autopilot/review-feedback.ts +649 -0
  141. package/src/modules/autopilot/review-support.ts +524 -0
  142. package/src/modules/autopilot/revision-run.ts +445 -0
  143. package/src/modules/autopilot/schemas.ts +485 -0
  144. package/src/modules/autopilot/state-mappers.ts +517 -0
  145. package/src/modules/autopilot/state-schemas.ts +450 -0
  146. package/src/modules/autopilot/state-store.ts +183 -0
  147. package/src/modules/autopilot/state.ts +255 -0
  148. package/src/modules/autopilot/triage-support.ts +234 -0
  149. package/src/modules/autopilot/triage.ts +156 -0
  150. package/src/modules/autopilot/utils.ts +145 -0
  151. package/src/modules/autopilot/worktree.ts +637 -0
  152. package/src/modules/autopilot-policy/config.ts +101 -0
  153. package/src/modules/autopilot-policy/index.ts +4 -0
  154. package/src/modules/autopilot-policy/risk.ts +359 -0
  155. package/src/modules/autopilot-policy/schemas.ts +229 -0
  156. package/src/modules/autopilot-policy/service.ts +272 -0
  157. package/src/modules/briefings/actions.ts +80 -0
  158. package/src/modules/briefings/index.ts +5 -0
  159. package/src/modules/briefings/schemas.ts +125 -0
  160. package/src/modules/briefings/service.ts +642 -0
  161. package/src/modules/briefings/snapshot.ts +291 -0
  162. package/src/modules/briefings/store.ts +644 -0
  163. package/src/modules/commands/actions.ts +112 -0
  164. package/src/modules/commands/handlers/index.ts +3 -0
  165. package/src/modules/commands/handlers/misc.ts +367 -0
  166. package/src/modules/commands/handlers/queue.ts +710 -0
  167. package/src/modules/commands/handlers/repo.ts +339 -0
  168. package/src/modules/commands/index.ts +5 -0
  169. package/src/modules/commands/registry.ts +157 -0
  170. package/src/modules/commands/runner.ts +152 -0
  171. package/src/modules/commands/schemas.ts +109 -0
  172. package/src/modules/commands/summaries.ts +108 -0
  173. package/src/modules/commands/utils.ts +113 -0
  174. package/src/modules/config/actions.ts +253 -0
  175. package/src/modules/config/events.ts +80 -0
  176. package/src/modules/config/files.ts +9 -0
  177. package/src/modules/config/history.ts +74 -0
  178. package/src/modules/config/index.ts +9 -0
  179. package/src/modules/config/mutations/dashboard.ts +333 -0
  180. package/src/modules/config/mutations/execution.ts +89 -0
  181. package/src/modules/config/mutations/models.ts +467 -0
  182. package/src/modules/config/mutations/providers.ts +163 -0
  183. package/src/modules/config/mutations/repos.ts +663 -0
  184. package/src/modules/config/read.ts +130 -0
  185. package/src/modules/config/result.ts +66 -0
  186. package/src/modules/config/schemas.ts +180 -0
  187. package/src/modules/docs-drift/index.ts +1 -0
  188. package/src/modules/docs-drift/service.ts +863 -0
  189. package/src/modules/execution/actions.ts +35 -0
  190. package/src/modules/execution/approvals.ts +322 -0
  191. package/src/modules/execution/exedev/checkouts.ts +356 -0
  192. package/src/modules/execution/exedev/context.ts +286 -0
  193. package/src/modules/execution/index.ts +7 -0
  194. package/src/modules/execution/policy.ts +102 -0
  195. package/src/modules/execution/run.ts +589 -0
  196. package/src/modules/execution/schemas.ts +116 -0
  197. package/src/modules/execution/scope.ts +137 -0
  198. package/src/modules/execution/store.ts +320 -0
  199. package/src/modules/execution/utils.ts +105 -0
  200. package/src/modules/execution-policy/index.ts +424 -0
  201. package/src/modules/flue/execution-context.ts +40 -0
  202. package/src/modules/flue/index.ts +2 -0
  203. package/src/modules/flue/origin.ts +7 -0
  204. package/src/modules/github/actions.ts +334 -0
  205. package/src/modules/github/checks.ts +484 -0
  206. package/src/modules/github/client.ts +110 -0
  207. package/src/modules/github/comments.ts +204 -0
  208. package/src/modules/github/errors.ts +50 -0
  209. package/src/modules/github/index.ts +93 -0
  210. package/src/modules/github/issues.ts +116 -0
  211. package/src/modules/github/pr-file-cache.ts +264 -0
  212. package/src/modules/github/pull-requests.ts +411 -0
  213. package/src/modules/github/queue.ts +350 -0
  214. package/src/modules/github/reviews.ts +1446 -0
  215. package/src/modules/github/schemas.ts +794 -0
  216. package/src/modules/github/state-truncation.ts +31 -0
  217. package/src/modules/handoff/index.ts +2 -0
  218. package/src/modules/handoff/schemas.ts +61 -0
  219. package/src/modules/handoff/service.ts +587 -0
  220. package/src/modules/hygiene/index.ts +1 -0
  221. package/src/modules/hygiene/service.ts +513 -0
  222. package/src/modules/kilo/actions.ts +229 -0
  223. package/src/modules/kilo/ci-fix-run-reconcile.ts +299 -0
  224. package/src/modules/kilo/docs-drift-boundary.ts +178 -0
  225. package/src/modules/kilo/index.ts +8 -0
  226. package/src/modules/kilo/notifications.ts +295 -0
  227. package/src/modules/kilo/process.ts +637 -0
  228. package/src/modules/kilo/results/actions.ts +66 -0
  229. package/src/modules/kilo/results/gates.ts +227 -0
  230. package/src/modules/kilo/results/index.ts +23 -0
  231. package/src/modules/kilo/results/schemas.ts +112 -0
  232. package/src/modules/kilo/results/service.ts +512 -0
  233. package/src/modules/kilo/results/state.ts +508 -0
  234. package/src/modules/kilo/results/verify.ts +328 -0
  235. package/src/modules/kilo/revision-reconcile.ts +187 -0
  236. package/src/modules/kilo/runtime-facts.ts +128 -0
  237. package/src/modules/kilo/schemas.ts +265 -0
  238. package/src/modules/kilo/service.ts +714 -0
  239. package/src/modules/kilo/sessions-adapters.ts +343 -0
  240. package/src/modules/kilo/sessions.ts +446 -0
  241. package/src/modules/kilo/store.ts +689 -0
  242. package/src/modules/kilo/utils.ts +166 -0
  243. package/src/modules/learning/automation-health.ts +441 -0
  244. package/src/modules/learning/automation-memory.ts +179 -0
  245. package/src/modules/learning/index.ts +6 -0
  246. package/src/modules/learning/observability.ts +616 -0
  247. package/src/modules/learning/operator.ts +404 -0
  248. package/src/modules/learning/reviews/agents.ts +33 -0
  249. package/src/modules/learning/reviews/complete.ts +321 -0
  250. package/src/modules/learning/reviews/context.ts +145 -0
  251. package/src/modules/learning/reviews/events.ts +306 -0
  252. package/src/modules/learning/reviews/index.ts +6 -0
  253. package/src/modules/learning/reviews/pr-cadence.ts +157 -0
  254. package/src/modules/learning/reviews/pr-context.ts +749 -0
  255. package/src/modules/learning/reviews/prepare.ts +387 -0
  256. package/src/modules/learning/reviews/schemas.ts +184 -0
  257. package/src/modules/learning/reviews/store.ts +405 -0
  258. package/src/modules/learning/skill-patches/actions.ts +86 -0
  259. package/src/modules/learning/skill-patches/index.ts +3 -0
  260. package/src/modules/learning/skill-patches/schemas.ts +60 -0
  261. package/src/modules/learning/skill-patches/service.ts +571 -0
  262. package/src/modules/learning/skill-patches/support.ts +417 -0
  263. package/src/modules/memory/actions.ts +183 -0
  264. package/src/modules/memory/candidates.ts +525 -0
  265. package/src/modules/memory/events.ts +2 -0
  266. package/src/modules/memory/index.ts +6 -0
  267. package/src/modules/memory/prompt.ts +214 -0
  268. package/src/modules/memory/schemas.ts +170 -0
  269. package/src/modules/memory/service.ts +578 -0
  270. package/src/modules/memory/store.ts +489 -0
  271. package/src/modules/pr-events/actions.ts +191 -0
  272. package/src/modules/pr-events/index.ts +46 -0
  273. package/src/modules/pr-events/schemas.ts +186 -0
  274. package/src/modules/pr-events/service.ts +1414 -0
  275. package/src/modules/pr-events/target.ts +222 -0
  276. package/src/modules/pr-events/utils.ts +85 -0
  277. package/src/modules/pr-events/watermarks.ts +308 -0
  278. package/src/modules/pr-local-diffs/index.ts +334 -0
  279. package/src/modules/pr-review-assist/actions.ts +239 -0
  280. package/src/modules/pr-review-assist/index.ts +3 -0
  281. package/src/modules/pr-review-assist/schemas.ts +86 -0
  282. package/src/modules/pr-review-assist/service.ts +706 -0
  283. package/src/modules/pr-reviews/events.ts +39 -0
  284. package/src/modules/pr-reviews/index.ts +4 -0
  285. package/src/modules/pr-reviews/service.ts +655 -0
  286. package/src/modules/pr-reviews/store.ts +186 -0
  287. package/src/modules/pr-reviews/types.ts +48 -0
  288. package/src/modules/prepared-diffs/actions.ts +132 -0
  289. package/src/modules/prepared-diffs/index.ts +53 -0
  290. package/src/modules/prepared-diffs/schemas.ts +255 -0
  291. package/src/modules/prepared-diffs/service.ts +791 -0
  292. package/src/modules/prepared-diffs/store.ts +678 -0
  293. package/src/modules/repo-guardrails/config.ts +61 -0
  294. package/src/modules/repo-guardrails/index.ts +162 -0
  295. package/src/modules/repo-guardrails/risk.ts +2 -0
  296. package/src/modules/reports/index.ts +1 -0
  297. package/src/modules/reports/service.ts +337 -0
  298. package/src/modules/repos/index.ts +3 -0
  299. package/src/modules/repos/model-discovery.ts +233 -0
  300. package/src/modules/repos/providers.ts +194 -0
  301. package/src/modules/repos/registry.ts +232 -0
  302. package/src/modules/runtime/agent-config.ts +167 -0
  303. package/src/modules/runtime/doctor.ts +528 -0
  304. package/src/modules/runtime/env.ts +123 -0
  305. package/src/modules/runtime/index.ts +12 -0
  306. package/src/modules/runtime/local-api-auth.ts +43 -0
  307. package/src/modules/runtime/metrics.ts +211 -0
  308. package/src/modules/runtime/skills-actions.ts +141 -0
  309. package/src/modules/runtime/skills.ts +689 -0
  310. package/src/modules/runtime/soul.ts +68 -0
  311. package/src/modules/runtime/status-database.ts +252 -0
  312. package/src/modules/runtime/status-schema.ts +149 -0
  313. package/src/modules/runtime/status.ts +481 -0
  314. package/src/modules/runtime/subagents.ts +37 -0
  315. package/src/modules/runtime/utility-model.ts +47 -0
  316. package/src/modules/safety/index.ts +3 -0
  317. package/src/modules/safety/policy-entries.ts +2528 -0
  318. package/src/modules/safety/schemas.ts +63 -0
  319. package/src/modules/safety/service.ts +58 -0
  320. package/src/modules/safety/tools.ts +15 -0
  321. package/src/modules/scheduled-tasks/actions.ts +113 -0
  322. package/src/modules/scheduled-tasks/dispatch.ts +107 -0
  323. package/src/modules/scheduled-tasks/index.ts +6 -0
  324. package/src/modules/scheduled-tasks/schemas.ts +91 -0
  325. package/src/modules/scheduled-tasks/service.ts +296 -0
  326. package/src/modules/scheduled-tasks/store.ts +814 -0
  327. package/src/modules/scheduled-tasks/triggers.ts +87 -0
  328. package/src/modules/scheduler/actions.ts +37 -0
  329. package/src/modules/scheduler/dispatch.ts +192 -0
  330. package/src/modules/scheduler/index.ts +4 -0
  331. package/src/modules/scheduler/lease.ts +247 -0
  332. package/src/modules/scheduler/pr-watch-event-deltas.ts +367 -0
  333. package/src/modules/scheduler/pr-watch-events.ts +834 -0
  334. package/src/modules/scheduler/schemas.ts +79 -0
  335. package/src/modules/scheduler/service.ts +228 -0
  336. package/src/modules/scheduler/utils.ts +106 -0
  337. package/src/modules/scheduler/workflow-invocation.ts +48 -0
  338. package/src/modules/sessions/actions.ts +213 -0
  339. package/src/modules/sessions/active-session.ts +46 -0
  340. package/src/modules/sessions/activity.ts +122 -0
  341. package/src/modules/sessions/agent-context.ts +152 -0
  342. package/src/modules/sessions/approval-nudges.ts +156 -0
  343. package/src/modules/sessions/events.ts +57 -0
  344. package/src/modules/sessions/index.ts +12 -0
  345. package/src/modules/sessions/queries.ts +252 -0
  346. package/src/modules/sessions/references.ts +113 -0
  347. package/src/modules/sessions/repo-context.ts +131 -0
  348. package/src/modules/sessions/schemas.ts +285 -0
  349. package/src/modules/sessions/service.ts +845 -0
  350. package/src/modules/sessions/store.ts +560 -0
  351. package/src/modules/sessions/summaries.ts +129 -0
  352. package/src/modules/sessions/utils.ts +18 -0
  353. package/src/modules/watches/actions.ts +115 -0
  354. package/src/modules/watches/index.ts +6 -0
  355. package/src/modules/watches/polling.ts +245 -0
  356. package/src/modules/watches/references.ts +293 -0
  357. package/src/modules/watches/schemas.ts +156 -0
  358. package/src/modules/watches/service.ts +557 -0
  359. package/src/modules/watches/store.ts +398 -0
  360. package/src/modules/watches/utils.ts +51 -0
  361. package/src/modules/worktree-verification/index.ts +256 -0
  362. package/src/modules/worktrees/access.ts +129 -0
  363. package/src/modules/worktrees/actions.ts +108 -0
  364. package/src/modules/worktrees/cleanup.ts +98 -0
  365. package/src/modules/worktrees/ensure-pr-worktree.ts +63 -0
  366. package/src/modules/worktrees/errors.ts +38 -0
  367. package/src/modules/worktrees/git.ts +48 -0
  368. package/src/modules/worktrees/index.ts +7 -0
  369. package/src/modules/worktrees/locks.ts +231 -0
  370. package/src/modules/worktrees/paths.ts +209 -0
  371. package/src/modules/worktrees/push-target.ts +39 -0
  372. package/src/modules/worktrees/queries.ts +31 -0
  373. package/src/modules/worktrees/schemas.ts +237 -0
  374. package/src/modules/worktrees/service.ts +680 -0
  375. package/src/modules/worktrees/store.ts +415 -0
  376. package/src/repo-edit/actions.ts +509 -0
  377. package/src/repo-edit/audit.ts +180 -0
  378. package/src/repo-edit/fuzzy-replace.ts +256 -0
  379. package/src/repo-edit/git.ts +830 -0
  380. package/src/repo-edit/index.ts +4 -0
  381. package/src/repo-edit/locks.ts +27 -0
  382. package/src/repo-edit/patch-parser.ts +212 -0
  383. package/src/repo-edit/patch-service.ts +572 -0
  384. package/src/repo-edit/path-safety.ts +299 -0
  385. package/src/repo-edit/schemas.ts +239 -0
  386. package/src/repo-edit/service.ts +488 -0
  387. package/src/repo-edit/support.ts +459 -0
  388. package/src/runtime-home/app-db/index.ts +74 -0
  389. package/src/runtime-home/app-db/migrate.ts +491 -0
  390. package/src/runtime-home/app-db/migrations/20260710061339_neondeck_pre_1_0_baseline/migration.sql +748 -0
  391. package/src/runtime-home/app-db/migrations/20260710061339_neondeck_pre_1_0_baseline/snapshot.json +7126 -0
  392. package/src/runtime-home/app-db/migrations/20260711171708_conversational_briefings/migration.sql +35 -0
  393. package/src/runtime-home/app-db/migrations/20260711171708_conversational_briefings/snapshot.json +7458 -0
  394. package/src/runtime-home/app-db/migrations/20260714191624_worktree_lock_revocation/migration.sql +1 -0
  395. package/src/runtime-home/app-db/migrations/20260714191624_worktree_lock_revocation/snapshot.json +7468 -0
  396. package/src/runtime-home/app-db/migrations/20260714213018_pr_reviews/migration.sql +34 -0
  397. package/src/runtime-home/app-db/migrations/20260714213018_pr_reviews/snapshot.json +7809 -0
  398. package/src/runtime-home/app-db/reconcile.ts +155 -0
  399. package/src/runtime-home/app-db/schema.ts +1209 -0
  400. package/src/runtime-home/bootstrap.ts +177 -0
  401. package/src/runtime-home/dashboard-migrations.ts +101 -0
  402. package/src/runtime-home/defaults.ts +54 -0
  403. package/src/runtime-home/files.ts +193 -0
  404. package/src/runtime-home/guardrails.ts +77 -0
  405. package/src/runtime-home/index.ts +71 -0
  406. package/src/runtime-home/paths.ts +75 -0
  407. package/src/runtime-home/schemas.ts +520 -0
  408. package/src/sandboxes/exedev.ts +676 -0
  409. package/src/server/app.ts +5 -0
  410. package/src/server/autopilot-push-dispatch.ts +326 -0
  411. package/src/server/create-app.ts +160 -0
  412. package/src/server/events/event-stream.ts +109 -0
  413. package/src/server/http.ts +56 -0
  414. package/src/server/learning-hooks.ts +489 -0
  415. package/src/server/middleware.ts +81 -0
  416. package/src/server/routes/autopilot.ts +318 -0
  417. package/src/server/routes/briefings.ts +34 -0
  418. package/src/server/routes/commands.ts +12 -0
  419. package/src/server/routes/config.ts +124 -0
  420. package/src/server/routes/execution.ts +71 -0
  421. package/src/server/routes/github.ts +559 -0
  422. package/src/server/routes/handoff.ts +69 -0
  423. package/src/server/routes/kilo.ts +179 -0
  424. package/src/server/routes/learning.ts +384 -0
  425. package/src/server/routes/mcp.ts +301 -0
  426. package/src/server/routes/memory.ts +99 -0
  427. package/src/server/routes/metrics.ts +12 -0
  428. package/src/server/routes/notifications.ts +48 -0
  429. package/src/server/routes/repo-edit.ts +115 -0
  430. package/src/server/routes/reports.ts +128 -0
  431. package/src/server/routes/repos.ts +50 -0
  432. package/src/server/routes/reviews.ts +257 -0
  433. package/src/server/routes/runtime.ts +48 -0
  434. package/src/server/routes/safety.ts +13 -0
  435. package/src/server/routes/scheduled-tasks.ts +60 -0
  436. package/src/server/routes/scheduler.ts +13 -0
  437. package/src/server/routes/sessions.ts +229 -0
  438. package/src/server/routes/skills.ts +103 -0
  439. package/src/server/routes/watches.ts +81 -0
  440. package/src/server/routes/workflows.ts +21 -0
  441. package/src/server/routes/worktrees.ts +64 -0
  442. package/src/server/scheduler-workflow.ts +541 -0
  443. package/src/server/serve.ts +100 -0
  444. package/src/setup.ts +162 -0
  445. package/src/skills/github-gh/SKILL.md +56 -0
  446. package/src/skills/neon-ci-fix/SKILL.md +15 -0
  447. package/src/skills/neon-docs-fix/SKILL.md +15 -0
  448. package/src/skills/neon-issue-triage/SKILL.md +13 -0
  449. package/src/skills/neon-pr-review/SKILL.md +19 -0
  450. package/src/skills/neondeck/SKILL.md +127 -0
  451. package/src/skills/neondeck-handoff/SKILL.md +31 -0
  452. package/src/workflows/briefing.ts +50 -0
  453. package/src/workflows/command-run.ts +15 -0
  454. package/src/workflows/comment-pr-autofix-result.ts +10 -0
  455. package/src/workflows/curate_learning_store.ts +37 -0
  456. package/src/workflows/dev-doctor.ts +10 -0
  457. package/src/workflows/fix-pr-ci-failure.ts +10 -0
  458. package/src/workflows/fix-pr-ci.ts +15 -0
  459. package/src/workflows/fix-pr-review-feedback.ts +10 -0
  460. package/src/workflows/handoff_to_kilo.ts +10 -0
  461. package/src/workflows/prepare-pr-worktree.ts +10 -0
  462. package/src/workflows/promote_kilo_result.ts +10 -0
  463. package/src/workflows/push-pr-autofix.ts +10 -0
  464. package/src/workflows/reconcile_kilo_task.ts +10 -0
  465. package/src/workflows/review-pr-for-human.ts +15 -0
  466. package/src/workflows/review_conversation_for_learning.ts +37 -0
  467. package/src/workflows/review_kilo_result.ts +10 -0
  468. package/src/workflows/review_pr_batch_for_learning.ts +37 -0
  469. package/src/workflows/scheduled-agent-instruction.ts +16 -0
  470. package/src/workflows/scheduler-tick.ts +10 -0
  471. package/src/workflows/summarize_kilo_session.ts +25 -0
  472. package/src/workflows/triage-pr-event.ts +10 -0
  473. package/src/workflows/verify-pr-worktree.ts +10 -0
  474. package/src/workflows/verify-then-push-pr-autofix.ts +82 -0
  475. package/src/workflows/verify_kilo_result.ts +10 -0
  476. package/src/workflows/watch-pr.ts +10 -0
  477. package/web/dist/assets/GitHubPrReview-Bf8PXCaq.js +3 -0
  478. package/web/dist/assets/MultiFileView-CFYStqTV.js +2970 -0
  479. package/web/dist/assets/PrReviewPopoutPage-CZN1CV82.js +1 -0
  480. package/web/dist/assets/abap-CLvhMVsD.js +1 -0
  481. package/web/dist/assets/actionscript-3--17pq3dv.js +1 -0
  482. package/web/dist/assets/ada-C5qYipkI.js +1 -0
  483. package/web/dist/assets/andromeeda-vGVdxbeo.js +1 -0
  484. package/web/dist/assets/angular-html-BVBpGdXr.js +1 -0
  485. package/web/dist/assets/angular-ts-BfdufMKP.js +1 -0
  486. package/web/dist/assets/apache-U0d_L8uA.js +1 -0
  487. package/web/dist/assets/apex-VAyPSnFM.js +1 -0
  488. package/web/dist/assets/apl-DWBSSoBH.js +1 -0
  489. package/web/dist/assets/applescript-CCn79oCD.js +1 -0
  490. package/web/dist/assets/ara-4CJ0cIlV.js +1 -0
  491. package/web/dist/assets/asciidoc-DE70LPWp.js +1 -0
  492. package/web/dist/assets/asm-Cmm7eHzH.js +1 -0
  493. package/web/dist/assets/astro-3LtMP0Sq.js +1 -0
  494. package/web/dist/assets/aurora-x-CDeNXAV0.js +1 -0
  495. package/web/dist/assets/awk-BWXHIvNe.js +1 -0
  496. package/web/dist/assets/ayu-dark-DluEY0Gj.js +1 -0
  497. package/web/dist/assets/ayu-light-C3h-C4tm.js +1 -0
  498. package/web/dist/assets/ayu-mirage-Bqwy1Gya.js +1 -0
  499. package/web/dist/assets/ballerina-B7ZEbQpA.js +1 -0
  500. package/web/dist/assets/bat-Bo4NYOV-.js +1 -0
  501. package/web/dist/assets/beancount-D-usSTwE.js +1 -0
  502. package/web/dist/assets/berry-DKpUyyne.js +1 -0
  503. package/web/dist/assets/bibtex-Ci_nEsc7.js +1 -0
  504. package/web/dist/assets/bicep-CUHmPFLl.js +1 -0
  505. package/web/dist/assets/bird2-C6vDhewU.js +1 -0
  506. package/web/dist/assets/blade-llJRbbtR.js +1 -0
  507. package/web/dist/assets/bsl-BkkzgIyY.js +1 -0
  508. package/web/dist/assets/c-Wt1voDr2.js +1 -0
  509. package/web/dist/assets/c3-BFHwR3_K.js +1 -0
  510. package/web/dist/assets/cadence-CQ2zXKGN.js +1 -0
  511. package/web/dist/assets/cairo-DLTphjLi.js +1 -0
  512. package/web/dist/assets/catppuccin-frappe-3VR1Za6u.js +1 -0
  513. package/web/dist/assets/catppuccin-latte-DwIHMF0Q.js +1 -0
  514. package/web/dist/assets/catppuccin-macchiato-DYnBP6_5.js +1 -0
  515. package/web/dist/assets/catppuccin-mocha-DYhrFGRu.js +1 -0
  516. package/web/dist/assets/ccount-CMHa3wy6.js +1 -0
  517. package/web/dist/assets/clarity-SemFz856.js +1 -0
  518. package/web/dist/assets/clojure-DqKBuwfJ.js +1 -0
  519. package/web/dist/assets/cmake-Bj61d0ZC.js +1 -0
  520. package/web/dist/assets/cobol-x_HIyl2P.js +1 -0
  521. package/web/dist/assets/codeowners-C8r90Shi.js +1 -0
  522. package/web/dist/assets/codeql-oeQT6MSM.js +1 -0
  523. package/web/dist/assets/coffee-CThvmt4R.js +1 -0
  524. package/web/dist/assets/common-lisp-Cv5bFMCO.js +1 -0
  525. package/web/dist/assets/coq-BrsZFFmf.js +1 -0
  526. package/web/dist/assets/cpp-NtAeskI3.js +1 -0
  527. package/web/dist/assets/crystal-DNu_sX0G.js +1 -0
  528. package/web/dist/assets/csharp-oqKa8noW.js +1 -0
  529. package/web/dist/assets/css-DJp_X0uY.js +1 -0
  530. package/web/dist/assets/csv-Dx-8-gkx.js +1 -0
  531. package/web/dist/assets/cue-CE9AQfxI.js +1 -0
  532. package/web/dist/assets/cypher-ClKdZ_lG.js +1 -0
  533. package/web/dist/assets/d-qD-0Kul2.js +1 -0
  534. package/web/dist/assets/dark-plus-Cs2F2srj.js +1 -0
  535. package/web/dist/assets/dart-CnvKMtbv.js +1 -0
  536. package/web/dist/assets/dax-BkyTk9wS.js +1 -0
  537. package/web/dist/assets/desktop-Dlh5hvp9.js +1 -0
  538. package/web/dist/assets/diff-woXpYk--.js +1 -0
  539. package/web/dist/assets/docker-IyjqRm3v.js +1 -0
  540. package/web/dist/assets/dotenv-_5a1GRtc.js +1 -0
  541. package/web/dist/assets/dracula-BHWKrbxM.js +1 -0
  542. package/web/dist/assets/dracula-soft-5eyTD99u.js +1 -0
  543. package/web/dist/assets/dream-maker-DW3nJb8Q.js +1 -0
  544. package/web/dist/assets/edge-ozw5tpLl.js +1 -0
  545. package/web/dist/assets/elixir-VhA6FeZt.js +1 -0
  546. package/web/dist/assets/elm-dREJmIFz.js +1 -0
  547. package/web/dist/assets/emacs-lisp-B4R74twV.js +1 -0
  548. package/web/dist/assets/erb-CIg6G69l.js +1 -0
  549. package/web/dist/assets/erlang-Cphh6RMH.js +1 -0
  550. package/web/dist/assets/everforest-dark-sB-x3p7T.js +1 -0
  551. package/web/dist/assets/everforest-light-Df2xbC6M.js +1 -0
  552. package/web/dist/assets/fennel-DQxkIbk2.js +1 -0
  553. package/web/dist/assets/fish-BJitypiv.js +1 -0
  554. package/web/dist/assets/fluent-C03EYrpw.js +1 -0
  555. package/web/dist/assets/fortran-fixed-form-DEKoE2YW.js +1 -0
  556. package/web/dist/assets/fortran-free-form-CYNrtFtB.js +1 -0
  557. package/web/dist/assets/fsharp-D13ZGOAj.js +1 -0
  558. package/web/dist/assets/gdresource-C0sCabJj.js +1 -0
  559. package/web/dist/assets/gdscript-Cp2uCuqX.js +1 -0
  560. package/web/dist/assets/gdshader-CBce3t8t.js +1 -0
  561. package/web/dist/assets/genie-CV2tkWYe.js +1 -0
  562. package/web/dist/assets/gherkin-DExj1W_8.js +1 -0
  563. package/web/dist/assets/git-commit-BSykSTBG.js +1 -0
  564. package/web/dist/assets/git-rebase-B44mJPta.js +1 -0
  565. package/web/dist/assets/github-dark-C-LZuMrd.js +1 -0
  566. package/web/dist/assets/github-dark-default-DXG-b-1a.js +1 -0
  567. package/web/dist/assets/github-dark-dimmed-Bx1FflLF.js +1 -0
  568. package/web/dist/assets/github-dark-high-contrast-B_tTalzw.js +1 -0
  569. package/web/dist/assets/github-light-EUqPIrTm.js +1 -0
  570. package/web/dist/assets/github-light-default-BXViO-2h.js +1 -0
  571. package/web/dist/assets/github-light-high-contrast-B68TUdTA.js +1 -0
  572. package/web/dist/assets/gleam-CSRkHgEL.js +1 -0
  573. package/web/dist/assets/glimmer-js-vH_gHG0-.js +1 -0
  574. package/web/dist/assets/glimmer-ts--abOzSAQ.js +1 -0
  575. package/web/dist/assets/glsl-Dv5r7kPw.js +1 -0
  576. package/web/dist/assets/gn-ilITqXS6.js +1 -0
  577. package/web/dist/assets/gnuplot-7GGW24-e.js +1 -0
  578. package/web/dist/assets/go-rLFTqkRN.js +1 -0
  579. package/web/dist/assets/graphql-CB4jsw2E.js +1 -0
  580. package/web/dist/assets/groovy-CacY0gHj.js +1 -0
  581. package/web/dist/assets/gruvbox-dark-hard-C820rvS2.js +1 -0
  582. package/web/dist/assets/gruvbox-dark-medium-BPjhmG05.js +1 -0
  583. package/web/dist/assets/gruvbox-dark-soft-MrdJrrXF.js +1 -0
  584. package/web/dist/assets/gruvbox-light-hard-BC_s9l72.js +1 -0
  585. package/web/dist/assets/gruvbox-light-medium-BAWPOn9u.js +1 -0
  586. package/web/dist/assets/gruvbox-light-soft-BSMLrYjP.js +1 -0
  587. package/web/dist/assets/hack-DvEYX148.js +1 -0
  588. package/web/dist/assets/haml-zE6W3STP.js +1 -0
  589. package/web/dist/assets/handlebars-CzBR2SDs.js +1 -0
  590. package/web/dist/assets/haskell-D8IpX4py.js +1 -0
  591. package/web/dist/assets/haxe-OTjmBuCE.js +1 -0
  592. package/web/dist/assets/hcl-Dh228itO.js +1 -0
  593. package/web/dist/assets/hjson-CxZEssPk.js +1 -0
  594. package/web/dist/assets/hlsl-Cvrh5tZx.js +1 -0
  595. package/web/dist/assets/horizon-CE9ld1lL.js +1 -0
  596. package/web/dist/assets/horizon-bright-DSNQnXHK.js +1 -0
  597. package/web/dist/assets/houston-CsvMBhTu.js +1 -0
  598. package/web/dist/assets/html-C8UlPnhE.js +1 -0
  599. package/web/dist/assets/html-derivative-CY6NRz-J.js +1 -0
  600. package/web/dist/assets/http-Cyd7bS_S.js +1 -0
  601. package/web/dist/assets/hurl-CWPsiEpf.js +1 -0
  602. package/web/dist/assets/hxml-B0Qn7Nwc.js +1 -0
  603. package/web/dist/assets/hy-CZbG8q4J.js +1 -0
  604. package/web/dist/assets/imba-DsUTQ-LC.js +1 -0
  605. package/web/dist/assets/index-BTjK1c82.js +44 -0
  606. package/web/dist/assets/index-D0kg2-9O.css +2 -0
  607. package/web/dist/assets/ini-B5eOa1yu.js +1 -0
  608. package/web/dist/assets/java-CGc3VwQr.js +1 -0
  609. package/web/dist/assets/javascript-CUt1pgmJ.js +1 -0
  610. package/web/dist/assets/jinja-CD-Z-FLd.js +1 -0
  611. package/web/dist/assets/jison-imPNup1l.js +1 -0
  612. package/web/dist/assets/json-Bg9ijW3F.js +1 -0
  613. package/web/dist/assets/json5-BR5RXkoi.js +1 -0
  614. package/web/dist/assets/jsonc-CYpm1nAK.js +1 -0
  615. package/web/dist/assets/jsonl-CmCQp5Yx.js +1 -0
  616. package/web/dist/assets/jsonnet-CJTPZ8u_.js +1 -0
  617. package/web/dist/assets/jssm-DXw9l8Rf.js +1 -0
  618. package/web/dist/assets/jsx-CY6oMTks.js +1 -0
  619. package/web/dist/assets/julia-Dc3O-irA.js +1 -0
  620. package/web/dist/assets/just-BhOq_Kbv.js +1 -0
  621. package/web/dist/assets/kanagawa-dragon-CXtmUGW6.js +1 -0
  622. package/web/dist/assets/kanagawa-lotus-BN08jTvb.js +1 -0
  623. package/web/dist/assets/kanagawa-wave-CTweb8Dz.js +1 -0
  624. package/web/dist/assets/kdl-CsD5j6eV.js +1 -0
  625. package/web/dist/assets/kilo-CvN-tXHs.js +1 -0
  626. package/web/dist/assets/kotlin-DhhofPvG.js +1 -0
  627. package/web/dist/assets/kusto-C7mF5XQf.js +1 -0
  628. package/web/dist/assets/laserwave-C_8bwKvT.js +1 -0
  629. package/web/dist/assets/latex-Cu4Y1d5w.js +1 -0
  630. package/web/dist/assets/lean-CewbzKMR.js +1 -0
  631. package/web/dist/assets/less-DVTAwKKz.js +1 -0
  632. package/web/dist/assets/light-plus-DVQuIRkW.js +1 -0
  633. package/web/dist/assets/liquid-CvXMrjlQ.js +1 -0
  634. package/web/dist/assets/llvm-Cm23YOpf.js +1 -0
  635. package/web/dist/assets/log-BNLmms1o.js +1 -0
  636. package/web/dist/assets/logo-Cluzi2Zq.js +1 -0
  637. package/web/dist/assets/lua-BjLEUjKY.js +1 -0
  638. package/web/dist/assets/luau-FMPmPwt6.js +1 -0
  639. package/web/dist/assets/make-Dixweg8N.js +1 -0
  640. package/web/dist/assets/markdown-BYOwaDjH.js +1 -0
  641. package/web/dist/assets/marko-DvhNOisQ.js +1 -0
  642. package/web/dist/assets/material-theme-Bm3Qr25_.js +1 -0
  643. package/web/dist/assets/material-theme-darker-2IIEA8gg.js +1 -0
  644. package/web/dist/assets/material-theme-lighter-uhdI0v04.js +1 -0
  645. package/web/dist/assets/material-theme-ocean-CHQ94UKr.js +1 -0
  646. package/web/dist/assets/material-theme-palenight-B5W6OYN7.js +1 -0
  647. package/web/dist/assets/matlab-D7qyCx1q.js +1 -0
  648. package/web/dist/assets/mdc-Bm9TpL1X.js +1 -0
  649. package/web/dist/assets/mdx-DQZ5AkYe.js +1 -0
  650. package/web/dist/assets/mermaid-Bk4SNUv9.js +1 -0
  651. package/web/dist/assets/min-dark-BSWPekZh.js +1 -0
  652. package/web/dist/assets/min-light-DDpmG2fV.js +1 -0
  653. package/web/dist/assets/mipsasm-BMqwQI7S.js +1 -0
  654. package/web/dist/assets/mojo-BgCJLMeH.js +1 -0
  655. package/web/dist/assets/monokai-CdkpiU2Y.js +1 -0
  656. package/web/dist/assets/moonbit-CaWjb8XO.js +1 -0
  657. package/web/dist/assets/move-B1IS1UjX.js +1 -0
  658. package/web/dist/assets/narrat-_X_XdTYD.js +1 -0
  659. package/web/dist/assets/nextflow-BJtWHP5T.js +1 -0
  660. package/web/dist/assets/nextflow-groovy-DJMQeKeT.js +1 -0
  661. package/web/dist/assets/nginx-Bhc82uuv.js +1 -0
  662. package/web/dist/assets/night-owl-DhmEMT88.js +1 -0
  663. package/web/dist/assets/night-owl-light-eJ-hLW7d.js +1 -0
  664. package/web/dist/assets/nim-DXTVBFnF.js +1 -0
  665. package/web/dist/assets/nix-IvuFDN5E.js +1 -0
  666. package/web/dist/assets/nord-Cb4Vim4T.js +1 -0
  667. package/web/dist/assets/nushell-DcLAeLz5.js +1 -0
  668. package/web/dist/assets/objective-c-D1A_Heim.js +1 -0
  669. package/web/dist/assets/objective-cpp-BsSzOQcm.js +1 -0
  670. package/web/dist/assets/ocaml-O90oeIOV.js +1 -0
  671. package/web/dist/assets/odin-B1RWQWA5.js +1 -0
  672. package/web/dist/assets/one-dark-pro-CLwyXe_n.js +1 -0
  673. package/web/dist/assets/one-light-D7Lr4KcI.js +1 -0
  674. package/web/dist/assets/openscad-BUDT5pXO.js +1 -0
  675. package/web/dist/assets/pascal-4ZHwLPI5.js +1 -0
  676. package/web/dist/assets/perl-C7veXV9z.js +1 -0
  677. package/web/dist/assets/php-BRiuMnnr.js +1 -0
  678. package/web/dist/assets/pierre-dark-CpLgRqie.js +1 -0
  679. package/web/dist/assets/pierre-dark-protanopia-deuteranopia-B35FxJx-.js +1 -0
  680. package/web/dist/assets/pierre-dark-soft-kZQmAZld.js +1 -0
  681. package/web/dist/assets/pierre-dark-tritanopia-CpjhbsIL.js +1 -0
  682. package/web/dist/assets/pierre-dark-vibrant-CpQYzh95.js +1 -0
  683. package/web/dist/assets/pierre-light-CoaEpmwp.js +1 -0
  684. package/web/dist/assets/pierre-light-protanopia-deuteranopia-0fSaH845.js +1 -0
  685. package/web/dist/assets/pierre-light-soft-lWLdNTOI.js +1 -0
  686. package/web/dist/assets/pierre-light-tritanopia-CEbqgOJL.js +1 -0
  687. package/web/dist/assets/pierre-light-vibrant-D80Fkn33.js +1 -0
  688. package/web/dist/assets/pkl-ot-7Btpt.js +1 -0
  689. package/web/dist/assets/plastic-DQwYfKfQ.js +1 -0
  690. package/web/dist/assets/plsql-DGHpHOYJ.js +1 -0
  691. package/web/dist/assets/po-BiJDBrnU.js +1 -0
  692. package/web/dist/assets/poimandres-DRFjx7u4.js +1 -0
  693. package/web/dist/assets/polar-C7UOKdEL.js +1 -0
  694. package/web/dist/assets/postcss-BXeXVLqQ.js +1 -0
  695. package/web/dist/assets/powerquery-DNMTfnFr.js +1 -0
  696. package/web/dist/assets/powershell-DshXNtvi.js +1 -0
  697. package/web/dist/assets/prisma-BsRQq5mF.js +1 -0
  698. package/web/dist/assets/prolog-iXnhIJG7.js +1 -0
  699. package/web/dist/assets/proto-DB4EqR-F.js +1 -0
  700. package/web/dist/assets/pug-C5hz5LQ7.js +1 -0
  701. package/web/dist/assets/puppet-CDv2pdJW.js +1 -0
  702. package/web/dist/assets/purescript-9MfHhQsQ.js +1 -0
  703. package/web/dist/assets/python-gzcpVVnB.js +1 -0
  704. package/web/dist/assets/qml-BdUV3aTS.js +1 -0
  705. package/web/dist/assets/qmldir-DCQb3MpD.js +1 -0
  706. package/web/dist/assets/qss-Fe1Jh2GI.js +1 -0
  707. package/web/dist/assets/r-8R7vtdQc.js +1 -0
  708. package/web/dist/assets/racket-DcIDlBhZ.js +1 -0
  709. package/web/dist/assets/raku-B3gFvitq.js +1 -0
  710. package/web/dist/assets/razor-DRL52XO2.js +1 -0
  711. package/web/dist/assets/red-CJ3rzSJv.js +1 -0
  712. package/web/dist/assets/reg-CRGYupPL.js +1 -0
  713. package/web/dist/assets/regexp-Omp9DhTb.js +1 -0
  714. package/web/dist/assets/rel-BtDbiS_P.js +1 -0
  715. package/web/dist/assets/reviews-CUXp47M8.js +1 -0
  716. package/web/dist/assets/riscv-Ckw8ddFX.js +1 -0
  717. package/web/dist/assets/rolldown-runtime-QTnfLwEv.js +1 -0
  718. package/web/dist/assets/ron-VUp2lXgN.js +1 -0
  719. package/web/dist/assets/rose-pine-BthvhNj6.js +1 -0
  720. package/web/dist/assets/rose-pine-dawn-Dg85fqjY.js +1 -0
  721. package/web/dist/assets/rose-pine-moon-hon4tzzS.js +1 -0
  722. package/web/dist/assets/rosmsg-CAekHB0j.js +1 -0
  723. package/web/dist/assets/rst-BHX71KW9.js +1 -0
  724. package/web/dist/assets/ruby-B--HzjGU.js +1 -0
  725. package/web/dist/assets/rust-Cfkwpbl8.js +1 -0
  726. package/web/dist/assets/sas-DrLaYOK_.js +1 -0
  727. package/web/dist/assets/sass-DXrisJhu.js +1 -0
  728. package/web/dist/assets/scala-DKOlJaKm.js +1 -0
  729. package/web/dist/assets/scheme-DQCgrYNe.js +1 -0
  730. package/web/dist/assets/scss-DdSxiZKl.js +1 -0
  731. package/web/dist/assets/sdbl-bTVj8UrX.js +1 -0
  732. package/web/dist/assets/shaderlab-TOUzSsQk.js +1 -0
  733. package/web/dist/assets/shellscript-DwcUjJBL.js +1 -0
  734. package/web/dist/assets/shellsession-CPZkydE6.js +1 -0
  735. package/web/dist/assets/slack-dark-DnToyrRv.js +1 -0
  736. package/web/dist/assets/slack-ochin-B2OO5cIa.js +1 -0
  737. package/web/dist/assets/smalltalk-B16xEiuN.js +1 -0
  738. package/web/dist/assets/snazzy-light-4G7pJPwS.js +1 -0
  739. package/web/dist/assets/solarized-dark-DV17i1UV.js +1 -0
  740. package/web/dist/assets/solarized-light-DSh2HLQt.js +1 -0
  741. package/web/dist/assets/solidity-CKzVLygQ.js +1 -0
  742. package/web/dist/assets/soy-Br5FhD7c.js +1 -0
  743. package/web/dist/assets/sparql-D_iOobhT.js +1 -0
  744. package/web/dist/assets/splunk-BC2Px7Mm.js +1 -0
  745. package/web/dist/assets/sql-DNssxck8.js +1 -0
  746. package/web/dist/assets/ssh-config-BgfXC-Er.js +1 -0
  747. package/web/dist/assets/stata-DXn1tqOr.js +1 -0
  748. package/web/dist/assets/stylus-B6D30XZt.js +1 -0
  749. package/web/dist/assets/surfaces-Dlg1xLbg.js +1 -0
  750. package/web/dist/assets/surrealql-IeLNQw0f.js +1 -0
  751. package/web/dist/assets/svelte-DOdLCIlh.js +1 -0
  752. package/web/dist/assets/swift-DonLKvLd.js +1 -0
  753. package/web/dist/assets/synthwave-84-nFMaYfgc.js +1 -0
  754. package/web/dist/assets/system-verilog-DJ5XKQeo.js +1 -0
  755. package/web/dist/assets/systemd-BxMlprV5.js +1 -0
  756. package/web/dist/assets/talonscript-CohzipZa.js +1 -0
  757. package/web/dist/assets/tasl-DMoTqEGO.js +1 -0
  758. package/web/dist/assets/tcl-CZd0xW_V.js +1 -0
  759. package/web/dist/assets/templ-CIwIngms.js +1 -0
  760. package/web/dist/assets/terraform-DswuEJGm.js +1 -0
  761. package/web/dist/assets/tex-D8QMumu5.js +1 -0
  762. package/web/dist/assets/tokyo-night-oM2G3aXe.js +1 -0
  763. package/web/dist/assets/toml-CcmNWLt0.js +1 -0
  764. package/web/dist/assets/ts-tags-BMVY4q-l.js +1 -0
  765. package/web/dist/assets/tsv-sltzmVWM.js +1 -0
  766. package/web/dist/assets/tsx-5Eka4NBX.js +1 -0
  767. package/web/dist/assets/turtle-ByJddavk.js +1 -0
  768. package/web/dist/assets/twig-C8o_5mgw.js +1 -0
  769. package/web/dist/assets/typescript-DOu2WMV5.js +1 -0
  770. package/web/dist/assets/typespec-BRdr0IET.js +1 -0
  771. package/web/dist/assets/typst-DI99ib-x.js +1 -0
  772. package/web/dist/assets/v-DETTlOr0.js +1 -0
  773. package/web/dist/assets/vala-zf12oZj6.js +1 -0
  774. package/web/dist/assets/vb-Djn5o6TS.js +1 -0
  775. package/web/dist/assets/verilog-CiiDBU1e.js +1 -0
  776. package/web/dist/assets/vesper-DdrHHSXu.js +1 -0
  777. package/web/dist/assets/vhdl-BroJfC0k.js +1 -0
  778. package/web/dist/assets/viml-DvXPmvsu.js +1 -0
  779. package/web/dist/assets/vitesse-black-fwtXNY1n.js +1 -0
  780. package/web/dist/assets/vitesse-dark-BZCL-v6S.js +1 -0
  781. package/web/dist/assets/vitesse-light-VbXTXTou.js +1 -0
  782. package/web/dist/assets/vue-BU18DNDL.js +1 -0
  783. package/web/dist/assets/vue-html-BeluIYX0.js +1 -0
  784. package/web/dist/assets/vue-vine-DGUAbOCX.js +1 -0
  785. package/web/dist/assets/vyper-CgoNMtux.js +1 -0
  786. package/web/dist/assets/wasm-BnjxR4X6.js +1 -0
  787. package/web/dist/assets/wasm-ByWQv1Qj.js +1 -0
  788. package/web/dist/assets/wenyan-C8pVoKbM.js +1 -0
  789. package/web/dist/assets/wgsl-BsKzXJz4.js +1 -0
  790. package/web/dist/assets/wikitext-ClFFjSW2.js +1 -0
  791. package/web/dist/assets/wit-DdvCle-K.js +1 -0
  792. package/web/dist/assets/wolfram-DLL8P-h_.js +1 -0
  793. package/web/dist/assets/worker-05jVtNwz.js +160 -0
  794. package/web/dist/assets/xml-DIqSwXR3.js +1 -0
  795. package/web/dist/assets/xsl-Ct_-YIAy.js +1 -0
  796. package/web/dist/assets/yaml-DTtCYNlS.js +1 -0
  797. package/web/dist/assets/zenscript-BnlCZFoB.js +1 -0
  798. package/web/dist/assets/zig-CMLA9XwU.js +1 -0
  799. package/web/dist/icons/neondeck-icon-192.png +0 -0
  800. package/web/dist/icons/neondeck-icon-512.png +0 -0
  801. package/web/dist/icons/neondeck-icon.svg +41 -0
  802. package/web/dist/icons/neondeck-maskable-512.png +0 -0
  803. package/web/dist/index.html +27 -0
  804. package/web/dist/manifest.webmanifest +28 -0
@@ -0,0 +1,1596 @@
1
+ import { Bn as listScheduledTasks, Ci as readChatSession, Di as createChatSession, Ea as listNotifications, Fi as updateChatSessionCommandEvent, Hn as readScheduledTask, Ja as runtimePaths, Kn as nextOccurrence, Li as publishSessionEvent, O as createCiFailureDossierReport, Ta as addNotification, Va as ensureRuntimeHome, Xa as asJsonValue, Ya as openDb, ea as readRepoRegistrySnapshot, gi as fetchGitHubLogin, ia as listWorktrees, o as readAutopilotState, oi as fetchPullRequestQueue, pa as listPreparedDiffs, qn as validateAutomationTrigger, yn as listPrWatchRecords } from "./autopilot-B8lfWyA1.js";
2
+ import { l as startPrReview } from "./pr-reviews-BtJ5cm5P.js";
3
+ import { defineAction, dispatch } from "@flue/runtime";
4
+ import { randomUUID } from "node:crypto";
5
+ import * as v from "valibot";
6
+ //#region src/modules/briefings/schemas.ts
7
+ var defaultBriefingProfileId = "morning";
8
+ var defaultBriefingInstructions = "Summarize what needs my attention today. Prioritize review requests, failing checks, blocked automation, and time-sensitive follow-up. Keep the briefing concise and distinguish observed facts from inference.";
9
+ var defaultBriefingSchedule = "0 8 * * 1-5";
10
+ var nonEmptyStringSchema = v.pipe(v.string(), v.trim(), v.minLength(1));
11
+ var timezoneSchema = v.pipe(nonEmptyStringSchema, v.check((value) => {
12
+ try {
13
+ new Intl.DateTimeFormat("en-US", { timeZone: value });
14
+ return true;
15
+ } catch {
16
+ return false;
17
+ }
18
+ }, "Timezone must be a valid IANA timezone."));
19
+ var briefingProfileUpdateSchema = v.object({
20
+ id: v.optional(v.pipe(nonEmptyStringSchema, v.maxLength(64))),
21
+ name: v.optional(v.pipe(nonEmptyStringSchema, v.maxLength(96))),
22
+ enabled: v.optional(v.boolean()),
23
+ instructions: v.optional(v.pipe(nonEmptyStringSchema, v.maxLength(8e3))),
24
+ schedule: v.optional(v.pipe(nonEmptyStringSchema, v.maxLength(160))),
25
+ timezone: v.optional(timezoneSchema)
26
+ });
27
+ var briefingRunNowSchema = v.object({
28
+ profileId: v.optional(v.pipe(nonEmptyStringSchema, v.maxLength(64))),
29
+ sessionId: v.optional(nonEmptyStringSchema),
30
+ commandEventId: v.optional(nonEmptyStringSchema),
31
+ trigger: v.optional(v.picklist(["manual", "dashboard"]))
32
+ });
33
+ var briefingWorkflowInputSchema = v.object({
34
+ profileId: v.optional(v.pipe(nonEmptyStringSchema, v.maxLength(64))),
35
+ taskId: v.optional(nonEmptyStringSchema),
36
+ sessionId: v.optional(nonEmptyStringSchema),
37
+ commandEventId: v.optional(nonEmptyStringSchema),
38
+ trigger: v.optional(v.picklist([
39
+ "manual",
40
+ "scheduled",
41
+ "dashboard"
42
+ ]))
43
+ });
44
+ var briefingSnapshotSchema = v.object({
45
+ version: v.literal(1),
46
+ collectedAt: nonEmptyStringSchema,
47
+ byteSize: v.pipe(v.number(), v.integer(), v.minValue(0)),
48
+ truncated: v.boolean(),
49
+ sources: v.record(v.string(), v.object({
50
+ status: v.picklist([
51
+ "ok",
52
+ "partial",
53
+ "unavailable"
54
+ ]),
55
+ fetchedAt: nonEmptyStringSchema,
56
+ truncated: v.boolean(),
57
+ error: v.optional(v.string()),
58
+ data: v.nullable(v.unknown())
59
+ }))
60
+ });
61
+ //#endregion
62
+ //#region src/modules/commands/summaries.ts
63
+ function compactCommandSummary(result) {
64
+ if (result.command === "review-queue" && result.data && typeof result.data === "object") {
65
+ const data = result.data;
66
+ return {
67
+ ok: result.ok,
68
+ command: result.command,
69
+ input: result.input,
70
+ status: result.status,
71
+ message: result.message,
72
+ fetchedAt: data.fetchedAt,
73
+ login: data.login,
74
+ repos: data.repos,
75
+ count: data.count,
76
+ truncated: data.truncated,
77
+ issues: data.issues,
78
+ triage: data.triage,
79
+ topActions: data.topActions
80
+ };
81
+ }
82
+ return result;
83
+ }
84
+ function completedCommand(command, input, message, data) {
85
+ return {
86
+ ok: true,
87
+ command,
88
+ input,
89
+ status: "completed",
90
+ message,
91
+ data: asJsonValue(data)
92
+ };
93
+ }
94
+ function runningCommand(command, input, message, data) {
95
+ return {
96
+ ok: true,
97
+ command,
98
+ input,
99
+ status: "running",
100
+ message,
101
+ data: asJsonValue(data)
102
+ };
103
+ }
104
+ function needsConfigCommand(command, input, message, details) {
105
+ return {
106
+ ok: false,
107
+ command,
108
+ input,
109
+ status: "needs-config",
110
+ message,
111
+ ...details.errors ? { errors: details.errors } : {},
112
+ ...details.requires ? { requires: details.requires } : {}
113
+ };
114
+ }
115
+ function failedCommand(command, input, message, details = {}) {
116
+ return {
117
+ ok: false,
118
+ command,
119
+ input,
120
+ status: "failed",
121
+ message,
122
+ ...details.errors ? { errors: details.errors } : {},
123
+ ...details.requires ? { requires: details.requires } : {},
124
+ ...details.data ? { data: asJsonValue(details.data) } : {}
125
+ };
126
+ }
127
+ //#endregion
128
+ //#region src/modules/commands/utils.ts
129
+ var allThinkingLevels = [
130
+ "off",
131
+ "minimal",
132
+ "low",
133
+ "medium",
134
+ "high",
135
+ "xhigh"
136
+ ];
137
+ function supportedReasoningLevelsForModel(model) {
138
+ const specifier = parseModelSpecifier(model);
139
+ if (!specifier) return ["off"];
140
+ if (specifier.provider === "openai") return isOpenAiReasoningModel(specifier.model) ? allThinkingLevels : ["off"];
141
+ if (specifier.provider === "anthropic") return isAnthropicReasoningModel(specifier.model) ? allThinkingLevels : ["off"];
142
+ if (specifier.provider === "kilocode") return isKilocodeReasoningModel(specifier.model) ? allThinkingLevels : ["off"];
143
+ return ["off"];
144
+ }
145
+ function parseModelSpecifier(model) {
146
+ const slash = model.indexOf("/");
147
+ if (slash <= 0 || slash === model.length - 1) return null;
148
+ return {
149
+ provider: model.slice(0, slash),
150
+ model: model.slice(slash + 1)
151
+ };
152
+ }
153
+ function isOpenAiReasoningModel(model) {
154
+ return /^(gpt-5|o[1-9])(?:[.-]|$)/i.test(model);
155
+ }
156
+ function isAnthropicReasoningModel(model) {
157
+ return /^claude-(?:.*-4|3-7)(?:[.-]|$)/i.test(model);
158
+ }
159
+ function isKilocodeReasoningModel(model) {
160
+ const nested = parseModelSpecifier(model);
161
+ if (nested?.provider === "openai") return isOpenAiReasoningModel(nested.model);
162
+ if (nested?.provider === "anthropic") return isAnthropicReasoningModel(nested.model);
163
+ return /^kilo-auto(?:\/|$)/i.test(model) || isOpenAiReasoningModel(model) || isAnthropicReasoningModel(model) || /(?:^|\/)(deepseek-r1|qwen.*thinking|.*reasoning.*)(?:[/:.-]|$)/i.test(model);
164
+ }
165
+ function formatList(values) {
166
+ if (values.length === 0) return "no";
167
+ if (values.length === 1) return values[0] ?? "";
168
+ return `${values.slice(0, -1).join(", ")} or ${values.at(-1)}`;
169
+ }
170
+ function isMemoryScope(value) {
171
+ return value === "user" || value === "local" || value === "project";
172
+ }
173
+ function isActiveMemoryScope(value) {
174
+ return value === "user" || value === "local" || value === "project";
175
+ }
176
+ function parseMemoryValue(raw) {
177
+ try {
178
+ return JSON.parse(raw);
179
+ } catch {
180
+ return raw;
181
+ }
182
+ }
183
+ function readStringArrayProperty(value, key) {
184
+ if (!value || typeof value !== "object" || !(key in value)) return void 0;
185
+ const property = value[key];
186
+ if (!Array.isArray(property)) return void 0;
187
+ return property.filter((item) => typeof item === "string");
188
+ }
189
+ function errorMessage(error) {
190
+ return error instanceof Error ? error.message : String(error);
191
+ }
192
+ //#endregion
193
+ //#region src/modules/commands/handlers/queue.ts
194
+ async function reviewQueueCommand(command, paths, dependencies) {
195
+ const queue = await readReviewQueue(paths, dependencies);
196
+ if (!queue.ok) return needsConfigCommand(command.name, command.raw, queue.message, {
197
+ requires: queue.requires,
198
+ errors: queue.errors
199
+ });
200
+ const watches = await listPrWatchRecords(paths);
201
+ const triage = triageReviewQueue(queue.queue, watches);
202
+ return completedCommand(command.name, command.raw, reviewQueueMessage(triage), {
203
+ fetchedAt: queue.queue.fetchedAt,
204
+ login: queue.queue.login,
205
+ repos: queue.queue.repos,
206
+ count: queue.queue.items.length,
207
+ truncated: queue.queue.truncated,
208
+ issues: queue.queue.issues,
209
+ items: queue.queue.items,
210
+ triage,
211
+ topActions: triage.topActions
212
+ });
213
+ }
214
+ async function reviewPrCommand(command, paths, dependencies) {
215
+ const ref = command.args.join(" ").trim();
216
+ if (!ref) return failedCommand(command.name, command.raw, "/review-pr requires a PR reference.", { requires: ["ref"] });
217
+ const { review, reviewId, runId } = await (dependencies.startPrReview ?? startPrReview)({
218
+ ref,
219
+ origin: "chat"
220
+ }, paths, dependencies.invokeReviewPrWorkflow ? { invokeWorkflow: (input) => dependencies.invokeReviewPrWorkflow({
221
+ ref: input.ref,
222
+ reviewId: input.reviewId,
223
+ attemptId: input.attemptId
224
+ }) } : void 0);
225
+ return runningCommand(command.name, command.raw, `Reviewing ${review.repoFullName}#${review.prNumber}.`, {
226
+ workflow: "review-pr-for-human",
227
+ reviewId,
228
+ runId,
229
+ ref: review.ref,
230
+ queued: true,
231
+ reviewUrl: review.reviewUrl,
232
+ trustBoundary: review.trustBoundary,
233
+ assistantBrief: "Track the durable review record. It will transition to ready with report links and local draft counts; the human reviewer owns edits and submission."
234
+ });
235
+ }
236
+ async function fixCiCommand(command, paths, dependencies) {
237
+ const explicitRef = command.args.join(" ").trim();
238
+ if (explicitRef) {
239
+ const parsed = parsePullRequestRef(explicitRef);
240
+ if (!parsed) return failedCommand(command.name, command.raw, "Expected a PR reference like repo#123, owner/repo#123, or a GitHub pull request URL.", { requires: ["pr"] });
241
+ return queueFixCiWorkflow(command, `${parsed.repo}#${parsed.number}`, dependencies);
242
+ }
243
+ const queue = await readReviewQueue(paths, dependencies);
244
+ if (!queue.ok) return needsConfigCommand(command.name, command.raw, queue.message, {
245
+ requires: queue.requires,
246
+ errors: queue.errors
247
+ });
248
+ const selected = selectPullRequest(queue.queue, command.args, { prefer: isCiFixCandidate });
249
+ if (!selected.ok) return failedCommand(command.name, command.raw, selected.message, {
250
+ requires: selected.requires,
251
+ data: { available: summarizePullRequests(queue.queue.items).slice(0, 10) }
252
+ });
253
+ if (!isCiFixCandidate(selected.item)) return failedCommand(command.name, command.raw, `${selected.item.repo}#${selected.item.number} does not have failing or unknown CI checks.`, {
254
+ requires: ["failingChecks"],
255
+ data: { pr: summarizePullRequests([selected.item])[0] }
256
+ });
257
+ return queueFixCiWorkflow(command, `${selected.item.repo}#${selected.item.number}`, dependencies);
258
+ }
259
+ async function queueFixCiWorkflow(command, ref, dependencies) {
260
+ const { runId } = await (dependencies.invokeFixCiWorkflow ?? invokeFixCiWorkflow)({ ref });
261
+ return completedCommand(command.name, command.raw, `Queued CI fix workflow ${runId} for ${ref}.`, {
262
+ workflow: "fix-pr-ci",
263
+ runId,
264
+ ref,
265
+ queued: true,
266
+ reportUrlHint: "/reports",
267
+ trustBoundary: "The workflow can create local reports, a managed local worktree, a Kilo task, and a prepared diff only; it does not push, comment, or submit a GitHub review.",
268
+ assistantBrief: "Track the returned workflow run id. The dossier report is local; any code changes must pass through the prepared-diff review loop."
269
+ });
270
+ }
271
+ async function invokeFixCiWorkflow(input) {
272
+ const { invoke } = await import("@flue/runtime");
273
+ return invoke((await import("./fix-pr-ci-P3dLxmbx.js")).default, { input });
274
+ }
275
+ async function explainCiCommand(command, paths, dependencies) {
276
+ const options = parseExplainCiArgs(command.args);
277
+ const queue = await readReviewQueue(paths, dependencies);
278
+ if (!queue.ok) return needsConfigCommand(command.name, command.raw, queue.message, {
279
+ requires: queue.requires,
280
+ errors: queue.errors
281
+ });
282
+ const selected = selectPullRequest(queue.queue, options.args, { prefer: (item) => item.checks?.status === "failure" || item.checkError !== void 0 || item.checks?.status === "pending" });
283
+ if (!selected.ok) return failedCommand(command.name, command.raw, selected.message, {
284
+ requires: selected.requires,
285
+ data: { available: summarizePullRequests(queue.queue.items).slice(0, 10) }
286
+ });
287
+ const pr = selected.item;
288
+ const explanation = ciExplanation(pr);
289
+ if (options.report) {
290
+ const report = await (dependencies.createCiFailureDossierReport ?? createCiFailureDossierReport)({
291
+ ref: `${pr.repo}#${pr.number}`,
292
+ reportOnly: true
293
+ }, paths);
294
+ if (!report.ok) {
295
+ const requires = "requires" in report ? report.requires : void 0;
296
+ const errors = "errors" in report ? report.errors : void 0;
297
+ return requires?.includes("GITHUB_TOKEN") ? needsConfigCommand(command.name, command.raw, report.message, {
298
+ requires,
299
+ errors
300
+ }) : failedCommand(command.name, command.raw, report.message, {
301
+ requires,
302
+ errors
303
+ });
304
+ }
305
+ if (!("report" in report)) return failedCommand(command.name, command.raw, "CI dossier report writer did not return a report record.", { requires: ["report"] });
306
+ return completedCommand(command.name, command.raw, `${explanation.message} Created CI dossier report ${report.report.id}.`, {
307
+ pr: summarizePullRequests([pr])[0],
308
+ checks: pr.checks,
309
+ checkError: pr.checkError,
310
+ explanation,
311
+ report: {
312
+ id: report.report.id,
313
+ kind: report.report.kind,
314
+ title: report.report.title,
315
+ url: `/reports/${report.report.id}`
316
+ },
317
+ assistantBrief: "Use the deterministic CI dossier report and queue facts first. Separate observed facts from likely next debugging steps."
318
+ });
319
+ }
320
+ return completedCommand(command.name, command.raw, explanation.message, {
321
+ pr: summarizePullRequests([pr])[0],
322
+ checks: pr.checks,
323
+ checkError: pr.checkError,
324
+ explanation,
325
+ assistantBrief: "Use these deterministic CI/check facts first. Separate observed facts from likely next debugging steps."
326
+ });
327
+ }
328
+ function parseExplainCiArgs(args) {
329
+ return {
330
+ report: args.includes("--report"),
331
+ args: args.filter((arg) => arg !== "--report")
332
+ };
333
+ }
334
+ async function summarizePrCommand(command, paths, dependencies) {
335
+ const queue = await readReviewQueue(paths, dependencies);
336
+ if (!queue.ok) return needsConfigCommand(command.name, command.raw, queue.message, {
337
+ requires: queue.requires,
338
+ errors: queue.errors
339
+ });
340
+ const selected = selectPullRequest(queue.queue, command.args);
341
+ if (!selected.ok) return failedCommand(command.name, command.raw, selected.message, {
342
+ requires: selected.requires,
343
+ data: { available: summarizePullRequests(queue.queue.items).slice(0, 10) }
344
+ });
345
+ const pr = selected.item;
346
+ const summary = {
347
+ headline: `${pr.repo}#${pr.number}: ${pr.title}`,
348
+ state: pr.state,
349
+ author: pr.author,
350
+ relations: pr.relations,
351
+ labels: pr.labels,
352
+ comments: pr.comments,
353
+ ageDays: pr.ageDays,
354
+ stale: pr.stale,
355
+ baseRef: pr.baseRef,
356
+ headSha: pr.headSha,
357
+ checks: pr.checks?.status ?? "unknown",
358
+ url: pr.url
359
+ };
360
+ return completedCommand(command.name, command.raw, `Summarized ${pr.repo}#${pr.number}.`, {
361
+ pr: summarizePullRequests([pr])[0],
362
+ summary,
363
+ assistantBrief: "Summarize the PR from these deterministic facts. Do not invent diff contents that were not fetched."
364
+ });
365
+ }
366
+ function triageReviewQueue(queue, watches) {
367
+ const authored = queue.items.filter((item) => item.relations.includes("authored"));
368
+ const assigned = queue.items.filter((item) => item.relations.includes("assigned"));
369
+ const requestedReviews = queue.items.filter((item) => item.relations.includes("review-requested"));
370
+ const failedChecks = queue.items.filter((item) => item.checks?.status === "failure");
371
+ const checkErrors = queue.items.filter((item) => item.checkError);
372
+ const stalePrs = queue.items.filter((item) => item.stale);
373
+ const activeWatches = watches.filter((watch) => [
374
+ "watching",
375
+ "merged",
376
+ "attention-needed"
377
+ ].includes(watch.status));
378
+ const watchedPrs = queue.items.filter((item) => activeWatches.some((watch) => watch.repoFullName === item.repo && watch.prNumber === item.number));
379
+ return {
380
+ summary: {
381
+ authored: authored.length,
382
+ assigned: assigned.length,
383
+ requestedReviews: requestedReviews.length,
384
+ failedChecks: failedChecks.length,
385
+ checkErrors: checkErrors.length,
386
+ stale: stalePrs.length,
387
+ activeWatches: activeWatches.length,
388
+ watchedPrs: watchedPrs.length,
389
+ truncated: queue.truncated,
390
+ issues: queue.issues.length
391
+ },
392
+ authored: summarizePullRequests(authored),
393
+ assigned: summarizePullRequests(assigned),
394
+ requestedReviews: summarizePullRequests(requestedReviews),
395
+ failedChecks: summarizePullRequests(failedChecks),
396
+ checkErrors: summarizePullRequests(checkErrors),
397
+ stalePrs: summarizePullRequests(stalePrs),
398
+ issues: summarizeQueueIssues(queue.issues),
399
+ activeWatches: activeWatches.map((watch) => ({
400
+ id: watch.id,
401
+ repo: watch.repoFullName,
402
+ number: watch.prNumber,
403
+ status: watch.status,
404
+ desiredTerminalState: watch.desiredTerminalState,
405
+ url: watch.url,
406
+ updatedAt: watch.updatedAt
407
+ })),
408
+ topActions: rankReviewQueueActions(queue.items, activeWatches, failedChecks, checkErrors, requestedReviews, assigned, stalePrs, authored).slice(0, 3)
409
+ };
410
+ }
411
+ function summarizePullRequests(items) {
412
+ return items.map((item) => ({
413
+ repo: item.repo,
414
+ number: item.number,
415
+ title: item.title,
416
+ url: item.url,
417
+ author: item.author,
418
+ relations: item.relations,
419
+ checks: item.checks?.status ?? "unknown",
420
+ checkError: item.checkError,
421
+ stale: item.stale,
422
+ ageDays: item.ageDays,
423
+ updatedAt: item.updatedAt
424
+ }));
425
+ }
426
+ function summarizeQueueIssues(issues) {
427
+ return issues.map((issue) => ({
428
+ type: issue.type,
429
+ message: issue.message,
430
+ query: issue.query,
431
+ repo: issue.repo,
432
+ number: issue.number
433
+ }));
434
+ }
435
+ function rankReviewQueueActions(items, watches, failedChecks, checkErrors, requestedReviews, assigned, stalePrs, authored) {
436
+ const actions = [];
437
+ for (const item of failedChecks) actions.push(prAction(item, "Fix failing checks", "urgent"));
438
+ for (const item of checkErrors) actions.push(prAction(item, "Investigate unknown CI status", "urgent"));
439
+ for (const watch of watches.filter((item) => item.status === "attention-needed")) actions.push({
440
+ title: `Resolve watch ${watch.id}`,
441
+ reason: `Watch is ${watch.status}.`,
442
+ priority: "urgent",
443
+ url: watch.url,
444
+ repo: watch.repoFullName,
445
+ number: watch.prNumber
446
+ });
447
+ for (const item of requestedReviews) actions.push(prAction(item, "Review requested PR", "high"));
448
+ for (const item of assigned) actions.push(prAction(item, "Move assigned PR forward", "high"));
449
+ for (const item of stalePrs) actions.push(prAction(item, "Refresh stale PR", "medium"));
450
+ for (const item of authored) actions.push(prAction(item, "Advance authored PR", "medium"));
451
+ for (const item of items) actions.push(prAction(item, "Inspect open PR", "low"));
452
+ return dedupeActions(actions);
453
+ }
454
+ function prAction(item, reason, priority) {
455
+ return {
456
+ title: `${reason}: ${item.repo}#${item.number}`,
457
+ reason: item.checks?.status === "failure" ? `${item.checks.failed} checks failed.` : item.checkError ? `GitHub enrichment failed: ${item.checkError}` : reason,
458
+ priority,
459
+ url: item.url,
460
+ repo: item.repo,
461
+ number: item.number
462
+ };
463
+ }
464
+ function dedupeActions(actions) {
465
+ const seen = /* @__PURE__ */ new Set();
466
+ return actions.filter((action) => {
467
+ const key = action.repo && action.number ? `${action.repo}#${action.number}` : `${action.title}:${action.reason}`;
468
+ if (seen.has(key)) return false;
469
+ seen.add(key);
470
+ return true;
471
+ });
472
+ }
473
+ function isCiFixCandidate(item) {
474
+ return item.checks?.status === "failure" || item.checkError !== void 0;
475
+ }
476
+ function reviewQueueMessage(triage) {
477
+ const { summary } = triage;
478
+ const partial = summary.truncated || summary.issues > 0;
479
+ return `Triaged ${summary.authored + summary.assigned + summary.requestedReviews} user-related PR signal${summary.authored + summary.assigned + summary.requestedReviews === 1 ? "" : "s"}: ${summary.requestedReviews} review request${summary.requestedReviews === 1 ? "" : "s"}, ${summary.failedChecks} failing check set${summary.failedChecks === 1 ? "" : "s"}, ${summary.checkErrors} unknown check state${summary.checkErrors === 1 ? "" : "s"}, ${summary.stale} stale PR${summary.stale === 1 ? "" : "s"}.${partial ? " Results are partial; inspect queue issues." : ""}`;
480
+ }
481
+ function selectPullRequest(queue, args, options = {}) {
482
+ const ref = args.join(" ").trim();
483
+ if (ref) {
484
+ const parsed = parsePullRequestRef(ref);
485
+ if (!parsed) return {
486
+ ok: false,
487
+ message: "Expected a PR reference like repo#123, owner/repo#123, or a GitHub pull request URL.",
488
+ requires: ["pr"]
489
+ };
490
+ const match = queue.items.find((item) => item.number === parsed.number && (item.repo.toLowerCase() === parsed.repo.toLowerCase() || item.repo.split("/").at(1)?.toLowerCase() === parsed.repo.toLowerCase()));
491
+ if (!match) return {
492
+ ok: false,
493
+ message: `PR ${parsed.repo}#${parsed.number} was not found in the current review queue.`,
494
+ requires: ["queuedPr"]
495
+ };
496
+ return {
497
+ ok: true,
498
+ item: match
499
+ };
500
+ }
501
+ const item = (options.prefer ? queue.items.find(options.prefer) : void 0) ?? queue.items[0];
502
+ if (!item) return {
503
+ ok: false,
504
+ message: "No pull requests are available in the current review queue.",
505
+ requires: ["pr"]
506
+ };
507
+ return {
508
+ ok: true,
509
+ item
510
+ };
511
+ }
512
+ function parsePullRequestRef(ref) {
513
+ const url = ref.match(/github\.com\/([^/\s]+)\/([^/\s]+)\/pull\/(\d+)/i);
514
+ if (url) return {
515
+ repo: `${url[1]}/${url[2].replace(/\.git$/, "")}`,
516
+ number: Number(url[3])
517
+ };
518
+ const hash = ref.match(/^([A-Za-z0-9_.-]+(?:\/[A-Za-z0-9_.-]+)?)#(\d+)$/);
519
+ if (!hash) return void 0;
520
+ return {
521
+ repo: hash[1],
522
+ number: Number(hash[2])
523
+ };
524
+ }
525
+ function ciExplanation(pr) {
526
+ if (pr.checkError) return {
527
+ status: "unknown",
528
+ message: `GitHub check status for ${pr.repo}#${pr.number} could not be enriched.`,
529
+ facts: [`Enrichment error: ${pr.checkError}`],
530
+ nextActions: ["Open the PR checks page in GitHub.", "Retry after confirming the token can read checks."]
531
+ };
532
+ if (!pr.checks) return {
533
+ status: "unknown",
534
+ message: `${pr.repo}#${pr.number} has no check summary in the queue.`,
535
+ facts: ["No check runs or commit statuses were available."],
536
+ nextActions: ["Confirm the PR head SHA and configured repository access."]
537
+ };
538
+ const facts = [
539
+ `${pr.checks.total} total check signal${pr.checks.total === 1 ? "" : "s"}.`,
540
+ `${pr.checks.failed} failed, ${pr.checks.pending} pending, ${pr.checks.successful} successful.`,
541
+ `${pr.checks.statusContexts ?? 0} legacy status context${pr.checks.statusContexts === 1 ? "" : "s"}.`
542
+ ];
543
+ const nextActions = pr.checks.status === "failure" ? [
544
+ "Open the failing GitHub checks and inspect the first failed job log.",
545
+ "Run the matching local validation command if the repo exposes one.",
546
+ "After fixing, rerun failed checks or push an update."
547
+ ] : pr.checks.status === "pending" ? ["Wait for pending checks or inspect queued jobs for capacity issues."] : pr.checks.status === "success" ? ["No CI action is needed unless review feedback remains."] : ["Confirm whether this repo is expected to publish checks."];
548
+ return {
549
+ status: pr.checks.status,
550
+ message: `${pr.repo}#${pr.number} CI is ${pr.checks.status}.`,
551
+ facts,
552
+ nextActions
553
+ };
554
+ }
555
+ async function readReviewQueue(paths, dependencies) {
556
+ const token = process.env.GITHUB_TOKEN;
557
+ if (!token) return {
558
+ ok: false,
559
+ message: "GITHUB_TOKEN is not configured.",
560
+ requires: ["GITHUB_TOKEN"]
561
+ };
562
+ try {
563
+ const registry = await readRepoRegistrySnapshot(paths);
564
+ const fetchLogin = dependencies.fetchGitHubLogin ?? fetchGitHubLogin;
565
+ return {
566
+ ok: true,
567
+ queue: await (dependencies.fetchPullRequestQueue ?? fetchPullRequestQueue)({
568
+ token,
569
+ login: process.env.GITHUB_LOGIN ?? await fetchLogin(token),
570
+ repos: registry.repos
571
+ })
572
+ };
573
+ } catch (error) {
574
+ return {
575
+ ok: false,
576
+ message: "Could not fetch GitHub review queue.",
577
+ errors: [errorMessage(error)]
578
+ };
579
+ }
580
+ }
581
+ //#endregion
582
+ //#region src/modules/hygiene/service.ts
583
+ async function readHygieneSummary(paths) {
584
+ const [worktrees, preparedDiffs, watches] = await Promise.all([
585
+ listWorktrees(paths),
586
+ listPreparedDiffs({}, paths),
587
+ listPrWatchRecords(paths)
588
+ ]);
589
+ const unusedApprovals = countUnusedExecutionApprovals(paths);
590
+ return {
591
+ worktreeCleanupCandidates: worktrees.worktrees.filter((worktree) => [
592
+ "cleanup-pending",
593
+ "failed",
594
+ "needs-sync"
595
+ ].includes(worktree.lifecycleStatus)).length,
596
+ stalledPreparedDiffs: (preparedDiffs.preparedDiffs ?? []).filter((diff) => [
597
+ "prepared",
598
+ "revision-requested",
599
+ "push-approved"
600
+ ].includes(diff.status)).length,
601
+ closedOrMergedWatches: watches.filter((watch) => ["closed", "merged"].includes(watch.status)).length,
602
+ unusedExecutionApprovals: unusedApprovals
603
+ };
604
+ }
605
+ function countUnusedExecutionApprovals(paths) {
606
+ const database = openDb(paths.neondeckDatabase, { readOnly: true });
607
+ try {
608
+ const row = database.prepare(`
609
+ SELECT COUNT(*) AS count
610
+ FROM execution_approvals
611
+ WHERE status = 'approved'
612
+ AND used_at IS NULL;
613
+ `).get();
614
+ return typeof row?.count === "number" ? row.count : 0;
615
+ } finally {
616
+ database.close();
617
+ }
618
+ }
619
+ //#endregion
620
+ //#region src/modules/briefings/snapshot.ts
621
+ var collectionLimit = 40;
622
+ var snapshotByteLimit = 96e3;
623
+ async function collectBriefingSnapshot(paths, dependencies = {}) {
624
+ const collectedAt = (/* @__PURE__ */ new Date()).toISOString();
625
+ const [repos, reviewQueue, watches, tasks, notifications, hygiene, autopilot] = await Promise.all([
626
+ capture("repos", async () => {
627
+ return boundedList((await (dependencies.readRepos ?? readRepoRegistrySnapshot)(paths)).repos.map((repo) => ({
628
+ id: repo.id,
629
+ fullName: `${repo.github.owner}/${repo.github.name}`,
630
+ localPath: repo.path
631
+ })));
632
+ }),
633
+ capture("reviewQueue", async () => {
634
+ const result = await readReviewQueue(paths, dependencies);
635
+ if (!result.ok) return {
636
+ data: {
637
+ available: false,
638
+ message: result.message,
639
+ requires: result.requires ?? [],
640
+ errors: result.errors ?? []
641
+ },
642
+ partial: true
643
+ };
644
+ const items = result.queue.items.map((item) => ({
645
+ repo: item.repo,
646
+ number: item.number,
647
+ title: item.title,
648
+ url: item.url,
649
+ author: item.author,
650
+ checks: item.checks,
651
+ updatedAt: item.updatedAt
652
+ }));
653
+ return {
654
+ ...boundedList(items),
655
+ data: {
656
+ ...boundedList(items).data,
657
+ issues: result.queue.issues.slice(0, 12),
658
+ fetchedAt: result.queue.fetchedAt
659
+ },
660
+ partial: result.queue.truncated || result.queue.issues.length > 0
661
+ };
662
+ }),
663
+ capture("watches", async () => {
664
+ return boundedList((await (dependencies.readWatches ?? listPrWatchRecords)(paths)).map((watch) => ({
665
+ id: watch.id,
666
+ repoId: watch.repoId,
667
+ prNumber: watch.prNumber,
668
+ title: watch.title,
669
+ status: watch.status,
670
+ url: watch.url,
671
+ lastCheckedAt: watch.lastCheckedAt
672
+ })));
673
+ }),
674
+ capture("scheduledTasks", async () => {
675
+ return boundedList((await (dependencies.readTasks ?? listScheduledTasks)(paths)).map((task) => ({
676
+ id: task.id,
677
+ kind: task.spec.kind,
678
+ enabled: task.enabled,
679
+ nextRunAt: task.nextRunAt,
680
+ lastRunAt: task.lastRunAt
681
+ })));
682
+ }),
683
+ capture("notifications", async () => {
684
+ return boundedList((await (dependencies.readNotifications ?? listNotifications)(paths)).filter((notification) => !notification.readAt).map((notification) => ({
685
+ id: notification.id,
686
+ level: notification.level,
687
+ title: notification.title,
688
+ message: notification.message,
689
+ source: notification.source,
690
+ createdAt: notification.createdAt
691
+ })));
692
+ }),
693
+ capture("hygiene", async () => ({ data: await (dependencies.readHygiene ?? readHygieneSummary)(paths) })),
694
+ capture("autopilot", async () => {
695
+ const state = await (dependencies.readAutopilot ?? readAutopilotState)(paths);
696
+ return {
697
+ data: {
698
+ summary: state.summary,
699
+ queue: state.queue.slice(0, collectionLimit),
700
+ preparedDiffs: state.preparedDiffs.slice(0, collectionLimit),
701
+ pendingApprovals: state.pendingApprovals.slice(0, collectionLimit),
702
+ runningChecks: state.runningChecks.slice(0, collectionLimit)
703
+ },
704
+ truncated: state.queue.length > collectionLimit || state.preparedDiffs.length > collectionLimit || state.pendingApprovals.length > collectionLimit || state.runningChecks.length > collectionLimit
705
+ };
706
+ })
707
+ ]);
708
+ const sources = {
709
+ repos,
710
+ reviewQueue,
711
+ watches,
712
+ scheduledTasks: tasks,
713
+ notifications,
714
+ hygiene,
715
+ autopilot
716
+ };
717
+ const sizedInitial = withByteSize({
718
+ version: 1,
719
+ collectedAt,
720
+ byteSize: 0,
721
+ truncated: Object.values(sources).some((source) => source.truncated),
722
+ sources
723
+ });
724
+ if (sizedInitial.byteSize <= snapshotByteLimit) return sizedInitial;
725
+ const compactSources = Object.fromEntries(Object.entries(sources).map(([name, source]) => [name, {
726
+ ...source,
727
+ status: source.status === "unavailable" ? "unavailable" : "partial",
728
+ truncated: true,
729
+ ...source.error ? { error: truncateText(source.error, 1e3) } : {},
730
+ data: asJsonValue(compactData(source.data))
731
+ }]));
732
+ const compact = {
733
+ version: 1,
734
+ collectedAt,
735
+ byteSize: 0,
736
+ truncated: true,
737
+ sources: compactSources
738
+ };
739
+ const sizedCompact = withByteSize(compact);
740
+ if (sizedCompact.byteSize <= snapshotByteLimit) return sizedCompact;
741
+ return withByteSize({
742
+ ...compact,
743
+ sources: Object.fromEntries(Object.entries(compactSources).map(([name, source]) => [name, {
744
+ ...source,
745
+ data: null,
746
+ error: source.error ? truncateText(source.error, 300) : void 0
747
+ }]))
748
+ });
749
+ }
750
+ async function capture(_name, read) {
751
+ const fetchedAt = (/* @__PURE__ */ new Date()).toISOString();
752
+ try {
753
+ const result = await read();
754
+ return {
755
+ status: result.partial || result.truncated ? "partial" : "ok",
756
+ fetchedAt,
757
+ truncated: Boolean(result.truncated),
758
+ data: asJsonValue(result.data)
759
+ };
760
+ } catch (error) {
761
+ return {
762
+ status: "unavailable",
763
+ fetchedAt,
764
+ truncated: false,
765
+ error: truncateText(error instanceof Error ? error.message : String(error), 1e3),
766
+ data: null
767
+ };
768
+ }
769
+ }
770
+ function withByteSize(snapshot) {
771
+ let candidate = snapshot;
772
+ for (let attempt = 0; attempt < 3; attempt += 1) {
773
+ const byteSize = Buffer.byteLength(JSON.stringify(candidate), "utf8");
774
+ if (byteSize === candidate.byteSize) return candidate;
775
+ candidate = {
776
+ ...candidate,
777
+ byteSize
778
+ };
779
+ }
780
+ return candidate;
781
+ }
782
+ function truncateText(value, limit) {
783
+ return value.length > limit ? `${value.slice(0, limit - 3)}...` : value;
784
+ }
785
+ function boundedList(items) {
786
+ return {
787
+ data: {
788
+ total: items.length,
789
+ items: items.slice(0, collectionLimit)
790
+ },
791
+ truncated: items.length > collectionLimit
792
+ };
793
+ }
794
+ function compactData(data, depth = 0) {
795
+ if (typeof data === "string") return data.length > 300 ? `${data.slice(0, 297)}...` : data;
796
+ if (data === null || typeof data === "number" || typeof data === "boolean" || data === void 0) return data ?? null;
797
+ if (depth >= 3) return Array.isArray(data) ? {
798
+ total: data.length,
799
+ truncated: true
800
+ } : { truncated: true };
801
+ if (Array.isArray(data)) return data.slice(0, 3).map((value) => compactData(value, depth + 1));
802
+ if (typeof data !== "object") return String(data);
803
+ return Object.fromEntries(Object.entries(data).slice(0, 3).map(([key, value]) => [key, compactData(value, depth + 1)]));
804
+ }
805
+ //#endregion
806
+ //#region src/modules/briefings/store.ts
807
+ var nullableString = v.nullable(v.string());
808
+ var persistedProfileSchema = v.object({
809
+ id: v.string(),
810
+ name: v.string(),
811
+ enabled: v.number(),
812
+ instructions: v.string(),
813
+ instructions_version: v.number(),
814
+ schedule: v.string(),
815
+ timezone: v.string(),
816
+ session_id: nullableString,
817
+ created_at: v.string(),
818
+ updated_at: v.string()
819
+ });
820
+ var persistedRunSchema = v.object({
821
+ id: v.string(),
822
+ profile_id: nullableString,
823
+ trigger: v.picklist([
824
+ "manual",
825
+ "scheduled",
826
+ "dashboard"
827
+ ]),
828
+ snapshot_json: v.string(),
829
+ instructions: v.string(),
830
+ instructions_version: v.number(),
831
+ session_id: v.string(),
832
+ command_event_id: nullableString,
833
+ dispatch_id: nullableString,
834
+ workflow_run_id: nullableString,
835
+ status: v.picklist([
836
+ "queued",
837
+ "ready",
838
+ "failed"
839
+ ]),
840
+ error: nullableString,
841
+ queued_at: v.string(),
842
+ completed_at: nullableString,
843
+ created_at: v.string(),
844
+ updated_at: v.string()
845
+ });
846
+ var persistedRunMetadataSchema = v.omit(persistedRunSchema, ["snapshot_json", "instructions"]);
847
+ var persistedBriefingTaskSchema = v.object({
848
+ kind: v.string(),
849
+ trigger_json: v.string(),
850
+ next_run_at: nullableString,
851
+ claim_id: nullableString,
852
+ claim_expires_at: nullableString,
853
+ last_run_at: nullableString,
854
+ created_at: v.string()
855
+ });
856
+ async function readBriefingProfile(id = defaultBriefingProfileId, paths = runtimePaths()) {
857
+ await ensureRuntimeHome(paths);
858
+ const database = openDb(paths.neondeckDatabase);
859
+ try {
860
+ const row = database.prepare("SELECT * FROM briefing_profiles WHERE id = ?;").get(id);
861
+ if (row) return readProfileRow(row, false);
862
+ } finally {
863
+ database.close();
864
+ }
865
+ const compatibleTask = await readScheduledTask(`briefing:${id}`, paths);
866
+ const timezone = compatibleTask?.trigger.kind === "cron" ? compatibleTask.trigger.timezone : Intl.DateTimeFormat().resolvedOptions().timeZone ?? "UTC";
867
+ if (!compatibleTask) return (await writeBriefingProfileAndTask({
868
+ id,
869
+ name: id === "morning" ? "Morning Briefing" : id,
870
+ enabled: true,
871
+ instructions: defaultBriefingInstructions,
872
+ instructionsVersion: 1,
873
+ schedule: defaultBriefingSchedule,
874
+ timezone,
875
+ sessionId: null
876
+ }, paths)).profile;
877
+ const cron = compatibleTask?.trigger.kind === "cron" ? compatibleTask.trigger : void 0;
878
+ return {
879
+ id,
880
+ name: id === "morning" ? "Morning Briefing" : id,
881
+ enabled: compatibleTask.enabled,
882
+ instructions: defaultBriefingInstructions,
883
+ instructionsVersion: 1,
884
+ schedule: cron?.expression ?? "0 8 * * 1-5",
885
+ timezone,
886
+ sessionId: null,
887
+ compatibility: true,
888
+ createdAt: null,
889
+ updatedAt: compatibleTask?.updatedAt ?? null
890
+ };
891
+ }
892
+ async function writeBriefingProfileAndTask(profile, paths = runtimePaths()) {
893
+ await ensureRuntimeHome(paths);
894
+ const triggerResult = validateAutomationTrigger({
895
+ kind: "cron",
896
+ expression: profile.schedule,
897
+ timezone: profile.timezone
898
+ });
899
+ if (!triggerResult.ok) throw new Error(triggerResult.message);
900
+ const trigger = triggerResult.trigger;
901
+ const taskId = `briefing:${profile.id}`;
902
+ const spec = {
903
+ kind: "run-briefing",
904
+ briefingId: profile.id
905
+ };
906
+ const database = openDb(paths.neondeckDatabase);
907
+ const now = /* @__PURE__ */ new Date();
908
+ const nowIso = now.toISOString();
909
+ try {
910
+ database.exec("BEGIN IMMEDIATE;");
911
+ const beforeProfile = database.prepare("SELECT * FROM briefing_profiles WHERE id = ?;").get(profile.id);
912
+ const beforeTaskRow = database.prepare("SELECT * FROM scheduled_tasks WHERE id = ?;").get(taskId);
913
+ const beforeTask = beforeTaskRow ? parsePersisted(persistedBriefingTaskSchema, beforeTaskRow, "briefing scheduled task") : void 0;
914
+ if (beforeTask && beforeTask.kind !== "run-briefing") throw new Error(`Scheduled task "${taskId}" cannot be replaced with a briefing task.`);
915
+ const triggerJson = JSON.stringify(asJsonValue(trigger));
916
+ const nextRunAt = beforeTask && beforeTask.trigger_json === triggerJson ? beforeTask.next_run_at : nextOccurrence(trigger, now);
917
+ database.prepare(`INSERT INTO scheduled_tasks (
918
+ id, kind, trigger_json, payload_json, enabled, next_run_at,
919
+ claim_id, claim_expires_at, last_run_at, created_at, updated_at
920
+ ) VALUES (?, 'run-briefing', ?, ?, ?, ?, ?, ?, ?, ?, ?)
921
+ ON CONFLICT(id) DO UPDATE SET
922
+ kind = excluded.kind,
923
+ trigger_json = excluded.trigger_json,
924
+ payload_json = excluded.payload_json,
925
+ enabled = excluded.enabled,
926
+ next_run_at = excluded.next_run_at,
927
+ updated_at = excluded.updated_at;`).run(taskId, triggerJson, JSON.stringify(asJsonValue(spec)), profile.enabled ? 1 : 0, nextRunAt, beforeTask?.claim_id ?? null, beforeTask?.claim_expires_at ?? null, beforeTask?.last_run_at ?? null, beforeTask?.created_at ?? nowIso, nowIso);
928
+ database.prepare(`INSERT INTO briefing_profiles (
929
+ id, name, enabled, instructions, instructions_version, schedule,
930
+ timezone, session_id, created_at, updated_at
931
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
932
+ ON CONFLICT(id) DO UPDATE SET
933
+ name = excluded.name,
934
+ enabled = excluded.enabled,
935
+ instructions = excluded.instructions,
936
+ instructions_version = excluded.instructions_version,
937
+ schedule = excluded.schedule,
938
+ timezone = excluded.timezone,
939
+ session_id = excluded.session_id,
940
+ updated_at = excluded.updated_at;`).run(profile.id, profile.name, profile.enabled ? 1 : 0, profile.instructions, profile.instructionsVersion, profile.schedule, profile.timezone, profile.sessionId, nowIso, nowIso);
941
+ const afterProfile = database.prepare("SELECT * FROM briefing_profiles WHERE id = ?;").get(profile.id);
942
+ database.prepare(`INSERT INTO config_history (
943
+ action, file, target, before_json, after_json, changed_at
944
+ ) VALUES ('briefing_profile_update', 'briefing_profiles', ?, ?, ?, ?);`).run(profile.id, beforeProfile ? JSON.stringify(readProfileRow(beforeProfile, false)) : null, JSON.stringify(readProfileRow(afterProfile, false)), nowIso);
945
+ database.exec("COMMIT;");
946
+ return {
947
+ profile: readProfileRow(afterProfile, false),
948
+ task: {
949
+ id: taskId,
950
+ spec,
951
+ trigger,
952
+ enabled: profile.enabled,
953
+ nextRunAt,
954
+ claimId: beforeTask?.claim_id ?? null,
955
+ claimExpiresAt: beforeTask?.claim_expires_at ?? null,
956
+ lastRunAt: beforeTask?.last_run_at ?? null,
957
+ createdAt: beforeTask?.created_at ?? nowIso,
958
+ updatedAt: nowIso
959
+ }
960
+ };
961
+ } catch (error) {
962
+ database.exec("ROLLBACK;");
963
+ throw error;
964
+ } finally {
965
+ database.close();
966
+ }
967
+ }
968
+ async function setBriefingProfileSession(id, sessionId, paths = runtimePaths()) {
969
+ await ensureRuntimeHome(paths);
970
+ const database = openDb(paths.neondeckDatabase);
971
+ try {
972
+ database.prepare("UPDATE briefing_profiles SET session_id = ?, updated_at = ? WHERE id = ?;").run(sessionId, (/* @__PURE__ */ new Date()).toISOString(), id);
973
+ } finally {
974
+ database.close();
975
+ }
976
+ }
977
+ async function createBriefingRun(input, paths = runtimePaths()) {
978
+ await ensureRuntimeHome(paths);
979
+ const now = (/* @__PURE__ */ new Date()).toISOString();
980
+ const id = `briefing:${now.replace(/\D/g, "").slice(0, 14)}:${randomUUID().slice(0, 8)}`;
981
+ const database = openDb(paths.neondeckDatabase);
982
+ try {
983
+ database.prepare(`INSERT INTO briefing_runs (
984
+ id, profile_id, trigger, snapshot_json, instructions,
985
+ instructions_version, session_id, command_event_id, dispatch_id,
986
+ workflow_run_id, status, error, queued_at, completed_at, created_at,
987
+ updated_at
988
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, NULL, NULL, 'queued', NULL, ?, NULL, ?, ?);`).run(id, input.profileId, input.trigger, JSON.stringify(input.snapshot), input.instructions, input.instructionsVersion, input.sessionId, input.commandEventId ?? null, now, now, now);
989
+ return readBriefingRun(id, paths);
990
+ } finally {
991
+ database.close();
992
+ }
993
+ }
994
+ async function attachBriefingDispatch(id, dispatchId, paths = runtimePaths()) {
995
+ const database = openDb(paths.neondeckDatabase);
996
+ try {
997
+ database.prepare("UPDATE briefing_runs SET dispatch_id = ?, updated_at = ? WHERE id = ?;").run(dispatchId, (/* @__PURE__ */ new Date()).toISOString(), id);
998
+ } finally {
999
+ database.close();
1000
+ }
1001
+ }
1002
+ async function attachBriefingWorkflowRun(id, workflowRunId, paths = runtimePaths()) {
1003
+ const database = openDb(paths.neondeckDatabase);
1004
+ try {
1005
+ database.prepare("UPDATE briefing_runs SET workflow_run_id = ?, updated_at = ? WHERE id = ?;").run(workflowRunId, (/* @__PURE__ */ new Date()).toISOString(), id);
1006
+ } finally {
1007
+ database.close();
1008
+ }
1009
+ }
1010
+ async function settleBriefingRun(dispatchId, status, error, paths = runtimePaths()) {
1011
+ await ensureRuntimeHome(paths);
1012
+ const now = (/* @__PURE__ */ new Date()).toISOString();
1013
+ const database = openDb(paths.neondeckDatabase);
1014
+ try {
1015
+ const update = database.prepare(`UPDATE briefing_runs
1016
+ SET status = ?, error = ?, completed_at = ?, updated_at = ?
1017
+ WHERE dispatch_id = ? AND status = 'queued';`).run(status, error, now, now, dispatchId);
1018
+ const row = database.prepare("SELECT * FROM briefing_runs WHERE dispatch_id = ?;").get(dispatchId);
1019
+ return {
1020
+ changed: update.changes === 1,
1021
+ run: row ? readRunRow(row) : null
1022
+ };
1023
+ } finally {
1024
+ database.close();
1025
+ }
1026
+ }
1027
+ async function failBriefingRunBeforeDispatch(id, error, paths = runtimePaths()) {
1028
+ const database = openDb(paths.neondeckDatabase);
1029
+ const now = (/* @__PURE__ */ new Date()).toISOString();
1030
+ try {
1031
+ database.prepare(`UPDATE briefing_runs SET status = 'failed', error = ?, completed_at = ?, updated_at = ? WHERE id = ?;`).run(error, now, now, id);
1032
+ } finally {
1033
+ database.close();
1034
+ }
1035
+ }
1036
+ async function readBriefingRun(id, paths = runtimePaths()) {
1037
+ await ensureRuntimeHome(paths);
1038
+ const database = openDb(paths.neondeckDatabase);
1039
+ try {
1040
+ const row = database.prepare("SELECT * FROM briefing_runs WHERE id = ?;").get(id);
1041
+ return row ? readRunRow(row) : null;
1042
+ } finally {
1043
+ database.close();
1044
+ }
1045
+ }
1046
+ async function readBriefingRunByDispatch(dispatchId, paths = runtimePaths()) {
1047
+ await ensureRuntimeHome(paths);
1048
+ const database = openDb(paths.neondeckDatabase);
1049
+ try {
1050
+ const row = database.prepare("SELECT * FROM briefing_runs WHERE dispatch_id = ?;").get(dispatchId);
1051
+ return row ? readRunRow(row) : null;
1052
+ } finally {
1053
+ database.close();
1054
+ }
1055
+ }
1056
+ async function listBriefingRunMetadata(paths = runtimePaths(), limit = 20) {
1057
+ await ensureRuntimeHome(paths);
1058
+ const database = openDb(paths.neondeckDatabase);
1059
+ try {
1060
+ return database.prepare(`SELECT
1061
+ id, profile_id, trigger, instructions_version, session_id,
1062
+ command_event_id, dispatch_id, workflow_run_id, status, error,
1063
+ queued_at, completed_at, created_at, updated_at,
1064
+ json_extract(snapshot_json, '$.version') AS snapshot_version,
1065
+ json_extract(snapshot_json, '$.collectedAt') AS snapshot_collected_at,
1066
+ json_extract(snapshot_json, '$.byteSize') AS snapshot_byte_size,
1067
+ json_extract(snapshot_json, '$.truncated') AS snapshot_truncated
1068
+ FROM briefing_runs
1069
+ ORDER BY created_at DESC
1070
+ LIMIT ?;`).all(limit).map(readRunMetadataRow);
1071
+ } finally {
1072
+ database.close();
1073
+ }
1074
+ }
1075
+ function readProfileRow(row, compatibility) {
1076
+ const value = parsePersisted(persistedProfileSchema, row, "briefing profile");
1077
+ return {
1078
+ id: value.id,
1079
+ name: value.name,
1080
+ enabled: value.enabled === 1,
1081
+ instructions: value.instructions,
1082
+ instructionsVersion: value.instructions_version,
1083
+ schedule: value.schedule,
1084
+ timezone: value.timezone,
1085
+ sessionId: value.session_id,
1086
+ compatibility,
1087
+ createdAt: value.created_at,
1088
+ updatedAt: value.updated_at
1089
+ };
1090
+ }
1091
+ function readRunRow(row) {
1092
+ const value = parsePersisted(persistedRunSchema, row, "briefing run");
1093
+ let snapshot;
1094
+ try {
1095
+ snapshot = v.parse(briefingSnapshotSchema, JSON.parse(value.snapshot_json));
1096
+ } catch (error) {
1097
+ throw new Error(`Invalid persisted briefing snapshot for ${value.id}.`, { cause: error });
1098
+ }
1099
+ return {
1100
+ id: value.id,
1101
+ profileId: value.profile_id,
1102
+ trigger: value.trigger,
1103
+ snapshot,
1104
+ instructions: value.instructions,
1105
+ instructionsVersion: value.instructions_version,
1106
+ sessionId: value.session_id,
1107
+ commandEventId: value.command_event_id,
1108
+ dispatchId: value.dispatch_id,
1109
+ workflowRunId: value.workflow_run_id,
1110
+ status: value.status,
1111
+ error: value.error,
1112
+ queuedAt: value.queued_at,
1113
+ completedAt: value.completed_at,
1114
+ createdAt: value.created_at,
1115
+ updatedAt: value.updated_at
1116
+ };
1117
+ }
1118
+ function readRunMetadataRow(row) {
1119
+ const value = parsePersisted(v.object({
1120
+ ...persistedRunMetadataSchema.entries,
1121
+ snapshot_version: v.literal(1),
1122
+ snapshot_collected_at: v.string(),
1123
+ snapshot_byte_size: v.number(),
1124
+ snapshot_truncated: v.number()
1125
+ }), row, "briefing run metadata");
1126
+ return {
1127
+ id: value.id,
1128
+ profileId: value.profile_id,
1129
+ trigger: value.trigger,
1130
+ instructionsVersion: value.instructions_version,
1131
+ sessionId: value.session_id,
1132
+ commandEventId: value.command_event_id,
1133
+ dispatchId: value.dispatch_id,
1134
+ workflowRunId: value.workflow_run_id,
1135
+ status: value.status,
1136
+ error: value.error,
1137
+ queuedAt: value.queued_at,
1138
+ completedAt: value.completed_at,
1139
+ createdAt: value.created_at,
1140
+ updatedAt: value.updated_at,
1141
+ snapshot: {
1142
+ version: 1,
1143
+ collectedAt: value.snapshot_collected_at,
1144
+ byteSize: value.snapshot_byte_size,
1145
+ truncated: value.snapshot_truncated === 1
1146
+ }
1147
+ };
1148
+ }
1149
+ function parsePersisted(schema, value, label) {
1150
+ try {
1151
+ return v.parse(schema, value);
1152
+ } catch (error) {
1153
+ throw new Error(`Invalid persisted ${label}.`, { cause: error });
1154
+ }
1155
+ }
1156
+ //#endregion
1157
+ //#region src/modules/briefings/service.ts
1158
+ var pendingBriefingTerminals = /* @__PURE__ */ new Map();
1159
+ var pendingTerminalTtlMs = 3e4;
1160
+ async function readBriefingState(paths = runtimePaths()) {
1161
+ const profile = await readBriefingProfile(defaultBriefingProfileId, paths);
1162
+ const [runs, notifications, linkedSession] = await Promise.all([
1163
+ listBriefingRunMetadata(paths),
1164
+ listNotifications(paths),
1165
+ profile.sessionId ? readChatSession({
1166
+ id: profile.sessionId,
1167
+ reason: "briefing-state-read"
1168
+ }, paths) : null
1169
+ ]);
1170
+ const session = linkedSession && "session" in linkedSession ? linkedSession.session : null;
1171
+ return {
1172
+ ok: true,
1173
+ action: "briefing_state_read",
1174
+ changed: false,
1175
+ profile,
1176
+ latestRun: runs[0] ?? null,
1177
+ runs,
1178
+ sessionStaleReasons: session?.staleReasons ?? [],
1179
+ unreadCount: notifications.filter((notification) => notification.source === "briefing" && !notification.readAt).length,
1180
+ fetchedAt: (/* @__PURE__ */ new Date()).toISOString()
1181
+ };
1182
+ }
1183
+ async function rotateBriefingSession(rawInput, paths = runtimePaths()) {
1184
+ const parsed = v.safeParse(v.object({ id: v.optional(v.string()) }), rawInput);
1185
+ if (!parsed.success) return {
1186
+ ok: false,
1187
+ action: "briefing_session_rotate",
1188
+ changed: false,
1189
+ message: "Invalid briefing session rotation request."
1190
+ };
1191
+ const profile = await readBriefingProfile(parsed.output.id ?? "morning", paths);
1192
+ if (profile.compatibility) await writeBriefingProfileAndTask({
1193
+ id: profile.id,
1194
+ name: profile.name,
1195
+ enabled: profile.enabled,
1196
+ instructions: profile.instructions,
1197
+ instructionsVersion: profile.instructionsVersion,
1198
+ schedule: profile.schedule,
1199
+ timezone: profile.timezone,
1200
+ sessionId: null
1201
+ }, paths);
1202
+ const created = await createChatSession({
1203
+ title: profile.name,
1204
+ kind: "briefing",
1205
+ linkedTaskId: `briefing:${profile.id}:rotation:${Date.now()}`,
1206
+ activate: false,
1207
+ surface: "dashboard",
1208
+ reason: "explicit-briefing-session-rotation",
1209
+ uiMetadata: { briefingProfileId: profile.id }
1210
+ }, paths);
1211
+ if (!("session" in created)) return {
1212
+ ok: false,
1213
+ action: "briefing_session_rotate",
1214
+ changed: false,
1215
+ message: "A fresh briefing conversation could not be created."
1216
+ };
1217
+ await setBriefingProfileSession(profile.id, created.session.id, paths);
1218
+ return {
1219
+ ok: true,
1220
+ action: "briefing_session_rotate",
1221
+ changed: true,
1222
+ message: "Started a fresh briefing conversation.",
1223
+ profile: await readBriefingProfile(profile.id, paths),
1224
+ session: created.session
1225
+ };
1226
+ }
1227
+ async function readBriefingRunDetails(id, paths = runtimePaths()) {
1228
+ const run = await readBriefingRun(id, paths);
1229
+ if (!run) return {
1230
+ ok: false,
1231
+ action: "briefing_run_read",
1232
+ changed: false,
1233
+ message: `Briefing run "${id}" was not found.`
1234
+ };
1235
+ return {
1236
+ ok: true,
1237
+ action: "briefing_run_read",
1238
+ changed: false,
1239
+ message: `Read briefing run "${id}".`,
1240
+ run
1241
+ };
1242
+ }
1243
+ async function updateBriefingProfile(rawInput, paths = runtimePaths()) {
1244
+ const parsed = v.safeParse(briefingProfileUpdateSchema, rawInput);
1245
+ if (!parsed.success) return {
1246
+ ok: false,
1247
+ action: "briefing_profile_update",
1248
+ changed: false,
1249
+ message: "Invalid briefing profile.",
1250
+ errors: [v.summarize(parsed.issues)]
1251
+ };
1252
+ const id = parsed.output.id ?? "morning";
1253
+ const current = await readBriefingProfile(id, paths);
1254
+ const instructions = parsed.output.instructions ?? current.instructions;
1255
+ const desired = {
1256
+ id,
1257
+ name: parsed.output.name ?? current.name,
1258
+ enabled: parsed.output.enabled ?? current.enabled,
1259
+ instructions,
1260
+ instructionsVersion: instructions === current.instructions ? current.instructionsVersion : current.instructionsVersion + 1,
1261
+ schedule: parsed.output.schedule ?? current.schedule,
1262
+ timezone: parsed.output.timezone ?? current.timezone,
1263
+ sessionId: current.sessionId
1264
+ };
1265
+ try {
1266
+ const updated = await writeBriefingProfileAndTask(desired, paths);
1267
+ return {
1268
+ ok: true,
1269
+ action: "briefing_profile_update",
1270
+ changed: true,
1271
+ message: "Updated the morning briefing profile and schedule.",
1272
+ profile: updated.profile,
1273
+ task: updated.task
1274
+ };
1275
+ } catch (error) {
1276
+ return {
1277
+ ok: false,
1278
+ action: "briefing_profile_update",
1279
+ changed: false,
1280
+ message: `The briefing profile was not changed: ${error instanceof Error ? error.message : String(error)}`
1281
+ };
1282
+ }
1283
+ }
1284
+ async function runBriefingNow(rawInput, paths = runtimePaths(), dependencies = {}) {
1285
+ const parsed = v.safeParse(briefingRunNowSchema, rawInput);
1286
+ if (!parsed.success) return {
1287
+ ok: false,
1288
+ action: "briefing_run",
1289
+ changed: false,
1290
+ message: "Invalid briefing run request.",
1291
+ errors: [v.summarize(parsed.issues)]
1292
+ };
1293
+ try {
1294
+ const input = {
1295
+ profileId: parsed.output.profileId ?? "morning",
1296
+ sessionId: parsed.output.sessionId,
1297
+ commandEventId: parsed.output.commandEventId,
1298
+ trigger: parsed.output.trigger ?? "dashboard"
1299
+ };
1300
+ const { runId } = await (dependencies.invokeWorkflow ?? invokeBriefingWorkflow)(input);
1301
+ return {
1302
+ ok: true,
1303
+ action: "briefing_run",
1304
+ changed: true,
1305
+ message: `Briefing workflow ${runId} queued.`,
1306
+ workflowRunId: runId
1307
+ };
1308
+ } catch (error) {
1309
+ return {
1310
+ ok: false,
1311
+ action: "briefing_run",
1312
+ changed: false,
1313
+ message: error instanceof Error ? error.message : String(error)
1314
+ };
1315
+ }
1316
+ }
1317
+ async function invokeBriefingWorkflow(input) {
1318
+ const { invoke } = await import("@flue/runtime");
1319
+ return invoke((await import("./briefing-VMdQPEGc.js")).default, { input });
1320
+ }
1321
+ async function admitBriefing(input, paths = runtimePaths(), dependencies = {}) {
1322
+ const profile = await readBriefingProfile(input.profileId, paths);
1323
+ const sessionId = input.sessionId ? await validateRequestedBriefingSession(input.sessionId, paths) : await resolveScheduledBriefingSession(profile, paths);
1324
+ const snapshot = await collectBriefingSnapshot(paths, dependencies);
1325
+ const run = await createBriefingRun({
1326
+ profileId: profile.id,
1327
+ trigger: input.trigger,
1328
+ snapshot,
1329
+ instructions: profile.instructions,
1330
+ instructionsVersion: profile.instructionsVersion,
1331
+ sessionId,
1332
+ commandEventId: input.commandEventId
1333
+ }, paths);
1334
+ if (!run) throw new Error("Briefing run could not be persisted.");
1335
+ try {
1336
+ const receipt = await (dependencies.dispatchAgent ?? dispatch)({
1337
+ agent: "display-assistant",
1338
+ id: sessionId,
1339
+ input: composeBriefingInput(run, profile)
1340
+ });
1341
+ await attachBriefingDispatch(run.id, receipt.dispatchId, paths);
1342
+ await reconcilePendingBriefingTerminal(receipt.dispatchId, paths);
1343
+ return {
1344
+ ...run,
1345
+ dispatchId: receipt.dispatchId
1346
+ };
1347
+ } catch (error) {
1348
+ const message = error instanceof Error ? error.message : String(error);
1349
+ await failBriefingRunBeforeDispatch(run.id, message, paths);
1350
+ await addNotification({
1351
+ level: "attention",
1352
+ title: "Morning briefing failed",
1353
+ message: "Neon could not start the briefing conversation.",
1354
+ source: "briefing",
1355
+ sourceId: run.id,
1356
+ data: {
1357
+ runId: run.id,
1358
+ sessionId,
1359
+ error: message
1360
+ }
1361
+ }, paths);
1362
+ throw error;
1363
+ }
1364
+ }
1365
+ async function settleBriefingObservation(event, paths = runtimePaths()) {
1366
+ if (!event.dispatchId) return null;
1367
+ const observation = event;
1368
+ if (observation.taskId || observation.parentSession) return null;
1369
+ if (typeof observation.agentName === "string" && observation.agentName !== "display-assistant") return null;
1370
+ if (event.type === "operation" && (event.operationKind !== "prompt" || !event.isError)) return null;
1371
+ const failed = event.type === "operation" ? event.isError : event.type === "submission_settled" ? event.outcome !== "completed" : false;
1372
+ const error = failed ? briefingObservationError(event) : null;
1373
+ const instanceId = typeof observation.instanceId === "string" ? observation.instanceId : "";
1374
+ let correlated = await readBriefingRunByDispatch(event.dispatchId, paths);
1375
+ if (!correlated) {
1376
+ const runId = briefingRunIdFromObservation(observation);
1377
+ if (runId) {
1378
+ const candidate = await readBriefingRun(runId, paths);
1379
+ if (candidate?.status === "queued" && (!instanceId || candidate.sessionId === instanceId)) {
1380
+ await attachBriefingDispatch(runId, event.dispatchId, paths);
1381
+ correlated = await readBriefingRunByDispatch(event.dispatchId, paths);
1382
+ }
1383
+ }
1384
+ }
1385
+ if (!correlated) {
1386
+ rememberPendingBriefingTerminal(paths, event.dispatchId, {
1387
+ failed,
1388
+ error,
1389
+ instanceId,
1390
+ recordedAt: Date.now()
1391
+ });
1392
+ return null;
1393
+ }
1394
+ if (instanceId && correlated.sessionId !== instanceId) return null;
1395
+ return finalizeBriefingTerminal(event.dispatchId, {
1396
+ failed,
1397
+ error,
1398
+ instanceId,
1399
+ recordedAt: Date.now()
1400
+ }, paths);
1401
+ }
1402
+ async function finalizeBriefingTerminal(dispatchId, terminal, paths) {
1403
+ const { failed, error } = terminal;
1404
+ const settled = await settleBriefingRun(dispatchId, failed ? "failed" : "ready", error, paths);
1405
+ if (!settled.changed || !settled.run) return settled.run;
1406
+ const run = settled.run;
1407
+ if (run.commandEventId) await updateChatSessionCommandEvent({
1408
+ sessionId: run.sessionId,
1409
+ eventId: run.commandEventId,
1410
+ status: failed ? "failed" : "completed",
1411
+ result: null,
1412
+ reason: "briefing-submission-settled"
1413
+ }, paths);
1414
+ await addNotification({
1415
+ level: failed ? "attention" : "ready",
1416
+ title: failed ? "Morning briefing failed" : "Morning briefing ready",
1417
+ message: failed ? "Neon could not complete the briefing. Open the conversation for context." : "Neon has added today's briefing to your Morning Briefing conversation.",
1418
+ source: "briefing",
1419
+ sourceId: run.id,
1420
+ data: {
1421
+ runId: run.id,
1422
+ sessionId: run.sessionId
1423
+ }
1424
+ }, paths);
1425
+ const sessionResult = await readChatSession({
1426
+ id: run.sessionId,
1427
+ reason: "briefing-submission-settled"
1428
+ }, paths);
1429
+ if ("session" in sessionResult && sessionResult.session) publishSessionEvent("updated", sessionResult.session, null);
1430
+ return run;
1431
+ }
1432
+ function briefingObservationError(event) {
1433
+ if (event.type === "submission_settled") return event.error?.message ?? `Briefing submission ${event.outcome}.`;
1434
+ if (event.type === "operation") {
1435
+ if (event.error instanceof Error) return event.error.message;
1436
+ if (typeof event.error === "string") return event.error;
1437
+ return event.errorInfo?.message ?? "Briefing model operation failed.";
1438
+ }
1439
+ return null;
1440
+ }
1441
+ async function linkBriefingWorkflowObservation(event, paths = runtimePaths()) {
1442
+ if (!("result" in event) || !event.result || typeof event.result !== "object") return;
1443
+ const briefingRunId = event.result.briefingRunId;
1444
+ if (typeof briefingRunId === "string") await attachBriefingWorkflowRun(briefingRunId, event.runId, paths);
1445
+ }
1446
+ function composeBriefingInput(run, profile) {
1447
+ const triggerLabel = run.trigger === "scheduled" ? "scheduled morning" : "manual";
1448
+ return [
1449
+ `[NEONDECK_INTERNAL_BRIEFING_INPUT v1 trigger=${run.trigger} run=${run.id}]`,
1450
+ `Prepare the ${triggerLabel} briefing for ${run.snapshot.collectedAt}.`,
1451
+ `Briefing snapshot id: ${run.id}.`,
1452
+ "Neondeck fact snapshot:",
1453
+ JSON.stringify(run.snapshot, null, 2),
1454
+ "User briefing instructions:",
1455
+ profile.instructions,
1456
+ "Respond to the user normally in this conversation. Use any configured MCP tools relevant to their instructions; do not assume a named external source was consulted unless you actually used it. If a deterministic or MCP source is unavailable, needs login, is denied, or awaits approval, explain that naturally and continue with the useful context you do have. Distinguish observed facts from inference. This briefing is informational; do not mutate external systems or auto-approve tool calls."
1457
+ ].join("\n\n");
1458
+ }
1459
+ function briefingRunIdFromObservation(observation) {
1460
+ const agentInput = observation.agentInput;
1461
+ if (!agentInput || typeof agentInput !== "object") return null;
1462
+ const raw = agentInput.text;
1463
+ if (typeof raw !== "string") return null;
1464
+ let text = raw;
1465
+ if (raw.startsWith("\"")) try {
1466
+ const decoded = JSON.parse(raw);
1467
+ if (typeof decoded === "string") text = decoded;
1468
+ } catch {
1469
+ return null;
1470
+ }
1471
+ return text.match(/\[NEONDECK_INTERNAL_BRIEFING_INPUT v1 trigger=\w+ run=([^\]\s]+)\]/)?.[1] ?? null;
1472
+ }
1473
+ function pendingTerminalKey(paths, dispatchId) {
1474
+ return `${paths.home}:${dispatchId}`;
1475
+ }
1476
+ function rememberPendingBriefingTerminal(paths, dispatchId, terminal) {
1477
+ const cutoff = Date.now() - pendingTerminalTtlMs;
1478
+ for (const [key, value] of pendingBriefingTerminals) if (value.recordedAt < cutoff) pendingBriefingTerminals.delete(key);
1479
+ if (pendingBriefingTerminals.size >= 100) {
1480
+ const oldest = pendingBriefingTerminals.keys().next().value;
1481
+ if (oldest) pendingBriefingTerminals.delete(oldest);
1482
+ }
1483
+ pendingBriefingTerminals.set(pendingTerminalKey(paths, dispatchId), terminal);
1484
+ }
1485
+ async function reconcilePendingBriefingTerminal(dispatchId, paths) {
1486
+ const key = pendingTerminalKey(paths, dispatchId);
1487
+ const terminal = pendingBriefingTerminals.get(key);
1488
+ if (!terminal) return;
1489
+ pendingBriefingTerminals.delete(key);
1490
+ if (Date.now() - terminal.recordedAt > pendingTerminalTtlMs) return;
1491
+ const run = await readBriefingRunByDispatch(dispatchId, paths);
1492
+ if (!run || terminal.instanceId && run.sessionId !== terminal.instanceId) return;
1493
+ await finalizeBriefingTerminal(dispatchId, terminal, paths);
1494
+ }
1495
+ async function resolveScheduledBriefingSession(profile, paths) {
1496
+ if (profile.sessionId) {
1497
+ const existing = await readChatSession({
1498
+ id: profile.sessionId,
1499
+ reason: "scheduled-briefing-reuse"
1500
+ }, paths);
1501
+ if ("session" in existing && !existing.session.archivedAt) {
1502
+ if (existing.session.staleReasons.length > 0) throw new Error("The briefing conversation context is stale. Start a fresh briefing conversation before running again.");
1503
+ return profile.sessionId;
1504
+ }
1505
+ }
1506
+ if (profile.compatibility) await writeBriefingProfileAndTask({
1507
+ id: profile.id,
1508
+ name: profile.name,
1509
+ enabled: profile.enabled,
1510
+ instructions: profile.instructions,
1511
+ instructionsVersion: profile.instructionsVersion,
1512
+ schedule: profile.schedule,
1513
+ timezone: profile.timezone,
1514
+ sessionId: null
1515
+ }, paths);
1516
+ const created = await createChatSession({
1517
+ title: profile.name,
1518
+ kind: "briefing",
1519
+ linkedTaskId: `briefing:${profile.id}`,
1520
+ activate: false,
1521
+ surface: "dashboard",
1522
+ reason: "scheduled-briefing-session",
1523
+ uiMetadata: { briefingProfileId: profile.id }
1524
+ }, paths);
1525
+ if (!("session" in created)) throw new Error("Briefing session could not be created.");
1526
+ if (created.session.staleReasons.length > 0) throw new Error("The briefing conversation context is stale. Start a fresh briefing conversation before running again.");
1527
+ await setBriefingProfileSession(profile.id, created.session.id, paths);
1528
+ return created.session.id;
1529
+ }
1530
+ async function validateRequestedBriefingSession(sessionId, paths) {
1531
+ const result = await readChatSession({
1532
+ id: sessionId,
1533
+ reason: "manual-briefing-admission"
1534
+ }, paths);
1535
+ if (!("session" in result) || result.session.archivedAt || result.session.agentName !== "display-assistant" || result.session.staleReasons.length > 0) throw new Error("Manual briefings require an active display-assistant chat session.");
1536
+ return result.session.id;
1537
+ }
1538
+ //#endregion
1539
+ //#region src/modules/briefings/actions.ts
1540
+ var outputSchema = v.looseObject({
1541
+ ok: v.boolean(),
1542
+ action: v.string(),
1543
+ changed: v.boolean(),
1544
+ message: v.optional(v.string())
1545
+ });
1546
+ var neondeckBriefingActions = [
1547
+ defineAction({
1548
+ name: "neondeck_briefing_profile_read",
1549
+ description: "Read the typed morning briefing profile, its durable conversation link, and recent operational run metadata.",
1550
+ input: v.object({}),
1551
+ output: outputSchema,
1552
+ async run() {
1553
+ return readBriefingState();
1554
+ }
1555
+ }),
1556
+ defineAction({
1557
+ name: "neondeck_briefing_profile_update",
1558
+ description: "Update the enabled state, cron schedule, timezone, title, or user-authored instructions for the morning briefing profile.",
1559
+ input: briefingProfileUpdateSchema,
1560
+ output: outputSchema,
1561
+ async run({ input }) {
1562
+ return updateBriefingProfile(input);
1563
+ }
1564
+ }),
1565
+ defineAction({
1566
+ name: "neondeck_briefing_run_read",
1567
+ description: "Read one exact persisted deterministic briefing snapshot and its operational dispatch metadata. This never reads or parses the assistant transcript.",
1568
+ input: v.object({ id: v.pipe(v.string(), v.minLength(1)) }),
1569
+ output: outputSchema,
1570
+ async run({ input }) {
1571
+ return readBriefingRunDetails(input.id);
1572
+ }
1573
+ }),
1574
+ defineAction({
1575
+ name: "neondeck_briefing_run_now",
1576
+ description: "Queue an informational briefing in its persistent briefing conversation. All configured display-assistant MCP tools remain available under their normal auth and approval controls.",
1577
+ input: briefingRunNowSchema,
1578
+ output: outputSchema,
1579
+ async run({ input }) {
1580
+ return runBriefingNow(input);
1581
+ }
1582
+ }),
1583
+ defineAction({
1584
+ name: "neondeck_briefing_session_rotate",
1585
+ description: "Explicitly start a fresh durable briefing conversation when its captured model, SOUL, memory, skill, or provider context is stale. The old transcript remains preserved.",
1586
+ input: v.object({ id: v.optional(v.string()) }),
1587
+ output: outputSchema,
1588
+ async run({ input }) {
1589
+ return rotateBriefingSession(input);
1590
+ }
1591
+ })
1592
+ ];
1593
+ //#endregion
1594
+ export { completedCommand as C, compactCommandSummary as S, briefingWorkflowInputSchema as T, isActiveMemoryScope as _, readBriefingState as a, readStringArrayProperty as b, settleBriefingObservation as c, explainCiCommand as d, fixCiCommand as f, formatList as g, summarizePrCommand as h, readBriefingRunDetails as i, updateBriefingProfile as l, reviewQueueCommand as m, admitBriefing as n, rotateBriefingSession as o, reviewPrCommand as p, linkBriefingWorkflowObservation as r, runBriefingNow as s, neondeckBriefingActions as t, collectBriefingSnapshot as u, isMemoryScope as v, failedCommand as w, supportedReasoningLevelsForModel as x, parseMemoryValue as y };
1595
+
1596
+ //# sourceMappingURL=briefings-DuApznpN.js.map