lastlight 0.1.8 → 0.2.0

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 +423 -437
  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 +31 -12
  272. package/dist/setup.js +516 -174
  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 -7
  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,213 @@
1
+ ---
2
+ name: security-review
3
+ description: Diff-scoped security review of SDLC concerns GitHub's scanners miss — workflow/CI hardening, auth changes, secret handling, supply-chain churn. Files one dated summary issue with a task-list of findings. Use on a security cron or when asked to scan a repo.
4
+ version: 2.0.0
5
+ tags: [github, security, review]
6
+ ---
7
+
8
+ # Security Review
9
+
10
+ Review **what changed in the repo since the last scan** with a security lens,
11
+ focused on SDLC concerns that GitHub's built-in scanners (Dependabot, Code
12
+ Scanning, Secret Scanning) and Renovate don't cover. File **one summary issue
13
+ per run**, dated, containing a GitHub task list of any findings. Honour
14
+ `SECURITY.md` to suppress accepted risks and false positives.
15
+
16
+ This is **not** a general vulnerability scanner. It does not run `npm audit`
17
+ (Dependabot does). It does not run `semgrep --config auto` over the whole tree
18
+ (Code Scanning does). It looks at the diff since the prior scan and surfaces what
19
+ humans introduced — CI hardening, auth changes, secret handling in new code,
20
+ supply-chain churn.
21
+
22
+ The summary issue's structure is the machine-parsed contract a maintainer's
23
+ later comment is processed against (the `security-feedback` skill). It is defined
24
+ in **[references/issue-format.md](references/issue-format.md)** — follow it
25
+ exactly when composing the issue (§9).
26
+
27
+ ## Context
28
+
29
+ - `context.repo` — `owner/name` to scan
30
+ - `context.deliverSlackSummary` — if true, output a one-line Slack summary as the final response
31
+ - `context.issueDir` — directory for the run summary file (e.g. `.lastlight/security-<date>`)
32
+
33
+ ## Procedure
34
+
35
+ ### 1. Clone, find the prior-scan anchor, read SECURITY.md
36
+
37
+ 1. Clone the target repo via `github_clone_repo`.
38
+ 2. **Prior scan anchor.** Query issues labelled `security-scan` (open OR closed),
39
+ newest first. Read the latest one's body for the
40
+ `<!-- lastlight-security-scan-ts: ... -->` comment and use that ISO-8601
41
+ timestamp as `priorScanTs`. No prior scan issue → `priorScanTs = now - 30 days`
42
+ (bootstrap floor — keeps the first run finite).
43
+ 3. Read `SECURITY.md` at the repo root (if present): per-tool severity floors
44
+ (default `medium`; skip `low`/`info`), the accepted-risks table, and the
45
+ false-positives table (both keyed by finding fingerprint).
46
+
47
+ ### 1.5. Compute the changeset
48
+
49
+ Most weeks the diff is dominated by Renovate/Dependabot churn — strip it so the
50
+ scope is what humans wrote.
51
+
52
+ 1. `git log --since="${priorScanTs}" --pretty=format:'%H|%an|%ae|%s'`.
53
+ 2. Drop a commit when **either**: author email matches
54
+ `*[bot]@users.noreply.github.com` and name is `dependabot[bot]` /
55
+ `renovate[bot]` / `github-actions[bot]`; OR the subject starts with
56
+ `chore(deps)`, `chore(deps-dev)`, `build(deps)`, `build(deps-dev)`, `fix(deps)`.
57
+ 3. Accumulate changed files from the surviving commits
58
+ (`git diff-tree --no-commit-id --name-only -r ${sha}`) into a deduped
59
+ `changedFiles` set.
60
+ 4. Drop entries that are **only** lockfiles (`package-lock.json`, `pnpm-lock.yaml`,
61
+ `yarn.lock`, `bun.lockb`, `Gemfile.lock`, `poetry.lock`, `uv.lock`,
62
+ `Cargo.lock`, `composer.lock`) — catches lockfile changes mixed into human commits.
63
+ 5. Build `commitsReviewed` = surviving commits as `{ shortSha, subject }` (used in the scope note).
64
+
65
+ **Early exit.** If `changedFiles` is empty after filtering, **stop**: run no
66
+ scanner, create no issue, emit no Slack message. Write the run summary file (§10)
67
+ recording "no relevant changes since prior scan" and return.
68
+
69
+ ### 2. Ensure labels exist
70
+
71
+ `github_create_label` for each (idempotent — ignore 422):
72
+
73
+ | Label | Color | Purpose |
74
+ |-------|-------|---------|
75
+ | `security` | `ee0701` | Any security-related issue |
76
+ | `security-scan` | `fbca04` | The per-run summary issue |
77
+ | `p0-critical` | `b60205` | Severity |
78
+ | `p1-high` | `d93f0b` | Severity |
79
+ | `p2-medium` | `fbca04` | Severity |
80
+ | `p3-low` | `0e8a16` | Severity |
81
+
82
+ ### 3. Run change-scoped scanners
83
+
84
+ Three sources, all narrowed to the changeset. Do **not** run `npm audit` or
85
+ `semgrep --config auto .` over the whole tree (covered elsewhere; the noise
86
+ drowns the signal).
87
+
88
+ - **Gitleaks (commit range):**
89
+ `gitleaks detect --source . --log-opts="--since=${priorScanTs}" --report-format json --report-path /tmp/gitleaks.json`
90
+ — secrets introduced in the new history.
91
+ - **Semgrep (changed files only):**
92
+ `semgrep --config auto --json $(printf -- '--include=%s ' "${changedFiles[@]}")`
93
+ — only files that changed; far less noise.
94
+ - **Claude SDLC review** — the unique value-add. Read `git diff ${priorScanTs}..HEAD`
95
+ plus the current contents of changed files against the checklist below. Each
96
+ match becomes a finding with `tool: "claude"` and the §4 severity.
97
+
98
+ - **GitHub Actions / CI** (`.github/workflows/*.yml`): actions pinned by
99
+ floating ref (`@main`/`@master`/`@v1`) not a commit SHA; `pull_request_target`
100
+ that checks out the PR head; missing top-level/job `permissions:` block;
101
+ `${{ secrets.* }}` interpolated into shell/`run:`/echo where it can land in
102
+ logs; untrusted PR body/title/branch interpolated into a `run:` block.
103
+ - **Dockerfile / compose**: base images on floating tags (no digest) introduced
104
+ here; new `RUN curl … | sh` / `wget … | bash`; new `--privileged`/`--cap-add`,
105
+ removed `security_opt`/`read_only` hardening; new host-exposed ports without need.
106
+ - **Auth / authorization**: modified middleware, route guards, role checks, CORS,
107
+ JWT verification, OAuth handlers, webhook signature verification (HMAC compare,
108
+ `crypto.timingSafeEqual` replaced with `===`).
109
+ - **Secret handling in new code**: new `process.env.*` reads whose value flows
110
+ into a log or HTTP response; new code logging Authorization headers/cookies/tokens;
111
+ hardcoded key/URL-shaped literals gitleaks missed.
112
+ - **Shell exec on attacker-influenced args**: new `execSync`/`exec`/`spawn` where
113
+ any argument is non-static (concatenation, interpolation, request-derived).
114
+ - **Supply-chain churn** (`package.json` diff): **new** top-level
115
+ `dependencies`/`devDependencies` entries (not version bumps — filtered at §1.5);
116
+ flag package name + publisher, higher severity for typosquat-shaped names;
117
+ removed integrity controls (`npm ci` → `npm install`, dropped `--ignore-scripts`
118
+ or provenance flags).
119
+ - **Release / publish flows**: changes to publish scripts, `npm publish`, release
120
+ CI steps, signing keys — anything touching what users download.
121
+
122
+ If the only changes are docs/tests/unrelated config and none of the above
123
+ applied, the run legitimately has **no findings** — proceed to §8.
124
+
125
+ ### 4. Normalize findings
126
+
127
+ Convert each to: `{ fingerprint, severity, tool, rule, file, line, title,
128
+ language, snippet, explanation, suggestedFix }`.
129
+
130
+ - `fingerprint` = `sha1(tool + ":" + rule + ":" + file + ":" + 3-line-context)`, lowercase hex.
131
+ - `severity` ∈ `p0-critical | p1-high | p2-medium | p3-low`.
132
+ - `tool` ∈ `npm-audit | semgrep | gitleaks | claude` (lowercase, hyphenated).
133
+ - `rule` = tool-native id, as-is. `file` = repo-relative, forward slashes.
134
+ - `line` = 1-based; `0` when not line-scoped. `title` = one line, no backticks/asterisks.
135
+
136
+ Severity mapping: npm-audit critical/high/moderate/low → p0/p1/p2/p3;
137
+ semgrep ERROR/WARNING/INFO → p1/p2/p3; gitleaks (all) → p1-high;
138
+ claude critical/high/medium/low → p0/p1/p2/p3.
139
+
140
+ ### 5. Apply severity floor
141
+
142
+ Drop findings below the SECURITY.md floor (default `medium` → drops `p3-low`).
143
+
144
+ ### 6. Filter accepted risks / false positives
145
+
146
+ Drop findings whose fingerprint prefix (first 16 hex chars) appears in the
147
+ SECURITY.md accepted-risks or false-positives tables.
148
+
149
+ ### 7. Sort and cap
150
+
151
+ Sort by `(severity rank p0<p1<p2<p3, then file asc, then line asc)`.
152
+
153
+ The issue body has a hard 65,536-char GitHub limit. Cap: keep **ALL** `p0-critical`
154
+ and **ALL** `p1-high`; keep at most **10** of `p2-medium`+`p3-low` combined (the
155
+ first 10 after the sort). Assign 1-based `item` numbers top-to-bottom across the
156
+ **kept** findings. `overflow` = survived-filtering minus kept; surface it in the
157
+ overflow note.
158
+
159
+ The cap intentionally puts no ceiling on critical/high — if a misconfigured
160
+ scanner emits hundreds of highs and the body still overflows, raise the
161
+ `SECURITY.md` floor or tune the scanner's rule severities (fix at the source, not
162
+ by hiding real findings).
163
+
164
+ ### 8. Early exit: no findings
165
+
166
+ If the filtered-and-capped list is empty, **do not** create the summary issue.
167
+ Write the run summary file (§10) recording why and return **silently** — no Slack
168
+ message. The cron is intentionally low-noise: only actual findings surface.
169
+
170
+ ### 9. Compose and create the summary issue
171
+
172
+ Render the body per [references/issue-format.md](references/issue-format.md) and
173
+ `github_create_issue` with `title: Security scan — {YYYY-MM-DD}` (UTC),
174
+ `labels: ["security", "security-scan"]`. Record `summaryIssueNumber`. Do **not**
175
+ touch prior `security-scan` issues — each scan is a point-in-time snapshot.
176
+
177
+ ### 10. Write the run summary file
178
+
179
+ Write `{issueDir}/security-summary.md`:
180
+
181
+ ```markdown
182
+ # Security Scan Summary — {repo}
183
+
184
+ **Date**: {YYYY-MM-DD}
185
+ **Prior scan anchor**: {priorScanTs} (issue #{priorScanIssueNumber} or "bootstrap floor")
186
+ **Commits reviewed**: {N} (after filtering Renovate/Dependabot/lockfile-only)
187
+ **Changed files**: {nFiles}
188
+ **Summary issue**: #{summaryIssueNumber} (or "none — no findings")
189
+
190
+ **Scanner raw counts**: gitleaks: {n}, semgrep: {n}, claude: {n}
191
+ **After severity floor**: {n}
192
+ **After SECURITY.md filtering**: {n} (filed)
193
+ **Suppressed**: {n} (accepted: {nA}, false-positive: {nFP})
194
+ {if overflow > 0}: **Overflow**: {overflow} lower-severity findings omitted (cap: ALL critical/high + first 10 medium/low)
195
+ ```
196
+
197
+ On a §1.5 early exit, still write the file and state `**Early exit**: no human
198
+ commits since prior scan`.
199
+
200
+ ### 11. Slack summary (optional)
201
+
202
+ If `context.deliverSlackSummary` is true, output as the final response:
203
+
204
+ - **With findings:**
205
+ ```
206
+ *Security scan: {repo}* — {n} findings filed in #{summaryIssueNumber} ({N} commits since {priorScanDate})
207
+ Critical: {nC} · High: {nH} · Medium: {nM} · Low: {nL}
208
+ ```
209
+ - **No findings** (scanners ran clean) or **§1.5 early exit** → emit nothing;
210
+ silence matches the cron's low-noise design. The run summary file still records
211
+ what was reviewed.
212
+
213
+ Otherwise output the run summary file contents as the final response.
@@ -0,0 +1,302 @@
1
+ # § Issue format
2
+
3
+ This is the **contract** between `security-review` (producer) and
4
+ `security-feedback` (consumer). Every rule here is machine-parsed; do not
5
+ deviate. `security-feedback` is staged into a separate workspace and cannot read
6
+ this file, so it keeps its own copy of the row/severity grammar — **if you change
7
+ the grammar here, update `skills/security-feedback/SKILL.md` in lockstep.**
8
+
9
+ ## Title
10
+
11
+ ```
12
+ Security scan — YYYY-MM-DD
13
+ ```
14
+
15
+ - Exactly one em-dash (` — `, U+2014), surrounded by single spaces.
16
+ - Date is the scan's UTC date in ISO form.
17
+ - Same-day re-scans produce a second issue with the same title. GitHub disambiguates by issue number; the scanner never edits a prior-run issue.
18
+
19
+ ## Body
20
+
21
+ The body is assembled from eight blocks, in this exact order, separated by blank lines:
22
+
23
+ ```
24
+ {header comments}
25
+
26
+ {intro paragraph}
27
+
28
+ {how-to-respond section}
29
+
30
+ {summary table}
31
+
32
+ {suppression note}
33
+
34
+ {scope note}
35
+
36
+ {overflow note — omitted when overflow == 0}
37
+
38
+ {findings sections}
39
+ ```
40
+
41
+ ### Block 1 — header comments
42
+
43
+ Three HTML comments, each on its own line, in this exact order:
44
+
45
+ ```
46
+ <!-- lastlight-security-scan-version: 1 -->
47
+ <!-- lastlight-security-scan-date: YYYY-MM-DD -->
48
+ <!-- lastlight-security-scan-ts: YYYY-MM-DDTHH:MM:SSZ -->
49
+ ```
50
+
51
+ - `version` is a format version. Bump if the structure changes incompatibly — `security-feedback` will check this and refuse to parse unknown versions.
52
+ - `date` matches the title.
53
+ - `ts` is an ISO-8601 UTC timestamp with second precision (no milliseconds).
54
+
55
+ ### Block 2 — intro paragraph
56
+
57
+ Exactly one paragraph, with the commit count and short-SHA range substituted:
58
+
59
+ ```
60
+ Reviewing {N} commits since {priorScanDate} ({firstShortSha}..{lastShortSha}). Findings here focus on SDLC and workflow changes — Dependabot, GitHub Code Scanning, and Renovate handle the rest. Tick the box once the underlying issue is resolved or recorded in `SECURITY.md`.
61
+ ```
62
+
63
+ `{N}` is the size of `commitsReviewed`. `{priorScanDate}` is the YYYY-MM-DD of the prior scan (or the bootstrap floor). When `N == 1`, both short SHAs are the same — render as `({onlyShortSha})` rather than `({sha}..{sha})`.
64
+
65
+ ### Block 3 — how-to-respond section
66
+
67
+ Verbatim, including the heading:
68
+
69
+ ```
70
+ ## How to respond
71
+
72
+ **Preferred flow** — tick the boxes on the findings you want broken out, then comment:
73
+
74
+ - `@last-light create issues` — files one issue per **ticked** finding (default)
75
+
76
+ **Other shortcuts:**
77
+
78
+ - `@last-light create issues for the criticals` — every Critical finding (ticked or not)
79
+ - `@last-light create issues for the highs` — same, for High
80
+ - `@last-light create issues for items 1, 3, 5` — specific items by number (1-based, top to bottom)
81
+ - `@last-light create issues for all` — every finding in this scan
82
+ - `@last-light accept-risk for item N: <reason>` — suppress this finding in future scans
83
+ - `@last-light false-positive for item N: <reason>` — suppress this finding in future scans
84
+ - Comment freely to ask questions or discuss
85
+ ```
86
+
87
+ (Item positions in commands map to the `item:N` HTML-comment markers defined below. Ticking a box in GitHub's UI rewrites the row from `[ ]` to `[x]` — the feedback skill treats that as your selection.)
88
+
89
+ ### Block 4 — summary table
90
+
91
+ Verbatim header, with numbers substituted. Always include all four severity rows, even when the count is 0.
92
+
93
+ `{nC}`, `{nH}`, `{nM}`, `{nL}` and `{nTotal}` are **TRUE counts** (post-filtering, pre-cap) — i.e. how many findings of each severity actually survived the SECURITY.md filtering, regardless of whether each individual row is listed below the cap. The same numbers appear in the `### 🔴 Critical ({nC})` etc. section headers. The overflow note (Block 6) communicates how many of those counts were truncated from the listed rows.
94
+
95
+ ```
96
+ ## Summary
97
+
98
+ | Severity | Count |
99
+ |----------|------:|
100
+ | Critical | {nC} |
101
+ | High | {nH} |
102
+ | Medium | {nM} |
103
+ | Low | {nL} |
104
+ | **Total**| **{nTotal}** |
105
+ ```
106
+
107
+ ### Block 5 — suppression note
108
+
109
+ A single line:
110
+
111
+ ```
112
+ Suppressed by `SECURITY.md`: {nSuppressed} (accepted: {nA}, false-positives: {nFP}). Below severity floor: {nFloor}.
113
+ ```
114
+
115
+ Set each count to 0 when N/A. Emit the line unconditionally so the structure is stable.
116
+
117
+ ### Block 6 — scope note
118
+
119
+ Always emit, immediately after the suppression note. Lists the human (non-bot) commits actually reviewed, so a maintainer can see what diff produced these findings:
120
+
121
+ ```
122
+ > Commits reviewed: {short-sha-1} {subject-1}, {short-sha-2} {subject-2}, …
123
+ ```
124
+
125
+ Cap at 10 entries; if there are more, append ` +{N} more` after the last item. Subjects are truncated to 60 chars with `…` if longer. Renovate/Dependabot commits are filtered out at § 1.5 and never appear here.
126
+
127
+ ### Block 7 — overflow note
128
+
129
+ Emit **only** when `overflow > 0`:
130
+
131
+ ```
132
+ > **Note** — {overflow} lower-severity findings are not listed here. The cap is: ALL critical and high, plus the first 10 medium/low (after sort). Tighten `SECURITY.md` severity floors or break out items from this scan, then re-run to surface the rest.
133
+ ```
134
+
135
+ ### Block 8 — findings sections
136
+
137
+ Four sections, in this **exact order** (Critical → High → Medium → Low). Always emit all four headers, even when a section has zero findings — the feedback skill relies on stable anchors.
138
+
139
+ The header counts (`{nC}` etc.) are the **true** post-filter counts, identical to those in Block 4's summary table. The rows listed under each header are subject to the § 7 cap: critical and high are always complete; medium + low are truncated to the first 10 combined. When a section is partially listed, append `(showing first N of {nM})` after the marker — see the per-section header rule below.
140
+
141
+ ```
142
+ ## Findings
143
+
144
+ ### 🔴 Critical ({nC})
145
+
146
+ {rows or "_No findings._"}
147
+
148
+ ### 🟠 High ({nH})
149
+
150
+ {rows or "_No findings._"}
151
+
152
+ ### 🟡 Medium ({nM}){if truncated: " (showing first {kM} of {nM})"}
153
+
154
+ {rows or "_No findings._"}
155
+
156
+ ### 🟢 Low ({nL}){if truncated: " (showing first {kL} of {nL})"}
157
+
158
+ {rows or "_No findings._"}
159
+ ```
160
+
161
+ Where `kM` and `kL` are the actual rows listed in this issue (sum of the two ≤ 10). When `kM == nM` or `kL == nL` (no truncation in that section), omit the parenthetical.
162
+
163
+ ### Finding-row grammar
164
+
165
+ Every finding is exactly two lines: a task-list row, then a `<details>` block (one blank line between rows within a section).
166
+
167
+ The task-list row is **one physical line** with this exact shape:
168
+
169
+ ```
170
+ - [ ] <!-- item:N fp:FINGERPRINT --> **TITLE** — `FILE:LINE` (TOOL · `RULE`)
171
+ ```
172
+
173
+ Matched by this canonical regex (multiline, case-sensitive) — covers all three row states:
174
+
175
+ ```
176
+ /^- \[([ x])\] <!-- item:(\d+) fp:([0-9a-f]{8,}) --> (?:~~)?\*\*(.+?)\*\* — `([^`]+):(\d+)` \(([a-z][a-z0-9-]*) · `([^`]+)`\)(?:~~ → #(\d+))?$/m
177
+ ```
178
+
179
+ Capture groups, in order:
180
+
181
+ 1. `checkbox` — `" "` (unticked) or `"x"` (ticked or broken-out)
182
+ 2. `itemNumber` (1-based across all severities)
183
+ 3. `fingerprint` (lowercase hex, ≥ 8 chars)
184
+ 4. `title` (plain text; no backticks, no asterisks)
185
+ 5. `file` (no backticks, forward-slash path)
186
+ 6. `line` (integer; use `0` when not line-scoped)
187
+ 7. `tool` (lowercase, hyphenated — e.g. `npm-audit`, `semgrep`, `gitleaks`, `claude`)
188
+ 8. `rule` (the tool's native rule id; may contain dots, hyphens)
189
+ 9. `subIssueNumber` — present **only** when the row has been broken out to a sub-issue; `undefined` otherwise
190
+
191
+ Derived state (the feedback skill computes these from the captures):
192
+
193
+ | State | Written as | `checkbox` | `subIssueNumber` |
194
+ |-------|------------|------------|------------------|
195
+ | **pending** | `- [ ] <!-- item:N fp:FP --> **TITLE** — …` | `" "` | `undefined` |
196
+ | **user-ticked** (maintainer clicked the box in GitHub's UI) | `- [x] <!-- item:N fp:FP --> **TITLE** — …` | `"x"` | `undefined` |
197
+ | **broken-out** (feedback skill created a sub-issue) | `- [x] <!-- item:N fp:FP --> ~~**TITLE** — …~~ → #SUBISSUE` | `"x"` | the sub-issue number |
198
+
199
+ Rules:
200
+
201
+ - `alreadyBrokenOut` ≡ `subIssueNumber != null`. Broken-out rows are immutable — the feedback skill never re-opens them, never touches their checkbox, never re-creates sub-issues from them.
202
+ - `userTicked` ≡ `checkbox === "x" && subIssueNumber == null`. These are the candidates the default `@last-light create issues` command selects.
203
+ - When creating sub-issues from ticked rows, the feedback skill transitions each row from **user-ticked** → **broken-out** by wrapping the visible text in `~~…~~` and appending ` → #{subIssueNumber}`. The checkbox stays `[x]`; the strikethrough + link is the canonical broken-out marker.
204
+ - Un-ticking (moving a user-ticked row back to `[ ]`) is fine — the row just becomes pending again. The scanner doesn't police this.
205
+
206
+ The per-finding detail block follows immediately on the next line:
207
+
208
+ ````
209
+ <details><summary>Details</summary>
210
+
211
+ ```{LANGUAGE}
212
+ {SNIPPET}
213
+ ```
214
+
215
+ {EXPLANATION}
216
+
217
+ **Suggested fix:** {SUGGESTED_FIX}
218
+
219
+ </details>
220
+ ````
221
+
222
+ Rules:
223
+ - `LANGUAGE` is the fenced-code language tag; empty string when unknown.
224
+ - `SNIPPET` is the code excerpt; no surrounding fences, no trailing blank line inside the fence.
225
+ - `EXPLANATION` and `SUGGESTED_FIX` are markdown strings; they may contain their own fenced code blocks and line breaks.
226
+ - The `<details>` block ends with `</details>` on its own line.
227
+
228
+ ## Worked example
229
+
230
+ A scan with 1 critical + 1 high finding renders like:
231
+
232
+ ````markdown
233
+ <!-- lastlight-security-scan-version: 1 -->
234
+ <!-- lastlight-security-scan-date: 2026-04-21 -->
235
+ <!-- lastlight-security-scan-ts: 2026-04-21T10:00:00Z -->
236
+
237
+ Reviewing 3 commits since 2026-04-14 (a1b2c3d..f9e8d7c). Findings here focus on SDLC and workflow changes — Dependabot, GitHub Code Scanning, and Renovate handle the rest. Tick the box once the underlying issue is resolved or recorded in `SECURITY.md`.
238
+
239
+ ## How to respond
240
+
241
+ - `@last-light create issues for the criticals` — file individual issues for every Critical finding
242
+ - `@last-light create issues for the highs` — same, for High
243
+ - `@last-light create issues for items 1, 3, 5` — file issues for specific items by number (1-based, top to bottom)
244
+ - `@last-light create issues for all` — every finding in this scan
245
+ - `@last-light accept-risk for item N: <reason>` — suppress this finding in future scans
246
+ - `@last-light false-positive for item N: <reason>` — suppress this finding in future scans
247
+ - Comment freely to ask questions or discuss
248
+
249
+ ## Summary
250
+
251
+ | Severity | Count |
252
+ |----------|------:|
253
+ | Critical | 1 |
254
+ | High | 1 |
255
+ | Medium | 0 |
256
+ | Low | 0 |
257
+ | **Total**| **2** |
258
+
259
+ Suppressed by `SECURITY.md`: 0 (accepted: 0, false-positives: 0). Below severity floor: 0.
260
+
261
+ > Commits reviewed: a1b2c3d wire user-supplied repo into git clone, e5f6a7b add admin shell endpoint, f9e8d7c rotate webhook secret
262
+
263
+ ## Findings
264
+
265
+ ### 🔴 Critical (1)
266
+
267
+ - [ ] <!-- item:1 fp:abc123def4567890 --> **Command injection in git clone** — `mcp-github-app/src/index.js:42` (semgrep · `javascript.lang.security.exec-shell-command`)
268
+ <details><summary>Details</summary>
269
+
270
+ ```javascript
271
+ execSync(`git clone ${userInput}`)
272
+ ```
273
+
274
+ `userInput` originates from an HTTP request and is concatenated directly into a shell command, allowing arbitrary command execution.
275
+
276
+ **Suggested fix:** use `execFileSync('git', ['clone', userInput])` so arguments aren't re-parsed by a shell.
277
+
278
+ </details>
279
+
280
+ ### 🟠 High (1)
281
+
282
+ - [ ] <!-- item:2 fp:def456abc7890123 --> **Hardcoded API key in config** — `src/config.ts:18` (gitleaks · `generic-api-key`)
283
+ <details><summary>Details</summary>
284
+
285
+ ```typescript
286
+ const API_KEY = "sk_live_abc123..."
287
+ ```
288
+
289
+ A live API key is committed to the repo. Anyone with read access to the repo (or the git history of a former branch) can use it.
290
+
291
+ **Suggested fix:** move the key to an environment variable (`process.env.API_KEY`) and rotate the exposed one immediately.
292
+
293
+ </details>
294
+
295
+ ### 🟡 Medium (0)
296
+
297
+ _No findings._
298
+
299
+ ### 🟢 Low (0)
300
+
301
+ _No findings._
302
+ ````
@@ -0,0 +1,118 @@
1
+ ---
2
+ name: verify
3
+ description: Test a behaviour claim as an investigator and report whether the evidence confirms or refutes it — CONFIRMED / REFUTED / INCONCLUSIVE with bash-captured evidence. Use when asked to verify a claim, prove a fix works, or check that a PR does what it says.
4
+ version: 1.0.0
5
+ tags: [github, verify, testing, evidence]
6
+ ---
7
+
8
+ # Verify
9
+
10
+ Test a specific claim about behaviour and report whether the evidence supports
11
+ or refutes it. The deliverable is a **verdict with evidence**, not an opinion.
12
+
13
+ This skill uses the **building** skill for installing dependencies and running
14
+ the repo's build/test commands in the sandbox.
15
+
16
+ > **Scope (text-evidence path).** In the default text phase the sandbox agent
17
+ > has bash, file read, and the github tools — no browser, no screenshots, no
18
+ > video. Prove claims with what bash can capture: test output, command
19
+ > stdout/stderr, `curl` against a dev-server you start, log excerpts, file
20
+ > contents, exit codes. Driving a real browser and attaching screenshots is the
21
+ > separate `browser-qa` skill, which is staged only in the gated browser phase
22
+ > running on the docker QA image (Playwright + Chromium). If that skill isn't in
23
+ > your catalogue and a claim genuinely can only be shown in a rendered UI, say
24
+ > so under **INCONCLUSIVE** rather than guessing — the browser phase will pick
25
+ > it up when available.
26
+
27
+ ## Ground rule — investigator, not advocate
28
+
29
+ Your job is to find out whether the claim is **true**, not to make it look true.
30
+ A conclusive "this is broken" with clear evidence is exactly as valuable as a
31
+ "this works". Specifically:
32
+
33
+ - **Never fabricate, hardcode, mock, or stage evidence** to match an expected
34
+ outcome. Do not edit the code under test to make a result appear.
35
+ - If the behaviour you observe **contradicts** the claim, that is the result —
36
+ report it as REFUTED with the evidence inline. Don't bury it.
37
+ - **Don't retry a failing test hoping for a different answer.** Retry only after
38
+ *changing* the environment or procedure (wrong branch, missing build step),
39
+ and only when you have reason to believe the test setup — not the code — was
40
+ wrong. One unexpected result that reproduces is a finding.
41
+
42
+ ## Parse the target
43
+
44
+ The Context block gives you the claim and (usually) a PR or issue. The claim may
45
+ arrive as:
46
+
47
+ - A **direct claim** — "ESC cancels streaming in bash mode", "the `--fork` flag
48
+ creates a new session".
49
+ - A **PR reference + claim** — verify the claim against that PR's head.
50
+ - A **PR reference only** — read the PR description + diff and identify the most
51
+ important, most testable claim it makes; state which claim you chose.
52
+
53
+ When a PR/issue is given, read its description and diff for context (from the
54
+ local checkout — see the **building** skill's workspace notes; don't pull the
55
+ diff through the API).
56
+
57
+ ## Decide what would convince a skeptic
58
+
59
+ Name the single behaviour to observe and the evidence that settles it:
60
+
61
+ - **Functional claim** (a feature works, a flow completes) → run it and capture
62
+ the output / exit code / resulting state.
63
+ - **Regression / fix claim** ("no longer clears the screen", "stops erroring") →
64
+ show the **before and after**: reproduce on the base ref, then show it gone on
65
+ the head ref. Both states must appear in the evidence — an off-camera "it's
66
+ fixed" doesn't count.
67
+ - **Output/encoding claim** → capture the exact bytes/text (`xxd`, `od -c`, raw
68
+ stdout) rather than describing them.
69
+
70
+ ## Run the test
71
+
72
+ Follow the **building** skill to install and build. Then exercise the claim with
73
+ the minimal sequence that demonstrates it, capturing evidence at the decisive
74
+ step. Start a dev-server in the background and `curl` it when the claim is about
75
+ a running service; run the CLI directly when it's a CLI claim; run the targeted
76
+ test when the repo already encodes the behaviour as a test.
77
+
78
+ If the environment blocks a clean test (missing dependency the sandbox can't
79
+ provide, build failure you can't resolve, infra that won't run), capture what
80
+ blocked it — that drives an **INCONCLUSIVE** result, not a guess.
81
+
82
+ ## Report
83
+
84
+ Produce your report as your **final message** in this shape — the workflow posts
85
+ it for you (don't `github_add_issue_comment` yourself; that would double-post).
86
+ **Keep it concise**: a one-line environment summary, the decisive evidence
87
+ (commands + key output, not every line), and a one-paragraph conclusion — not an
88
+ exhaustive walkthrough.
89
+
90
+ ```
91
+ ## Verify: <claim>
92
+
93
+ **Environment:** <branch / commit, package manager, how the app was run>
94
+
95
+ ### Evidence
96
+ <commands run + their captured output — fenced. Include both states for a
97
+ before/after claim.>
98
+
99
+ ### Conclusion
100
+ **CONFIRMED** | **REFUTED** | **INCONCLUSIVE**
101
+
102
+ <one paragraph: what the evidence shows and why it settles the claim.>
103
+ ```
104
+
105
+ - **REFUTED** — state the expected behaviour (from the claim), the observed
106
+ behaviour (from the evidence), include the evidence inline, and note any
107
+ environmental factors (branch, commit, OS). This is a valuable finding, not a
108
+ failed run.
109
+ - **INCONCLUSIVE** — report exactly what blocked the test and what would be
110
+ needed to resolve it. Do not guess at the outcome.
111
+
112
+ ## Do NOT
113
+
114
+ - Retry a failing test more than once without changing the environment/procedure.
115
+ - Hardcode expected output, mock responses, or edit the code under test to force
116
+ a result.
117
+ - Assume unexpected behaviour means *you* made a mistake — it may be a real bug.
118
+ - Omit evidence that contradicts the claim.
@@ -0,0 +1,37 @@
1
+ kind: answer
2
+ name: answer
3
+ description: |
4
+ Answer a question issue directly. Used when a newly-opened issue asks for
5
+ information, an explanation, or a comparison rather than a code change — the
6
+ bot researches (repo docs + web search) and posts a single sourced answer
7
+ comment, labels the issue `question`, and leaves it open. No agent brief, no
8
+ ready-for-agent, no PR.
9
+
10
+ Delivery is uniform: the agent's final message (the answer) is captured as
11
+ `answerResult` and posted by the harness via `postComment` — as a comment on
12
+ the originating issue for GitHub-initiated runs, or into the Slack thread for
13
+ Slack-initiated runs. The skill therefore does NOT post the answer itself; it
14
+ only applies the `question` label when answering a GitHub issue.
15
+
16
+ Triggered by:
17
+ - issue.opened webhook when the router classifies the issue as a question
18
+ - a Slack message classified as a question against a managed repo
19
+ - manual override via routes.github.issue_answer / routes.slack.answer
20
+
21
+ phases:
22
+ - name: phase_0
23
+ label: Context
24
+ type: context
25
+
26
+ - name: answer
27
+ label: Answer
28
+ prompt: prompts/answer.md
29
+ skill: issue-answer
30
+ model: "{{models.answer}}"
31
+ web_search: true
32
+ unrestricted_egress: true
33
+ output_var: answerResult
34
+ messages:
35
+ on_start: "Researching and drafting an answer..."
36
+ on_success: "{{answerResult}}"
37
+ on_failure: "I couldn't put together an answer — see the logs for details."