lastlight 0.1.15 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (478) hide show
  1. package/README.md +265 -118
  2. package/agent-context/rules.md +62 -9
  3. package/agent-context/security.md +69 -0
  4. package/config/default.yaml +89 -0
  5. package/deploy/.env.production.example +20 -2
  6. package/deploy/entrypoint.sh +16 -17
  7. package/deploy/native/README.md +160 -0
  8. package/deploy/native/install.sh +110 -0
  9. package/deploy/native/lastlight.env.example +95 -0
  10. package/deploy/native/lastlight.service +50 -0
  11. package/deploy/sandbox-entrypoint.sh +59 -42
  12. package/dist/admin/auth.d.ts +1 -1
  13. package/dist/admin/auth.js +3 -1
  14. package/dist/admin/auth.js.map +1 -1
  15. package/dist/admin/chat-session-reader.d.ts +11 -14
  16. package/dist/admin/chat-session-reader.js +27 -51
  17. package/dist/admin/chat-session-reader.js.map +1 -1
  18. package/dist/admin/docker.d.ts +37 -0
  19. package/dist/admin/docker.js +86 -1
  20. package/dist/admin/docker.js.map +1 -1
  21. package/dist/admin/index.js +38 -3
  22. package/dist/admin/index.js.map +1 -1
  23. package/dist/admin/log-search.test.d.ts +1 -0
  24. package/dist/admin/log-search.test.js +78 -0
  25. package/dist/admin/log-search.test.js.map +1 -0
  26. package/dist/admin/routes.d.ts +52 -3
  27. package/dist/admin/routes.js +780 -63
  28. package/dist/admin/routes.js.map +1 -1
  29. package/dist/admin/routes.test.js +680 -14
  30. package/dist/admin/routes.test.js.map +1 -1
  31. package/dist/admin/server-logs.test.d.ts +1 -0
  32. package/dist/admin/server-logs.test.js +58 -0
  33. package/dist/admin/server-logs.test.js.map +1 -0
  34. package/dist/admin/sessions.d.ts +26 -39
  35. package/dist/admin/sessions.js +86 -310
  36. package/dist/admin/sessions.js.map +1 -1
  37. package/dist/admin/sessions.test.d.ts +1 -0
  38. package/dist/admin/sessions.test.js +78 -0
  39. package/dist/admin/sessions.test.js.map +1 -0
  40. package/dist/admin/version.d.ts +15 -0
  41. package/dist/admin/version.js +73 -0
  42. package/dist/admin/version.js.map +1 -0
  43. package/dist/admin/version.test.d.ts +1 -0
  44. package/dist/admin/version.test.js +71 -0
  45. package/dist/admin/version.test.js.map +1 -0
  46. package/dist/cli-config.d.ts +55 -0
  47. package/dist/cli-config.js +119 -0
  48. package/dist/cli-config.js.map +1 -0
  49. package/dist/cli-config.test.d.ts +1 -0
  50. package/dist/cli-config.test.js +92 -0
  51. package/dist/cli-config.test.js.map +1 -0
  52. package/dist/cli-format.d.ts +19 -0
  53. package/dist/cli-format.js +107 -0
  54. package/dist/cli-format.js.map +1 -0
  55. package/dist/cli-server.d.ts +73 -0
  56. package/dist/cli-server.js +347 -0
  57. package/dist/cli-server.js.map +1 -0
  58. package/dist/cli-server.test.d.ts +1 -0
  59. package/dist/cli-server.test.js +38 -0
  60. package/dist/cli-server.test.js.map +1 -0
  61. package/dist/cli-timeline.d.ts +35 -0
  62. package/dist/cli-timeline.js +373 -0
  63. package/dist/cli-timeline.js.map +1 -0
  64. package/dist/cli-timeline.test.d.ts +1 -0
  65. package/dist/cli-timeline.test.js +104 -0
  66. package/dist/cli-timeline.test.js.map +1 -0
  67. package/dist/cli.d.ts +0 -19
  68. package/dist/cli.js +910 -194
  69. package/dist/cli.js.map +1 -1
  70. package/dist/config-overlay.test.d.ts +1 -0
  71. package/dist/config-overlay.test.js +112 -0
  72. package/dist/config-overlay.test.js.map +1 -0
  73. package/dist/config-resolve.d.ts +28 -0
  74. package/dist/config-resolve.js +47 -0
  75. package/dist/config-resolve.js.map +1 -0
  76. package/dist/config-resolve.test.d.ts +1 -0
  77. package/dist/config-resolve.test.js +68 -0
  78. package/dist/config-resolve.test.js.map +1 -0
  79. package/dist/config.d.ts +62 -49
  80. package/dist/config.js +452 -76
  81. package/dist/config.js.map +1 -1
  82. package/dist/config.test.js +201 -32
  83. package/dist/config.test.js.map +1 -1
  84. package/dist/connectors/github-webhook.js +83 -5
  85. package/dist/connectors/github-webhook.js.map +1 -1
  86. package/dist/connectors/github-webhook.test.d.ts +1 -0
  87. package/dist/connectors/github-webhook.test.js +156 -0
  88. package/dist/connectors/github-webhook.test.js.map +1 -0
  89. package/dist/connectors/messaging/session-manager.d.ts +18 -0
  90. package/dist/connectors/messaging/session-manager.js +83 -2
  91. package/dist/connectors/messaging/session-manager.js.map +1 -1
  92. package/dist/connectors/messaging/session-manager.test.d.ts +1 -0
  93. package/dist/connectors/messaging/session-manager.test.js +144 -0
  94. package/dist/connectors/messaging/session-manager.test.js.map +1 -0
  95. package/dist/connectors/slack/connector.d.ts +9 -0
  96. package/dist/connectors/slack/connector.js +15 -0
  97. package/dist/connectors/slack/connector.js.map +1 -1
  98. package/dist/connectors/slack/mrkdwn.js +81 -0
  99. package/dist/connectors/slack/mrkdwn.js.map +1 -1
  100. package/dist/connectors/slack/mrkdwn.test.js +49 -0
  101. package/dist/connectors/slack/mrkdwn.test.js.map +1 -1
  102. package/dist/connectors/types.d.ts +1 -1
  103. package/dist/cron/fanout.d.ts +33 -0
  104. package/dist/cron/fanout.js +55 -0
  105. package/dist/cron/fanout.js.map +1 -0
  106. package/dist/cron/fanout.test.d.ts +1 -0
  107. package/dist/cron/fanout.test.js +73 -0
  108. package/dist/cron/fanout.test.js.map +1 -0
  109. package/dist/cron/jobs.d.ts +5 -0
  110. package/dist/cron/jobs.js +10 -3
  111. package/dist/cron/jobs.js.map +1 -1
  112. package/dist/cron/scheduler.d.ts +12 -0
  113. package/dist/cron/scheduler.js +27 -1
  114. package/dist/cron/scheduler.js.map +1 -1
  115. package/dist/engine/agent-executor.d.ts +158 -0
  116. package/dist/engine/agent-executor.js +1140 -0
  117. package/dist/engine/agent-executor.js.map +1 -0
  118. package/dist/engine/agent-executor.test.d.ts +1 -0
  119. package/dist/engine/agent-executor.test.js +395 -0
  120. package/dist/engine/agent-executor.test.js.map +1 -0
  121. package/dist/engine/chat-runner.d.ts +123 -0
  122. package/dist/engine/chat-runner.js +379 -0
  123. package/dist/engine/chat-runner.js.map +1 -0
  124. package/dist/engine/chat-runner.test.d.ts +1 -0
  125. package/dist/engine/chat-runner.test.js +104 -0
  126. package/dist/engine/chat-runner.test.js.map +1 -0
  127. package/dist/engine/chat-skills.d.ts +45 -0
  128. package/dist/engine/chat-skills.js +184 -0
  129. package/dist/engine/chat-skills.js.map +1 -0
  130. package/dist/engine/chat-skills.test.d.ts +1 -0
  131. package/dist/engine/chat-skills.test.js +20 -0
  132. package/dist/engine/chat-skills.test.js.map +1 -0
  133. package/dist/engine/chat.d.ts +20 -23
  134. package/dist/engine/chat.js +251 -155
  135. package/dist/engine/chat.js.map +1 -1
  136. package/dist/engine/chat.test.d.ts +1 -0
  137. package/dist/engine/chat.test.js +42 -0
  138. package/dist/engine/chat.test.js.map +1 -0
  139. package/dist/engine/classifier.d.ts +35 -2
  140. package/dist/engine/classifier.js +170 -31
  141. package/dist/engine/classifier.js.map +1 -1
  142. package/dist/engine/classifier.test.d.ts +1 -0
  143. package/dist/engine/classifier.test.js +115 -0
  144. package/dist/engine/classifier.test.js.map +1 -0
  145. package/dist/engine/dispatcher.d.ts +60 -0
  146. package/dist/engine/dispatcher.js +601 -0
  147. package/dist/engine/dispatcher.js.map +1 -0
  148. package/dist/engine/dispatcher.test.d.ts +1 -0
  149. package/dist/engine/dispatcher.test.js +511 -0
  150. package/dist/engine/dispatcher.test.js.map +1 -0
  151. package/dist/engine/event-shim.d.ts +117 -0
  152. package/dist/engine/event-shim.js +435 -0
  153. package/dist/engine/event-shim.js.map +1 -0
  154. package/dist/engine/event-shim.test.d.ts +1 -0
  155. package/dist/engine/event-shim.test.js +194 -0
  156. package/dist/engine/event-shim.test.js.map +1 -0
  157. package/dist/engine/git-auth.d.ts +13 -17
  158. package/dist/engine/git-auth.js +99 -42
  159. package/dist/engine/git-auth.js.map +1 -1
  160. package/dist/engine/git-auth.test.d.ts +1 -0
  161. package/dist/engine/git-auth.test.js +117 -0
  162. package/dist/engine/git-auth.test.js.map +1 -0
  163. package/dist/engine/github-app-client.d.ts +7 -0
  164. package/dist/engine/github-app-client.js +16 -0
  165. package/dist/engine/github-app-client.js.map +1 -0
  166. package/dist/engine/github-app-client.test.d.ts +1 -0
  167. package/dist/engine/github-app-client.test.js +44 -0
  168. package/dist/engine/github-app-client.test.js.map +1 -0
  169. package/dist/engine/github-tools.d.ts +12 -0
  170. package/dist/engine/github-tools.js +261 -0
  171. package/dist/engine/github-tools.js.map +1 -0
  172. package/dist/engine/github.d.ts +1027 -43
  173. package/dist/engine/github.js +153 -14
  174. package/dist/engine/github.js.map +1 -1
  175. package/dist/engine/llm.d.ts +47 -0
  176. package/dist/engine/llm.js +221 -0
  177. package/dist/engine/llm.js.map +1 -0
  178. package/dist/engine/llm.test.d.ts +1 -0
  179. package/dist/engine/llm.test.js +189 -0
  180. package/dist/engine/llm.test.js.map +1 -0
  181. package/dist/engine/profiles.d.ts +249 -0
  182. package/dist/engine/profiles.js +42 -0
  183. package/dist/engine/profiles.js.map +1 -0
  184. package/dist/engine/router.d.ts +12 -6
  185. package/dist/engine/router.js +339 -81
  186. package/dist/engine/router.js.map +1 -1
  187. package/dist/engine/router.test.js +428 -78
  188. package/dist/engine/router.test.js.map +1 -1
  189. package/dist/engine/screen.d.ts +41 -0
  190. package/dist/engine/screen.js +93 -0
  191. package/dist/engine/screen.js.map +1 -0
  192. package/dist/engine/screen.test.d.ts +1 -0
  193. package/dist/engine/screen.test.js +82 -0
  194. package/dist/engine/screen.test.js.map +1 -0
  195. package/dist/index.js +377 -432
  196. package/dist/index.js.map +1 -1
  197. package/dist/managed-repos.d.ts +7 -9
  198. package/dist/managed-repos.js +12 -15
  199. package/dist/managed-repos.js.map +1 -1
  200. package/dist/managed-repos.test.js +24 -19
  201. package/dist/managed-repos.test.js.map +1 -1
  202. package/dist/notify/index.d.ts +15 -0
  203. package/dist/notify/index.js +6 -0
  204. package/dist/notify/index.js.map +1 -0
  205. package/dist/notify/model.d.ts +57 -0
  206. package/dist/notify/model.js +89 -0
  207. package/dist/notify/model.js.map +1 -0
  208. package/dist/notify/model.test.d.ts +1 -0
  209. package/dist/notify/model.test.js +109 -0
  210. package/dist/notify/model.test.js.map +1 -0
  211. package/dist/notify/notifier.d.ts +17 -0
  212. package/dist/notify/notifier.js +87 -0
  213. package/dist/notify/notifier.js.map +1 -0
  214. package/dist/notify/notifier.test.d.ts +1 -0
  215. package/dist/notify/notifier.test.js +100 -0
  216. package/dist/notify/notifier.test.js.map +1 -0
  217. package/dist/notify/render.d.ts +21 -0
  218. package/dist/notify/render.js +59 -0
  219. package/dist/notify/render.js.map +1 -0
  220. package/dist/notify/render.test.d.ts +1 -0
  221. package/dist/notify/render.test.js +65 -0
  222. package/dist/notify/render.test.js.map +1 -0
  223. package/dist/notify/transports/github.d.ts +26 -0
  224. package/dist/notify/transports/github.js +26 -0
  225. package/dist/notify/transports/github.js.map +1 -0
  226. package/dist/notify/transports/slack.d.ts +26 -0
  227. package/dist/notify/transports/slack.js +28 -0
  228. package/dist/notify/transports/slack.js.map +1 -0
  229. package/dist/notify/transports.test.d.ts +1 -0
  230. package/dist/notify/transports.test.js +71 -0
  231. package/dist/notify/transports.test.js.map +1 -0
  232. package/dist/notify/types.d.ts +95 -0
  233. package/dist/notify/types.js +16 -0
  234. package/dist/notify/types.js.map +1 -0
  235. package/dist/sandbox/docker-compose.test.d.ts +1 -0
  236. package/dist/sandbox/docker-compose.test.js +128 -0
  237. package/dist/sandbox/docker-compose.test.js.map +1 -0
  238. package/dist/sandbox/docker.d.ts +97 -9
  239. package/dist/sandbox/docker.js +192 -41
  240. package/dist/sandbox/docker.js.map +1 -1
  241. package/dist/sandbox/docker.test.d.ts +1 -0
  242. package/dist/sandbox/docker.test.js +137 -0
  243. package/dist/sandbox/docker.test.js.map +1 -0
  244. package/dist/sandbox/egress-allowlist.d.ts +69 -0
  245. package/dist/sandbox/egress-allowlist.js +164 -0
  246. package/dist/sandbox/egress-allowlist.js.map +1 -0
  247. package/dist/sandbox/egress-allowlist.test.d.ts +1 -0
  248. package/dist/sandbox/egress-allowlist.test.js +65 -0
  249. package/dist/sandbox/egress-allowlist.test.js.map +1 -0
  250. package/dist/sandbox/egress-firewall-config.d.ts +127 -0
  251. package/dist/sandbox/egress-firewall-config.js +434 -0
  252. package/dist/sandbox/egress-firewall-config.js.map +1 -0
  253. package/dist/sandbox/egress-firewall-config.test.d.ts +1 -0
  254. package/dist/sandbox/egress-firewall-config.test.js +244 -0
  255. package/dist/sandbox/egress-firewall-config.test.js.map +1 -0
  256. package/dist/sandbox/images.d.ts +23 -0
  257. package/dist/sandbox/images.js +55 -0
  258. package/dist/sandbox/images.js.map +1 -0
  259. package/dist/sandbox/index.d.ts +82 -3
  260. package/dist/sandbox/index.js +223 -93
  261. package/dist/sandbox/index.js.map +1 -1
  262. package/dist/sandbox/index.test.d.ts +1 -0
  263. package/dist/sandbox/index.test.js +157 -0
  264. package/dist/sandbox/index.test.js.map +1 -0
  265. package/dist/session-log.d.ts +63 -0
  266. package/dist/session-log.js +290 -0
  267. package/dist/session-log.js.map +1 -0
  268. package/dist/session-log.test.d.ts +1 -0
  269. package/dist/session-log.test.js +85 -0
  270. package/dist/session-log.test.js.map +1 -0
  271. package/dist/setup.d.ts +30 -1
  272. package/dist/setup.js +241 -25
  273. package/dist/setup.js.map +1 -1
  274. package/dist/setup.test.js +138 -6
  275. package/dist/setup.test.js.map +1 -1
  276. package/dist/state/approval-store.d.ts +86 -0
  277. package/dist/state/approval-store.js +140 -0
  278. package/dist/state/approval-store.js.map +1 -0
  279. package/dist/state/build-assets.d.ts +50 -0
  280. package/dist/state/build-assets.js +154 -0
  281. package/dist/state/build-assets.js.map +1 -0
  282. package/dist/state/build-assets.test.d.ts +1 -0
  283. package/dist/state/build-assets.test.js +106 -0
  284. package/dist/state/build-assets.test.js.map +1 -0
  285. package/dist/state/db.d.ts +65 -333
  286. package/dist/state/db.js +112 -835
  287. package/dist/state/db.js.map +1 -1
  288. package/dist/state/db.test.js +127 -91
  289. package/dist/state/db.test.js.map +1 -1
  290. package/dist/state/execution-store.d.ts +257 -0
  291. package/dist/state/execution-store.js +527 -0
  292. package/dist/state/execution-store.js.map +1 -0
  293. package/dist/state/migrate.d.ts +15 -0
  294. package/dist/state/migrate.js +175 -0
  295. package/dist/state/migrate.js.map +1 -0
  296. package/dist/state/workflow-run-store.d.ts +195 -0
  297. package/dist/state/workflow-run-store.js +363 -0
  298. package/dist/state/workflow-run-store.js.map +1 -0
  299. package/dist/state/workflow-run-store.test.d.ts +1 -0
  300. package/dist/state/workflow-run-store.test.js +264 -0
  301. package/dist/state/workflow-run-store.test.js.map +1 -0
  302. package/dist/telemetry/index.d.ts +38 -0
  303. package/dist/telemetry/index.js +253 -0
  304. package/dist/telemetry/index.js.map +1 -0
  305. package/dist/telemetry/index.test.d.ts +1 -0
  306. package/dist/telemetry/index.test.js +73 -0
  307. package/dist/telemetry/index.test.js.map +1 -0
  308. package/dist/telemetry/pi-events.d.ts +12 -0
  309. package/dist/telemetry/pi-events.js +134 -0
  310. package/dist/telemetry/pi-events.js.map +1 -0
  311. package/dist/telemetry/pi-events.test.d.ts +1 -0
  312. package/dist/telemetry/pi-events.test.js +69 -0
  313. package/dist/telemetry/pi-events.test.js.map +1 -0
  314. package/dist/workflows/dag.d.ts +13 -1
  315. package/dist/workflows/dag.js +7 -3
  316. package/dist/workflows/dag.js.map +1 -1
  317. package/dist/workflows/dag.test.js +22 -0
  318. package/dist/workflows/dag.test.js.map +1 -1
  319. package/dist/workflows/golden-build.test.d.ts +1 -0
  320. package/dist/workflows/golden-build.test.js +45 -0
  321. package/dist/workflows/golden-build.test.js.map +1 -0
  322. package/dist/workflows/loader-overlay.test.d.ts +1 -0
  323. package/dist/workflows/loader-overlay.test.js +101 -0
  324. package/dist/workflows/loader-overlay.test.js.map +1 -0
  325. package/dist/workflows/loader.d.ts +36 -11
  326. package/dist/workflows/loader.js +311 -87
  327. package/dist/workflows/loader.js.map +1 -1
  328. package/dist/workflows/loader.test.js +114 -10
  329. package/dist/workflows/loader.test.js.map +1 -1
  330. package/dist/workflows/loop-eval.js +2 -0
  331. package/dist/workflows/loop-eval.js.map +1 -1
  332. package/dist/workflows/loop-eval.test.js +14 -0
  333. package/dist/workflows/loop-eval.test.js.map +1 -1
  334. package/dist/workflows/phase-executor.d.ts +145 -0
  335. package/dist/workflows/phase-executor.js +691 -0
  336. package/dist/workflows/phase-executor.js.map +1 -0
  337. package/dist/workflows/phase-executor.test.d.ts +1 -0
  338. package/dist/workflows/phase-executor.test.js +434 -0
  339. package/dist/workflows/phase-executor.test.js.map +1 -0
  340. package/dist/workflows/phase-ref.d.ts +44 -0
  341. package/dist/workflows/phase-ref.js +78 -0
  342. package/dist/workflows/phase-ref.js.map +1 -0
  343. package/dist/workflows/phase-ref.test.d.ts +1 -0
  344. package/dist/workflows/phase-ref.test.js +24 -0
  345. package/dist/workflows/phase-ref.test.js.map +1 -0
  346. package/dist/workflows/resume.d.ts +5 -11
  347. package/dist/workflows/resume.js +88 -7
  348. package/dist/workflows/resume.js.map +1 -1
  349. package/dist/workflows/runner.d.ts +34 -27
  350. package/dist/workflows/runner.js +252 -930
  351. package/dist/workflows/runner.js.map +1 -1
  352. package/dist/workflows/runner.test.js +346 -35
  353. package/dist/workflows/runner.test.js.map +1 -1
  354. package/dist/workflows/schema.d.ts +52 -10
  355. package/dist/workflows/schema.js +147 -7
  356. package/dist/workflows/schema.js.map +1 -1
  357. package/dist/workflows/simple.d.ts +67 -3
  358. package/dist/workflows/simple.js +248 -87
  359. package/dist/workflows/simple.js.map +1 -1
  360. package/dist/workflows/simple.test.d.ts +1 -0
  361. package/dist/workflows/simple.test.js +107 -0
  362. package/dist/workflows/simple.test.js.map +1 -0
  363. package/dist/workflows/templates.d.ts +29 -0
  364. package/dist/workflows/templates.js +42 -4
  365. package/dist/workflows/templates.js.map +1 -1
  366. package/dist/workflows/templates.test.js +103 -0
  367. package/dist/workflows/templates.test.js.map +1 -1
  368. package/dist/workflows/triggers.d.ts +21 -0
  369. package/dist/workflows/triggers.js +44 -0
  370. package/dist/workflows/triggers.js.map +1 -0
  371. package/dist/workflows/verdict.d.ts +19 -0
  372. package/dist/workflows/verdict.js +30 -0
  373. package/dist/workflows/verdict.js.map +1 -0
  374. package/dist/workflows/verdict.test.d.ts +1 -0
  375. package/dist/workflows/verdict.test.js +44 -0
  376. package/dist/workflows/verdict.test.js.map +1 -0
  377. package/dist/worktree/manager.d.ts +1 -1
  378. package/dist/worktree/manager.js +14 -14
  379. package/dist/worktree/manager.js.map +1 -1
  380. package/dist/worktree/manager.test.d.ts +1 -0
  381. package/dist/worktree/manager.test.js +87 -0
  382. package/dist/worktree/manager.test.js.map +1 -0
  383. package/docker-compose.yml +206 -5
  384. package/package.json +19 -9
  385. package/sandbox.Dockerfile +97 -18
  386. package/skills/README.md +40 -0
  387. package/skills/browser-qa/SKILL.md +193 -0
  388. package/skills/browser-qa/scripts/agent-browser.mjs +380 -0
  389. package/skills/building/SKILL.md +95 -0
  390. package/skills/chat/SKILL.md +30 -11
  391. package/skills/code-review/SKILL.md +59 -0
  392. package/skills/debug-production/SKILL.md +108 -0
  393. package/skills/demo/SKILL.md +194 -0
  394. package/skills/demo/scripts/compose-demo.sh +205 -0
  395. package/skills/issue-answer/SKILL.md +90 -0
  396. package/skills/issue-comment/SKILL.md +38 -24
  397. package/skills/issue-triage/SKILL.md +103 -37
  398. package/skills/issue-triage/references/AGENT-BRIEF.md +61 -0
  399. package/skills/pr-comment/SKILL.md +64 -0
  400. package/skills/pr-review/SKILL.md +65 -49
  401. package/skills/qa-test/SKILL.md +97 -0
  402. package/skills/repo-health/SKILL.md +48 -45
  403. package/skills/security-feedback/SKILL.md +173 -0
  404. package/skills/security-feedback/references/templates.md +77 -0
  405. package/skills/security-review/SKILL.md +213 -0
  406. package/skills/security-review/references/issue-format.md +302 -0
  407. package/skills/verify/SKILL.md +118 -0
  408. package/workflows/answer.yaml +37 -0
  409. package/workflows/build.yaml +32 -22
  410. package/workflows/cron-security.yaml +6 -0
  411. package/workflows/demo.yaml +55 -0
  412. package/workflows/explore.yaml +9 -0
  413. package/workflows/pr-comment.yaml +16 -0
  414. package/workflows/pr-fix.yaml +3 -0
  415. package/workflows/pr-review.yaml +4 -1
  416. package/workflows/prompts/answer.md +67 -0
  417. package/workflows/prompts/architect.md +24 -7
  418. package/workflows/prompts/demo.md +100 -0
  419. package/workflows/prompts/executor.md +29 -20
  420. package/workflows/prompts/explore-ask.md +51 -22
  421. package/workflows/prompts/explore-publish.md +2 -2
  422. package/workflows/prompts/explore-read.md +24 -10
  423. package/workflows/prompts/explore-synthesize.md +15 -8
  424. package/workflows/prompts/fix.md +9 -10
  425. package/workflows/prompts/guardrails.md +26 -8
  426. package/workflows/prompts/pr-fix.md +6 -7
  427. package/workflows/prompts/pr.md +11 -10
  428. package/workflows/prompts/qa-browser.md +95 -0
  429. package/workflows/prompts/qa-synth.md +44 -0
  430. package/workflows/prompts/qa-test.md +60 -0
  431. package/workflows/prompts/re-reviewer.md +8 -9
  432. package/workflows/prompts/reviewer.md +10 -9
  433. package/workflows/prompts/verify-browser.md +93 -0
  434. package/workflows/prompts/verify-synth.md +44 -0
  435. package/workflows/prompts/verify.md +63 -0
  436. package/workflows/qa-test.yaml +87 -0
  437. package/workflows/security-feedback.yaml +25 -0
  438. package/workflows/security-review.yaml +29 -0
  439. package/workflows/verify.yaml +85 -0
  440. package/deploy/mcp-config.tmpl.json +0 -14
  441. package/dist/cron/rate-limits.d.ts +0 -26
  442. package/dist/cron/rate-limits.js +0 -193
  443. package/dist/cron/rate-limits.js.map +0 -1
  444. package/dist/engine/executor.d.ts +0 -75
  445. package/dist/engine/executor.js +0 -292
  446. package/dist/engine/executor.js.map +0 -1
  447. package/mcp-github-app/package.json +0 -18
  448. package/mcp-github-app/src/auth.js +0 -66
  449. package/mcp-github-app/src/github.js +0 -371
  450. package/mcp-github-app/src/index.js +0 -534
  451. package/skills/devops/webhook-subscriptions/SKILL.md +0 -180
  452. package/skills/github/DESCRIPTION.md +0 -3
  453. package/skills/github/codebase-inspection/SKILL.md +0 -115
  454. package/skills/github/github-auth/SKILL.md +0 -54
  455. package/skills/github/github-auth/scripts/gh-env.sh +0 -66
  456. package/skills/github/github-code-review/SKILL.md +0 -480
  457. package/skills/github/github-code-review/references/review-output-template.md +0 -74
  458. package/skills/github/github-issues/SKILL.md +0 -369
  459. package/skills/github/github-issues/templates/bug-report.md +0 -35
  460. package/skills/github/github-issues/templates/feature-request.md +0 -31
  461. package/skills/github/github-pr-workflow/SKILL.md +0 -395
  462. package/skills/github/github-pr-workflow/references/ci-troubleshooting.md +0 -183
  463. package/skills/github/github-pr-workflow/references/conventional-commits.md +0 -71
  464. package/skills/github/github-pr-workflow/templates/pr-body-bugfix.md +0 -35
  465. package/skills/github/github-pr-workflow/templates/pr-body-feature.md +0 -33
  466. package/skills/github/github-repo-management/SKILL.md +0 -515
  467. package/skills/github/github-repo-management/references/github-api-cheatsheet.md +0 -161
  468. package/skills/github-orchestrator/SKILL.md +0 -103
  469. package/skills/mcp/DESCRIPTION.md +0 -3
  470. package/skills/mcp/mcporter/SKILL.md +0 -122
  471. package/skills/mcp/native-mcp/SKILL.md +0 -356
  472. package/skills/software-development/architect/SKILL.md +0 -154
  473. package/skills/software-development/assure-guardrails/SKILL.md +0 -239
  474. package/skills/software-development/plan/SKILL.md +0 -64
  475. package/skills/software-development/requesting-code-review/SKILL.md +0 -291
  476. package/skills/software-development/subagent-driven-development/SKILL.md +0 -433
  477. package/skills/software-development/systematic-debugging/SKILL.md +0 -366
  478. package/skills/software-development/test-driven-development/SKILL.md +0 -342
@@ -0,0 +1,87 @@
1
+ /**
2
+ * `ProgressNotifier` — the concrete {@link ProgressReporter} the runner drives.
3
+ *
4
+ * It owns the current {@link ProgressModel}, re-renders once per mutation, and
5
+ * fans the rendered markdown out to every wired transport's `publish()`. It
6
+ * knows nothing about GitHub or Slack — that lives behind
7
+ * {@link NotifierTransport}. Multiple transports can be attached (e.g. a
8
+ * GitHub-triggered build that also mirrors to a Slack thread); each owns its
9
+ * own in-place-update handle.
10
+ *
11
+ * Mutations are serialized through an in-flight chain so two quick transitions
12
+ * can't race on `publish()` and post out of order (or double-create the
13
+ * surface before the first create's handle is stored).
14
+ */
15
+ import { renderProgress } from "./render.js";
16
+ import { setStep, upsertBefore } from "./model.js";
17
+ export class ProgressNotifier {
18
+ model = null;
19
+ transports;
20
+ chain = Promise.resolve();
21
+ constructor(transports) {
22
+ this.transports = transports.filter(Boolean);
23
+ }
24
+ /** Serialize a mutation + publish so transitions can't interleave. */
25
+ enqueue(fn) {
26
+ this.chain = this.chain.then(fn, fn);
27
+ return this.chain;
28
+ }
29
+ async publish() {
30
+ if (!this.model)
31
+ return;
32
+ const body = renderProgress(this.model);
33
+ // Best-effort per transport — one platform failing must not block the other.
34
+ await Promise.all(this.transports.map((t) => t.publish(body).catch((err) => {
35
+ const m = err instanceof Error ? err.message : String(err);
36
+ console.warn(`[notifier] publish failed: ${m}`);
37
+ })));
38
+ }
39
+ start(model) {
40
+ return this.enqueue(async () => {
41
+ this.model = model;
42
+ await this.publish();
43
+ });
44
+ }
45
+ step(key, status, detail) {
46
+ return this.enqueue(async () => {
47
+ if (!this.model)
48
+ return;
49
+ this.model = { ...this.model, steps: setStep(this.model.steps, key, status, detail) };
50
+ await this.publish();
51
+ });
52
+ }
53
+ insertStep(step, beforeKey) {
54
+ return this.enqueue(async () => {
55
+ if (!this.model)
56
+ return;
57
+ this.model = { ...this.model, steps: upsertBefore(this.model.steps, step, beforeKey) };
58
+ await this.publish();
59
+ });
60
+ }
61
+ footer(markdown) {
62
+ return this.enqueue(async () => {
63
+ if (!this.model)
64
+ return;
65
+ const footer = markdown.trim() || undefined;
66
+ this.model = { ...this.model, footer };
67
+ await this.publish();
68
+ });
69
+ }
70
+ note(markdown) {
71
+ return this.noteTo(this.transports, markdown);
72
+ }
73
+ noteTerminal(markdown) {
74
+ return this.noteTo(this.transports.filter((t) => t.terminalPing), markdown);
75
+ }
76
+ noteTo(transports, markdown) {
77
+ return this.enqueue(async () => {
78
+ if (!markdown.trim() || transports.length === 0)
79
+ return;
80
+ await Promise.all(transports.map((t) => t.note(markdown).catch((err) => {
81
+ const m = err instanceof Error ? err.message : String(err);
82
+ console.warn(`[notifier] note failed: ${m}`);
83
+ })));
84
+ });
85
+ }
86
+ }
87
+ //# sourceMappingURL=notifier.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"notifier.js","sourceRoot":"","sources":["../../src/notify/notifier.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,100 @@
1
+ import { describe, it, expect, vi } from "vitest";
2
+ import { ProgressNotifier } from "./notifier.js";
3
+ function fakeTransport(opts = {}) {
4
+ const published = [];
5
+ const notes = [];
6
+ const t = {
7
+ publish: vi.fn(async (md) => { published.push(md); }),
8
+ note: vi.fn(async (md) => { notes.push(md); }),
9
+ terminalPing: opts.terminalPing,
10
+ };
11
+ return { t, published, notes };
12
+ }
13
+ const model = {
14
+ title: "build for #1",
15
+ steps: [
16
+ { key: "a", label: "A", status: "pending" },
17
+ { key: "b", label: "B", status: "pending" },
18
+ ],
19
+ };
20
+ describe("ProgressNotifier", () => {
21
+ it("publishes the initial model on start and re-publishes on each mutation", async () => {
22
+ const { t, published } = fakeTransport();
23
+ const n = new ProgressNotifier([t]);
24
+ await n.start(model);
25
+ await n.step("a", "running", "working");
26
+ await n.step("a", "done");
27
+ expect(published).toHaveLength(3);
28
+ expect(published[0]).toContain("**A**");
29
+ expect(published[1]).toContain("**A** — working");
30
+ expect(published[2]).toMatch(/✅ \*\*A\*\*/);
31
+ });
32
+ it("insertStep adds a dynamic row before the named key", async () => {
33
+ const { t, published } = fakeTransport();
34
+ const n = new ProgressNotifier([t]);
35
+ await n.start(model);
36
+ await n.insertStep({ key: "x", label: "Fix (cycle 1)", status: "running" }, "b");
37
+ const last = published[published.length - 1];
38
+ expect(last.indexOf("Fix (cycle 1)")).toBeGreaterThan(last.indexOf("**A**"));
39
+ expect(last.indexOf("Fix (cycle 1)")).toBeLessThan(last.indexOf("**B**"));
40
+ });
41
+ it("note posts a standalone message to every transport and skips empties", async () => {
42
+ const { t, notes } = fakeTransport();
43
+ const n = new ProgressNotifier([t]);
44
+ await n.start(model);
45
+ await n.note("done!");
46
+ await n.note(" ");
47
+ expect(notes).toEqual(["done!"]);
48
+ });
49
+ it("fans out to multiple transports and survives one failing", async () => {
50
+ const ok = fakeTransport();
51
+ const bad = {
52
+ publish: vi.fn(async () => { throw new Error("boom"); }),
53
+ note: vi.fn(async () => { }),
54
+ };
55
+ const n = new ProgressNotifier([bad, ok.t]);
56
+ await expect(n.start(model)).resolves.toBeUndefined();
57
+ expect(ok.published).toHaveLength(1); // healthy transport still got it
58
+ });
59
+ it("noteTerminal only hits transports that want a terminal ping", async () => {
60
+ const gh = fakeTransport({ terminalPing: false }); // GitHub: no terminal ping
61
+ const slack = fakeTransport({ terminalPing: true }); // Slack: wants it
62
+ const n = new ProgressNotifier([gh.t, slack.t]);
63
+ await n.start(model);
64
+ await n.noteTerminal("✅ build complete — PR #1.");
65
+ expect(slack.notes).toEqual(["✅ build complete — PR #1."]);
66
+ expect(gh.notes).toEqual([]);
67
+ });
68
+ it("footer sets the trailing section and re-publishes in place", async () => {
69
+ const { t, published } = fakeTransport();
70
+ const n = new ProgressNotifier([t]);
71
+ await n.start(model);
72
+ await n.footer("## CONFIRMED\nthe verdict");
73
+ const last = published[published.length - 1];
74
+ expect(last).toContain("## CONFIRMED");
75
+ expect(last).toContain("the verdict");
76
+ // Still the same surface (in-place update), not a standalone note.
77
+ expect(last).toContain("**A**");
78
+ });
79
+ it("footer with blank content clears the footer and re-publishes", async () => {
80
+ const { t, published } = fakeTransport();
81
+ const n = new ProgressNotifier([t]);
82
+ await n.start(model);
83
+ await n.footer("temp");
84
+ await n.footer(" ");
85
+ expect(published[published.length - 1]).not.toContain("temp");
86
+ });
87
+ it("no-ops cleanly with zero transports", async () => {
88
+ const n = new ProgressNotifier([]);
89
+ await expect(n.start(model)).resolves.toBeUndefined();
90
+ await expect(n.step("a", "done")).resolves.toBeUndefined();
91
+ await expect(n.note("x")).resolves.toBeUndefined();
92
+ });
93
+ it("ignores step/insert before start (no model yet)", async () => {
94
+ const { t, published } = fakeTransport();
95
+ const n = new ProgressNotifier([t]);
96
+ await n.step("a", "done");
97
+ expect(published).toHaveLength(0);
98
+ });
99
+ });
100
+ //# sourceMappingURL=notifier.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"notifier.test.js","sourceRoot":"","sources":["../../src/notify/notifier.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * The single shared renderer. Turns a {@link ProgressModel} into markdown.
3
+ * GitHub posts the output as-is; the Slack transport converts it via
4
+ * `markdownToSlackMrkdwn` first. There is exactly one renderer so the two
5
+ * platforms can never drift in content.
6
+ */
7
+ import type { ProgressModel, StepStatus } from "./types.js";
8
+ /** Status → leading emoji. Ported from the Mastra rebuild's EMOJI map. */
9
+ export declare const STATUS_EMOJI: Record<StepStatus, string>;
10
+ /** Render the model to a single markdown body. */
11
+ export declare function renderProgress(model: ProgressModel): string;
12
+ /**
13
+ * Collapse a rendered multi-line message into a compact one-line checklist
14
+ * detail: the first non-empty line, capped on *visible* length. The cap
15
+ * measures the rendered length (a markdown link counts as just its link
16
+ * text, not its URL) so a short label backed by a long URL is kept whole —
17
+ * truncating the raw string would slice through the URL and break the link.
18
+ * When a detail is genuinely too long, the link-stripped form is truncated,
19
+ * which can never produce a broken link.
20
+ */
21
+ export declare function collapseDetail(s: string): string | undefined;
@@ -0,0 +1,59 @@
1
+ /** Status → leading emoji. Ported from the Mastra rebuild's EMOJI map. */
2
+ export const STATUS_EMOJI = {
3
+ pending: "⬜",
4
+ running: "🔄",
5
+ done: "✅",
6
+ blocked: "⛔",
7
+ awaiting: "⏸️",
8
+ failed: "❌",
9
+ skipped: "➖",
10
+ };
11
+ /** Render the model to a single markdown body. */
12
+ export function renderProgress(model) {
13
+ const lines = [];
14
+ lines.push(`### 🤖 ${model.title}`);
15
+ if (model.subtitle) {
16
+ lines.push("");
17
+ lines.push(`**${model.subtitle}**`);
18
+ }
19
+ if (model.meta && model.meta.length > 0) {
20
+ lines.push("");
21
+ for (const m of model.meta)
22
+ if (m.trim())
23
+ lines.push(m);
24
+ }
25
+ lines.push("");
26
+ for (const step of model.steps) {
27
+ const emoji = STATUS_EMOJI[step.status] ?? STATUS_EMOJI.pending;
28
+ const detail = step.detail ? ` — ${step.detail}` : "";
29
+ lines.push(`- ${emoji} **${step.label}**${detail}`);
30
+ }
31
+ if (model.footer && model.footer.trim()) {
32
+ lines.push("");
33
+ lines.push(model.footer);
34
+ }
35
+ return lines.join("\n");
36
+ }
37
+ /** Markdown link `[text](url)` → its visible text, for length measurement. */
38
+ const visibleText = (s) => s.replace(/\[([^\]]+)\]\([^)]+\)/g, "$1");
39
+ /**
40
+ * Collapse a rendered multi-line message into a compact one-line checklist
41
+ * detail: the first non-empty line, capped on *visible* length. The cap
42
+ * measures the rendered length (a markdown link counts as just its link
43
+ * text, not its URL) so a short label backed by a long URL is kept whole —
44
+ * truncating the raw string would slice through the URL and break the link.
45
+ * When a detail is genuinely too long, the link-stripped form is truncated,
46
+ * which can never produce a broken link.
47
+ */
48
+ export function collapseDetail(s) {
49
+ const first = s
50
+ .split("\n")
51
+ .map((l) => l.trim())
52
+ .find((l) => l.length > 0);
53
+ if (!first)
54
+ return undefined;
55
+ if (visibleText(first).length <= 160)
56
+ return first;
57
+ return `${visibleText(first).slice(0, 159)}…`;
58
+ }
59
+ //# sourceMappingURL=render.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render.js","sourceRoot":"","sources":["../../src/notify/render.ts"],"names":[],"mappings":"AAQA,0EAA0E;AAC1E,MAAM,CAAC,MAAM,YAAY,GAA+B;IACtD,OAAO,EAAE,GAAG;IACZ,OAAO,EAAE,IAAI;IACb,IAAI,EAAE,GAAG;IACT,OAAO,EAAE,GAAG;IACZ,QAAQ,EAAE,IAAI;IACd,MAAM,EAAE,GAAG;IACX,OAAO,EAAE,GAAG;CACb,CAAC;AAEF,kDAAkD;AAClD,MAAM,UAAU,cAAc,CAAC,KAAoB;IACjD,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,KAAK,CAAC,IAAI,CAAC,UAAU,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC;IACpC,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;QACnB,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACf,KAAK,CAAC,IAAI,CAAC,KAAK,KAAK,CAAC,QAAQ,IAAI,CAAC,CAAC;IACtC,CAAC;IACD,IAAI,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACf,KAAK,MAAM,CAAC,IAAI,KAAK,CAAC,IAAI;YAAE,IAAI,CAAC,CAAC,IAAI,EAAE;gBAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC1D,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACf,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;QAC/B,MAAM,KAAK,GAAG,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,YAAY,CAAC,OAAO,CAAC;QAChE,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACtD,KAAK,CAAC,IAAI,CAAC,KAAK,KAAK,MAAM,IAAI,CAAC,KAAK,KAAK,MAAM,EAAE,CAAC,CAAC;IACtD,CAAC;IAED,IAAI,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC;QACxC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACf,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAC3B,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED,8EAA8E;AAC9E,MAAM,WAAW,GAAG,CAAC,CAAS,EAAU,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,wBAAwB,EAAE,IAAI,CAAC,CAAC;AAErF;;;;;;;;GAQG;AACH,MAAM,UAAU,cAAc,CAAC,CAAS;IACtC,MAAM,KAAK,GAAG,CAAC;SACZ,KAAK,CAAC,IAAI,CAAC;SACX,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;SACpB,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAC7B,IAAI,CAAC,KAAK;QAAE,OAAO,SAAS,CAAC;IAC7B,IAAI,WAAW,CAAC,KAAK,CAAC,CAAC,MAAM,IAAI,GAAG;QAAE,OAAO,KAAK,CAAC;IACnD,OAAO,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,GAAG,CAAC;AAChD,CAAC"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,65 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { renderProgress, collapseDetail, STATUS_EMOJI } from "./render.js";
3
+ describe("renderProgress", () => {
4
+ const model = {
5
+ title: "build for #18",
6
+ subtitle: "Add retry to fetch",
7
+ meta: ["Branch: [`lastlight/18`](https://example/tree/lastlight/18)"],
8
+ steps: [
9
+ { key: "guardrails", label: "Guardrails", status: "done", detail: "READY" },
10
+ { key: "architect", label: "Architect", status: "running" },
11
+ { key: "pr", label: "PR", status: "pending" },
12
+ ],
13
+ footer: "Artifacts: .lastlight/",
14
+ };
15
+ it("renders heading, subtitle, meta, checklist and footer in order", () => {
16
+ const out = renderProgress(model);
17
+ const lines = out.split("\n");
18
+ expect(lines[0]).toBe("### 🤖 build for #18");
19
+ expect(out).toContain("**Add retry to fetch**");
20
+ expect(out).toContain("Branch: [`lastlight/18`]");
21
+ expect(out).toContain(`- ${STATUS_EMOJI.done} **Guardrails** — READY`);
22
+ expect(out).toContain(`- ${STATUS_EMOJI.running} **Architect**`);
23
+ expect(out).toContain(`- ${STATUS_EMOJI.pending} **PR**`);
24
+ expect(out.trimEnd().endsWith("Artifacts: .lastlight/")).toBe(true);
25
+ });
26
+ it("omits detail dash when a step has no detail", () => {
27
+ const out = renderProgress(model);
28
+ expect(out).toContain(`**Architect**\n`);
29
+ expect(out).not.toContain("**Architect** —");
30
+ });
31
+ it("renders a minimal model (no subtitle/meta/footer)", () => {
32
+ const out = renderProgress({ title: "t", steps: [{ key: "a", label: "A", status: "pending" }] });
33
+ expect(out).toContain("### 🤖 t");
34
+ expect(out).toContain(`- ${STATUS_EMOJI.pending} **A**`);
35
+ });
36
+ });
37
+ describe("collapseDetail", () => {
38
+ it("keeps a short-label markdown link intact even when the URL is long (regression)", () => {
39
+ // The exact shape from build.yaml: short link text, very long branch-encoded URL.
40
+ const url = "https://github.com/cliftonc/lastlight/blob/" +
41
+ encodeURIComponent("lastlight/91-feature-allow-configuration-of-otel-endp") +
42
+ "/.lastlight/issue-91/architect-plan.md";
43
+ const detail = `Plan ready — [architect-plan.md](${url})`;
44
+ expect(detail.length).toBeGreaterThan(160); // raw string would trip a naive cap
45
+ const out = collapseDetail(detail);
46
+ expect(out).toBe(detail); // returned whole — not truncated
47
+ expect(out.endsWith(")")).toBe(true); // link closes cleanly
48
+ expect(out).not.toContain("…");
49
+ });
50
+ it("truncates genuinely long prose (no link) with an ellipsis", () => {
51
+ const prose = "x".repeat(200);
52
+ const out = collapseDetail(prose);
53
+ expect(out).toBe(`${"x".repeat(159)}…`);
54
+ expect(out.length).toBe(160);
55
+ });
56
+ it("collapses to the first non-empty trimmed line", () => {
57
+ const out = collapseDetail("\n \n hello world \nsecond line\n");
58
+ expect(out).toBe("hello world");
59
+ });
60
+ it("returns undefined for empty or whitespace-only input", () => {
61
+ expect(collapseDetail("")).toBeUndefined();
62
+ expect(collapseDetail(" \n \n")).toBeUndefined();
63
+ });
64
+ });
65
+ //# sourceMappingURL=render.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render.test.js","sourceRoot":"","sources":["../../src/notify/render.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * GitHub binding for the progress notifier. Owns a single comment id and edits
3
+ * it in place on every `publish()`; `note()` posts a fresh comment for moments
4
+ * that deserve a real notification (approval prompts, terminal summary).
5
+ */
6
+ import type { GitHubClient } from "../../engine/github.js";
7
+ import type { NotifierTransport } from "../types.js";
8
+ export interface GitHubTransportDeps {
9
+ github: GitHubClient;
10
+ owner: string;
11
+ repo: string;
12
+ issueNumber: number;
13
+ /** Existing status-comment id from a resumed run, if any. */
14
+ commentId?: number;
15
+ /** Persist the comment id the first time it's created (so resume re-attaches). */
16
+ save?: (commentId: number) => void;
17
+ }
18
+ export declare class GitHubTransport implements NotifierTransport {
19
+ private readonly deps;
20
+ /** No terminal ping — the finished checklist + the PR-opened event suffice. */
21
+ readonly terminalPing = false;
22
+ private commentId?;
23
+ constructor(deps: GitHubTransportDeps);
24
+ publish(markdown: string): Promise<void>;
25
+ note(markdown: string): Promise<void>;
26
+ }
@@ -0,0 +1,26 @@
1
+ export class GitHubTransport {
2
+ deps;
3
+ /** No terminal ping — the finished checklist + the PR-opened event suffice. */
4
+ terminalPing = false;
5
+ commentId;
6
+ constructor(deps) {
7
+ this.deps = deps;
8
+ this.commentId = deps.commentId;
9
+ }
10
+ async publish(markdown) {
11
+ const { github, owner, repo, issueNumber } = this.deps;
12
+ if (this.commentId !== undefined) {
13
+ await github.updateComment(owner, repo, this.commentId, markdown);
14
+ }
15
+ else {
16
+ const id = await github.postComment(owner, repo, issueNumber, markdown);
17
+ this.commentId = id;
18
+ this.deps.save?.(id);
19
+ }
20
+ }
21
+ async note(markdown) {
22
+ const { github, owner, repo, issueNumber } = this.deps;
23
+ await github.postComment(owner, repo, issueNumber, markdown);
24
+ }
25
+ }
26
+ //# sourceMappingURL=github.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"github.js","sourceRoot":"","sources":["../../../src/notify/transports/github.ts"],"names":[],"mappings":"AAmBA,MAAM,OAAO,eAAe;IAKG;IAJ7B,+EAA+E;IACtE,YAAY,GAAG,KAAK,CAAC;IACtB,SAAS,CAAU;IAE3B,YAA6B,IAAyB;QAAzB,SAAI,GAAJ,IAAI,CAAqB;QACpD,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC;IAClC,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,QAAgB;QAC5B,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,WAAW,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC;QACvD,IAAI,IAAI,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC;YACjC,MAAM,MAAM,CAAC,aAAa,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;QACpE,CAAC;aAAM,CAAC;YACN,MAAM,EAAE,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,KAAK,EAAE,IAAI,EAAE,WAAW,EAAE,QAAQ,CAAC,CAAC;YACxE,IAAI,CAAC,SAAS,GAAG,EAAE,CAAC;YACpB,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC;QACvB,CAAC;IACH,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,QAAgB;QACzB,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,WAAW,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC;QACvD,MAAM,MAAM,CAAC,WAAW,CAAC,KAAK,EAAE,IAAI,EAAE,WAAW,EAAE,QAAQ,CAAC,CAAC;IAC/D,CAAC;CACF"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Slack binding for the progress notifier. Owns a single message `ts` and
3
+ * edits it in place via `chat.update` on every `publish()`; `note()` posts a
4
+ * fresh threaded message for moments that deserve a real ping (approval
5
+ * prompts, terminal summary) — `chat.update` itself is silent.
6
+ */
7
+ import type { SlackConnector } from "../../connectors/slack/connector.js";
8
+ import type { NotifierTransport } from "../types.js";
9
+ export interface SlackTransportDeps {
10
+ slack: SlackConnector;
11
+ channel: string;
12
+ thread: string;
13
+ /** Existing status-message ts from a resumed run, if any. */
14
+ ts?: string;
15
+ /** Persist the ts the first time it's created (so resume re-attaches). */
16
+ save?: (ts: string) => void;
17
+ }
18
+ export declare class SlackTransport implements NotifierTransport {
19
+ private readonly deps;
20
+ /** Slack edits are silent and there's no other signal — so it wants the ping. */
21
+ readonly terminalPing = true;
22
+ private ts?;
23
+ constructor(deps: SlackTransportDeps);
24
+ publish(markdown: string): Promise<void>;
25
+ note(markdown: string): Promise<void>;
26
+ }
@@ -0,0 +1,28 @@
1
+ export class SlackTransport {
2
+ deps;
3
+ /** Slack edits are silent and there's no other signal — so it wants the ping. */
4
+ terminalPing = true;
5
+ ts;
6
+ constructor(deps) {
7
+ this.deps = deps;
8
+ this.ts = deps.ts;
9
+ }
10
+ async publish(markdown) {
11
+ const { slack, channel, thread } = this.deps;
12
+ if (this.ts !== undefined) {
13
+ await slack.updateMessage(channel, this.ts, markdown);
14
+ }
15
+ else {
16
+ const ts = await slack.sendMessage(channel, thread, markdown);
17
+ if (typeof ts === "string") {
18
+ this.ts = ts;
19
+ this.deps.save?.(ts);
20
+ }
21
+ }
22
+ }
23
+ async note(markdown) {
24
+ const { slack, channel, thread } = this.deps;
25
+ await slack.sendMessage(channel, thread, markdown);
26
+ }
27
+ }
28
+ //# sourceMappingURL=slack.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"slack.js","sourceRoot":"","sources":["../../../src/notify/transports/slack.ts"],"names":[],"mappings":"AAmBA,MAAM,OAAO,cAAc;IAKI;IAJ7B,iFAAiF;IACxE,YAAY,GAAG,IAAI,CAAC;IACrB,EAAE,CAAU;IAEpB,YAA6B,IAAwB;QAAxB,SAAI,GAAJ,IAAI,CAAoB;QACnD,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC,EAAE,CAAC;IACpB,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,QAAgB;QAC5B,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC;QAC7C,IAAI,IAAI,CAAC,EAAE,KAAK,SAAS,EAAE,CAAC;YAC1B,MAAM,KAAK,CAAC,aAAa,CAAC,OAAO,EAAE,IAAI,CAAC,EAAE,EAAE,QAAQ,CAAC,CAAC;QACxD,CAAC;aAAM,CAAC;YACN,MAAM,EAAE,GAAG,MAAM,KAAK,CAAC,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC;YAC9D,IAAI,OAAO,EAAE,KAAK,QAAQ,EAAE,CAAC;gBAC3B,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC;gBACb,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC;YACvB,CAAC;QACH,CAAC;IACH,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,QAAgB;QACzB,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC;QAC7C,MAAM,KAAK,CAAC,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC;IACrD,CAAC;CACF"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,71 @@
1
+ import { describe, it, expect, vi } from "vitest";
2
+ import { GitHubTransport } from "./transports/github.js";
3
+ import { SlackTransport } from "./transports/slack.js";
4
+ describe("GitHubTransport", () => {
5
+ it("creates the comment on first publish (storing the id) then edits it", async () => {
6
+ const postComment = vi.fn(async () => 555);
7
+ const updateComment = vi.fn(async () => { });
8
+ const github = { postComment, updateComment };
9
+ const saved = [];
10
+ const t = new GitHubTransport({
11
+ github, owner: "o", repo: "r", issueNumber: 7, save: (id) => saved.push(id),
12
+ });
13
+ await t.publish("first");
14
+ await t.publish("second");
15
+ expect(postComment).toHaveBeenCalledTimes(1);
16
+ expect(postComment).toHaveBeenCalledWith("o", "r", 7, "first");
17
+ expect(updateComment).toHaveBeenCalledTimes(1);
18
+ expect(updateComment).toHaveBeenCalledWith("o", "r", 555, "second");
19
+ expect(saved).toEqual([555]);
20
+ });
21
+ it("re-attaches to an existing comment id (resume) and only edits", async () => {
22
+ const postComment = vi.fn(async () => 999);
23
+ const updateComment = vi.fn(async () => { });
24
+ const github = { postComment, updateComment };
25
+ const t = new GitHubTransport({ github, owner: "o", repo: "r", issueNumber: 7, commentId: 42 });
26
+ await t.publish("edit me");
27
+ expect(postComment).not.toHaveBeenCalled();
28
+ expect(updateComment).toHaveBeenCalledWith("o", "r", 42, "edit me");
29
+ });
30
+ it("note always posts a fresh comment", async () => {
31
+ const postComment = vi.fn(async () => 1);
32
+ const github = { postComment, updateComment: vi.fn() };
33
+ const t = new GitHubTransport({ github, owner: "o", repo: "r", issueNumber: 7, commentId: 42 });
34
+ await t.note("ping");
35
+ expect(postComment).toHaveBeenCalledWith("o", "r", 7, "ping");
36
+ });
37
+ });
38
+ describe("SlackTransport", () => {
39
+ it("posts the message on first publish (storing the ts) then updates it", async () => {
40
+ const sendMessage = vi.fn(async () => "111.222");
41
+ const updateMessage = vi.fn(async () => { });
42
+ const slack = { sendMessage, updateMessage };
43
+ const saved = [];
44
+ const t = new SlackTransport({
45
+ slack, channel: "C", thread: "T", save: (ts) => saved.push(ts),
46
+ });
47
+ await t.publish("first");
48
+ await t.publish("second");
49
+ expect(sendMessage).toHaveBeenCalledTimes(1);
50
+ expect(sendMessage).toHaveBeenCalledWith("C", "T", "first");
51
+ expect(updateMessage).toHaveBeenCalledTimes(1);
52
+ expect(updateMessage).toHaveBeenCalledWith("C", "111.222", "second");
53
+ expect(saved).toEqual(["111.222"]);
54
+ });
55
+ it("wants a terminal ping (silent edits, no other signal) unlike GitHub", () => {
56
+ const slack = new SlackTransport({ slack: {}, channel: "C", thread: "T" });
57
+ const gh = new GitHubTransport({ github: {}, owner: "o", repo: "r", issueNumber: 1 });
58
+ expect(slack.terminalPing).toBe(true);
59
+ expect(gh.terminalPing).toBeFalsy();
60
+ });
61
+ it("re-attaches to an existing ts (resume) and only updates", async () => {
62
+ const sendMessage = vi.fn(async () => "x");
63
+ const updateMessage = vi.fn(async () => { });
64
+ const slack = { sendMessage, updateMessage };
65
+ const t = new SlackTransport({ slack, channel: "C", thread: "T", ts: "900.1" });
66
+ await t.publish("edit");
67
+ expect(sendMessage).not.toHaveBeenCalled();
68
+ expect(updateMessage).toHaveBeenCalledWith("C", "900.1", "edit");
69
+ });
70
+ });
71
+ //# sourceMappingURL=transports.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transports.test.js","sourceRoot":"","sources":["../../src/notify/transports.test.ts"],"names":[],"mappings":"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"}