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,107 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { workflowScopedTaskId, resolveRunBranch, PER_TARGET_REUSE_WORKFLOWS, PREPOPULATE_SYNTH_WORKFLOWS } from "./simple.js";
3
+ const RUN = "abcdef12-3456-7890-abcd-ef1234567890";
4
+ describe("workflowScopedTaskId", () => {
5
+ it("keys pr-review / pr-fix by (repo, PR) with no run suffix so they reuse one workspace", () => {
6
+ for (const wf of PER_TARGET_REUSE_WORKFLOWS) {
7
+ const a = workflowScopedTaskId("drizzle-cube", 918, wf, RUN);
8
+ const b = workflowScopedTaskId("drizzle-cube", 918, wf, "different-run-id");
9
+ expect(a).toBe(`drizzle-cube-918-${wf}`);
10
+ // Two separate runs on the same PR resolve to the same dir → reuse.
11
+ expect(a).toBe(b);
12
+ }
13
+ });
14
+ it("keeps the run suffix for build so each run gets a fresh workspace", () => {
15
+ const id = workflowScopedTaskId("drizzle-cube", 918, "build", RUN);
16
+ expect(id).toBe("drizzle-cube-918-build-abcdef12");
17
+ });
18
+ it("keeps the run suffix for repo-scoped (no number) workflows", () => {
19
+ const id = workflowScopedTaskId("drizzle-cube", undefined, "health", RUN);
20
+ expect(id).toBe("drizzle-cube-health-abcdef12");
21
+ });
22
+ it("does not reuse when a per-PR workflow has no number", () => {
23
+ const id = workflowScopedTaskId("drizzle-cube", undefined, "pr-review", RUN);
24
+ expect(id).toBe("drizzle-cube-pr-review-abcdef12");
25
+ });
26
+ });
27
+ describe("resolveRunBranch", () => {
28
+ it("derives lastlight/N-<title-slug> from the issue title on a fresh dispatch", () => {
29
+ const { branch, prePopulateBranch } = resolveRunBranch({
30
+ issueNumber: 3,
31
+ issueTitle: "I want to make the todos header red",
32
+ workflowName: "build",
33
+ });
34
+ expect(branch).toBe("lastlight/3-i-want-to-make-the-todos-header-red");
35
+ // build pre-populates, so prePopulateBranch tracks the synthesized branch.
36
+ expect(prePopulateBranch).toBe(branch);
37
+ });
38
+ it("pins to the stored branch on reuse even when the resume event has no title", () => {
39
+ // Regression: a build that paused at an approval gate resumes via
40
+ // runSimpleWorkflow with an empty issueTitle. Without recovering the stored
41
+ // branch this collapsed to `lastlight/3-issue-3` — a ref that was never
42
+ // pushed — so the PR phase's `head:` 422'd on github_create_pull_request.
43
+ const stored = {
44
+ branch: "lastlight/3-i-want-to-make-the-todos-header-red",
45
+ prePopulateBranch: "lastlight/3-i-want-to-make-the-todos-header-red",
46
+ };
47
+ const { branch, prePopulateBranch } = resolveRunBranch({
48
+ stored,
49
+ issueNumber: 3,
50
+ issueTitle: "", // resume events carry no issue title
51
+ workflowName: "build",
52
+ });
53
+ expect(branch).toBe("lastlight/3-i-want-to-make-the-todos-header-red");
54
+ expect(prePopulateBranch).toBe("lastlight/3-i-want-to-make-the-todos-header-red");
55
+ // Specifically NOT the empty-title fallback that caused the production 422.
56
+ expect(branch).not.toBe("lastlight/3-issue-3");
57
+ });
58
+ it("falls back to lastlight/N-issue-N only when there is no stored branch and no title", () => {
59
+ const { branch } = resolveRunBranch({
60
+ issueNumber: 3,
61
+ issueTitle: "",
62
+ workflowName: "build",
63
+ });
64
+ expect(branch).toBe("lastlight/3-issue-3");
65
+ });
66
+ it("prefers an explicit request prePopulateBranch (pr-review / pr-fix head ref)", () => {
67
+ const { branch, prePopulateBranch } = resolveRunBranch({
68
+ requestPrePopulateBranch: "feature/some-pr-head",
69
+ issueNumber: 918,
70
+ issueTitle: "unused when prePopulateBranch is set",
71
+ workflowName: "pr-review",
72
+ });
73
+ expect(branch).toBe("feature/some-pr-head");
74
+ expect(prePopulateBranch).toBe("feature/some-pr-head");
75
+ });
76
+ it("ignores an empty stored branch and recomputes from the title", () => {
77
+ const { branch } = resolveRunBranch({
78
+ stored: { branch: "" },
79
+ issueNumber: 3,
80
+ issueTitle: "Make it red",
81
+ workflowName: "build",
82
+ });
83
+ expect(branch).toBe("lastlight/3-make-it-red");
84
+ });
85
+ it("does not set prePopulateBranch for non-prepopulating workflows", () => {
86
+ const { prePopulateBranch } = resolveRunBranch({
87
+ issueNumber: 5,
88
+ issueTitle: "scan request",
89
+ workflowName: "triage",
90
+ });
91
+ expect(prePopulateBranch).toBeUndefined();
92
+ });
93
+ });
94
+ describe("PREPOPULATE_SYNTH_WORKFLOWS", () => {
95
+ it("includes verify and qa-test so their browser-QA screenshots harvest correctly", () => {
96
+ // The harvest fix hinges on these pre-populating like build (cwd = repo
97
+ // root), so server-mode artifacts land where serverArtifacts() reads them.
98
+ expect(PREPOPULATE_SYNTH_WORKFLOWS.has("verify")).toBe(true);
99
+ expect(PREPOPULATE_SYNTH_WORKFLOWS.has("qa-test")).toBe(true);
100
+ expect(PREPOPULATE_SYNTH_WORKFLOWS.has("build")).toBe(true);
101
+ });
102
+ it("does not pre-populate read-only scan workflows that clone in-session", () => {
103
+ expect(PREPOPULATE_SYNTH_WORKFLOWS.has("triage")).toBe(false);
104
+ expect(PREPOPULATE_SYNTH_WORKFLOWS.has("answer")).toBe(false);
105
+ });
106
+ });
107
+ //# sourceMappingURL=simple.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"simple.test.js","sourceRoot":"","sources":["../../src/workflows/simple.test.ts"],"names":[],"mappings":"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"}
@@ -20,6 +20,34 @@ export interface TemplateContext {
20
20
  taskId: string;
21
21
  issueDir: string;
22
22
  bootstrapLabel: string;
23
+ /**
24
+ * True only in server mode (handoff docs externalized to the Last Light
25
+ * store instead of committed into the target repo). Prompts gate their
26
+ * `git add .lastlight/ && commit` behind `{{#if !externalizeArtifacts}}`, so
27
+ * an absent flag defaults to repo behaviour (commit the docs) — fail-safe for
28
+ * any render path that doesn't set it.
29
+ */
30
+ externalizeArtifacts?: boolean;
31
+ /**
32
+ * Dashboard base URL (no trailing slash). Used by the `{{artifactUrl file}}`
33
+ * helper to build a server-mode dashboard link to a handoff doc. Absent when
34
+ * no public URL is configured.
35
+ */
36
+ publicUrl?: string;
37
+ /**
38
+ * Public, unauthenticated, image-only base URL for inline screenshot embeds
39
+ * in the browser-QA comment (`<publicUrl>/admin/api/public/artifacts/<owner>/
40
+ * <repo>/<issueKey>`). The agent appends `/<name>.png` per screenshot. Empty
41
+ * string when no public URL is configured — browser-QA prompts then fall back
42
+ * to filename-only references via `{{#if !artifactBaseUrl}}`.
43
+ */
44
+ artifactBaseUrl?: string;
45
+ /**
46
+ * Id of the approval being created — injected into an approval-gate message's
47
+ * render context by `PhaseExecutor.pauseForApproval` so the `{{approvalUrl}}`
48
+ * helper can deep-link to the focused approval view.
49
+ */
50
+ approvalId?: string;
23
51
  approved?: boolean;
24
52
  fixCycles?: number;
25
53
  reviewerNote?: string;
@@ -30,6 +58,7 @@ export interface TemplateContext {
30
58
  prBody?: string;
31
59
  failedChecks?: string;
32
60
  ciSection?: string;
61
+ prePopulateBranch?: string;
33
62
  contextSnapshot?: string;
34
63
  iteration?: number;
35
64
  maxIterations?: number;
@@ -35,8 +35,12 @@ export function renderTemplate(template, ctx) {
35
35
  // any missing intermediate.
36
36
  const walkKey = (key) => {
37
37
  const parts = key.split(".");
38
- if (parts.length === 1)
39
- return ctx[key];
38
+ if (parts.length === 1) {
39
+ const val = ctx[key];
40
+ if (val !== undefined && val !== null)
41
+ return val;
42
+ return ctx.phaseOutputs?.[key];
43
+ }
40
44
  let cur = ctx[parts[0]];
41
45
  if (cur === undefined || cur === null)
42
46
  cur = ctx.phaseOutputs?.[parts[0]];
@@ -48,7 +52,9 @@ export function renderTemplate(template, ctx) {
48
52
  return cur;
49
53
  };
50
54
  // 1. Conditional blocks: {{#if varName}}...{{/if}} (supports dot notation).
51
- result = result.replace(/\{\{#if\s+(!?)(\w+(?:\.\w+)*)\}\}([\s\S]*?)\{\{\/if\}\}/g, (_match, negate, varName, body) => {
55
+ // Key segments allow hyphens so phase/model keys like `pr-fix` resolve
56
+ // (e.g. {{models.pr-fix}}); \w alone would leave them unrendered.
57
+ result = result.replace(/\{\{#if\s+(!?)([\w-]+(?:\.[\w-]+)*)\}\}([\s\S]*?)\{\{\/if\}\}/g, (_match, negate, varName, body) => {
52
58
  const val = walkKey(varName);
53
59
  // Truthy: non-empty string, non-zero number, non-empty array, true boolean
54
60
  const truthy = val !== undefined &&
@@ -72,13 +78,45 @@ export function renderTemplate(template, ctx) {
72
78
  const encoded = encodeURIComponent(ctx.branch);
73
79
  return `https://github.com/${ctx.owner}/${ctx.repo}/blob/${encoded}/${ctx.issueDir}/${file}`;
74
80
  });
81
+ // 3b. Artifact URL helper: {{artifactUrl filename}} — mode-aware link to a
82
+ // handoff doc. In repo mode it's identical to {{branchUrl}} (the doc is
83
+ // committed on the branch). In server mode the doc lives on the Last Light
84
+ // host, so the link points at the admin dashboard's Artifacts view. Falls
85
+ // back to the branch URL when no publicUrl is configured so a server-mode
86
+ // deploy without PUBLIC_URL still produces a usable (if GitHub-less) link.
87
+ result = result.replace(/\{\{artifactUrl\s+(\S+)\}\}/g, (_match, file) => {
88
+ const branchHref = `https://github.com/${ctx.owner}/${ctx.repo}/blob/${encodeURIComponent(ctx.branch)}/${ctx.issueDir}/${file}`;
89
+ if (!ctx.externalizeArtifacts)
90
+ return branchHref;
91
+ if (!ctx.publicUrl)
92
+ return branchHref;
93
+ const issueKey = ctx.issueDir.replace(/^\.lastlight\//, "");
94
+ const base = String(ctx.publicUrl).replace(/\/+$/, "");
95
+ const q = `repo=${encodeURIComponent(`${ctx.owner}/${ctx.repo}`)}` +
96
+ `&key=${encodeURIComponent(issueKey)}` +
97
+ `&doc=${encodeURIComponent(file)}`;
98
+ return `${base}/admin/?tab=artifacts&${q}`;
99
+ });
100
+ // 3c. Approval URL helper: {{approvalUrl}} — deep link to the focused
101
+ // approval view for the gate currently being rendered. `approvalId` is
102
+ // injected into the message context by PhaseExecutor.pauseForApproval, and
103
+ // `publicUrl` is the dashboard base. Renders empty when either is absent
104
+ // (e.g. no PUBLIC_URL configured) so the rest of the gate message still
105
+ // posts cleanly.
106
+ result = result.replace(/\{\{approvalUrl\}\}/g, () => {
107
+ if (!ctx.publicUrl || !ctx.approvalId)
108
+ return "";
109
+ const base = String(ctx.publicUrl).replace(/\/+$/, "");
110
+ return `${base}/admin/?approval=${encodeURIComponent(String(ctx.approvalId))}`;
111
+ });
75
112
  // 4. Simple variable substitution: {{varName}} and {{a.b.c...}}.
76
113
  // Dotted access first checks top-level ctx, then falls back to
77
114
  // ctx.phaseOutputs[parent] for the first segment so YAML phases can
78
115
  // emit structured output via `output_var` and downstream prompts can
79
116
  // read it directly — and the socratic explore loop can read
80
117
  // {{scratch.socratic.qa}}.
81
- result = result.replace(/\{\{(\w+(?:\.\w+)*)\}\}/g, (_match, key) => {
118
+ // Key segments allow hyphens (e.g. {{models.pr-fix}}) see #1.
119
+ result = result.replace(/\{\{([\w-]+(?:\.[\w-]+)*)\}\}/g, (_match, key) => {
82
120
  const val = walkKey(key);
83
121
  if (val === undefined || val === null)
84
122
  return "";
@@ -1 +1 @@
1
- {"version":3,"file":"templates.js","sourceRoot":"","sources":["../../src/workflows/templates.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"templates.js","sourceRoot":"","sources":["../../src/workflows/templates.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AA2GH,MAAM,UAAU,OAAO,CAAC,IAAY;IAClC,OAAO,IAAI;SACR,WAAW,EAAE;SACb,OAAO,CAAC,aAAa,EAAE,GAAG,CAAC;SAC3B,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC;SACrB,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AAClB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,QAAgB,EAAE,GAAoB;IACnE,IAAI,MAAM,GAAG,QAAQ,CAAC;IAEtB,8EAA8E;IAC9E,IAAI,GAAG,CAAC,YAAY,EAAE,CAAC;QACrB,MAAM,YAAY,GAAG,GAAG,CAAC,YAAY,CAAC;QACtC,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,sBAAsB,EAAE,CAAC,MAAM,EAAE,SAAiB,EAAE,EAAE;YAC5E,MAAM,GAAG,GAAG,YAAY,CAAC,SAAS,CAAC,CAAC;YACpC,IAAI,GAAG,KAAK,SAAS,IAAI,GAAG,KAAK,IAAI;gBAAE,OAAO,EAAE,CAAC;YACjD,OAAO,OAAO,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAE,GAA4B,EAAE,MAAM,IAAI,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC;QAC9G,CAAC,CAAC,CAAC;IACL,CAAC;IAED,uEAAuE;IACvE,uEAAuE;IACvE,4BAA4B;IAC5B,MAAM,OAAO,GAAG,CAAC,GAAW,EAAW,EAAE;QACvC,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC7B,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACvB,MAAM,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;YACrB,IAAI,GAAG,KAAK,SAAS,IAAI,GAAG,KAAK,IAAI;gBAAE,OAAO,GAAG,CAAC;YAClD,OAAO,GAAG,CAAC,YAAY,EAAE,CAAC,GAAG,CAAC,CAAC;QACjC,CAAC;QACD,IAAI,GAAG,GAAY,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QACjC,IAAI,GAAG,KAAK,SAAS,IAAI,GAAG,KAAK,IAAI;YAAE,GAAG,GAAG,GAAG,CAAC,YAAY,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QAC1E,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACtC,IAAI,GAAG,KAAK,IAAI,IAAI,OAAO,GAAG,KAAK,QAAQ;gBAAE,OAAO,SAAS,CAAC;YAC9D,GAAG,GAAI,GAA+B,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QACnD,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC,CAAC;IAEF,4EAA4E;IAC5E,0EAA0E;IAC1E,qEAAqE;IACrE,MAAM,GAAG,MAAM,CAAC,OAAO,CACrB,gEAAgE,EAChE,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE;QAChC,MAAM,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;QAC7B,2EAA2E;QAC3E,MAAM,MAAM,GACV,GAAG,KAAK,SAAS;YACjB,GAAG,KAAK,IAAI;YACZ,GAAG,KAAK,EAAE;YACV,GAAG,KAAK,KAAK;YACb,GAAG,KAAK,CAAC;YACT,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC;QAC5C,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;IACjD,CAAC,CACF,CAAC;IAEF,yCAAyC;IACzC,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,0BAA0B,EAAE,CAAC,MAAM,EAAE,OAAO,EAAE,EAAE;QACtE,MAAM,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,CAAC;QACzB,IAAI,GAAG,KAAK,SAAS,IAAI,GAAG,KAAK,IAAI;YAAE,OAAO,EAAE,CAAC;QACjD,OAAO,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;IAC9B,CAAC,CAAC,CAAC;IAEH,+CAA+C;IAC/C,yFAAyF;IACzF,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,4BAA4B,EAAE,CAAC,MAAM,EAAE,IAAI,EAAE,EAAE;QACrE,MAAM,OAAO,GAAG,kBAAkB,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAC/C,OAAO,sBAAsB,GAAG,CAAC,KAAK,IAAI,GAAG,CAAC,IAAI,SAAS,OAAO,IAAI,GAAG,CAAC,QAAQ,IAAI,IAAI,EAAE,CAAC;IAC/F,CAAC,CAAC,CAAC;IAEH,2EAA2E;IAC3E,wEAAwE;IACxE,2EAA2E;IAC3E,0EAA0E;IAC1E,0EAA0E;IAC1E,2EAA2E;IAC3E,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,8BAA8B,EAAE,CAAC,MAAM,EAAE,IAAI,EAAE,EAAE;QACvE,MAAM,UAAU,GAAG,sBAAsB,GAAG,CAAC,KAAK,IAAI,GAAG,CAAC,IAAI,SAAS,kBAAkB,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,GAAG,CAAC,QAAQ,IAAI,IAAI,EAAE,CAAC;QAChI,IAAI,CAAC,GAAG,CAAC,oBAAoB;YAAE,OAAO,UAAU,CAAC;QACjD,IAAI,CAAC,GAAG,CAAC,SAAS;YAAE,OAAO,UAAU,CAAC;QACtC,MAAM,QAAQ,GAAG,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,gBAAgB,EAAE,EAAE,CAAC,CAAC;QAC5D,MAAM,IAAI,GAAG,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;QACvD,MAAM,CAAC,GACL,QAAQ,kBAAkB,CAAC,GAAG,GAAG,CAAC,KAAK,IAAI,GAAG,CAAC,IAAI,EAAE,CAAC,EAAE;YACxD,QAAQ,kBAAkB,CAAC,QAAQ,CAAC,EAAE;YACtC,QAAQ,kBAAkB,CAAC,IAAI,CAAC,EAAE,CAAC;QACrC,OAAO,GAAG,IAAI,yBAAyB,CAAC,EAAE,CAAC;IAC7C,CAAC,CAAC,CAAC;IAEH,sEAAsE;IACtE,uEAAuE;IACvE,2EAA2E;IAC3E,yEAAyE;IACzE,wEAAwE;IACxE,iBAAiB;IACjB,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,sBAAsB,EAAE,GAAG,EAAE;QACnD,IAAI,CAAC,GAAG,CAAC,SAAS,IAAI,CAAC,GAAG,CAAC,UAAU;YAAE,OAAO,EAAE,CAAC;QACjD,MAAM,IAAI,GAAG,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;QACvD,OAAO,GAAG,IAAI,oBAAoB,kBAAkB,CAAC,MAAM,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC;IACjF,CAAC,CAAC,CAAC;IAEH,iEAAiE;IACjE,kEAAkE;IAClE,uEAAuE;IACvE,wEAAwE;IACxE,+DAA+D;IAC/D,8BAA8B;IAC9B,mEAAmE;IACnE,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,gCAAgC,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE,EAAE;QACxE,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;QACzB,IAAI,GAAG,KAAK,SAAS,IAAI,GAAG,KAAK,IAAI;YAAE,OAAO,EAAE,CAAC;QACjD,OAAO,OAAO,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACrE,CAAC,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -32,6 +32,60 @@ describe("slugify", () => {
32
32
  expect(slugify("foo -- bar !! baz")).toBe("foo-bar-baz");
33
33
  });
34
34
  });
35
+ describe("renderTemplate — {{artifactUrl}} (build-assets mode)", () => {
36
+ it("repo mode (flag absent) → GitHub blob URL", () => {
37
+ const result = renderTemplate("{{artifactUrl architect-plan.md}}", BASE_CTX);
38
+ expect(result).toBe("https://github.com/acme/widget/blob/lastlight%2F42-add-rate-limiter/.lastlight/issue-42/architect-plan.md");
39
+ });
40
+ it("server mode → dashboard deep link when publicUrl is set", () => {
41
+ const result = renderTemplate("{{artifactUrl architect-plan.md}}", {
42
+ ...BASE_CTX,
43
+ externalizeArtifacts: true,
44
+ publicUrl: "https://last.example.com/",
45
+ });
46
+ expect(result).toBe("https://last.example.com/admin/?tab=artifacts&repo=acme%2Fwidget&key=issue-42&doc=architect-plan.md");
47
+ });
48
+ it("server mode without publicUrl → falls back to the branch URL", () => {
49
+ const result = renderTemplate("{{artifactUrl status.md}}", {
50
+ ...BASE_CTX,
51
+ externalizeArtifacts: true,
52
+ });
53
+ expect(result).toContain("https://github.com/acme/widget/blob/");
54
+ });
55
+ });
56
+ describe("renderTemplate — {{approvalUrl}} (focused approval deep link)", () => {
57
+ it("builds a focused-view link from publicUrl + approvalId", () => {
58
+ const result = renderTemplate("{{approvalUrl}}", {
59
+ ...BASE_CTX,
60
+ publicUrl: "https://last.example.com/",
61
+ approvalId: "appr-123",
62
+ });
63
+ expect(result).toBe("https://last.example.com/admin/?approval=appr-123");
64
+ });
65
+ it("renders empty when publicUrl is absent (so the rest of the message still posts)", () => {
66
+ const result = renderTemplate("see {{approvalUrl}} now", {
67
+ ...BASE_CTX,
68
+ approvalId: "appr-123",
69
+ });
70
+ expect(result).toBe("see now");
71
+ });
72
+ it("renders empty when approvalId is absent", () => {
73
+ const result = renderTemplate("{{approvalUrl}}", {
74
+ ...BASE_CTX,
75
+ publicUrl: "https://last.example.com",
76
+ });
77
+ expect(result).toBe("");
78
+ });
79
+ });
80
+ describe("renderTemplate — doc-commit gate", () => {
81
+ const TEMPLATE = "{{#if !externalizeArtifacts}}git commit docs{{/if}}{{#if externalizeArtifacts}}harness persists{{/if}}";
82
+ it("repo mode (flag absent) renders the git commit", () => {
83
+ expect(renderTemplate(TEMPLATE, BASE_CTX)).toBe("git commit docs");
84
+ });
85
+ it("server mode renders the persistence note instead", () => {
86
+ expect(renderTemplate(TEMPLATE, { ...BASE_CTX, externalizeArtifacts: true })).toBe("harness persists");
87
+ });
88
+ });
35
89
  describe("renderTemplate — simple substitution", () => {
36
90
  it("replaces {{varName}} with context value", () => {
37
91
  const result = renderTemplate("Hello {{owner}}/{{repo}}#{{issueNumber}}", BASE_CTX);
@@ -46,6 +100,25 @@ describe("renderTemplate — simple substitution", () => {
46
100
  expect(result).toBe("Issue 42");
47
101
  });
48
102
  });
103
+ describe("renderTemplate — phaseOutputs fallback", () => {
104
+ it("resolves single-segment {{varName}} from phaseOutputs when not on ctx", () => {
105
+ const ctx = {
106
+ ...BASE_CTX,
107
+ phaseOutputs: { publishResult: "**Spec published:** https://github.com/a/b/issues/1" },
108
+ };
109
+ const result = renderTemplate("{{publishResult}}", ctx);
110
+ expect(result).toBe("**Spec published:** https://github.com/a/b/issues/1");
111
+ });
112
+ it("prefers top-level ctx over phaseOutputs on name collision", () => {
113
+ const ctx = {
114
+ ...BASE_CTX,
115
+ owner: "ctxOwner",
116
+ phaseOutputs: { owner: "phaseOwner" },
117
+ };
118
+ const result = renderTemplate("{{owner}}", ctx);
119
+ expect(result).toBe("ctxOwner");
120
+ });
121
+ });
49
122
  describe("renderTemplate — nested variable (two-level)", () => {
50
123
  it("resolves models.architect style vars", () => {
51
124
  const ctx = {
@@ -60,6 +133,21 @@ describe("renderTemplate — nested variable (two-level)", () => {
60
133
  const result = renderTemplate("{{models.architect}}", ctx);
61
134
  expect(result).toBe("");
62
135
  });
136
+ it("resolves hyphenated keys like models.pr-fix", () => {
137
+ const ctx = {
138
+ ...BASE_CTX,
139
+ models: { "pr-fix": "claude-haiku-4-5", default: "claude-sonnet-4-6" },
140
+ };
141
+ const result = renderTemplate("{{models.pr-fix}}", ctx);
142
+ expect(result).toBe("claude-haiku-4-5");
143
+ });
144
+ it("renders a hyphenated key to empty (not the literal) when unset", () => {
145
+ // Regression: \w-only key regex left {{models.pr-fix}} unrendered, which
146
+ // then reached the sandbox model validator as a literal and was rejected.
147
+ const ctx = { ...BASE_CTX, models: { default: "claude-sonnet-4-6" } };
148
+ const result = renderTemplate("{{models.pr-fix}}", ctx);
149
+ expect(result).toBe("");
150
+ });
63
151
  });
64
152
  describe("renderTemplate — slugify helper", () => {
65
153
  it("applies slugify to the named variable", () => {
@@ -107,6 +195,21 @@ describe("renderTemplate — conditional blocks", () => {
107
195
  expect(result).toContain("failures here");
108
196
  });
109
197
  });
198
+ describe("renderTemplate — artifactBaseUrl (inline screenshot embeds)", () => {
199
+ const tmpl = "{{#if artifactBaseUrl}}![home]({{artifactBaseUrl}}/home.png){{/if}}" +
200
+ "{{#if !artifactBaseUrl}}see home.png in the Artifacts view{{/if}}";
201
+ it("emits an inline image URL when the base is set", () => {
202
+ const ctx = { ...BASE_CTX, artifactBaseUrl: "https://ll.example.com/admin/api/public/artifacts/acme/widget/issue-42" };
203
+ expect(renderTemplate(tmpl, ctx)).toBe("![home](https://ll.example.com/admin/api/public/artifacts/acme/widget/issue-42/home.png)");
204
+ });
205
+ it("falls back to the filename note when the base is empty", () => {
206
+ const ctx = { ...BASE_CTX, artifactBaseUrl: "" };
207
+ expect(renderTemplate(tmpl, ctx)).toBe("see home.png in the Artifacts view");
208
+ });
209
+ it("falls back when the base is absent", () => {
210
+ expect(renderTemplate(tmpl, BASE_CTX)).toBe("see home.png in the Artifacts view");
211
+ });
212
+ });
110
213
  describe("renderTemplate — deep dotted access (scratch.a.b)", () => {
111
214
  it("resolves three-level dotted paths via walkKey", () => {
112
215
  const ctx = {
@@ -1 +1 @@
1
- {"version":3,"file":"templates.test.js","sourceRoot":"","sources":["../../src/workflows/templates.test.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"templates.test.js","sourceRoot":"","sources":["../../src/workflows/templates.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ export type TriggerInfo = {
2
+ kind: "cron";
3
+ name: string;
4
+ schedule: string;
5
+ } | {
6
+ kind: "github";
7
+ event: string;
8
+ description: string;
9
+ } | {
10
+ kind: "slack";
11
+ command: string;
12
+ description: string;
13
+ } | {
14
+ kind: "mention";
15
+ description: string;
16
+ } | {
17
+ kind: "internal";
18
+ description: string;
19
+ };
20
+ export declare function getWorkflowTriggers(workflowName: string): TriggerInfo[];
21
+ export declare function getWorkflowTriggerKinds(workflowName: string): TriggerInfo["kind"][];
@@ -0,0 +1,44 @@
1
+ import { getCronWorkflows } from "./loader.js";
2
+ import { getRoutes } from "../config.js";
3
+ function add(map, name, info) {
4
+ if (!name)
5
+ return;
6
+ const effectiveName = name === "github-orchestrator" ? "build" : name;
7
+ map.set(effectiveName, [...(map.get(effectiveName) || []), info]);
8
+ }
9
+ function routeTriggers() {
10
+ const routes = getRoutes();
11
+ const map = new Map();
12
+ add(map, routes.github.issue_opened, { kind: "github", event: "issue.opened", description: "An issue is opened" });
13
+ add(map, routes.github.issue_reopened, { kind: "github", event: "issue.reopened", description: "An issue is reopened" });
14
+ add(map, routes.github.pr_opened, { kind: "github", event: "pr.opened", description: "A PR is opened" });
15
+ add(map, routes.github.pr_synchronize, { kind: "github", event: "pr.synchronize", description: "A PR is updated" });
16
+ add(map, routes.github.pr_reopened, { kind: "github", event: "pr.reopened", description: "A PR is reopened" });
17
+ add(map, routes.github.pr_fix, { kind: "mention", description: "`@last-light build …` on a PR comment (maintainers only)" });
18
+ add(map, routes.github.pr_comment, { kind: "mention", description: "`@last-light <message>` on a PR comment / review" });
19
+ add(map, routes.github.issue_build, { kind: "mention", description: "`@last-light build …` on an issue comment (maintainers only)" });
20
+ add(map, routes.github.issue_explore, { kind: "mention", description: "`@last-light explore …` on an issue comment" });
21
+ add(map, routes.github.issue_comment, { kind: "mention", description: "`@last-light <message>` on an issue comment" });
22
+ add(map, routes.github.security_feedback, { kind: "internal", description: "Chained from `security-review` when issues are found" });
23
+ add(map, routes.slack.build, { kind: "slack", command: "build", description: "Slack: `build <repo>#<n>`" });
24
+ add(map, routes.slack.triage, { kind: "slack", command: "triage", description: "Slack: `triage <repo>`" });
25
+ add(map, routes.slack.review, { kind: "slack", command: "review", description: "Slack: `review <repo>`" });
26
+ add(map, routes.slack.security, { kind: "slack", command: "security", description: "Slack: `security <repo>`" });
27
+ add(map, routes.slack.explore, { kind: "slack", command: "explore", description: "Slack: `explore <repo>#<n>`" });
28
+ return map;
29
+ }
30
+ export function getWorkflowTriggers(workflowName) {
31
+ const cronTriggers = getCronWorkflows()
32
+ .filter((c) => c.workflow === workflowName)
33
+ .map((c) => ({ kind: "cron", name: c.name, schedule: c.schedule }));
34
+ return [...cronTriggers, ...(routeTriggers().get(workflowName) ?? [])];
35
+ }
36
+ export function getWorkflowTriggerKinds(workflowName) {
37
+ const triggers = getWorkflowTriggers(workflowName);
38
+ const seen = new Set();
39
+ for (const t of triggers)
40
+ seen.add(t.kind);
41
+ const order = ["cron", "github", "mention", "slack", "internal"];
42
+ return order.filter((k) => seen.has(k));
43
+ }
44
+ //# sourceMappingURL=triggers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"triggers.js","sourceRoot":"","sources":["../../src/workflows/triggers.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * The single parser for a reviewer phase's verdict.
3
+ *
4
+ * A reviewer agent is asked to end its output with a `VERDICT:` marker line —
5
+ * either `VERDICT: APPROVED` or `VERDICT: REQUEST_CHANGES`. When that marker is
6
+ * present we trust it. When it's absent we fall back to a fragile heuristic
7
+ * (preserved here exactly as both runner sites had it): treat the output as
8
+ * approved only when it does NOT mention `REQUEST_CHANGES` and DOES start with
9
+ * `APPROVED`. `viaFallback` lets callers warn when the marker was missing.
10
+ *
11
+ * Hardening the fallback is deliberately out of scope — this parser is
12
+ * behaviour-neutral on verdict semantics.
13
+ */
14
+ export type ReviewerVerdict = "APPROVED" | "REQUEST_CHANGES";
15
+ export interface ParsedVerdict {
16
+ verdict: ReviewerVerdict;
17
+ viaFallback: boolean;
18
+ }
19
+ export declare function parseReviewerVerdict(output: string): ParsedVerdict;
@@ -0,0 +1,30 @@
1
+ /**
2
+ * The single parser for a reviewer phase's verdict.
3
+ *
4
+ * A reviewer agent is asked to end its output with a `VERDICT:` marker line —
5
+ * either `VERDICT: APPROVED` or `VERDICT: REQUEST_CHANGES`. When that marker is
6
+ * present we trust it. When it's absent we fall back to a fragile heuristic
7
+ * (preserved here exactly as both runner sites had it): treat the output as
8
+ * approved only when it does NOT mention `REQUEST_CHANGES` and DOES start with
9
+ * `APPROVED`. `viaFallback` lets callers warn when the marker was missing.
10
+ *
11
+ * Hardening the fallback is deliberately out of scope — this parser is
12
+ * behaviour-neutral on verdict semantics.
13
+ */
14
+ export function parseReviewerVerdict(output) {
15
+ const marker = output.match(/^\s*VERDICT:\s*(APPROVED|REQUEST_CHANGES)\s*$/im);
16
+ if (marker) {
17
+ return {
18
+ verdict: marker[1].toUpperCase() === "APPROVED" ? "APPROVED" : "REQUEST_CHANGES",
19
+ viaFallback: false,
20
+ };
21
+ }
22
+ const upper = output.toUpperCase();
23
+ const hasRequestChanges = /\bREQUEST_CHANGES\b/.test(upper);
24
+ const isApproved = !hasRequestChanges && /^APPROVED\b/.test(upper);
25
+ return {
26
+ verdict: isApproved ? "APPROVED" : "REQUEST_CHANGES",
27
+ viaFallback: true,
28
+ };
29
+ }
30
+ //# sourceMappingURL=verdict.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verdict.js","sourceRoot":"","sources":["../../src/workflows/verdict.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AASH,MAAM,UAAU,oBAAoB,CAAC,MAAc;IACjD,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,iDAAiD,CAAC,CAAC;IAC/E,IAAI,MAAM,EAAE,CAAC;QACX,OAAO;YACL,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,KAAK,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,iBAAiB;YAChF,WAAW,EAAE,KAAK;SACnB,CAAC;IACJ,CAAC;IAED,MAAM,KAAK,GAAG,MAAM,CAAC,WAAW,EAAE,CAAC;IACnC,MAAM,iBAAiB,GAAG,qBAAqB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC5D,MAAM,UAAU,GAAG,CAAC,iBAAiB,IAAI,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACnE,OAAO;QACL,OAAO,EAAE,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,iBAAiB;QACpD,WAAW,EAAE,IAAI;KAClB,CAAC;AACJ,CAAC"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,44 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { parseReviewerVerdict } from "./verdict.js";
3
+ describe("parseReviewerVerdict — explicit VERDICT: marker", () => {
4
+ it("reads VERDICT: APPROVED with no fallback", () => {
5
+ expect(parseReviewerVerdict("VERDICT: APPROVED\nLooks great!")).toEqual({
6
+ verdict: "APPROVED",
7
+ viaFallback: false,
8
+ });
9
+ });
10
+ it("reads VERDICT: REQUEST_CHANGES with no fallback", () => {
11
+ expect(parseReviewerVerdict("VERDICT: REQUEST_CHANGES\nFix the bug")).toEqual({
12
+ verdict: "REQUEST_CHANGES",
13
+ viaFallback: false,
14
+ });
15
+ });
16
+ it("matches a case-insensitive marker on a non-first line (/im)", () => {
17
+ const output = "Here is my review.\n\nverdict: approved\n";
18
+ expect(parseReviewerVerdict(output)).toEqual({
19
+ verdict: "APPROVED",
20
+ viaFallback: false,
21
+ });
22
+ });
23
+ });
24
+ describe("parseReviewerVerdict — fallback (no VERDICT: marker)", () => {
25
+ it("approves when output starts with APPROVED and never says REQUEST_CHANGES", () => {
26
+ expect(parseReviewerVerdict("APPROVED — ship it")).toEqual({
27
+ verdict: "APPROVED",
28
+ viaFallback: true,
29
+ });
30
+ });
31
+ it("requests changes when output mentions REQUEST_CHANGES", () => {
32
+ expect(parseReviewerVerdict("I think this needs work: REQUEST_CHANGES")).toEqual({
33
+ verdict: "REQUEST_CHANGES",
34
+ viaFallback: true,
35
+ });
36
+ });
37
+ it("treats ambiguous output as not approved", () => {
38
+ expect(parseReviewerVerdict("This looks mostly fine but I'm unsure.")).toEqual({
39
+ verdict: "REQUEST_CHANGES",
40
+ viaFallback: true,
41
+ });
42
+ });
43
+ });
44
+ //# sourceMappingURL=verdict.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verdict.test.js","sourceRoot":"","sources":["../../src/workflows/verdict.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAEpD,QAAQ,CAAC,iDAAiD,EAAE,GAAG,EAAE;IAC/D,EAAE,CAAC,0CAA0C,EAAE,GAAG,EAAE;QAClD,MAAM,CAAC,oBAAoB,CAAC,iCAAiC,CAAC,CAAC,CAAC,OAAO,CAAC;YACtE,OAAO,EAAE,UAAU;YACnB,WAAW,EAAE,KAAK;SACnB,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iDAAiD,EAAE,GAAG,EAAE;QACzD,MAAM,CAAC,oBAAoB,CAAC,uCAAuC,CAAC,CAAC,CAAC,OAAO,CAAC;YAC5E,OAAO,EAAE,iBAAiB;YAC1B,WAAW,EAAE,KAAK;SACnB,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6DAA6D,EAAE,GAAG,EAAE;QACrE,MAAM,MAAM,GAAG,2CAA2C,CAAC;QAC3D,MAAM,CAAC,oBAAoB,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC;YAC3C,OAAO,EAAE,UAAU;YACnB,WAAW,EAAE,KAAK;SACnB,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,sDAAsD,EAAE,GAAG,EAAE;IACpE,EAAE,CAAC,0EAA0E,EAAE,GAAG,EAAE;QAClF,MAAM,CAAC,oBAAoB,CAAC,oBAAoB,CAAC,CAAC,CAAC,OAAO,CAAC;YACzD,OAAO,EAAE,UAAU;YACnB,WAAW,EAAE,IAAI;SAClB,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uDAAuD,EAAE,GAAG,EAAE;QAC/D,MAAM,CAAC,oBAAoB,CAAC,0CAA0C,CAAC,CAAC,CAAC,OAAO,CAAC;YAC/E,OAAO,EAAE,iBAAiB;YAC1B,WAAW,EAAE,IAAI;SAClB,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yCAAyC,EAAE,GAAG,EAAE;QACjD,MAAM,CAAC,oBAAoB,CAAC,wCAAwC,CAAC,CAAC,CAAC,OAAO,CAAC;YAC7E,OAAO,EAAE,iBAAiB;YAC1B,WAAW,EAAE,IAAI;SAClB,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -15,7 +15,7 @@ export declare class WorktreeManager {
15
15
  private baseDir;
16
16
  private active;
17
17
  constructor(baseDir?: string);
18
- private exec;
18
+ private execGit;
19
19
  /**
20
20
  * Create a new worktree for a task.
21
21
  * Clones the repo first (if not already cloned), then creates a worktree.