lastlight 0.16.0 → 0.16.2

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 (385) hide show
  1. package/README.md +71 -692
  2. package/dist/cli-config.js.map +1 -0
  3. package/dist/cli-format.js.map +1 -0
  4. package/dist/{cli/cli-server.d.ts → cli-server.d.ts} +39 -1
  5. package/dist/{cli/cli-server.js → cli-server.js} +105 -5
  6. package/dist/cli-server.js.map +1 -0
  7. package/dist/cli-timeline.js.map +1 -0
  8. package/dist/{cli/cli.js → cli.js} +9 -7
  9. package/dist/cli.js.map +1 -0
  10. package/dist/{cli/fork-cli.d.ts → fork-cli.d.ts} +3 -3
  11. package/dist/{cli/fork-cli.js → fork-cli.js} +28 -27
  12. package/dist/fork-cli.js.map +1 -0
  13. package/dist/{cli/oauth-cli.js → oauth-cli.js} +1 -1
  14. package/dist/oauth-cli.js.map +1 -0
  15. package/dist/{cli/setup.js → setup.js} +10 -4
  16. package/dist/setup.js.map +1 -0
  17. package/dist/{cli/skills-install.d.ts → skills-install.d.ts} +6 -0
  18. package/dist/{cli/skills-install.js → skills-install.js} +6 -2
  19. package/dist/skills-install.js.map +1 -0
  20. package/package.json +20 -65
  21. package/plugins/lastlight/.claude-plugin/plugin.json +1 -1
  22. package/agent-context/rules.md +0 -80
  23. package/agent-context/security.md +0 -69
  24. package/agent-context/soul.md +0 -21
  25. package/config/default.yaml +0 -119
  26. package/deploy/.env.production.example +0 -100
  27. package/deploy/entrypoint.sh +0 -82
  28. package/deploy/native/README.md +0 -160
  29. package/deploy/native/install.sh +0 -110
  30. package/deploy/native/lastlight.env.example +0 -95
  31. package/deploy/native/lastlight.service +0 -50
  32. package/deploy/sandbox-entrypoint.sh +0 -93
  33. package/dist/admin/auth.d.ts +0 -51
  34. package/dist/admin/auth.js +0 -121
  35. package/dist/admin/auth.js.map +0 -1
  36. package/dist/admin/chat-session-reader.d.ts +0 -39
  37. package/dist/admin/chat-session-reader.js +0 -84
  38. package/dist/admin/chat-session-reader.js.map +0 -1
  39. package/dist/admin/docker.d.ts +0 -61
  40. package/dist/admin/docker.js +0 -187
  41. package/dist/admin/docker.js.map +0 -1
  42. package/dist/admin/index.d.ts +0 -9
  43. package/dist/admin/index.js +0 -59
  44. package/dist/admin/index.js.map +0 -1
  45. package/dist/admin/routes.d.ts +0 -81
  46. package/dist/admin/routes.js +0 -1381
  47. package/dist/admin/routes.js.map +0 -1
  48. package/dist/admin/sessions.d.ts +0 -89
  49. package/dist/admin/sessions.js +0 -204
  50. package/dist/admin/sessions.js.map +0 -1
  51. package/dist/admin/tail.d.ts +0 -12
  52. package/dist/admin/tail.js +0 -145
  53. package/dist/admin/tail.js.map +0 -1
  54. package/dist/admin/version.d.ts +0 -22
  55. package/dist/admin/version.js +0 -92
  56. package/dist/admin/version.js.map +0 -1
  57. package/dist/cli/cli-config.js.map +0 -1
  58. package/dist/cli/cli-format.js.map +0 -1
  59. package/dist/cli/cli-server.js.map +0 -1
  60. package/dist/cli/cli-timeline.js.map +0 -1
  61. package/dist/cli/cli.js.map +0 -1
  62. package/dist/cli/fork-cli.js.map +0 -1
  63. package/dist/cli/oauth-cli.js.map +0 -1
  64. package/dist/cli/setup.js.map +0 -1
  65. package/dist/cli/skills-install.js.map +0 -1
  66. package/dist/config/config-resolve.d.ts +0 -28
  67. package/dist/config/config-resolve.js +0 -47
  68. package/dist/config/config-resolve.js.map +0 -1
  69. package/dist/config/config.d.ts +0 -157
  70. package/dist/config/config.js +0 -581
  71. package/dist/config/config.js.map +0 -1
  72. package/dist/config/core-pin.d.ts +0 -16
  73. package/dist/config/core-pin.js +0 -85
  74. package/dist/config/core-pin.js.map +0 -1
  75. package/dist/config/overlay-assets.d.ts +0 -20
  76. package/dist/config/overlay-assets.js +0 -114
  77. package/dist/config/overlay-assets.js.map +0 -1
  78. package/dist/config/overlay-bootstrap.d.ts +0 -44
  79. package/dist/config/overlay-bootstrap.js +0 -304
  80. package/dist/config/overlay-bootstrap.js.map +0 -1
  81. package/dist/connectors/github-webhook.d.ts +0 -45
  82. package/dist/connectors/github-webhook.js +0 -321
  83. package/dist/connectors/github-webhook.js.map +0 -1
  84. package/dist/connectors/index.d.ts +0 -18
  85. package/dist/connectors/index.js +0 -41
  86. package/dist/connectors/index.js.map +0 -1
  87. package/dist/connectors/messaging/base.d.ts +0 -42
  88. package/dist/connectors/messaging/base.js +0 -139
  89. package/dist/connectors/messaging/base.js.map +0 -1
  90. package/dist/connectors/messaging/delivery.d.ts +0 -14
  91. package/dist/connectors/messaging/delivery.js +0 -38
  92. package/dist/connectors/messaging/delivery.js.map +0 -1
  93. package/dist/connectors/messaging/index.d.ts +0 -4
  94. package/dist/connectors/messaging/index.js +0 -4
  95. package/dist/connectors/messaging/index.js.map +0 -1
  96. package/dist/connectors/messaging/session-manager.d.ts +0 -53
  97. package/dist/connectors/messaging/session-manager.js +0 -255
  98. package/dist/connectors/messaging/session-manager.js.map +0 -1
  99. package/dist/connectors/messaging/types.d.ts +0 -58
  100. package/dist/connectors/messaging/types.js +0 -7
  101. package/dist/connectors/messaging/types.js.map +0 -1
  102. package/dist/connectors/slack/connector.d.ts +0 -142
  103. package/dist/connectors/slack/connector.js +0 -494
  104. package/dist/connectors/slack/connector.js.map +0 -1
  105. package/dist/connectors/slack/index.d.ts +0 -2
  106. package/dist/connectors/slack/index.js +0 -3
  107. package/dist/connectors/slack/index.js.map +0 -1
  108. package/dist/connectors/slack/mrkdwn.d.ts +0 -19
  109. package/dist/connectors/slack/mrkdwn.js +0 -240
  110. package/dist/connectors/slack/mrkdwn.js.map +0 -1
  111. package/dist/connectors/types.d.ts +0 -61
  112. package/dist/connectors/types.js +0 -2
  113. package/dist/connectors/types.js.map +0 -1
  114. package/dist/cron/fanout.d.ts +0 -33
  115. package/dist/cron/fanout.js +0 -55
  116. package/dist/cron/fanout.js.map +0 -1
  117. package/dist/cron/jobs.d.ts +0 -18
  118. package/dist/cron/jobs.js +0 -37
  119. package/dist/cron/jobs.js.map +0 -1
  120. package/dist/cron/scheduler.d.ts +0 -45
  121. package/dist/cron/scheduler.js +0 -105
  122. package/dist/cron/scheduler.js.map +0 -1
  123. package/dist/engine/agent-executor.d.ts +0 -34
  124. package/dist/engine/agent-executor.js +0 -246
  125. package/dist/engine/agent-executor.js.map +0 -1
  126. package/dist/engine/chat/chat-runner.d.ts +0 -132
  127. package/dist/engine/chat/chat-runner.js +0 -424
  128. package/dist/engine/chat/chat-runner.js.map +0 -1
  129. package/dist/engine/chat/chat-skills.d.ts +0 -45
  130. package/dist/engine/chat/chat-skills.js +0 -184
  131. package/dist/engine/chat/chat-skills.js.map +0 -1
  132. package/dist/engine/chat/chat.d.ts +0 -54
  133. package/dist/engine/chat/chat.js +0 -316
  134. package/dist/engine/chat/chat.js.map +0 -1
  135. package/dist/engine/chat/message-batcher.d.ts +0 -32
  136. package/dist/engine/chat/message-batcher.js +0 -109
  137. package/dist/engine/chat/message-batcher.js.map +0 -1
  138. package/dist/engine/dispatcher.d.ts +0 -73
  139. package/dist/engine/dispatcher.js +0 -663
  140. package/dist/engine/dispatcher.js.map +0 -1
  141. package/dist/engine/event-shim.d.ts +0 -117
  142. package/dist/engine/event-shim.js +0 -435
  143. package/dist/engine/event-shim.js.map +0 -1
  144. package/dist/engine/executors/orchestrator.d.ts +0 -81
  145. package/dist/engine/executors/orchestrator.js +0 -365
  146. package/dist/engine/executors/orchestrator.js.map +0 -1
  147. package/dist/engine/executors/shared.d.ts +0 -189
  148. package/dist/engine/executors/shared.js +0 -616
  149. package/dist/engine/executors/shared.js.map +0 -1
  150. package/dist/engine/github/git-auth.d.ts +0 -62
  151. package/dist/engine/github/git-auth.js +0 -161
  152. package/dist/engine/github/git-auth.js.map +0 -1
  153. package/dist/engine/github/github-app-client.d.ts +0 -23
  154. package/dist/engine/github/github-app-client.js +0 -33
  155. package/dist/engine/github/github-app-client.js.map +0 -1
  156. package/dist/engine/github/github-tools.d.ts +0 -18
  157. package/dist/engine/github/github-tools.js +0 -263
  158. package/dist/engine/github/github-tools.js.map +0 -1
  159. package/dist/engine/github/github.d.ts +0 -1193
  160. package/dist/engine/github/github.js +0 -357
  161. package/dist/engine/github/github.js.map +0 -1
  162. package/dist/engine/github/profiles.d.ts +0 -279
  163. package/dist/engine/github/profiles.js +0 -42
  164. package/dist/engine/github/profiles.js.map +0 -1
  165. package/dist/engine/github/review-poster.d.ts +0 -98
  166. package/dist/engine/github/review-poster.js +0 -177
  167. package/dist/engine/github/review-poster.js.map +0 -1
  168. package/dist/engine/llm.d.ts +0 -79
  169. package/dist/engine/llm.js +0 -269
  170. package/dist/engine/llm.js.map +0 -1
  171. package/dist/engine/oauth.d.ts +0 -43
  172. package/dist/engine/oauth.js +0 -103
  173. package/dist/engine/oauth.js.map +0 -1
  174. package/dist/engine/router.d.ts +0 -29
  175. package/dist/engine/router.js +0 -680
  176. package/dist/engine/router.js.map +0 -1
  177. package/dist/engine/screen/classifier.d.ts +0 -93
  178. package/dist/engine/screen/classifier.js +0 -215
  179. package/dist/engine/screen/classifier.js.map +0 -1
  180. package/dist/engine/screen/screen.d.ts +0 -41
  181. package/dist/engine/screen/screen.js +0 -93
  182. package/dist/engine/screen/screen.js.map +0 -1
  183. package/dist/evals-api.d.ts +0 -24
  184. package/dist/evals-api.js +0 -22
  185. package/dist/evals-api.js.map +0 -1
  186. package/dist/index.d.ts +0 -1
  187. package/dist/index.js +0 -940
  188. package/dist/index.js.map +0 -1
  189. package/dist/managed-repos.d.ts +0 -30
  190. package/dist/managed-repos.js +0 -72
  191. package/dist/managed-repos.js.map +0 -1
  192. package/dist/notify/blocks.d.ts +0 -23
  193. package/dist/notify/blocks.js +0 -118
  194. package/dist/notify/blocks.js.map +0 -1
  195. package/dist/notify/index.d.ts +0 -17
  196. package/dist/notify/index.js +0 -7
  197. package/dist/notify/index.js.map +0 -1
  198. package/dist/notify/model.d.ts +0 -57
  199. package/dist/notify/model.js +0 -89
  200. package/dist/notify/model.js.map +0 -1
  201. package/dist/notify/notifier.d.ts +0 -18
  202. package/dist/notify/notifier.js +0 -100
  203. package/dist/notify/notifier.js.map +0 -1
  204. package/dist/notify/render.d.ts +0 -21
  205. package/dist/notify/render.js +0 -59
  206. package/dist/notify/render.js.map +0 -1
  207. package/dist/notify/transports/github.d.ts +0 -26
  208. package/dist/notify/transports/github.js +0 -27
  209. package/dist/notify/transports/github.js.map +0 -1
  210. package/dist/notify/transports/slack.d.ts +0 -27
  211. package/dist/notify/transports/slack.js +0 -37
  212. package/dist/notify/transports/slack.js.map +0 -1
  213. package/dist/notify/types.d.ts +0 -119
  214. package/dist/notify/types.js +0 -16
  215. package/dist/notify/types.js.map +0 -1
  216. package/dist/providers.d.ts +0 -125
  217. package/dist/providers.js +0 -279
  218. package/dist/providers.js.map +0 -1
  219. package/dist/sandbox/docker.d.ts +0 -180
  220. package/dist/sandbox/docker.js +0 -517
  221. package/dist/sandbox/docker.js.map +0 -1
  222. package/dist/sandbox/egress-allowlist.d.ts +0 -74
  223. package/dist/sandbox/egress-allowlist.js +0 -164
  224. package/dist/sandbox/egress-allowlist.js.map +0 -1
  225. package/dist/sandbox/egress-firewall-config.d.ts +0 -127
  226. package/dist/sandbox/egress-firewall-config.js +0 -434
  227. package/dist/sandbox/egress-firewall-config.js.map +0 -1
  228. package/dist/sandbox/images.d.ts +0 -23
  229. package/dist/sandbox/images.js +0 -55
  230. package/dist/sandbox/images.js.map +0 -1
  231. package/dist/sandbox/index.d.ts +0 -112
  232. package/dist/sandbox/index.js +0 -332
  233. package/dist/sandbox/index.js.map +0 -1
  234. package/dist/sandbox/sandbox.d.ts +0 -214
  235. package/dist/sandbox/sandbox.js +0 -453
  236. package/dist/sandbox/sandbox.js.map +0 -1
  237. package/dist/sandbox/smol.d.ts +0 -162
  238. package/dist/sandbox/smol.js +0 -485
  239. package/dist/sandbox/smol.js.map +0 -1
  240. package/dist/session-log.d.ts +0 -63
  241. package/dist/session-log.js +0 -290
  242. package/dist/session-log.js.map +0 -1
  243. package/dist/state/approval-store.d.ts +0 -88
  244. package/dist/state/approval-store.js +0 -149
  245. package/dist/state/approval-store.js.map +0 -1
  246. package/dist/state/build-assets.d.ts +0 -50
  247. package/dist/state/build-assets.js +0 -154
  248. package/dist/state/build-assets.js.map +0 -1
  249. package/dist/state/db.d.ts +0 -81
  250. package/dist/state/db.js +0 -155
  251. package/dist/state/db.js.map +0 -1
  252. package/dist/state/execution-store.d.ts +0 -257
  253. package/dist/state/execution-store.js +0 -527
  254. package/dist/state/execution-store.js.map +0 -1
  255. package/dist/state/migrate.d.ts +0 -15
  256. package/dist/state/migrate.js +0 -175
  257. package/dist/state/migrate.js.map +0 -1
  258. package/dist/state/workflow-run-store.d.ts +0 -216
  259. package/dist/state/workflow-run-store.js +0 -403
  260. package/dist/state/workflow-run-store.js.map +0 -1
  261. package/dist/telemetry/index.d.ts +0 -38
  262. package/dist/telemetry/index.js +0 -253
  263. package/dist/telemetry/index.js.map +0 -1
  264. package/dist/telemetry/pi-events.d.ts +0 -12
  265. package/dist/telemetry/pi-events.js +0 -134
  266. package/dist/telemetry/pi-events.js.map +0 -1
  267. package/dist/workflows/dag.d.ts +0 -37
  268. package/dist/workflows/dag.js +0 -118
  269. package/dist/workflows/dag.js.map +0 -1
  270. package/dist/workflows/loader.d.ts +0 -53
  271. package/dist/workflows/loader.js +0 -421
  272. package/dist/workflows/loader.js.map +0 -1
  273. package/dist/workflows/loop-eval.d.ts +0 -28
  274. package/dist/workflows/loop-eval.js +0 -74
  275. package/dist/workflows/loop-eval.js.map +0 -1
  276. package/dist/workflows/phase-executor.d.ts +0 -222
  277. package/dist/workflows/phase-executor.js +0 -1153
  278. package/dist/workflows/phase-executor.js.map +0 -1
  279. package/dist/workflows/phase-ref.d.ts +0 -50
  280. package/dist/workflows/phase-ref.js +0 -91
  281. package/dist/workflows/phase-ref.js.map +0 -1
  282. package/dist/workflows/resume.d.ts +0 -58
  283. package/dist/workflows/resume.js +0 -313
  284. package/dist/workflows/resume.js.map +0 -1
  285. package/dist/workflows/runner.d.ts +0 -63
  286. package/dist/workflows/runner.js +0 -381
  287. package/dist/workflows/runner.js.map +0 -1
  288. package/dist/workflows/schema.d.ts +0 -344
  289. package/dist/workflows/schema.js +0 -460
  290. package/dist/workflows/schema.js.map +0 -1
  291. package/dist/workflows/simple.d.ts +0 -90
  292. package/dist/workflows/simple.js +0 -393
  293. package/dist/workflows/simple.js.map +0 -1
  294. package/dist/workflows/target-policy.d.ts +0 -74
  295. package/dist/workflows/target-policy.js +0 -80
  296. package/dist/workflows/target-policy.js.map +0 -1
  297. package/dist/workflows/templates.d.ts +0 -88
  298. package/dist/workflows/templates.js +0 -127
  299. package/dist/workflows/templates.js.map +0 -1
  300. package/dist/workflows/triggers.d.ts +0 -21
  301. package/dist/workflows/triggers.js +0 -45
  302. package/dist/workflows/triggers.js.map +0 -1
  303. package/dist/workflows/verdict.d.ts +0 -19
  304. package/dist/workflows/verdict.js +0 -30
  305. package/dist/workflows/verdict.js.map +0 -1
  306. package/dist/worktree/manager.d.ts +0 -43
  307. package/dist/worktree/manager.js +0 -127
  308. package/dist/worktree/manager.js.map +0 -1
  309. package/docker-compose.yml +0 -274
  310. package/sandbox.Dockerfile +0 -68
  311. package/skills/README.md +0 -42
  312. package/skills/browser-qa/SKILL.md +0 -208
  313. package/skills/browser-qa/scripts/agent-browser.mjs +0 -531
  314. package/skills/building/SKILL.md +0 -95
  315. package/skills/chat/SKILL.md +0 -36
  316. package/skills/code-review/SKILL.md +0 -82
  317. package/skills/debug-production/SKILL.md +0 -108
  318. package/skills/demo/SKILL.md +0 -228
  319. package/skills/demo/scripts/compose-demo.sh +0 -243
  320. package/skills/issue-answer/SKILL.md +0 -91
  321. package/skills/issue-comment/SKILL.md +0 -49
  322. package/skills/issue-triage/SKILL.md +0 -149
  323. package/skills/issue-triage/references/AGENT-BRIEF.md +0 -65
  324. package/skills/pr-comment/SKILL.md +0 -64
  325. package/skills/pr-review/SKILL.md +0 -148
  326. package/skills/pr-review/references/findings-schema.md +0 -89
  327. package/skills/qa-test/SKILL.md +0 -97
  328. package/skills/repo-health/SKILL.md +0 -67
  329. package/skills/security-feedback/SKILL.md +0 -173
  330. package/skills/security-feedback/references/templates.md +0 -77
  331. package/skills/security-review/SKILL.md +0 -215
  332. package/skills/security-review/references/issue-format.md +0 -302
  333. package/skills/verify/SKILL.md +0 -118
  334. package/workflows/answer.yaml +0 -44
  335. package/workflows/build.yaml +0 -129
  336. package/workflows/cron-health.yaml +0 -6
  337. package/workflows/cron-review.yaml +0 -8
  338. package/workflows/cron-security.yaml +0 -6
  339. package/workflows/cron-triage.yaml +0 -8
  340. package/workflows/demo.yaml +0 -62
  341. package/workflows/examples/bash-smoke.yaml +0 -41
  342. package/workflows/examples/parallel-review.yaml +0 -36
  343. package/workflows/examples/tdd-loop.yaml +0 -17
  344. package/workflows/explore.yaml +0 -80
  345. package/workflows/issue-comment.yaml +0 -15
  346. package/workflows/issue-triage.yaml +0 -22
  347. package/workflows/pr-comment.yaml +0 -16
  348. package/workflows/pr-fix.yaml +0 -17
  349. package/workflows/pr-review.yaml +0 -50
  350. package/workflows/prompts/answer.md +0 -68
  351. package/workflows/prompts/architect.md +0 -44
  352. package/workflows/prompts/classifier.md +0 -60
  353. package/workflows/prompts/classify-adds-info.md +0 -17
  354. package/workflows/prompts/demo.md +0 -125
  355. package/workflows/prompts/executor.md +0 -42
  356. package/workflows/prompts/explore-ask.md +0 -99
  357. package/workflows/prompts/explore-publish.md +0 -31
  358. package/workflows/prompts/explore-read.md +0 -120
  359. package/workflows/prompts/explore-synthesize.md +0 -88
  360. package/workflows/prompts/fix.md +0 -18
  361. package/workflows/prompts/guardrails.md +0 -96
  362. package/workflows/prompts/pr-fix.md +0 -26
  363. package/workflows/prompts/pr.md +0 -39
  364. package/workflows/prompts/qa-browser.md +0 -95
  365. package/workflows/prompts/qa-synth.md +0 -44
  366. package/workflows/prompts/qa-test.md +0 -60
  367. package/workflows/prompts/re-reviewer.md +0 -33
  368. package/workflows/prompts/reviewer.md +0 -60
  369. package/workflows/prompts/verify-browser.md +0 -93
  370. package/workflows/prompts/verify-synth.md +0 -44
  371. package/workflows/prompts/verify.md +0 -63
  372. package/workflows/qa-test.yaml +0 -94
  373. package/workflows/repo-health.yaml +0 -15
  374. package/workflows/security-feedback.yaml +0 -25
  375. package/workflows/security-review.yaml +0 -37
  376. package/workflows/verify.yaml +0 -93
  377. /package/dist/{cli/cli-config.d.ts → cli-config.d.ts} +0 -0
  378. /package/dist/{cli/cli-config.js → cli-config.js} +0 -0
  379. /package/dist/{cli/cli-format.d.ts → cli-format.d.ts} +0 -0
  380. /package/dist/{cli/cli-format.js → cli-format.js} +0 -0
  381. /package/dist/{cli/cli-timeline.d.ts → cli-timeline.d.ts} +0 -0
  382. /package/dist/{cli/cli-timeline.js → cli-timeline.js} +0 -0
  383. /package/dist/{cli/cli.d.ts → cli.d.ts} +0 -0
  384. /package/dist/{cli/oauth-cli.d.ts → oauth-cli.d.ts} +0 -0
  385. /package/dist/{cli/setup.d.ts → setup.d.ts} +0 -0
@@ -1,97 +0,0 @@
1
- ---
2
- name: qa-test
3
- description: Run an automated QA flow against a CLI or a locally-served app and report step-level pass/fail with evidence. Use when asked to QA-test a feature, exercise a flow end-to-end, or smoke-test what a PR changed.
4
- version: 1.0.0
5
- tags: [github, qa, testing, evidence]
6
- ---
7
-
8
- # QA Test
9
-
10
- Drive a target through a sequence of steps and report **step-level pass/fail**
11
- with evidence for each step. The deliverable is a QA report, not a single
12
- verdict — partial coverage with documented failures is the expected output.
13
-
14
- This skill uses the **building** skill for installing dependencies and running
15
- the repo's build/run commands in the sandbox.
16
-
17
- > **Scope (text-evidence path).** In the default text phase the sandbox agent
18
- > has bash, file read, and the github tools — no browser, no screenshots. QA a
19
- > **CLI** directly, or a **web service** by starting its dev-server in the
20
- > background and exercising it with `curl` (status codes, response bodies,
21
- > headers). Capture stdout/stderr, exit codes, and log excerpts as per-step
22
- > evidence. Driving a real browser UI and attaching screenshots is the separate
23
- > `browser-qa` skill, staged only in the gated browser phase running on the
24
- > docker QA image (Playwright + Chromium). If that skill isn't in your
25
- > catalogue, mark a step that genuinely needs rendered-UI interaction
26
- > **BLOCKED** with the reason rather than faking a result — the browser phase
27
- > will pick it up when available.
28
-
29
- ## Parse the target
30
-
31
- The Context block gives you what to test and (usually) a PR/issue. The target
32
- may be:
33
-
34
- - A **CLI command** (`my-cli --flag`, a subcommand) → run it directly.
35
- - A **local web service** (an app the repo serves on a port) → start it, hit it
36
- with `curl`.
37
- - A **PR reference + focus area** → read the diff and infer the flow that
38
- exercises what changed.
39
- - A **free-text flow** ("create a project, then list it") → infer concrete steps.
40
-
41
- When a PR/issue is given, read its description + diff (from the local checkout —
42
- see the **building** skill) to decide what's worth testing.
43
-
44
- ## Define the steps
45
-
46
- If the request specifies steps, use them. Otherwise design a reasonable flow:
47
-
48
- - **CLI**: invoke with valid input → assert output/exit code → invoke an edge
49
- case (bad flag, missing arg) → assert it's handled → done.
50
- - **Web service**: start the server → wait until it's ready → hit the primary
51
- endpoint(s) → assert status + body → hit an error case → assert handling →
52
- stop the server.
53
-
54
- State the steps and their success criteria before running. If the flow or the
55
- success criteria are genuinely ambiguous and you can't infer them from the diff,
56
- say what's unclear in the report rather than inventing a pass.
57
-
58
- ## Run each step
59
-
60
- Follow the **building** skill to install and build first. Then run each step in
61
- order, capturing evidence (command + stdout/stderr + exit code) at every step.
62
-
63
- - **Record each step's result as you go** — PASS, FAIL, or BLOCKED.
64
- - **On failure, continue to the next step** for maximum coverage — *unless* the
65
- failure blocks everything downstream (e.g. the server never starts, or a login
66
- step fails). If it's a hard blocker, record it, mark the rest BLOCKED, and stop.
67
- - Treat a wrong result as a real finding, not your mistake. Don't edit the code
68
- under test to make a step pass.
69
-
70
- ## Report
71
-
72
- Produce your report as your **final message** in this shape — the workflow posts
73
- it for you (don't `github_add_issue_comment` yourself; that would double-post).
74
- **Keep it concise**: a one-line environment summary, the results table (terse
75
- Evidence cells), the failures, and a short coverage note — not a step-by-step
76
- narration.
77
-
78
- ```
79
- ## QA Test: <target>
80
-
81
- **Environment:** <branch / commit, package manager, how the app was run>
82
-
83
- ### Results
84
- | Step | Status | Evidence |
85
- |------|--------|----------|
86
- | <step description> | PASS / FAIL / BLOCKED | <command + key output / exit code> |
87
-
88
- ### Issues found
89
- - <each FAIL with the expected vs observed behaviour and the evidence>
90
-
91
- ### Coverage
92
- <what was tested, and what was not tested and why (e.g. a UI-only step that the
93
- text-evidence sandbox can't drive).>
94
- ```
95
-
96
- Every defined step must have a row and a result. Never report a flow as
97
- "passed" with steps you didn't actually run — list them as untested instead.
@@ -1,67 +0,0 @@
1
- ---
2
- name: repo-health
3
- description: Generate a health report for a GitHub repository — open-issue and PR backlog, unreviewed PRs, stale needs-info, failing CI, and the resulting action items. Use for a status report or on a weekly cron.
4
- version: 2.0.0
5
- tags: [github, monitoring, reporting]
6
- ---
7
-
8
- # Repo Health
9
-
10
- Produce a point-in-time health snapshot of a repo and the action items it
11
- implies. One report per run.
12
-
13
- ## Procedure
14
-
15
- ### 1. Gather metrics
16
-
17
- Pull these via `github_*` MCP tools. Done when each number below is filled.
18
-
19
- - **Open issues** — total, and a breakdown by the repo's own priority/severity
20
- labels *if it uses any* (don't assume a fixed scheme).
21
- - **Open PRs** — total, and how long each has been open. Exclude drafts from any
22
- "awaiting review" count.
23
- - **Unreviewed PRs** — open, non-draft, no reviews yet.
24
- - **Stale `needs-info`** — issues labelled `needs-info` with no activity for 14+ days.
25
- - **Recent throughput** — issues closed and PRs merged in the last 7 days.
26
-
27
- Batch requests and don't fetch full history — rate limits bite on large repos.
28
-
29
- ### 2. Derive action items
30
-
31
- Each is a checkbox line with the number and the reason:
32
-
33
- - PRs open > 7 days with no review.
34
- - High-priority issues still open (by whatever priority labels the repo uses).
35
- - `ready-for-agent` issues sitting unactioned (agent backlog).
36
- - Stale `needs-info` (14+ days).
37
- - PRs with failing CI.
38
-
39
- ### 3. Render the report
40
-
41
- ```markdown
42
- ## Repo Health: {owner}/{repo} — {YYYY-MM-DD}
43
-
44
- ### Overview
45
- - Open issues: {X} ({breakdown by the repo's priority labels, if any})
46
- - Open PRs: {X} ({Y} awaiting review)
47
- - Merged this week: {X} PRs · Closed this week: {X} issues
48
-
49
- ### Action items
50
- - [ ] PR #123 — open 12 days, no review
51
- - [ ] Issue #456 — high priority, open 3 days
52
- - [ ] Issue #789 — needs-info, stale 21 days
53
-
54
- ### Trends
55
- - Issue velocity: +{X} opened, −{Y} closed (net {±Z})
56
- ```
57
-
58
- Omit a section that has nothing in it rather than printing "none".
59
-
60
- ### 4. Deliver
61
-
62
- Output the report as the final response. The harness routes it (direct display
63
- interactively, or to the configured channel on a cron run).
64
-
65
- ## Verification
66
-
67
- Spot-check 2–3 of the reported numbers against the GitHub UI before delivering.
@@ -1,173 +0,0 @@
1
- ---
2
- name: security-feedback
3
- description: Process a maintainer's comment on a security scan-summary issue — break selected findings out into individual actionable issues, or record accepted risks / false positives in SECURITY.md.
4
- version: 2.0.0
5
- tags: [github, security, feedback]
6
- ---
7
-
8
- # Security Feedback
9
-
10
- A maintainer commented on a `security`-labelled issue — almost always a per-run
11
- **security scan summary** (one issue per scan, a task-list of findings). Based on
12
- the comment, either:
13
-
14
- - **Break selected findings into individual issues** (each can later feed `build`). Primary flow.
15
- - **Record a suppression** in `SECURITY.md` (accepted risk / false positive).
16
- - Reply for discussion, or ignore noise.
17
-
18
- The parent issue's grammar is the contract defined in
19
- `skills/security-review/references/issue-format.md`. This skill is staged into its
20
- own workspace and **cannot read that file**, so it carries its own copy of the
21
- row/severity regex below — **if you change the grammar, update both in lockstep.**
22
-
23
- ## Context
24
-
25
- - `context.repo` — `owner/name`
26
- - `context.issueNumber` — the security summary issue (parent)
27
- - `context.commentBody` — the triggering comment
28
- - `context.sender` — the commenter's GitHub login
29
-
30
- The parent body is not passed — fetch it at step 1.
31
-
32
- ## 1. Fetch and parse the parent issue
33
-
34
- `github_get_issue({ owner, repo, issue_number: issueNumber })`.
35
-
36
- **Version check.** The body MUST start with `<!-- lastlight-security-scan-version: 1 -->`.
37
- If the marker is missing or the version isn't `1`, reply: "Unknown scan-summary
38
- format — this skill is at version 1 but the parent reports a different version.
39
- Ask the maintainer to re-run `@last-light security-review`." Do not parse further.
40
-
41
- **Parse each finding row** with this canonical regex (all three states):
42
-
43
- ```
44
- /^- \[([ x])\] <!-- item:(\d+) fp:([0-9a-f]{8,}) --> (?:~~)?\*\*(.+?)\*\* — `([^`]+):(\d+)` \(([a-z][a-z0-9-]*) · `([^`]+)`\)(?:~~ → #(\d+))?$/m
45
- ```
46
-
47
- Captures: `checkbox` (` `/`x`), `item`, `fp`, `title`, `file`, `line`, `tool`,
48
- `rule`, and `subIssueNumber` (only when already broken out). Derive per row:
49
-
50
- | Derived | Definition |
51
- |---------|------------|
52
- | `alreadyBrokenOut` | `subIssueNumber != null` — turned into a sub-issue on a prior run |
53
- | `userTicked` | `checkbox === "x" && !alreadyBrokenOut` — the maintainer ticked the box, selecting it |
54
-
55
- `userTicked` is the primary selection signal; `alreadyBrokenOut` rows are never
56
- re-selected regardless of checkbox state.
57
-
58
- **Severity** comes from the nearest preceding section header (tolerating a
59
- trailing truncation suffix like `(showing first 7 of 25)`):
60
-
61
- ```
62
- /^### (🔴|🟠|🟡|🟢) (Critical|High|Medium|Low) \((\d+)\)(?:\s.*)?$/m
63
- ```
64
-
65
- Map Critical/High/Medium/Low → `p0-critical`/`p1-high`/`p2-medium`/`p3-low`.
66
-
67
- **Parse the `<details>` block** after each row (starts `<details><summary>Details</summary>`,
68
- ends `</details>`): the fenced block → `snippet` + `language`; paragraphs between
69
- the fence and `**Suggested fix:**` → `explanation`; text after `**Suggested fix:**`
70
- → `suggestedFix`.
71
-
72
- Store each finding as `{ item, fp, title, file, line, tool, rule, severity,
73
- language, snippet, explanation, suggestedFix, userTicked, alreadyBrokenOut, subIssueNumber? }`.
74
-
75
- ## 2. Classify the comment intent
76
-
77
- Pick the single best-fit bucket:
78
-
79
- - **create-issues** — break selected findings out. Signals: bare `@last-light
80
- create issues` (defaults to ticked), "create issues for…", "make issues for…",
81
- "break out…", "file sub-issues for…", "create an issue for items 1, 3".
82
- - **accept-risk** — accept a finding's risk. Signals: "accept-risk:", "we know
83
- about this", "won't fix", "accepted".
84
- - **false-positive** — not real. Signals: "false-positive:", "not a vulnerability",
85
- "not applicable".
86
- - **reopen** — re-evaluate a suppressed finding. Signals: "reopen", "re-evaluate".
87
- - **discuss** — a question or conversation about the findings.
88
- - **ignore** — noise (thanks, unrelated remark).
89
-
90
- `accept-risk` / `false-positive` / `reopen` MUST name a specific finding via
91
- `item N` / `item: N` — fall through to `discuss` if unresolved.
92
-
93
- ## 3. Act
94
-
95
- ### create-issues
96
-
97
- 1. **Resolve the selection** (first match wins):
98
- - **`ticked` / `checked` / `selected`** → every `userTicked` finding. Preferred UX.
99
- - **Default (no qualifier)** → treat as `ticked`. If no rows are ticked, reply:
100
- ```
101
- No rows are ticked. Tick the checkboxes on the findings you want broken out, then comment again — or use one of:
102
- - `@last-light create issues for the criticals`
103
- - `@last-light create issues for items 1, 3, 5`
104
- - `@last-light create issues for all`
105
- ```
106
- - `all` / `every` → every parsed finding regardless of tick state.
107
- - `criticals` / `the criticals` / `p0-critical` → every `p0-critical` (same for
108
- highs/mediums/lows). A count in the comment ("5 criticals") is ignored.
109
- - `items N, M` / `item N` → specific 1-based item numbers from `<!-- item:N -->`.
110
-
111
- In every form, silently drop `alreadyBrokenOut` findings and mention them in the
112
- summary. If the selection is empty, reply:
113
- ```
114
- No findings matched `{selection text}`. This scan has: {nC} critical, {nH} high, {nM} medium, {nL} low. Ticked: {nTicked}. Already broken out: {nDone}.
115
- ```
116
- and create nothing. If the form is unrecognised (ambiguous), ask for clarification — don't guess.
117
-
118
- 2. **For each selected finding**, `github_create_issue` using the sub-issue body
119
- template in [references/templates.md](references/templates.md). Record each new
120
- `subIssueNumber` against its `item`.
121
-
122
- 3. **Rewrite the parent body.** For every finding just broken out, transition its
123
- row to **broken-out**:
124
- ```
125
- - [x] <!-- item:N fp:FP --> ~~**TITLE** — `FILE:LINE` (TOOL · `RULE`)~~ → #SUBISSUE
126
- ```
127
- (checkbox `[x]`, title+location wrapped in `~~…~~`, ` → #SUBISSUE` appended).
128
- Match by `item:N`. Do **not** touch rows that weren't selected, even if ticked.
129
- Preserve all other content byte-for-byte. `github_update_issue`.
130
-
131
- 4. **Post a summary comment** on the parent:
132
- ```
133
- Created {N} sub-issue(s) at @{sender}'s request:
134
-
135
- - #{subN1} — {title 1} (item {item1})
136
- …
137
-
138
- {if any skipped}: Skipped {M} item(s) already broken out: items {list}.
139
-
140
- Comment `@last-light build` on any sub-issue to start a fix.
141
- ```
142
-
143
- ### accept-risk / false-positive
144
-
145
- 1. Resolve the target by `item N`; fall through to `discuss` if absent/unknown.
146
- 2. Extract the reason (text after the first `:`, trimmed; "no reason given" if absent).
147
- 3. `github_clone_repo`. Read `SECURITY.md`; create from the scaffold in
148
- [references/templates.md](references/templates.md) if missing.
149
- 4. Append a row to the matching table (accepted risks OR false positives) per the
150
- template.
151
- 5. Commit on branch `security/feedback-{parentIssueNumber}-{shortFingerprint}`,
152
- push, and open a PR titled `security: record {accept-risk|false-positive} for {shortFingerprint}`.
153
- 6. Comment on the parent: `Opened PR #{prNumber} to record this in SECURITY.md.
154
- Once merged, this finding will be suppressed in future scans.`
155
- 7. Do **not** tick the task-list checkbox — that marker is reserved for "broken out to sub-issue".
156
-
157
- ### reopen
158
-
159
- Reply: "To re-evaluate this finding, run `@last-light security-review` — the next
160
- scan re-picks it up if `SECURITY.md` has been updated." Do not modify `SECURITY.md`.
161
-
162
- ### discuss
163
-
164
- Reply conversationally using the finding's `<details>` block (risk, tool, suggested
165
- fix). Don't modify `SECURITY.md` or create sub-issues.
166
-
167
- ### ignore
168
-
169
- Take no action.
170
-
171
- ## Tool usage
172
-
173
- GitHub operations via `github_*` MCP tools only — never `gh` CLI, `curl`, or raw HTTP.
@@ -1,77 +0,0 @@
1
- # security-feedback templates
2
-
3
- ## Sub-issue body (create-issues)
4
-
5
- `github_create_issue` with `title` = the finding's `title` (exactly as parsed, no
6
- prefix/suffix), `labels` = `["security", severity]` (e.g. `["security",
7
- "p0-critical"]`), and this body:
8
-
9
- ````markdown
10
- <!-- fp:{fingerprint} -->
11
- <!-- parent-security-scan: #{parentIssueNumber} -->
12
-
13
- Broken out from security scan #{parentIssueNumber} on {today's date} at @{sender}'s request.
14
-
15
- **File**: `{file}:{line}`
16
- **Tool**: {tool} · `{rule}`
17
- **Severity**: {severity}
18
-
19
- ```{language}
20
- {snippet}
21
- ```
22
-
23
- {explanation}
24
-
25
- ## Suggested fix
26
-
27
- {suggestedFix}
28
-
29
- ---
30
-
31
- _To build a fix for this finding, comment `@last-light build` on this issue._
32
- ````
33
-
34
- ## SECURITY.md scaffold (accept-risk / false-positive)
35
-
36
- Create this if `SECURITY.md` is missing, then append the row:
37
-
38
- ```markdown
39
- # SECURITY.md
40
-
41
- This file configures the Last Light security scanner for this repository.
42
-
43
- ## Tool configuration
44
-
45
- | Tool | Severity floor |
46
- |------|---------------|
47
- | npm-audit | medium |
48
- | semgrep | medium |
49
- | gitleaks | high |
50
- | claude | medium |
51
-
52
- ## Accepted risks
53
-
54
- Findings in this table are known risks the maintainers have explicitly accepted.
55
- The scanner will not re-file issues for these findings.
56
-
57
- | Fingerprint | Title | Reason | Date | Issue |
58
- |-------------|-------|--------|------|-------|
59
-
60
- ## False positives
61
-
62
- Findings in this table have been classified as not real security issues.
63
- The scanner will not re-file issues for these findings.
64
-
65
- | Fingerprint | Title | Reason | Date | Issue |
66
- |-------------|-------|--------|------|-------|
67
- ```
68
-
69
- Appended row (to whichever table matches the intent):
70
-
71
- | Column | Value |
72
- |--------|-------|
73
- | Fingerprint | First 16 hex chars of the finding's `fp` |
74
- | Title | Finding's `title` |
75
- | Reason | Extracted reason (text after the first `:`; "no reason given" if absent) |
76
- | Date | Today's date (YYYY-MM-DD, UTC) |
77
- | Issue | `#{parentIssueNumber}` |
@@ -1,215 +0,0 @@
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
- One idempotent `github_ensure_labels` call — pass every row below as a single
72
- `labels` array of `{name, color}` (it creates only the missing ones, never
73
- errors on existing labels):
74
-
75
- | Label | Color | Purpose |
76
- |-------|-------|---------|
77
- | `security` | `ee0701` | Any security-related issue |
78
- | `security-scan` | `fbca04` | The per-run summary issue |
79
- | `p0-critical` | `b60205` | Severity |
80
- | `p1-high` | `d93f0b` | Severity |
81
- | `p2-medium` | `fbca04` | Severity |
82
- | `p3-low` | `0e8a16` | Severity |
83
-
84
- ### 3. Run change-scoped scanners
85
-
86
- Three sources, all narrowed to the changeset. Do **not** run `npm audit` or
87
- `semgrep --config auto .` over the whole tree (covered elsewhere; the noise
88
- drowns the signal).
89
-
90
- - **Gitleaks (commit range):**
91
- `gitleaks detect --source . --log-opts="--since=${priorScanTs}" --report-format json --report-path /tmp/gitleaks.json`
92
- — secrets introduced in the new history.
93
- - **Semgrep (changed files only):**
94
- `semgrep --config auto --json $(printf -- '--include=%s ' "${changedFiles[@]}")`
95
- — only files that changed; far less noise.
96
- - **Claude SDLC review** — the unique value-add. Read `git diff ${priorScanTs}..HEAD`
97
- plus the current contents of changed files against the checklist below. Each
98
- match becomes a finding with `tool: "claude"` and the §4 severity.
99
-
100
- - **GitHub Actions / CI** (`.github/workflows/*.yml`): actions pinned by
101
- floating ref (`@main`/`@master`/`@v1`) not a commit SHA; `pull_request_target`
102
- that checks out the PR head; missing top-level/job `permissions:` block;
103
- `${{ secrets.* }}` interpolated into shell/`run:`/echo where it can land in
104
- logs; untrusted PR body/title/branch interpolated into a `run:` block.
105
- - **Dockerfile / compose**: base images on floating tags (no digest) introduced
106
- here; new `RUN curl … | sh` / `wget … | bash`; new `--privileged`/`--cap-add`,
107
- removed `security_opt`/`read_only` hardening; new host-exposed ports without need.
108
- - **Auth / authorization**: modified middleware, route guards, role checks, CORS,
109
- JWT verification, OAuth handlers, webhook signature verification (HMAC compare,
110
- `crypto.timingSafeEqual` replaced with `===`).
111
- - **Secret handling in new code**: new `process.env.*` reads whose value flows
112
- into a log or HTTP response; new code logging Authorization headers/cookies/tokens;
113
- hardcoded key/URL-shaped literals gitleaks missed.
114
- - **Shell exec on attacker-influenced args**: new `execSync`/`exec`/`spawn` where
115
- any argument is non-static (concatenation, interpolation, request-derived).
116
- - **Supply-chain churn** (`package.json` diff): **new** top-level
117
- `dependencies`/`devDependencies` entries (not version bumps — filtered at §1.5);
118
- flag package name + publisher, higher severity for typosquat-shaped names;
119
- removed integrity controls (`npm ci` → `npm install`, dropped `--ignore-scripts`
120
- or provenance flags).
121
- - **Release / publish flows**: changes to publish scripts, `npm publish`, release
122
- CI steps, signing keys — anything touching what users download.
123
-
124
- If the only changes are docs/tests/unrelated config and none of the above
125
- applied, the run legitimately has **no findings** — proceed to §8.
126
-
127
- ### 4. Normalize findings
128
-
129
- Convert each to: `{ fingerprint, severity, tool, rule, file, line, title,
130
- language, snippet, explanation, suggestedFix }`.
131
-
132
- - `fingerprint` = `sha1(tool + ":" + rule + ":" + file + ":" + 3-line-context)`, lowercase hex.
133
- - `severity` ∈ `p0-critical | p1-high | p2-medium | p3-low`.
134
- - `tool` ∈ `npm-audit | semgrep | gitleaks | claude` (lowercase, hyphenated).
135
- - `rule` = tool-native id, as-is. `file` = repo-relative, forward slashes.
136
- - `line` = 1-based; `0` when not line-scoped. `title` = one line, no backticks/asterisks.
137
-
138
- Severity mapping: npm-audit critical/high/moderate/low → p0/p1/p2/p3;
139
- semgrep ERROR/WARNING/INFO → p1/p2/p3; gitleaks (all) → p1-high;
140
- claude critical/high/medium/low → p0/p1/p2/p3.
141
-
142
- ### 5. Apply severity floor
143
-
144
- Drop findings below the SECURITY.md floor (default `medium` → drops `p3-low`).
145
-
146
- ### 6. Filter accepted risks / false positives
147
-
148
- Drop findings whose fingerprint prefix (first 16 hex chars) appears in the
149
- SECURITY.md accepted-risks or false-positives tables.
150
-
151
- ### 7. Sort and cap
152
-
153
- Sort by `(severity rank p0<p1<p2<p3, then file asc, then line asc)`.
154
-
155
- The issue body has a hard 65,536-char GitHub limit. Cap: keep **ALL** `p0-critical`
156
- and **ALL** `p1-high`; keep at most **10** of `p2-medium`+`p3-low` combined (the
157
- first 10 after the sort). Assign 1-based `item` numbers top-to-bottom across the
158
- **kept** findings. `overflow` = survived-filtering minus kept; surface it in the
159
- overflow note.
160
-
161
- The cap intentionally puts no ceiling on critical/high — if a misconfigured
162
- scanner emits hundreds of highs and the body still overflows, raise the
163
- `SECURITY.md` floor or tune the scanner's rule severities (fix at the source, not
164
- by hiding real findings).
165
-
166
- ### 8. Early exit: no findings
167
-
168
- If the filtered-and-capped list is empty, **do not** create the summary issue.
169
- Write the run summary file (§10) recording why and return **silently** — no Slack
170
- message. The cron is intentionally low-noise: only actual findings surface.
171
-
172
- ### 9. Compose and create the summary issue
173
-
174
- Render the body per [references/issue-format.md](references/issue-format.md) and
175
- `github_create_issue` with `title: Security scan — {YYYY-MM-DD}` (UTC),
176
- `labels: ["security", "security-scan"]`. Record `summaryIssueNumber`. Do **not**
177
- touch prior `security-scan` issues — each scan is a point-in-time snapshot.
178
-
179
- ### 10. Write the run summary file
180
-
181
- Write `{issueDir}/security-summary.md`:
182
-
183
- ```markdown
184
- # Security Scan Summary — {repo}
185
-
186
- **Date**: {YYYY-MM-DD}
187
- **Prior scan anchor**: {priorScanTs} (issue #{priorScanIssueNumber} or "bootstrap floor")
188
- **Commits reviewed**: {N} (after filtering Renovate/Dependabot/lockfile-only)
189
- **Changed files**: {nFiles}
190
- **Summary issue**: #{summaryIssueNumber} (or "none — no findings")
191
-
192
- **Scanner raw counts**: gitleaks: {n}, semgrep: {n}, claude: {n}
193
- **After severity floor**: {n}
194
- **After SECURITY.md filtering**: {n} (filed)
195
- **Suppressed**: {n} (accepted: {nA}, false-positive: {nFP})
196
- {if overflow > 0}: **Overflow**: {overflow} lower-severity findings omitted (cap: ALL critical/high + first 10 medium/low)
197
- ```
198
-
199
- On a §1.5 early exit, still write the file and state `**Early exit**: no human
200
- commits since prior scan`.
201
-
202
- ### 11. Slack summary (optional)
203
-
204
- If `context.deliverSlackSummary` is true, output as the final response:
205
-
206
- - **With findings:**
207
- ```
208
- *Security scan: {repo}* — {n} findings filed in #{summaryIssueNumber} ({N} commits since {priorScanDate})
209
- Critical: {nC} · High: {nH} · Medium: {nM} · Low: {nL}
210
- ```
211
- - **No findings** (scanners ran clean) or **§1.5 early exit** → emit nothing;
212
- silence matches the cron's low-noise design. The run summary file still records
213
- what was reviewed.
214
-
215
- Otherwise output the run summary file contents as the final response.