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,194 @@
1
+ ---
2
+ name: demo
3
+ description: Record a short demo VIDEO of a PR or feature — drive the repo's web UI in a real headless browser, capture the session, and composite a titled, size-capped mp4 with ffmpeg. Use on the docker QA image when the deliverable is a playable demo clip (single walkthrough or before/after comparison), not a text/screenshot report.
4
+ version: 1.0.0
5
+ tags: [demo, video, browser, ffmpeg, evidence]
6
+ ---
7
+
8
+ # Demo
9
+
10
+ Turn a PR or feature into a short, polished **demo video**: drive the repo's
11
+ web UI in a real headless Chromium, screen-record the session, and composite a
12
+ titled, size-capped **mp4** the maintainer can watch inline.
13
+
14
+ This is the **video** sibling of `browser-qa` (screenshots) and `verify`/
15
+ `qa-test` (text evidence). It only works on the `lastlight-sandbox-qa:latest`
16
+ docker image, which bakes in Playwright + Chromium **and ffmpeg**. You have
17
+ bash + file tools but **no vision** — you reason over the driver's JSON stdout
18
+ and the ffprobe summary; you never "see" the video.
19
+
20
+ Compositing is **ffmpeg only** — there is no Remotion / cinematic-effects
21
+ pipeline. You get a title card, optional before/after side-by-side, trim/speed,
22
+ and a size cap. That's the deliverable: a clear, honest walkthrough, not a
23
+ marketing reel.
24
+
25
+ This skill uses **browser-qa** (the headless driver) and **building** (install
26
+ + start the dev-server).
27
+
28
+ ## When this applies
29
+
30
+ A phase on the docker QA image whose target is a **web app** the repo serves on
31
+ `localhost`, where a *moving* demonstration adds value over a screenshot. For a
32
+ CLI, a curl-able API, or pure pass/fail evidence, use `qa-test`/`verify`. For
33
+ static screenshot evidence, use `browser-qa`. Don't record a video you don't
34
+ need.
35
+
36
+ ## FIRST — probe for a browser
37
+
38
+ The browser driver lives in the **browser-qa** skill bundle at
39
+ `<browser-qa-dir>/scripts/agent-browser.mjs`, and this skill's compositor at
40
+ `<demo-dir>/scripts/compose-demo.sh`. Resolve both `<…-dir>` paths from the
41
+ available-skills catalogue (it gives each skill's absolute staged path); do not
42
+ assume a relative path from `$PWD` — your cwd is the checked-out repo, the
43
+ bundles are siblings.
44
+
45
+ Run the runtime probe before anything else:
46
+
47
+ ```bash
48
+ node <browser-qa-dir>/scripts/agent-browser.mjs doctor
49
+ ```
50
+
51
+ - Exit 0 with `{"ok":true,...}` → proceed.
52
+ - Exit non-zero (lean image / gondolin / no Chromium) → **DO NOT attempt a demo.**
53
+ Report that the demo path was unavailable on this host and stop. (The workflow
54
+ gates this phase to the QA image, so this should be rare — but never fake a
55
+ recording.)
56
+
57
+ ## Understand what to prove
58
+
59
+ Read the PR (description, diff, linked issue) from the context the prompt gives
60
+ you. For each change, ask: *what could a viewer confuse this with?* Design the
61
+ demo so the viewer sees something that **only happens if the feature works as
62
+ claimed** — both states (before/after, input/result) must appear on screen.
63
+
64
+ State your **commitments** up front, then honour them:
65
+
66
+ - **Layout** — `single` (default: a new feature, a fix proof, a walkthrough) or
67
+ `side-by-side` (only when the story is fundamentally a comparison: regression
68
+ fixed, behaviour-preserving refactor). Never fabricate a "before" to justify
69
+ side-by-side.
70
+ - **Speed** — target a watchable length; speed up dead time rather than leaving
71
+ it. 30–60s is a good single-feature target.
72
+
73
+ ## Build and run the app
74
+
75
+ Follow the **building** skill to install dependencies, then start the repo's
76
+ dev-server **in the background** and poll with `curl` until it answers on
77
+ `localhost:PORT`. Note the port — you pass it as `--base-url`.
78
+
79
+ ## Capture the session
80
+
81
+ Author a `flow.json` (same shape as **browser-qa**) that scripts the
82
+ interaction as a *director*, not an operator:
83
+
84
+ - **Record the baseline first** — the starting state is act one.
85
+ - **Hold after state changes** — add a `waitFor`/short pause so text is readable.
86
+ - **Verify between steps** — `waitFor` the expected element before the next
87
+ action; don't blindly fire keys into an unsettled page.
88
+
89
+ Record the session by passing `--record-dir`:
90
+
91
+ ```bash
92
+ node <browser-qa-dir>/scripts/agent-browser.mjs run flow.json \
93
+ --base-url http://localhost:PORT \
94
+ --record-dir /tmp/demo-cap
95
+ # → writes /tmp/demo-cap/session.webm, reports {"video":"…/session.webm", …}
96
+ ```
97
+
98
+ Pick the viewport to match the layout so the clip isn't letterboxed:
99
+ `1280x720` for `single`; `~960x1000` per panel for `side-by-side` (set it in the
100
+ flow's `viewport`).
101
+
102
+ **Before/after comparison:** check out and run each branch in turn (the
103
+ `building` skill), recording the **same** scripted interaction against each —
104
+ `session-before.webm` (base branch) and `session-after.webm` (PR head). Only the
105
+ behaviour should differ.
106
+
107
+ ## Compose the video
108
+
109
+ Composite the raw recording(s) into the final mp4 with the bundled wrapper:
110
+
111
+ ```bash
112
+ # Single walkthrough
113
+ <demo-dir>/scripts/compose-demo.sh \
114
+ --output <artifact-dir>/demo.mp4 \
115
+ --title "PR #42 — Add dark mode toggle" \
116
+ --subtitle "Toggling persists the theme across reloads" \
117
+ --layout single --speed 1.5 --target-size-mb 5 \
118
+ /tmp/demo-cap/session.webm
119
+
120
+ # Before/after comparison
121
+ <demo-dir>/scripts/compose-demo.sh \
122
+ --output <artifact-dir>/demo.mp4 \
123
+ --title "PR #51 — Fix flicker on load" \
124
+ --layout side-by-side --labels "BEFORE (main)" "AFTER (PR)" \
125
+ --target-size-mb 5 \
126
+ /tmp/before/session-before.webm /tmp/after/session-after.webm
127
+ ```
128
+
129
+ Flags: `--title` (required, on the card), `--subtitle`, `--layout
130
+ single|side-by-side`, `--labels A B` (side-by-side), `--speed N`, `--trim
131
+ START:END` (seconds, single layout), `--target-size-mb` (default 5),
132
+ `--width/--height` (default 1280×720), `--title-secs`. The script normalizes,
133
+ lays out, adds the title card, and does a **two-pass** encode to land under the
134
+ size cap (`+faststart`, `yuv420p`). It prints a JSON summary line:
135
+ `{"output":"…","resolution":"1280x720","duration":"38.4","size_mb":3.1}`.
136
+
137
+ ## Guardrails — self-check before reporting
138
+
139
+ Confirm the output with `ffprobe` (the script's summary already reports these):
140
+
141
+ - **Resolution** matches the requested size (default 1920-free 1280×720).
142
+ - **Duration** is sane — not 0s, within a watchable band (~15–90s).
143
+ - **Size ≤ 5 MB** so GitHub embeds it inline (25 MB hard limit). If over, re-run
144
+ with a lower `--target-size-mb` or a higher `--speed`.
145
+
146
+ If the recording is too short to be meaningful (a couple of seconds), go back
147
+ and add interaction steps — don't ship a clip that proves nothing.
148
+
149
+ ## Output location
150
+
151
+ Write `demo.mp4` into the **artifact directory the prompt provides** (the run's
152
+ `.lastlight/<issueKey>/` dir, referenced by the template variable the prompt
153
+ passes). The harness harvests it into the dashboard Artifacts view, and the
154
+ public artifact URL makes it playable inline on GitHub. Do **not** commit the
155
+ mp4 into the repo, and do **not** post it yourself — the workflow embeds it.
156
+
157
+ Video delivery requires **server-mode build-assets**. If the mp4 can't be
158
+ persisted (no artifact dir provided, or repo-mode), say so in the report and
159
+ describe what the demo showed instead.
160
+
161
+ ## Evidence rules
162
+
163
+ Mirror `verify`/`browser-qa` — you are demonstrating real behaviour, not selling
164
+ it:
165
+
166
+ - **Never fake it.** Don't edit the code under test to force a nicer demo, and
167
+ don't stage a result the feature didn't actually produce.
168
+ - **Show the disambiguating moment** — the thing that only happens if the change
169
+ works. Off-camera claims don't count.
170
+ - If something doesn't work, the honest demo shows that — report it; don't trim
171
+ the failure out and call it a success.
172
+
173
+ ## Report
174
+
175
+ Produce your report as your **final message** — the workflow posts it (don't
176
+ comment yourself). Keep it short:
177
+
178
+ ```
179
+ ## Demo: <target>
180
+
181
+ **Environment:** <branch / commit, package manager, how served, Chromium version>
182
+
183
+ <one or two sentences: what the video demonstrates and the key moment to watch>
184
+
185
+ - **Layout:** single | side-by-side
186
+ - **Video:** demo.mp4 (<resolution>, <duration>s, <size>MB)
187
+
188
+ ### Not covered
189
+ <one line: anything the demo doesn't show, and why>
190
+ ```
191
+
192
+ The workflow embeds the playable video from the artifact store; reference it as
193
+ `demo.mp4`. If the browser or compositor was unavailable, say so plainly instead
194
+ of pretending a clip exists.
@@ -0,0 +1,205 @@
1
+ #!/usr/bin/env bash
2
+ # compose-demo.sh — composite a raw browser screen recording into a titled,
3
+ # size-capped demo mp4 using ffmpeg only (NO Remotion, NO headless render).
4
+ #
5
+ # Used by the `/demo` workflow: agent-browser records the session to a .webm,
6
+ # this script turns it into a polished, GitHub-embeddable mp4.
7
+ #
8
+ # Usage:
9
+ # compose-demo.sh --output demo.mp4 --title "PR #42 — Add dark mode" \
10
+ # [--subtitle "..."] [--layout single|side-by-side] \
11
+ # [--labels "BEFORE (main)" "AFTER (PR)"] [--speed 1.5] \
12
+ # [--trim START:END] [--target-size-mb 5] [--width 1280] [--height 720] \
13
+ # [--title-secs 2.5] <clip1.webm> [clip2.webm]
14
+ #
15
+ # What it does:
16
+ # 1. Normalizes each input clip (optional trim, speed-up, scale+pad to the
17
+ # panel size, fps/pixfmt/SAR normalize, optional per-panel label).
18
+ # 2. Lays out the body: a single panel, or two panels side-by-side (hstack).
19
+ # 3. Prepends a title/subtitle card (solid bg + drawtext).
20
+ # 4. Two-pass H.264 encode targeting --target-size-mb so the mp4 lands under
21
+ # GitHub's inline-embed limit; yuv420p + +faststart for web streaming.
22
+ # 5. Prints an ffprobe summary (resolution / duration / size).
23
+ #
24
+ # Prerequisites: ffmpeg, ffprobe (baked into lastlight-sandbox-qa:latest).
25
+ # Runs fully offline.
26
+
27
+ set -euo pipefail
28
+
29
+ die() { echo "compose-demo.sh: error: $*" >&2; exit 1; }
30
+ require_cmd() { command -v "$1" >/dev/null 2>&1 || die "required command not found: $1"; }
31
+ require_cmd ffmpeg
32
+ require_cmd ffprobe
33
+
34
+ # ── Defaults ────────────────────────────────────────────────────────────────
35
+ OUTPUT=""
36
+ TITLE=""
37
+ SUBTITLE=""
38
+ LAYOUT="single"
39
+ LABEL1=""
40
+ LABEL2=""
41
+ SPEED="1"
42
+ TRIM=""
43
+ TARGET_MB="5"
44
+ WIDTH="1280"
45
+ HEIGHT="720"
46
+ TITLE_SECS="2.5"
47
+ CLIPS=()
48
+
49
+ # ── Parse args ──────────────────────────────────────────────────────────────
50
+ while [[ $# -gt 0 ]]; do
51
+ case "$1" in
52
+ --output) OUTPUT="$2"; shift 2;;
53
+ --title) TITLE="$2"; shift 2;;
54
+ --subtitle) SUBTITLE="$2"; shift 2;;
55
+ --layout) LAYOUT="$2"; shift 2;;
56
+ --labels) LABEL1="$2"; LABEL2="$3"; shift 3;;
57
+ --speed) SPEED="$2"; shift 2;;
58
+ --trim) TRIM="$2"; shift 2;;
59
+ --target-size-mb) TARGET_MB="$2"; shift 2;;
60
+ --width) WIDTH="$2"; shift 2;;
61
+ --height) HEIGHT="$2"; shift 2;;
62
+ --title-secs) TITLE_SECS="$2"; shift 2;;
63
+ -*) die "unknown flag: $1";;
64
+ *) CLIPS+=("$1"); shift;;
65
+ esac
66
+ done
67
+
68
+ [[ -n "$OUTPUT" ]] || die "--output is required"
69
+ [[ ${#CLIPS[@]} -ge 1 ]] || die "at least one input clip is required"
70
+ for c in "${CLIPS[@]}"; do [[ -f "$c" ]] || die "clip not found: $c"; done
71
+ if [[ "$LAYOUT" == "side-by-side" ]]; then
72
+ [[ ${#CLIPS[@]} -ge 2 ]] || die "side-by-side layout needs two clips"
73
+ fi
74
+
75
+ WORK="$(mktemp -d "${TMPDIR:-/tmp}/compose-demo-XXXXXX")"
76
+ cleanup() { rm -rf "$WORK"; }
77
+ trap cleanup EXIT
78
+
79
+ # ── Font for drawtext ────────────────────────────────────────────────────────
80
+ # Prefer an explicit fontfile (Liberation ships in the QA image via
81
+ # fonts-liberation); fall back to fontconfig's default Sans family.
82
+ FONT="${DEMO_FONT:-}"
83
+ if [[ -z "$FONT" ]]; then
84
+ for f in \
85
+ /usr/share/fonts/truetype/liberation/LiberationSans-Regular.ttf \
86
+ /usr/share/fonts/truetype/dejavu/DejaVuSans.ttf; do
87
+ [[ -f "$f" ]] && FONT="$f" && break
88
+ done
89
+ fi
90
+ if [[ -n "$FONT" ]]; then FONTARG="fontfile=${FONT}"; else FONTARG="font=Sans"; fi
91
+
92
+ # drawtext drives the title card and per-panel labels. The Debian `ffmpeg`
93
+ # package (the QA image) is built with libfreetype so it's present; but degrade
94
+ # gracefully on a build without it (omit text overlays) rather than failing the
95
+ # whole compose — the demo video is still worth shipping.
96
+ HAS_DRAWTEXT=0
97
+ if ffmpeg -hide_banner -filters 2>/dev/null | grep -q 'drawtext'; then
98
+ HAS_DRAWTEXT=1
99
+ else
100
+ echo "compose-demo.sh: warning: this ffmpeg lacks the drawtext filter — title card and labels omitted." >&2
101
+ fi
102
+
103
+ # Panel size: side-by-side splits the width into two equal panels.
104
+ PH="$HEIGHT"
105
+ if [[ "$LAYOUT" == "side-by-side" ]]; then PW=$(( WIDTH / 2 )); else PW="$WIDTH"; fi
106
+
107
+ # ── Stage A: normalize one clip into a body panel ─────────────────────────────
108
+ # Args: <input> <outfile> <label-file-or-empty> <apply-trim:0|1>
109
+ build_panel() {
110
+ local input="$1" outfile="$2" labelfile="$3" apply_trim="$4"
111
+ local trim_args=()
112
+ if [[ "$apply_trim" == "1" && -n "$TRIM" ]]; then
113
+ local start="${TRIM%%:*}" end="${TRIM##*:}"
114
+ [[ -n "$start" ]] && trim_args+=(-ss "$start")
115
+ [[ -n "$end" ]] && trim_args+=(-to "$end")
116
+ fi
117
+ local vf="setpts=PTS/${SPEED}"
118
+ vf+=",scale=${PW}:${PH}:force_original_aspect_ratio=decrease"
119
+ vf+=",pad=${PW}:${PH}:(ow-iw)/2:(oh-ih)/2:color=black"
120
+ vf+=",fps=30,format=yuv420p,setsar=1"
121
+ if [[ -n "$labelfile" && "$HAS_DRAWTEXT" == "1" ]]; then
122
+ vf+=",drawtext=${FONTARG}:textfile=${labelfile}:x=(w-text_w)/2:y=h-th-24"
123
+ vf+=":fontsize=26:fontcolor=white:box=1:boxcolor=black@0.55:boxborderw=12"
124
+ fi
125
+ # `${arr[@]+"${arr[@]}"}` expands to nothing when the array is empty without
126
+ # tripping `set -u` (an empty `"${arr[@]}"` errors on bash < 4.4, e.g. macOS).
127
+ ffmpeg -y -loglevel error ${trim_args[@]+"${trim_args[@]}"} -i "$input" \
128
+ -vf "$vf" -an -c:v libx264 -crf 20 -preset veryfast "$outfile"
129
+ }
130
+
131
+ # Per-panel labels (side-by-side) written to files to avoid drawtext escaping.
132
+ LABELFILE1=""; LABELFILE2=""
133
+ if [[ "$LAYOUT" == "side-by-side" ]]; then
134
+ if [[ -n "$LABEL1" ]]; then LABELFILE1="$WORK/label1.txt"; printf '%s' "$LABEL1" > "$LABELFILE1"; fi
135
+ if [[ -n "$LABEL2" ]]; then LABELFILE2="$WORK/label2.txt"; printf '%s' "$LABEL2" > "$LABELFILE2"; fi
136
+ fi
137
+
138
+ echo "compose-demo.sh: normalizing clips (layout=$LAYOUT, speed=${SPEED}x)…" >&2
139
+ build_panel "${CLIPS[0]}" "$WORK/panel0.mp4" "$LABELFILE1" 1
140
+ BODY="$WORK/body.mp4"
141
+ if [[ "$LAYOUT" == "side-by-side" ]]; then
142
+ build_panel "${CLIPS[1]}" "$WORK/panel1.mp4" "$LABELFILE2" 1
143
+ ffmpeg -y -loglevel error -i "$WORK/panel0.mp4" -i "$WORK/panel1.mp4" \
144
+ -filter_complex "[0:v][1:v]hstack=inputs=2,format=yuv420p,setsar=1[v]" \
145
+ -map "[v]" -an -c:v libx264 -crf 20 -preset veryfast "$BODY"
146
+ else
147
+ BODY="$WORK/panel0.mp4"
148
+ fi
149
+
150
+ # ── Stage B: title card (skipped when drawtext is unavailable) ───────────────
151
+ TITLE_CLIP=""
152
+ TITLE_DUR="0"
153
+ if [[ "$HAS_DRAWTEXT" == "1" ]]; then
154
+ TITLEFILE="$WORK/title.txt"; printf '%s' "${TITLE:-Demo}" > "$TITLEFILE"
155
+ TITLE_VF="drawtext=${FONTARG}:textfile=${TITLEFILE}:x=(w-text_w)/2:y=(h/2)-th-10:fontsize=48:fontcolor=white"
156
+ if [[ -n "$SUBTITLE" ]]; then
157
+ SUBFILE="$WORK/subtitle.txt"; printf '%s' "$SUBTITLE" > "$SUBFILE"
158
+ TITLE_VF+=",drawtext=${FONTARG}:textfile=${SUBFILE}:x=(w-text_w)/2:y=(h/2)+10:fontsize=26:fontcolor=0xb0b0b0"
159
+ fi
160
+ TITLE_VF+=",format=yuv420p"
161
+ ffmpeg -y -loglevel error -f lavfi -i "color=c=0x101418:s=${WIDTH}x${HEIGHT}:d=${TITLE_SECS}:r=30" \
162
+ -vf "$TITLE_VF" -c:v libx264 -crf 20 -preset veryfast "$WORK/title.mp4"
163
+ TITLE_CLIP="$WORK/title.mp4"
164
+ TITLE_DUR="$TITLE_SECS"
165
+ fi
166
+
167
+ # ── Stage C: (concat title +) body, two-pass size cap, faststart ─────────────
168
+ BODY_DUR="$(ffprobe -v error -show_entries format=duration -of csv=p=0 "$BODY" || echo 0)"
169
+ TOTAL_DUR="$(awk -v a="$TITLE_DUR" -v b="$BODY_DUR" 'BEGIN{printf "%.3f", a + b}')"
170
+ # Target video bitrate (kbit/s) = target_bytes * 8 / duration / 1000, with a
171
+ # small headroom factor for the muxer; floored so very short clips still encode.
172
+ BR_K="$(awk -v mb="$TARGET_MB" -v d="$TOTAL_DUR" 'BEGIN{
173
+ if (d <= 0) d = 1;
174
+ br = (mb * 1024 * 1024 * 8) / d / 1000 * 0.92;
175
+ if (br < 200) br = 200;
176
+ printf "%d", br;
177
+ }')"
178
+
179
+ # With a title card: concat it ahead of the body. Without: pass the body
180
+ # through (`null`) so the same two-pass/faststart encode applies either way.
181
+ if [[ -n "$TITLE_CLIP" ]]; then
182
+ IN_ARGS=(-i "$TITLE_CLIP" -i "$BODY")
183
+ FILTER='[0:v][1:v]concat=n=2:v=1:a=0[v]'
184
+ else
185
+ IN_ARGS=(-i "$BODY")
186
+ FILTER='[0:v]null[v]'
187
+ fi
188
+ PASSLOG="$WORK/ff2pass"
189
+ echo "compose-demo.sh: encoding (${TOTAL_DUR}s, target ${TARGET_MB}MB → ${BR_K}kbit/s, two-pass)…" >&2
190
+ ffmpeg -y -loglevel error "${IN_ARGS[@]}" \
191
+ -filter_complex "$FILTER" -map "[v]" -an \
192
+ -c:v libx264 -b:v "${BR_K}k" -pass 1 -passlogfile "$PASSLOG" -preset medium -f mp4 /dev/null
193
+ ffmpeg -y -loglevel error "${IN_ARGS[@]}" \
194
+ -filter_complex "$FILTER" -map "[v]" -an \
195
+ -c:v libx264 -b:v "${BR_K}k" -pass 2 -passlogfile "$PASSLOG" -preset medium \
196
+ -pix_fmt yuv420p -movflags +faststart "$OUTPUT"
197
+
198
+ # ── Stage D: report ───────────────────────────────────────────────────────────
199
+ RES="$(ffprobe -v error -select_streams v:0 -show_entries stream=width,height -of csv=p=0:s=x "$OUTPUT" || echo '?')"
200
+ DUR="$(ffprobe -v error -show_entries format=duration -of csv=p=0 "$OUTPUT" || echo '?')"
201
+ BYTES="$(wc -c < "$OUTPUT" | tr -d ' ')"
202
+ MB="$(awk -v b="$BYTES" 'BEGIN{printf "%.2f", b/1024/1024}')"
203
+ echo "compose-demo.sh: wrote $OUTPUT (${RES}, ${DUR}s, ${MB}MB)" >&2
204
+ # Machine-readable line for the agent to parse.
205
+ echo "{\"output\":\"${OUTPUT}\",\"resolution\":\"${RES}\",\"duration\":\"${DUR}\",\"size_mb\":${MB}}"
@@ -0,0 +1,90 @@
1
+ ---
2
+ name: issue-answer
3
+ description: Answer a question directly — a sourced, neutral reply to an information/explanation/comparison request, from a GitHub issue or a Slack thread. Research repo docs and the web, output the answer, label `question` (GitHub only), leave open. Never write an agent brief, mark ready-for-agent, or change code.
4
+ version: 1.1.0
5
+ tags: [github, issues, questions]
6
+ ---
7
+
8
+ # Issue Answer
9
+
10
+ A user asked a **question** — they want information, an explanation, or a
11
+ comparison, not a code change. The router already decided this is a question;
12
+ your job is to **answer it well and stop**. Do not re-triage it into a work item.
13
+
14
+ The question reaches you from one of two places, and the prompt tells you which:
15
+ - a **GitHub issue** (an `issueNumber` is set), or
16
+ - a **Slack thread** (no `issueNumber`).
17
+
18
+ ## How your answer is delivered
19
+
20
+ Your **final message is the answer** — the harness posts it for you (as a
21
+ comment on the issue for GitHub-initiated runs, or into the Slack thread for
22
+ Slack-initiated runs). So:
23
+
24
+ - Make your final message the complete, self-contained answer in clean markdown.
25
+ - **Do NOT post the answer yourself** with `github_add_issue_comment` — the
26
+ harness delivers it, and posting it too would double-post.
27
+
28
+ ## Hard caps
29
+
30
+ This skill answers; it never queues work. Per invocation:
31
+
32
+ - Produce **one** answer (your final message).
33
+ - The only GitHub write you make is the `question` **label**, and only when
34
+ answering a GitHub issue.
35
+ - **Never** write an agent brief, apply `ready-for-agent` / `ready-for-human`,
36
+ create branches, push code, or open a PR.
37
+ - **Never** close the issue — leave it open for the human to close once the
38
+ answer satisfies them.
39
+
40
+ If, while reading, you conclude the request is actually a bug or feature request
41
+ (not a pure question), do **not** answer it as one. Make your final message a
42
+ short note saying it looks like work rather than a question and asking a
43
+ maintainer to `@last-light build` (or `explore`) it — let triage own work items.
44
+
45
+ ## Procedure
46
+
47
+ 1. **Understand the question.** Read the question from the prompt — the issue
48
+ title/body (and existing comments, for a GitHub issue) or the Slack message.
49
+ Identify exactly what the user wants to know.
50
+ 2. **Research.**
51
+ - **The repo** — read what's relevant to the answer: `CONTEXT.md`,
52
+ `README`, `docs/`, `spec/`, and code only as needed to ground claims about
53
+ this project. Don't survey the whole codebase; read what the question needs.
54
+ - **The web** — when the question references anything outside this repo
55
+ (another tool, framework, library, standard, or a "X vs Y" comparison),
56
+ use the `web_search` and `web_fetch` tools to consult current,
57
+ authoritative sources. Prefer official docs and primary sources.
58
+ - **Budget your research and converge.** You have a bounded number of tool
59
+ calls before the run ends — research is for grounding the answer, not
60
+ exhaustive coverage. Front-load the searches you need, then stop looking.
61
+ **Critical:** the moment you think *"I have enough"* (or *"let me just
62
+ confirm one more thing"*), do **not** fire another tool call — write the
63
+ answer **now**, in that same turn. Your reply being cut off mid-research
64
+ delivers a useless half-sentence to the user, which is worse than an
65
+ answer that omits a minor detail. If a fact is unverified, state it as
66
+ unverified in the answer rather than spending your last turn chasing it.
67
+ For broad/open-ended questions (e.g. "what's missing vs tool X"), gather a
68
+ representative sample and answer from it — explicitly noting it's a
69
+ sample, not an exhaustive audit — rather than enumerating everything.
70
+ 3. **Label (GitHub issue only).** Apply `question` with `github_add_labels`
71
+ (create it first with `github_create_label`, color `d876e3`; ignore a 422
72
+ "already exists"). If label creation/adding is denied, skip it — the answer
73
+ is the deliverable. For a Slack-initiated question there is no issue to label.
74
+ 4. **Write the answer as your final message** (the harness delivers it — see
75
+ above; do not post it yourself):
76
+ - Direct and structured. Lead with the answer; use short sections or a
77
+ comparison table when it helps.
78
+ - **Neutral and grounded.** Claims about this project come from its docs;
79
+ claims about external things are **cited** with links to the sources you
80
+ used. Don't invent pricing, capabilities, or roadmap.
81
+ - **Honest about uncertainty.** If something is fast-moving or you couldn't
82
+ verify it, say so rather than stating it as fact.
83
+ 5. **Stop.** The answer is the conversation; a human closes the issue when satisfied.
84
+
85
+ ## Tool usage
86
+
87
+ - GitHub operations via `github_*` MCP tools only — never `gh` CLI, `curl`, or
88
+ raw HTTP. In chat you have no GitHub write tools beyond labelling; that's
89
+ expected — the answer is delivered as your final message.
90
+ - External research via the `web_search` / `web_fetch` tools only.
@@ -1,33 +1,47 @@
1
1
  ---
2
2
  name: issue-comment
3
- description: Handle non-build maintainer comments on issues and PRs — close, label, answer questions, triage
4
- version: 1.0.0
3
+ description: Handle a non-build maintainer comment on an issue or PR — close, reopen, label, dedupe, answer a brief question, or triage. Action-only; redirect anything that needs code changes to /build.
4
+ version: 2.0.0
5
5
  tags: [github, issues, comments]
6
6
  ---
7
7
 
8
- # Issue Comment Skill
8
+ # Issue Comment
9
9
 
10
- ## When to Use
11
- When a maintainer @mentions last-light on an issue or PR with a request that is NOT asking for code changes. Examples: close an issue, add labels, answer a question, check for duplicates, provide status, triage.
10
+ A maintainer @mentioned the bot on an issue or PR with a request that is **not**
11
+ asking for code changes. Do the one bounded thing they asked, confirm it in one
12
+ short comment, and stop.
13
+
14
+ ## Hard caps
15
+
16
+ This skill is deliberately small. Per invocation: **at most 2 file reads and 1
17
+ outgoing comment.** Never make code changes, create branches, or push.
12
18
 
13
19
  ## Procedure
14
20
 
15
- 1. **Read the comment** carefully to understand what the maintainer is asking
16
- 2. **Read the issue/PR** context — title, body, existing labels, existing comments
17
- 3. **Execute the request**:
18
- - **Close/reopen**: Use `update_issue` to change state
19
- - **Label**: Use `add_labels` or `remove_label`
20
- - **Duplicate check**: Search for similar issues, comment with findings
21
- - **Answer/explain**: Read the relevant code and respond with a comment
22
- - **Triage**: Apply labels and priority based on the issue content
23
- - **Other**: Use best judgment — if unclear, comment asking for clarification
24
- 4. **Respond** with a brief comment confirming what was done
25
-
26
- ## Tool Usage
27
-
28
- **Always use MCP tools** (`mcp_github_*`) for all GitHub operations. Never use `gh` CLI, `curl`, or raw HTTP requests. The MCP server handles authentication.
29
-
30
- ## Pitfalls
31
- - NEVER make code changes, create branches, or push commits this is an action-only skill
32
- - Keep comments concise one short confirmation, not a wall of text
33
- - If the request actually needs code changes, comment suggesting the maintainer ask for a build instead
21
+ 1. **Read the request.** The triggering comment is the job read it, plus the
22
+ issue/PR title, body, existing labels, and existing comments for context.
23
+ 2. **Do the bounded action:**
24
+ - Close / reopen `github_update_issue`
25
+ - Label `github_add_labels` / `github_remove_label` (use the canonical
26
+ triage roles from `docs/agents/triage-labels.md` where relevant)
27
+ - Duplicate check search similar issues, link the original in one comment
28
+ - Answer a direct question ≤5 sentences, ≤2 file reads. Don't survey the
29
+ codebase or compile a report.
30
+ 3. **Confirm** in one short comment what you did. Done.
31
+
32
+ ## Redirect, don't comply
33
+
34
+ The classifier owns intent routing. If a request that needs *building* reached
35
+ you anyway, the correct response is to **redirect, not do it** — even if the
36
+ comment seems to greenlight the work, and even if the issue body describes a
37
+ task. An issue titled "Security Review" asking you to "find and fix issues" is a
38
+ build request: reply asking the maintainer to use `@last-light build` (or
39
+ `@last-light explore`). Do **not** run the audit yourself from this skill.
40
+
41
+ If the request is unclear or out of scope, post one short comment asking them to
42
+ clarify or to use the right command. Do nothing else.
43
+
44
+ ## Tool usage
45
+
46
+ GitHub operations via `github_*` MCP tools only — never `gh` CLI, `curl`, or raw
47
+ HTTP.