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,244 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { COREDNS_OPEN_IP, COREDNS_STRICT_IP, NGINX_OPEN_IP, NGINX_STRICT_IP, OTEL_COLLECTOR_IP, OTEL_COLLECTOR_OTLP_GRPC_PORT, OTEL_COLLECTOR_OTLP_HTTP_PORT, OTEL_COLLECTOR_SANDBOX_ENDPOINT, renderCorefileOpen, renderCorefileStrict, renderNginxOpenConf, renderNginxStrictConf, renderOtelCollectorConfig, SANDBOX_EGRESS_SUBNET, } from "./egress-firewall-config.js";
3
+ import { DEFAULT_ALLOWLIST } from "./egress-allowlist.js";
4
+ import { parse as parseYaml } from "yaml";
5
+ describe("static IP constants", () => {
6
+ it("all four service IPs sit inside the sandbox-egress subnet", () => {
7
+ const prefix = SANDBOX_EGRESS_SUBNET.split("/")[0].split(".").slice(0, 3).join(".");
8
+ for (const ip of [COREDNS_STRICT_IP, COREDNS_OPEN_IP, NGINX_STRICT_IP, NGINX_OPEN_IP]) {
9
+ expect(ip.startsWith(prefix + ".")).toBe(true);
10
+ }
11
+ });
12
+ it("strict and open IPs are distinct in both pairs", () => {
13
+ expect(COREDNS_STRICT_IP).not.toBe(COREDNS_OPEN_IP);
14
+ expect(NGINX_STRICT_IP).not.toBe(NGINX_OPEN_IP);
15
+ });
16
+ });
17
+ describe("nginx strict config", () => {
18
+ const conf = renderNginxStrictConf();
19
+ it("listens on 443 with ssl_preread enabled", () => {
20
+ expect(conf).toMatch(/listen\s+443;/);
21
+ expect(conf).toMatch(/ssl_preread\s+on;/);
22
+ });
23
+ it("defaults unknown SNIs to a black-hole upstream (instant reset)", () => {
24
+ expect(conf).toMatch(/default\s+127\.0\.0\.1:1;/);
25
+ });
26
+ it("emits a leading-dot map entry per allowlist host (apex+subdomain match)", () => {
27
+ for (const host of DEFAULT_ALLOWLIST) {
28
+ // nginx's `.foo.com` syntax matches `foo.com` and any subdomain.
29
+ // Upstream is the live SNI value, not pinned at config time.
30
+ expect(conf).toContain(`.${host} $ssl_preread_server_name:443;`);
31
+ }
32
+ });
33
+ it("uses docker's embedded DNS as the upstream resolver", () => {
34
+ expect(conf).toMatch(/resolver\s+127\.0\.0\.11/);
35
+ });
36
+ it("declares `hostnames` in the map block so leading-dot wildcards work", () => {
37
+ // Without `hostnames;`, nginx's `map` does exact string match only —
38
+ // `.github.com` becomes a literal key that never matches anything.
39
+ // We hit this in prod: every allowlisted host fell through to the
40
+ // black-hole default. Pin the contract so it can't regress.
41
+ expect(conf).toMatch(/map\s+\$ssl_preread_server_name\s+\$upstream_target\s*\{\s*\n\s*hostnames;/);
42
+ });
43
+ });
44
+ describe("nginx open config", () => {
45
+ const conf = renderNginxOpenConf();
46
+ it("tunnels whatever SNI was sent — no allowlist map", () => {
47
+ expect(conf).toMatch(/proxy_pass\s+\$ssl_preread_server_name:443;/);
48
+ expect(conf).not.toMatch(/map\s+\$ssl_preread_server_name/);
49
+ });
50
+ it("still listens on 443 with ssl_preread enabled", () => {
51
+ expect(conf).toMatch(/listen\s+443;/);
52
+ expect(conf).toMatch(/ssl_preread\s+on;/);
53
+ });
54
+ });
55
+ describe("coredns strict Corefile", () => {
56
+ const conf = renderCorefileStrict();
57
+ it("uses a SINGLE template block with one match line per allowlist host", () => {
58
+ // CoreDNS only honours one `template` block per (class, type, zone) —
59
+ // multiple blocks silently shadow each other. Catching a regression
60
+ // matters because we hit this exact bug in prod.
61
+ const templateBlocks = conf.match(/template\s+IN\s+A\s*\{/g) || [];
62
+ expect(templateBlocks.length).toBe(1);
63
+ for (const host of DEFAULT_ALLOWLIST) {
64
+ const escaped = host.replaceAll(".", "\\.");
65
+ expect(conf).toContain(`(^|\\.)${escaped}\\.$`);
66
+ }
67
+ });
68
+ it("answers with the nginx-strict IP", () => {
69
+ expect(conf).toContain(`IN A ${NGINX_STRICT_IP}`);
70
+ });
71
+ it("catches every unmatched query with an NXDOMAIN template", () => {
72
+ expect(conf).toMatch(/template\s+IN\s+ANY\s*\{[\s\S]*rcode\s+NXDOMAIN[\s\S]*\}/);
73
+ });
74
+ });
75
+ describe("coredns open Corefile", () => {
76
+ const conf = renderCorefileOpen();
77
+ it("returns the nginx-open IP for arbitrary A queries", () => {
78
+ expect(conf).toContain(`IN A ${NGINX_OPEN_IP}`);
79
+ });
80
+ it("hard-denies cloud metadata literals even in unrestricted mode", () => {
81
+ // Each hard-deny host gets its own zone block so CoreDNS's
82
+ // longest-suffix routing intercepts the apex + subdomains before
83
+ // the catch-all `.` zone sees them.
84
+ expect(conf).toMatch(/metadata\.google\.internal:53\s*\{[\s\S]*?rcode\s+NXDOMAIN/);
85
+ expect(conf).toMatch(/169\.254\.169\.254:53\s*\{[\s\S]*?rcode\s+NXDOMAIN/);
86
+ });
87
+ it("returns NOERROR / empty for AAAA so IPv6 doesn't accidentally bypass us", () => {
88
+ expect(conf).toMatch(/template\s+IN\s+AAAA\s*\{[\s\S]*rcode\s+NOERROR[\s\S]*\}/);
89
+ });
90
+ });
91
+ describe("otel collector config", () => {
92
+ // Most tests run with forwarding active; the gating tests below cover inactive.
93
+ const renderActive = (env) => parseYaml(renderOtelCollectorConfig({ active: true, env }));
94
+ it("sandbox endpoint points at the collector's static IP + OTLP/HTTP port", () => {
95
+ expect(OTEL_COLLECTOR_SANDBOX_ENDPOINT).toBe(`http://${OTEL_COLLECTOR_IP}:${OTEL_COLLECTOR_OTLP_HTTP_PORT}`);
96
+ });
97
+ it("receives OTLP on both http and grpc, on all interfaces", () => {
98
+ const cfg = renderActive({});
99
+ expect(cfg.receivers.otlp.protocols.http.endpoint).toBe(`0.0.0.0:${OTEL_COLLECTOR_OTLP_HTTP_PORT}`);
100
+ expect(cfg.receivers.otlp.protocols.grpc.endpoint).toBe(`0.0.0.0:${OTEL_COLLECTOR_OTLP_GRPC_PORT}`);
101
+ });
102
+ it("re-exports to the generic endpoint (as a base URL) with parsed auth headers on every signal", () => {
103
+ const cfg = renderActive({
104
+ OTEL_EXPORTER_OTLP_ENDPOINT: "https://collector.example.com:4318",
105
+ OTEL_EXPORTER_OTLP_HEADERS: "api-key=secret-123,x-tenant=acme",
106
+ });
107
+ for (const signal of ["traces", "metrics", "logs"]) {
108
+ const exp = cfg.exporters[`otlphttp/${signal}`];
109
+ // Generic endpoint → `endpoint` field (collector appends /v1/<signal>).
110
+ expect(exp.endpoint).toBe("https://collector.example.com:4318");
111
+ expect(exp[`${signal}_endpoint`]).toBeUndefined();
112
+ expect(exp.headers).toEqual({ "api-key": "secret-123", "x-tenant": "acme" });
113
+ expect(cfg.service.pipelines[signal].exporters).toEqual([`otlphttp/${signal}`]);
114
+ }
115
+ });
116
+ it("routes per-signal endpoints to their own pipeline (no fallback-chain misrouting)", () => {
117
+ // The bug the reviewer flagged: separate traces/metrics endpoints must not
118
+ // both export to whichever one won a `||` chain.
119
+ const cfg = renderActive({
120
+ OTEL_EXPORTER_OTLP_TRACES_ENDPOINT: "https://traces.example.com/v1/traces",
121
+ OTEL_EXPORTER_OTLP_METRICS_ENDPOINT: "https://metrics.example.com/v1/metrics",
122
+ });
123
+ // Signal-specific endpoints are used verbatim via `<signal>_endpoint`.
124
+ expect(cfg.exporters["otlphttp/traces"].traces_endpoint).toBe("https://traces.example.com/v1/traces");
125
+ expect(cfg.exporters["otlphttp/metrics"].metrics_endpoint).toBe("https://metrics.example.com/v1/metrics");
126
+ expect(cfg.service.pipelines.traces.exporters).toEqual(["otlphttp/traces"]);
127
+ expect(cfg.service.pipelines.metrics.exporters).toEqual(["otlphttp/metrics"]);
128
+ // logs had no endpoint configured → debug, not silently misrouted.
129
+ expect(cfg.service.pipelines.logs.exporters).toEqual(["debug"]);
130
+ expect(cfg.exporters.debug).toBeDefined();
131
+ });
132
+ it("honours a logs-only endpoint instead of dropping it (the silent-drop case)", () => {
133
+ const cfg = renderActive({
134
+ OTEL_EXPORTER_OTLP_LOGS_ENDPOINT: "https://logs.example.com/v1/logs",
135
+ });
136
+ expect(cfg.exporters["otlphttp/logs"].logs_endpoint).toBe("https://logs.example.com/v1/logs");
137
+ expect(cfg.service.pipelines.logs.exporters).toEqual(["otlphttp/logs"]);
138
+ expect(cfg.service.pipelines.traces.exporters).toEqual(["debug"]);
139
+ expect(cfg.service.pipelines.metrics.exporters).toEqual(["debug"]);
140
+ });
141
+ it("lets a signal-specific endpoint override the generic one for just that signal", () => {
142
+ const cfg = renderActive({
143
+ OTEL_EXPORTER_OTLP_ENDPOINT: "https://generic.example.com",
144
+ OTEL_EXPORTER_OTLP_TRACES_ENDPOINT: "https://traces.example.com/v1/traces",
145
+ });
146
+ // traces → verbatim specific URL; metrics/logs → generic base.
147
+ expect(cfg.exporters["otlphttp/traces"].traces_endpoint).toBe("https://traces.example.com/v1/traces");
148
+ expect(cfg.exporters["otlphttp/metrics"].endpoint).toBe("https://generic.example.com");
149
+ expect(cfg.exporters["otlphttp/logs"].endpoint).toBe("https://generic.example.com");
150
+ });
151
+ it("applies per-signal header overrides, falling back to generic headers", () => {
152
+ const cfg = renderActive({
153
+ OTEL_EXPORTER_OTLP_ENDPOINT: "https://generic.example.com",
154
+ OTEL_EXPORTER_OTLP_HEADERS: "authorization=generic",
155
+ OTEL_EXPORTER_OTLP_TRACES_HEADERS: "authorization=traces-only",
156
+ });
157
+ expect(cfg.exporters["otlphttp/traces"].headers.authorization).toBe("traces-only");
158
+ expect(cfg.exporters["otlphttp/metrics"].headers.authorization).toBe("generic");
159
+ });
160
+ it("supports a non-443 / custom-port HTTPS backend the strict SNI firewall could not reach", () => {
161
+ // This is the case the reviewer flagged for the old direct-forward path.
162
+ // It now works because the collector dials the backend on its trusted
163
+ // outbound leg, not through ssl_preread.
164
+ const cfg = renderActive({ OTEL_EXPORTER_OTLP_ENDPOINT: "https://otel.internal:4318" });
165
+ expect(cfg.exporters["otlphttp/traces"].endpoint).toBe("https://otel.internal:4318");
166
+ });
167
+ it("preserves '=' inside header values (bearer tokens survive intact)", () => {
168
+ const cfg = renderActive({
169
+ OTEL_EXPORTER_OTLP_ENDPOINT: "https://b.example.com",
170
+ OTEL_EXPORTER_OTLP_HEADERS: "authorization=Bearer abc=def==",
171
+ });
172
+ expect(cfg.exporters["otlphttp/traces"].headers.authorization).toBe("Bearer abc=def==");
173
+ });
174
+ it("falls back to a debug exporter (no data leaves) when active but no backend is configured", () => {
175
+ const cfg = renderActive({});
176
+ expect(cfg.exporters.debug).toBeDefined();
177
+ expect(cfg.exporters["otlphttp/traces"]).toBeUndefined();
178
+ for (const signal of ["traces", "metrics", "logs"]) {
179
+ expect(cfg.service.pipelines[signal].exporters).toEqual(["debug"]);
180
+ }
181
+ });
182
+ it("produces valid YAML even with quote/backslash-bearing header values", () => {
183
+ // Crucially, a single quote in a header value no longer fails anything:
184
+ // it lives in the host-side collector config, never a sandbox shell wrap.
185
+ const cfg = renderActive({
186
+ OTEL_EXPORTER_OTLP_ENDPOINT: "https://b.example.com",
187
+ OTEL_EXPORTER_OTLP_HEADERS: `x-quote=it's "quoted" \\ backslash`,
188
+ });
189
+ expect(cfg.exporters["otlphttp/traces"].headers["x-quote"]).toBe(`it's "quoted" \\ backslash`);
190
+ });
191
+ it("drops CR/LF-bearing header pairs (no header injection, no broken YAML) but keeps the rest", () => {
192
+ // A newline in a header value would be header injection on the
193
+ // collector→backend leg and would also break the YAML scalar.
194
+ const raw = renderOtelCollectorConfig({
195
+ active: true,
196
+ env: {
197
+ OTEL_EXPORTER_OTLP_ENDPOINT: "https://b.example.com",
198
+ OTEL_EXPORTER_OTLP_HEADERS: "x-good=ok,x-bad=line1\nline2",
199
+ },
200
+ });
201
+ expect(() => parseYaml(raw)).not.toThrow();
202
+ const cfg = parseYaml(raw);
203
+ expect(cfg.exporters["otlphttp/traces"].headers).toEqual({ "x-good": "ok" });
204
+ });
205
+ describe("forwarding gate (security floor)", () => {
206
+ it("when inactive, drops every signal to debug and emits no backend endpoint or credential", () => {
207
+ const raw = renderOtelCollectorConfig({
208
+ active: false,
209
+ env: {
210
+ OTEL_EXPORTER_OTLP_ENDPOINT: "https://real-backend.example.com",
211
+ OTEL_EXPORTER_OTLP_HEADERS: "authorization=super-secret-token",
212
+ OTEL_EXPORTER_OTLP_TRACES_ENDPOINT: "https://traces.example.com",
213
+ },
214
+ });
215
+ // No backend URL or secret leaks into the generated file at all.
216
+ expect(raw).not.toContain("real-backend.example.com");
217
+ expect(raw).not.toContain("super-secret-token");
218
+ expect(raw).not.toContain("traces.example.com");
219
+ expect(raw).not.toContain("otlphttp");
220
+ const cfg = parseYaml(raw);
221
+ expect(cfg.exporters.debug).toBeDefined();
222
+ for (const signal of ["traces", "metrics", "logs"]) {
223
+ expect(cfg.service.pipelines[signal].exporters).toEqual(["debug"]);
224
+ }
225
+ // Receiver still listens so sandboxes don't get connection errors.
226
+ expect(cfg.receivers.otlp.protocols.http.endpoint).toBe(`0.0.0.0:${OTEL_COLLECTOR_OTLP_HTTP_PORT}`);
227
+ });
228
+ });
229
+ });
230
+ describe("apex + subdomain match sanity", () => {
231
+ // Pin behaviour: a bare entry like "github.com" must match both
232
+ // the apex and any subdomain in both backends.
233
+ it("'github.com' generates an nginx leading-dot map entry", () => {
234
+ const conf = renderNginxStrictConf();
235
+ expect(conf).toMatch(/\s\.github\.com\s+\$ssl_preread_server_name:443;/);
236
+ });
237
+ it("'github.com' generates a CoreDNS pattern matching apex + subdomains", () => {
238
+ const conf = renderCorefileStrict();
239
+ // (^|\.)github\.com\.$ matches both "github.com." and "api.github.com."
240
+ // in FQDN-with-trailing-dot form.
241
+ expect(conf).toContain("(^|\\.)github\\.com\\.$");
242
+ });
243
+ });
244
+ //# sourceMappingURL=egress-firewall-config.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"egress-firewall-config.test.js","sourceRoot":"","sources":["../../src/sandbox/egress-firewall-config.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Sandbox image names + the docker availability probes. Kept in this
3
+ * dependency-light module (only `child_process`, no `./docker.js`) so callers
4
+ * like the workflow runner can check image availability without importing the
5
+ * full `DockerSandbox` machinery — `docker.ts` runs `promisify(execFile)` at
6
+ * module load, which trips test suites that mock `child_process`.
7
+ */
8
+ /** The lean default sandbox image (`sandbox.Dockerfile`). */
9
+ export declare const SANDBOX_IMAGE = "lastlight-sandbox:latest";
10
+ /**
11
+ * The enriched browser-QA image (Playwright + Chromium baked in). Built only
12
+ * when QA is enabled (`sandbox-qa.Dockerfile`); a phase opts into it with
13
+ * `sandbox_image: qa`. Fixed name, deliberately not overridable.
14
+ */
15
+ export declare const SANDBOX_IMAGE_QA = "lastlight-sandbox-qa:latest";
16
+ /** Check if Docker sandbox mode is available (docker up + lean image built). */
17
+ export declare function isSandboxAvailable(): boolean;
18
+ /**
19
+ * Whether the browser-QA sandbox image is present on this host. Used by the
20
+ * runner to gracefully skip a `sandbox_image: qa` phase when the image hasn't
21
+ * been built (the lean default deploy), rather than failing the run.
22
+ */
23
+ export declare function qaImageAvailable(): boolean;
@@ -0,0 +1,55 @@
1
+ import { execFileSync } from "child_process";
2
+ /**
3
+ * Sandbox image names + the docker availability probes. Kept in this
4
+ * dependency-light module (only `child_process`, no `./docker.js`) so callers
5
+ * like the workflow runner can check image availability without importing the
6
+ * full `DockerSandbox` machinery — `docker.ts` runs `promisify(execFile)` at
7
+ * module load, which trips test suites that mock `child_process`.
8
+ */
9
+ /** The lean default sandbox image (`sandbox.Dockerfile`). */
10
+ export const SANDBOX_IMAGE = "lastlight-sandbox:latest";
11
+ /**
12
+ * The enriched browser-QA image (Playwright + Chromium baked in). Built only
13
+ * when QA is enabled (`sandbox-qa.Dockerfile`); a phase opts into it with
14
+ * `sandbox_image: qa`. Fixed name, deliberately not overridable.
15
+ */
16
+ export const SANDBOX_IMAGE_QA = "lastlight-sandbox-qa:latest";
17
+ /** Check if Docker sandbox mode is available (docker up + lean image built). */
18
+ export function isSandboxAvailable() {
19
+ return dockerAvailable() && sandboxImageExists(SANDBOX_IMAGE);
20
+ }
21
+ /** Cached check — only probe for the QA image once per process. */
22
+ let _qaImageAvailable = null;
23
+ /**
24
+ * Whether the browser-QA sandbox image is present on this host. Used by the
25
+ * runner to gracefully skip a `sandbox_image: qa` phase when the image hasn't
26
+ * been built (the lean default deploy), rather than failing the run.
27
+ */
28
+ export function qaImageAvailable() {
29
+ if (_qaImageAvailable === null) {
30
+ _qaImageAvailable = dockerAvailable() && sandboxImageExists(SANDBOX_IMAGE_QA);
31
+ }
32
+ return _qaImageAvailable;
33
+ }
34
+ function dockerAvailable() {
35
+ try {
36
+ execFileSync("docker", ["info"], { stdio: "ignore", timeout: 5000 });
37
+ return true;
38
+ }
39
+ catch {
40
+ return false;
41
+ }
42
+ }
43
+ function sandboxImageExists(imageName) {
44
+ try {
45
+ const out = execFileSync("docker", ["images", "-q", imageName], {
46
+ encoding: "utf-8",
47
+ stdio: ["pipe", "pipe", "pipe"],
48
+ });
49
+ return out.trim().length > 0;
50
+ }
51
+ catch {
52
+ return false;
53
+ }
54
+ }
55
+ //# sourceMappingURL=images.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"images.js","sourceRoot":"","sources":["../../src/sandbox/images.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAE7C;;;;;;GAMG;AAEH,6DAA6D;AAC7D,MAAM,CAAC,MAAM,aAAa,GAAG,0BAA0B,CAAC;AAExD;;;;GAIG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,6BAA6B,CAAC;AAE9D,gFAAgF;AAChF,MAAM,UAAU,kBAAkB;IAChC,OAAO,eAAe,EAAE,IAAI,kBAAkB,CAAC,aAAa,CAAC,CAAC;AAChE,CAAC;AAED,mEAAmE;AACnE,IAAI,iBAAiB,GAAmB,IAAI,CAAC;AAE7C;;;;GAIG;AACH,MAAM,UAAU,gBAAgB;IAC9B,IAAI,iBAAiB,KAAK,IAAI,EAAE,CAAC;QAC/B,iBAAiB,GAAG,eAAe,EAAE,IAAI,kBAAkB,CAAC,gBAAgB,CAAC,CAAC;IAChF,CAAC;IACD,OAAO,iBAAiB,CAAC;AAC3B,CAAC;AAED,SAAS,eAAe;IACtB,IAAI,CAAC;QACH,YAAY,CAAC,QAAQ,EAAE,CAAC,MAAM,CAAC,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;QACrE,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,SAAS,kBAAkB,CAAC,SAAiB;IAC3C,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,YAAY,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE,IAAI,EAAE,SAAS,CAAC,EAAE;YAC9D,QAAQ,EAAE,OAAO;YACjB,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;SAChC,CAAC,CAAC;QACH,OAAO,GAAG,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC;IAC/B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
@@ -1,15 +1,34 @@
1
1
  import { DockerSandbox } from "./docker.js";
2
2
  export { DockerSandbox } from "./docker.js";
3
+ export { SANDBOX_IMAGE, SANDBOX_IMAGE_QA, isSandboxAvailable, qaImageAvailable, } from "./images.js";
3
4
  /**
4
5
  * Clean up orphaned sandbox containers from previous runs.
5
6
  * Called on startup to remove containers that survived a harness restart.
6
7
  */
7
8
  export declare function cleanupOrphanedSandboxes(): void;
9
+ export declare function sandboxAvailable(): boolean;
8
10
  /**
9
- * Check if Docker sandbox mode is available.
11
+ * Set up the per-task worktree directory (mkdir + optional pre-clone) without
12
+ * touching Docker. Used by the non-docker sandbox modes (gondolin / none) where
13
+ * agentic-pi runs in-process or in a VM rather than a container, but still
14
+ * wants a per-task workspace cloned from the target branch.
10
15
  */
11
- export declare function isSandboxAvailable(): boolean;
12
- export declare function sandboxAvailable(): boolean;
16
+ export declare function setupTaskWorktree(opts: {
17
+ taskId: string;
18
+ stateDir: string;
19
+ sandboxDir?: string;
20
+ prePopulate?: {
21
+ owner: string;
22
+ repo: string;
23
+ branch: string;
24
+ token: string;
25
+ /** Owning run id — stamped into a marker so a reused per-PR workspace
26
+ * refreshes across runs but is preserved between phases of one run. */
27
+ runId?: string;
28
+ /** Clone shallowly (`--depth 1 --single-branch`) for read-only workflows. */
29
+ shallow?: boolean;
30
+ };
31
+ }): string;
13
32
  /**
14
33
  * Create a sandbox for a task. Returns the sandbox and a cleanup function.
15
34
  * If Docker is not available, returns null (caller should fall back to direct execution).
@@ -19,8 +38,68 @@ export declare function createTaskSandbox(opts: {
19
38
  stateDir: string;
20
39
  sandboxDir?: string;
21
40
  env?: Record<string, string>;
41
+ /**
42
+ * When set, the harness clones the repo into workDir at the named branch
43
+ * before starting the sandbox container. The agent then enters a
44
+ * workspace that's already checked out, avoiding a redundant
45
+ * `clone_repo` MCP call inside the session.
46
+ *
47
+ * Token must be alphanumeric (shape asserted upstream) and is embedded
48
+ * into the clone URL just for this one-shot operation — git's own
49
+ * credential.helper inside the sandbox covers subsequent push/pull.
50
+ */
51
+ prePopulate?: {
52
+ owner: string;
53
+ repo: string;
54
+ branch: string;
55
+ token: string;
56
+ /** Owning run id — stamped into a marker so a reused per-PR workspace
57
+ * refreshes across runs but is preserved between phases of one run. */
58
+ runId?: string;
59
+ /** Clone shallowly (`--depth 1 --single-branch`) for read-only workflows. */
60
+ shallow?: boolean;
61
+ };
62
+ /**
63
+ * IP of the coredns sidecar to use as the sandbox's DNS resolver.
64
+ * Selects the egress policy: `172.30.0.10` (coredns-strict) for the
65
+ * default allowlist, `172.30.0.11` (coredns-open) for phases that
66
+ * declared `unrestricted_egress: true`. Passed to `docker run` as
67
+ * `--dns <ip>`. See src/sandbox/egress-firewall-config.ts.
68
+ */
69
+ dnsIp?: string;
70
+ /**
71
+ * Override the container image. Defaults to the lean `SANDBOX_IMAGE`; a
72
+ * browser-QA phase passes `SANDBOX_IMAGE_QA`. The caller is responsible for
73
+ * ensuring the image exists (see `qaImageAvailable`).
74
+ */
75
+ imageName?: string;
22
76
  }): Promise<{
23
77
  sandbox: DockerSandbox;
24
78
  workDir: string;
25
79
  cleanup: () => Promise<void>;
26
80
  } | null>;
81
+ type PrePopulate = {
82
+ owner: string;
83
+ repo: string;
84
+ branch: string;
85
+ token: string;
86
+ runId?: string;
87
+ shallow?: boolean;
88
+ };
89
+ /**
90
+ * Clone the repo into `<workDir>/<repo>` at the given branch.
91
+ *
92
+ * Three cases:
93
+ * - **Fresh dir** (no `.git`): clone. `--depth 1 --single-branch` for
94
+ * read-only workflows (`pre.shallow`), `--depth 50` otherwise.
95
+ * - **Same run revisiting the workspace** (`.git` exists, run marker matches
96
+ * `pre.runId`): preserve — this is a later phase of the same run reading
97
+ * what an earlier phase wrote (architect's `plan.md`, the reviewer's
98
+ * checkout). No git ops.
99
+ * - **A fresh run reusing an old per-PR workspace** (`.git` exists, marker
100
+ * differs/absent): fetch + hard-reset to the remote branch + `git clean`
101
+ * that **keeps `node_modules`** so the next `npm install` is incremental.
102
+ * This is the re-review fast path from issue #107.
103
+ */
104
+ export { prePopulateWorkspace as __prePopulateWorkspaceForTest };
105
+ declare function prePopulateWorkspace(workDir: string, pre: PrePopulate): void;