lastlight 0.16.0 → 0.16.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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} +26 -1
  5. package/dist/{cli/cli-server.js → cli-server.js} +40 -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} +4 -3
  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,154 +0,0 @@
1
- /**
2
- * Server-side store for build handoff docs ("server mode").
3
- *
4
- * In the default "repo" mode the per-phase docs (architect-plan.md, status.md,
5
- * executor-summary.md, reviewer-verdict.md, …) are committed into the target
6
- * repo under `.lastlight/<issueKey>/` and ride the working branch. In "server"
7
- * mode they live here instead — on the Last Light host, never committed — and
8
- * are staged into each sandbox phase from outside the repo (the same way skills
9
- * are) and harvested back after the phase runs.
10
- *
11
- * Layout mirrors the rest of `$STATE_DIR` (opencode-home/projects, sandboxes):
12
- *
13
- * <root>/<owner>/<repo>/<issueKey>/<file>.md
14
- *
15
- * `root` defaults to `$STATE_DIR/build-assets` (override `BUILD_ASSETS_DIR`).
16
- * Every path segment is validated to stay inside `root` — the admin API serves
17
- * these by name, so traversal must be impossible.
18
- */
19
- import { cpSync, existsSync, mkdirSync, readdirSync, readFileSync, rmSync, statSync, writeFileSync, } from "fs";
20
- import { join, resolve, sep } from "path";
21
- /**
22
- * Derive the stable per-run key used both as the store sub-path and (with a
23
- * `.lastlight/` prefix) as the in-repo `issueDir`. Issue-scoped runs share a
24
- * key by issue number; non-issue runs (explore, health, …) get a run-scoped
25
- * key so concurrent sessions never overlap. Mirrors the derivation that lived
26
- * inline in `src/workflows/simple.ts`.
27
- */
28
- export function buildAssetIssueKey(workflowName, issueNumber, workflowId) {
29
- return issueNumber !== undefined
30
- ? `issue-${issueNumber}`
31
- : `${workflowName}-${workflowId.slice(0, 8)}`;
32
- }
33
- /**
34
- * A single path segment (owner / repo / issueKey / filename) is safe when it is
35
- * non-empty, carries no path separators, and is not a `.`/`..` traversal token.
36
- * GitHub owners/repos and our own issueKeys/filenames all satisfy this; anything
37
- * else is rejected rather than sanitized so a bad input fails loudly.
38
- */
39
- function assertSafeSegment(segment, label) {
40
- if (!segment ||
41
- segment === "." ||
42
- segment === ".." ||
43
- segment.includes("/") ||
44
- segment.includes("\\") ||
45
- segment.includes("\0")) {
46
- throw new Error(`Unsafe build-asset ${label}: ${JSON.stringify(segment)}`);
47
- }
48
- }
49
- /** True when `child` resolves to a path inside `parent`. */
50
- function isInside(parent, child) {
51
- const p = resolve(parent);
52
- const c = resolve(child);
53
- return c === p || c.startsWith(p + sep);
54
- }
55
- export class BuildAssetStore {
56
- root;
57
- constructor(root) {
58
- this.root = resolve(root);
59
- }
60
- /** Absolute directory for a run's doc set. Validates every segment. */
61
- dirFor(ref) {
62
- assertSafeSegment(ref.owner, "owner");
63
- assertSafeSegment(ref.repo, "repo");
64
- assertSafeSegment(ref.issueKey, "issueKey");
65
- const dir = join(this.root, ref.owner, ref.repo, ref.issueKey);
66
- if (!isInside(this.root, dir)) {
67
- throw new Error(`build-asset dir escapes store root: ${dir}`);
68
- }
69
- return dir;
70
- }
71
- /** Absolute path for one doc file, with traversal validation on the name. */
72
- fileFor(ref, file) {
73
- assertSafeSegment(file, "filename");
74
- const path = join(this.dirFor(ref), file);
75
- if (!isInside(this.root, path)) {
76
- throw new Error(`build-asset file escapes store root: ${path}`);
77
- }
78
- return path;
79
- }
80
- /** Read one doc, or undefined when it does not exist. */
81
- read(ref, file) {
82
- const path = this.fileFor(ref, file);
83
- if (!existsSync(path))
84
- return undefined;
85
- return readFileSync(path, "utf-8");
86
- }
87
- /**
88
- * Read one doc as raw bytes, or undefined when it does not exist. Same
89
- * traversal validation as {@link read}, but no text decoding — the admin
90
- * API uses this to serve binary artifacts (e.g. PNG screenshot evidence)
91
- * intact, since `read()`'s utf-8 decode corrupts binary content.
92
- */
93
- readBuffer(ref, file) {
94
- const path = this.fileFor(ref, file);
95
- if (!existsSync(path))
96
- return undefined;
97
- return readFileSync(path);
98
- }
99
- /** Write (create or overwrite) one doc, creating the run dir as needed. */
100
- write(ref, file, content) {
101
- const path = this.fileFor(ref, file);
102
- mkdirSync(this.dirFor(ref), { recursive: true });
103
- writeFileSync(path, content);
104
- }
105
- /** List the `<owner>/<repo>` run keys present in the store (issueKeys). */
106
- listKeys(owner, repo) {
107
- assertSafeSegment(owner, "owner");
108
- assertSafeSegment(repo, "repo");
109
- const dir = join(this.root, owner, repo);
110
- if (!isInside(this.root, dir) || !existsSync(dir))
111
- return [];
112
- return readdirSync(dir, { withFileTypes: true })
113
- .filter((e) => e.isDirectory())
114
- .map((e) => e.name)
115
- .sort();
116
- }
117
- /** List the doc filenames stored for one run. */
118
- listFiles(ref) {
119
- const dir = this.dirFor(ref);
120
- if (!existsSync(dir))
121
- return [];
122
- return readdirSync(dir, { withFileTypes: true })
123
- .filter((e) => e.isFile())
124
- .map((e) => e.name)
125
- .sort();
126
- }
127
- /**
128
- * Stage the run's stored docs into `localDir` (created fresh) so a sandbox
129
- * phase reads prior-phase context. A no-op-with-empty-dir when nothing is
130
- * stored yet — the first phase starts from a clean slate, identical to repo
131
- * mode's empty `.lastlight/<issueKey>/`.
132
- */
133
- stageInto(ref, localDir) {
134
- mkdirSync(localDir, { recursive: true });
135
- const src = this.dirFor(ref);
136
- if (!existsSync(src))
137
- return;
138
- cpSync(src, localDir, { recursive: true });
139
- }
140
- /**
141
- * Harvest docs written by a phase back into the store, replacing the stored
142
- * set with whatever the phase left in `localDir`. Last-harvest-wins; the
143
- * runner is sequential per workspace so there is no concurrent writer.
144
- */
145
- harvestFrom(ref, localDir) {
146
- if (!existsSync(localDir) || !statSync(localDir).isDirectory())
147
- return;
148
- const dest = this.dirFor(ref);
149
- rmSync(dest, { recursive: true, force: true });
150
- mkdirSync(dest, { recursive: true });
151
- cpSync(localDir, dest, { recursive: true });
152
- }
153
- }
154
- //# sourceMappingURL=build-assets.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"build-assets.js","sourceRoot":"","sources":["../../src/state/build-assets.ts"],"names":[],"mappings":"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"}
@@ -1,81 +0,0 @@
1
- import Database from "better-sqlite3";
2
- import { ExecutionStore } from "./execution-store.js";
3
- import { ApprovalStore } from "./approval-store.js";
4
- import { WorkflowRunStore } from "./workflow-run-store.js";
5
- export type { ExecutionRecord } from "./execution-store.js";
6
- export type { WorkflowApproval } from "./approval-store.js";
7
- export type { WorkflowRun, PhaseHistoryEntry, PhaseMarker } from "./workflow-run-store.js";
8
- export { ExecutionStore } from "./execution-store.js";
9
- export { ApprovalStore } from "./approval-store.js";
10
- export { WorkflowRunStore } from "./workflow-run-store.js";
11
- export interface CronOverride {
12
- name: string;
13
- enabled: boolean;
14
- /** Cron expression overriding the YAML default; null means use the YAML value. */
15
- schedule: string | null;
16
- updatedAt: string;
17
- updatedBy: string | null;
18
- }
19
- /**
20
- * Per-workflow kill switch persisted to SQLite. When `enabled` is false,
21
- * `runSimpleWorkflow` short-circuits and does not create a `workflow_runs`
22
- * row — applies to every trigger source (cron, webhooks, mentions, Slack).
23
- * No row at all means "enabled" (default).
24
- */
25
- export interface WorkflowOverride {
26
- name: string;
27
- enabled: boolean;
28
- updatedAt: string;
29
- updatedBy: string | null;
30
- }
31
- /**
32
- * Lightweight SQLite state for operational tracking.
33
- * NOT for conversation history — only execution logs and rate limits.
34
- *
35
- * Construction root for the three per-table stores (issue #97): it opens the
36
- * single `Database` connection, runs {@link migrate}, and builds
37
- * {@link ExecutionStore} / {@link ApprovalStore} / {@link WorkflowRunStore} on
38
- * top of it (all sharing the one connection so better-sqlite3 transactions
39
- * span every store). Callers reach the stores via `db.runs` / `db.approvals` /
40
- * `db.executions`. StateDb itself retains only the cross-cutting cron-override
41
- * and workflow kill-switch concerns.
42
- */
43
- export declare class StateDb {
44
- private db;
45
- /** Owns the `executions` ledger. */
46
- readonly executions: ExecutionStore;
47
- /** Owns the `workflow_approvals` table. */
48
- readonly approvals: ApprovalStore;
49
- /** Aggregate root for `workflow_runs` + the atomic lifecycle operations. */
50
- readonly runs: WorkflowRunStore;
51
- constructor(dbPath?: string);
52
- /** Get the override row for a single cron, or null if none. */
53
- getCronOverride(name: string): CronOverride | null;
54
- /** All override rows keyed by cron name. */
55
- getAllCronOverrides(): Map<string, CronOverride>;
56
- /**
57
- * Upsert an override. Pass only the fields you want to change — undefined
58
- * fields preserve the existing value (or default to enabled=1, schedule=null
59
- * on insert).
60
- */
61
- setCronOverride(name: string, patch: {
62
- enabled?: boolean;
63
- schedule?: string | null;
64
- updatedBy?: string;
65
- }): void;
66
- /** Remove the override entirely (revert to YAML defaults). */
67
- clearCronOverride(name: string): void;
68
- private deserializeCronOverride;
69
- /**
70
- * Cheap check used by every dispatch path. Returns true unless an explicit
71
- * `workflow_overrides` row says otherwise.
72
- */
73
- isWorkflowEnabled(name: string): boolean;
74
- getWorkflowOverride(name: string): WorkflowOverride | null;
75
- getAllWorkflowOverrides(): Map<string, WorkflowOverride>;
76
- setWorkflowEnabled(name: string, enabled: boolean, updatedBy?: string): void;
77
- private deserializeWorkflowOverride;
78
- /** Expose the underlying Database instance (for SessionManager, etc.) */
79
- get database(): Database.Database;
80
- close(): void;
81
- }
package/dist/state/db.js DELETED
@@ -1,155 +0,0 @@
1
- import Database from "better-sqlite3";
2
- import { resolve } from "path";
3
- import { migrate } from "./migrate.js";
4
- import { ExecutionStore } from "./execution-store.js";
5
- import { ApprovalStore } from "./approval-store.js";
6
- import { WorkflowRunStore } from "./workflow-run-store.js";
7
- export { ExecutionStore } from "./execution-store.js";
8
- export { ApprovalStore } from "./approval-store.js";
9
- export { WorkflowRunStore } from "./workflow-run-store.js";
10
- const DEFAULT_DB_PATH = "lastlight.db";
11
- /**
12
- * Lightweight SQLite state for operational tracking.
13
- * NOT for conversation history — only execution logs and rate limits.
14
- *
15
- * Construction root for the three per-table stores (issue #97): it opens the
16
- * single `Database` connection, runs {@link migrate}, and builds
17
- * {@link ExecutionStore} / {@link ApprovalStore} / {@link WorkflowRunStore} on
18
- * top of it (all sharing the one connection so better-sqlite3 transactions
19
- * span every store). Callers reach the stores via `db.runs` / `db.approvals` /
20
- * `db.executions`. StateDb itself retains only the cross-cutting cron-override
21
- * and workflow kill-switch concerns.
22
- */
23
- export class StateDb {
24
- db;
25
- /** Owns the `executions` ledger. */
26
- executions;
27
- /** Owns the `workflow_approvals` table. */
28
- approvals;
29
- /** Aggregate root for `workflow_runs` + the atomic lifecycle operations. */
30
- runs;
31
- constructor(dbPath) {
32
- // ":memory:" stays a real per-connection in-memory DB (used by tests for
33
- // isolation) — only filesystem paths go through resolve(). Previously
34
- // resolve(":memory:") produced a shared on-disk file named ":memory:",
35
- // which let parallel test files contend on one DB and deadlock once the
36
- // stores started holding write transactions.
37
- const target = dbPath === ":memory:" ? ":memory:" : resolve(dbPath || DEFAULT_DB_PATH);
38
- this.db = new Database(target);
39
- this.db.pragma("journal_mode = WAL");
40
- migrate(this.db);
41
- this.executions = new ExecutionStore(this.db);
42
- this.approvals = new ApprovalStore(this.db);
43
- this.runs = new WorkflowRunStore(this.db, { approvals: this.approvals });
44
- }
45
- // ── Cron overrides ─────────────────────────────────────────────
46
- /** Get the override row for a single cron, or null if none. */
47
- getCronOverride(name) {
48
- const row = this.db
49
- .prepare(`SELECT name, enabled, schedule, updated_at, updated_by FROM cron_overrides WHERE name = ?`)
50
- .get(name);
51
- return row ? this.deserializeCronOverride(row) : null;
52
- }
53
- /** All override rows keyed by cron name. */
54
- getAllCronOverrides() {
55
- const rows = this.db
56
- .prepare(`SELECT name, enabled, schedule, updated_at, updated_by FROM cron_overrides`)
57
- .all();
58
- const map = new Map();
59
- for (const row of rows) {
60
- const o = this.deserializeCronOverride(row);
61
- map.set(o.name, o);
62
- }
63
- return map;
64
- }
65
- /**
66
- * Upsert an override. Pass only the fields you want to change — undefined
67
- * fields preserve the existing value (or default to enabled=1, schedule=null
68
- * on insert).
69
- */
70
- setCronOverride(name, patch) {
71
- const now = new Date().toISOString();
72
- const existing = this.getCronOverride(name);
73
- const enabled = patch.enabled ?? existing?.enabled ?? true;
74
- const schedule = patch.schedule === undefined ? existing?.schedule ?? null : patch.schedule;
75
- this.db
76
- .prepare(`INSERT INTO cron_overrides (name, enabled, schedule, updated_at, updated_by)
77
- VALUES (?, ?, ?, ?, ?)
78
- ON CONFLICT(name) DO UPDATE SET
79
- enabled = excluded.enabled,
80
- schedule = excluded.schedule,
81
- updated_at = excluded.updated_at,
82
- updated_by = excluded.updated_by`)
83
- .run(name, enabled ? 1 : 0, schedule, now, patch.updatedBy ?? null);
84
- }
85
- /** Remove the override entirely (revert to YAML defaults). */
86
- clearCronOverride(name) {
87
- this.db.prepare(`DELETE FROM cron_overrides WHERE name = ?`).run(name);
88
- }
89
- deserializeCronOverride(row) {
90
- return {
91
- name: row.name,
92
- enabled: row.enabled === 1,
93
- schedule: row.schedule ?? null,
94
- updatedAt: row.updated_at,
95
- updatedBy: row.updated_by ?? null,
96
- };
97
- }
98
- // ── Workflow overrides (kill switch) ───────────────────────────
99
- /**
100
- * Cheap check used by every dispatch path. Returns true unless an explicit
101
- * `workflow_overrides` row says otherwise.
102
- */
103
- isWorkflowEnabled(name) {
104
- const row = this.db
105
- .prepare(`SELECT enabled FROM workflow_overrides WHERE name = ?`)
106
- .get(name);
107
- if (!row)
108
- return true;
109
- return row.enabled === 1;
110
- }
111
- getWorkflowOverride(name) {
112
- const row = this.db
113
- .prepare(`SELECT name, enabled, updated_at, updated_by FROM workflow_overrides WHERE name = ?`)
114
- .get(name);
115
- return row ? this.deserializeWorkflowOverride(row) : null;
116
- }
117
- getAllWorkflowOverrides() {
118
- const rows = this.db
119
- .prepare(`SELECT name, enabled, updated_at, updated_by FROM workflow_overrides`)
120
- .all();
121
- const map = new Map();
122
- for (const row of rows) {
123
- const o = this.deserializeWorkflowOverride(row);
124
- map.set(o.name, o);
125
- }
126
- return map;
127
- }
128
- setWorkflowEnabled(name, enabled, updatedBy) {
129
- const now = new Date().toISOString();
130
- this.db
131
- .prepare(`INSERT INTO workflow_overrides (name, enabled, updated_at, updated_by)
132
- VALUES (?, ?, ?, ?)
133
- ON CONFLICT(name) DO UPDATE SET
134
- enabled = excluded.enabled,
135
- updated_at = excluded.updated_at,
136
- updated_by = excluded.updated_by`)
137
- .run(name, enabled ? 1 : 0, now, updatedBy ?? null);
138
- }
139
- deserializeWorkflowOverride(row) {
140
- return {
141
- name: row.name,
142
- enabled: row.enabled === 1,
143
- updatedAt: row.updated_at,
144
- updatedBy: row.updated_by ?? null,
145
- };
146
- }
147
- /** Expose the underlying Database instance (for SessionManager, etc.) */
148
- get database() {
149
- return this.db;
150
- }
151
- close() {
152
- this.db.close();
153
- }
154
- }
155
- //# sourceMappingURL=db.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"db.js","sourceRoot":"","sources":["../../src/state/db.ts"],"names":[],"mappings":"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"}
@@ -1,257 +0,0 @@
1
- import type Database from "better-sqlite3";
2
- export interface ExecutionRecord {
3
- id: string;
4
- triggerType: "webhook" | "cron" | "chat" | "api";
5
- triggerId: string;
6
- skill: string;
7
- repo?: string;
8
- issueNumber?: number;
9
- startedAt: string;
10
- finishedAt?: string;
11
- success?: boolean;
12
- error?: string;
13
- turns?: number;
14
- durationMs?: number;
15
- /**
16
- * Runtime session id (OpenCode `ses_…`) captured from the event stream.
17
- * Used by the dashboard to look up the session log for a given phase.
18
- */
19
- sessionId?: string;
20
- /** Total USD cost reported by the runtime on the final step. Zero under OAuth/subscription auth. */
21
- costUsd?: number;
22
- /** Fresh input tokens (no cache hit). */
23
- inputTokens?: number;
24
- /** Tokens that triggered a cache write. */
25
- cacheCreationInputTokens?: number;
26
- /** Tokens served from prompt cache. */
27
- cacheReadInputTokens?: number;
28
- /** Output tokens generated by the model. */
29
- outputTokens?: number;
30
- /** API-side duration (excludes orchestrator overhead). */
31
- apiDurationMs?: number;
32
- /** Result subtype, e.g. "success" or "error_max_turns". */
33
- stopReason?: string;
34
- /**
35
- * JSON-serialized {@link ExtensionStatusMap} — which agentic-pi extensions
36
- * (file-search / github / web-search) were active for this execution.
37
- */
38
- extensionStatus?: string;
39
- /**
40
- * JSON-serialized {@link SkillsStatus} — agentic-pi's skill-loading status
41
- * for this execution (which skills were discovered/available). Null when
42
- * the run reported no skills.
43
- */
44
- skillsStatus?: string;
45
- /**
46
- * Workflow run that owns this execution. Scopes dedup: a fresh re-trigger
47
- * creates a new workflow_run_id, so `shouldRunPhase` won't find matching
48
- * rows from the prior run and will correctly run the phase again.
49
- */
50
- workflowRunId?: string;
51
- }
52
- /**
53
- * Owns every read/write against the `executions` table — the harness's
54
- * append-only ledger of agent runs. The dashboard derives phase status from
55
- * this table (primary source, ahead of the `phase_history` fallback), and the
56
- * runner's resume path skips already-completed phases via {@link shouldRunPhase}.
57
- *
58
- * Carved out of the old `StateDb` god-class (issue #97). Constructed from the
59
- * single shared `Database` so it sits in the same connection / transaction
60
- * scope as the other stores.
61
- */
62
- export declare class ExecutionStore {
63
- private db;
64
- constructor(db: Database.Database);
65
- recordStart(record: Omit<ExecutionRecord, "finishedAt" | "success" | "error" | "turns" | "durationMs">): void;
66
- /**
67
- * Mid-run update: persist the agent session id as soon as the executor sees
68
- * the stream-json `system/init` line. Lets the dashboard surface the live
69
- * session log for an in-flight phase, not just for completed ones.
70
- */
71
- recordSessionId(id: string, sessionId: string): void;
72
- /**
73
- * Persist the final assistant text for a loop-iteration execution.
74
- * Used by the runner when a scratch slot would otherwise inline the
75
- * full LLM output into `workflow_runs.scratch` — the scratch entry
76
- * stores `lastOutputExecutionId` and resolves the text through
77
- * `getExecutionOutput` on read.
78
- */
79
- recordOutputText(id: string, output: string): void;
80
- /** Read the persisted output text for an execution, or null if none. */
81
- getExecutionOutput(id: string): string | null;
82
- /**
83
- * Most recent finished execution's `output_text` for a phase (`skill`), or
84
- * null. Used by the reviewer loop on resume to re-derive a completed review's
85
- * verdict from its persisted output (a dedup-`done` review must not be
86
- * assumed APPROVED — it may have requested changes).
87
- */
88
- getPhaseOutput(skill: string, triggerId: string, workflowRunId?: string): string | null;
89
- recordFinish(id: string, result: {
90
- success: boolean;
91
- error?: string;
92
- turns?: number;
93
- durationMs?: number;
94
- sessionId?: string;
95
- costUsd?: number;
96
- inputTokens?: number;
97
- cacheCreationInputTokens?: number;
98
- cacheReadInputTokens?: number;
99
- outputTokens?: number;
100
- apiDurationMs?: number;
101
- stopReason?: string;
102
- /** JSON-serialized ExtensionStatusMap (extensions active this run). */
103
- extensionStatus?: string;
104
- /** JSON-serialized SkillsStatus (skills available this run). */
105
- skillsStatus?: string;
106
- }): void;
107
- /**
108
- * Record a phase that the scheduler skipped because its trigger rule was
109
- * not satisfied (a failed/skipped upstream cascaded down a chain). The
110
- * executions ledger is the single source of truth the dashboard derives
111
- * phase status from, so skips are written here too — as a finished,
112
- * non-successful row (`success = 0`, `stop_reason = 'skipped'`). Because it
113
- * is not `success = 1`, `shouldRunPhase` re-evaluates it on resume (the node
114
- * will simply be re-skipped if the upstream is still failed).
115
- */
116
- recordSkippedPhase(skill: string, triggerId: string, workflowRunId?: string, repo?: string): void;
117
- /**
118
- * List chat threads aggregated from the executions table.
119
- *
120
- * Each row collapses every execution sharing a `trigger_id` (the messaging
121
- * session id) into one summary so the dashboard's chat-sessions tab can
122
- * show one card per Slack thread, not one per turn. Joined with
123
- * `messaging_sessions` for the agent SDK session id (used to resolve to
124
- * the on-disk jsonl when streaming messages) and with `messaging_messages`
125
- * for the most recent assistant text (preview snippet).
126
- */
127
- listChatThreads(limit: number): {
128
- triggerId: string;
129
- agentSessionId: string | null;
130
- platform: string | null;
131
- firstStartedAt: string;
132
- lastActivityAt: string;
133
- turnCount: number;
134
- totalCost: number;
135
- inputTokens: number;
136
- outputTokens: number;
137
- cacheReadTokens: number;
138
- lastAssistantContent: string | null;
139
- }[];
140
- /** Look up a single chat thread by its messaging session id (= trigger_id). */
141
- getChatThread(triggerId: string): {
142
- triggerId: string;
143
- agentSessionId: string | null;
144
- platform: string | null;
145
- firstStartedAt: string;
146
- lastActivityAt: string;
147
- turnCount: number;
148
- totalCost: number;
149
- inputTokens: number;
150
- outputTokens: number;
151
- cacheReadTokens: number;
152
- lastAssistantContent: string | null;
153
- } | null;
154
- /** Check if a skill is currently running for a given trigger */
155
- isRunning(skill: string, triggerId: string): boolean;
156
- /** Check if a skill has already completed successfully for a given trigger */
157
- isCompleted(skill: string, triggerId: string): boolean;
158
- /**
159
- * Check if a phase should run: not currently running AND not already
160
- * succeeded. When `workflowRunId` is provided, scopes the check to that
161
- * specific run — a fresh re-trigger (new workflow_run_id) will see no
162
- * matching rows and correctly return "run" even if a prior completed run
163
- * for the same trigger exists. Omit `workflowRunId` for legacy callers
164
- * (e.g. chat/status-report dedup) that want the old trigger-wide scope.
165
- */
166
- shouldRunPhase(skill: string, triggerId: string, workflowRunId?: string): "run" | "running" | "done";
167
- /** Mark all stale "running" executions for a skill/trigger as failed.
168
- * Called when we detect no matching Docker container is alive. */
169
- markStaleAsFailed(skill: string, triggerId: string, workflowRunId?: string): number;
170
- /**
171
- * Mark every unfinished execution row for a trigger as failed, regardless
172
- * of skill. Used by the boot-time recovery sweep to clear out phases that
173
- * were running when the harness crashed/restarted, so the runner's dedup
174
- * logic doesn't think they're still in flight.
175
- */
176
- markAllStaleForTrigger(triggerId: string, reason: string): number;
177
- /**
178
- * Mark the most recent execution for a skill/trigger as failed.
179
- * Used when the agent SDK reported success but the orchestrator decided
180
- * the business outcome was a failure (e.g. guardrails BLOCKED, reviewer
181
- * REQUEST_CHANGES). Without this, runPhase would skip the phase on the
182
- * next run because the DB still says success=1.
183
- */
184
- markLatestAsFailed(skill: string, triggerId: string, reason: string, workflowRunId?: string): number;
185
- /** Get recent executions for a skill */
186
- recentExecutions(skill: string, limit?: number): ExecutionRecord[];
187
- /** Count consecutive failures for a skill (for cron failure tracking) */
188
- consecutiveFailures(skill: string): number;
189
- /** Get all executions with pagination */
190
- allExecutions(limit?: number, offset?: number): ExecutionRecord[];
191
- /**
192
- * Free-text search across the `executions` ledger — matches `error`, `skill`,
193
- * or `repo` against a substring (case-insensitive via SQLite's LIKE). Used by
194
- * the `/admin/api/log-search` endpoint and the `lastlight logs search` CLI to
195
- * find failing/relevant phases without SSHing to the box. Parameterized; the
196
- * pattern is escaped so user input can't smuggle LIKE wildcards.
197
- */
198
- searchErrors(query: string, limit?: number): Array<{
199
- id: string;
200
- skill: string;
201
- repo?: string;
202
- error?: string;
203
- success?: boolean;
204
- startedAt: string;
205
- finishedAt?: string;
206
- sessionId?: string;
207
- workflowRunId?: string;
208
- triggerId: string;
209
- }>;
210
- /**
211
- * Get every execution recorded for a workflow run, with camelCase fields
212
- * ready for the dashboard. Ordered by start time ascending so phases
213
- * display in the order they ran. Scopes to a specific `workflow_run_id`
214
- * when provided (preferred — isolates fresh re-triggers from prior runs);
215
- * falls back to the legacy trigger-wide scope for rows written before the
216
- * workflow_run_id column existed.
217
- */
218
- getExecutionsForWorkflowRun(workflowRunId: string, triggerId: string, workflowName?: string): ExecutionRecord[];
219
- /** Get currently running executions (no finished_at) */
220
- runningExecutions(): ExecutionRecord[];
221
- /** Aggregate execution stats */
222
- executionStats(): {
223
- total_executions: number;
224
- today_count: number;
225
- by_skill: Record<string, {
226
- count: number;
227
- success: number;
228
- fail: number;
229
- }>;
230
- by_trigger: Record<string, number>;
231
- running: number;
232
- };
233
- /** Daily aggregated stats for the last N days */
234
- dailyStats(days: number): {
235
- date: string;
236
- executions: number;
237
- successes: number;
238
- failures: number;
239
- totalTokens: number;
240
- inputTokens: number;
241
- outputTokens: number;
242
- cacheReadTokens: number;
243
- costUsd: number;
244
- }[];
245
- /** Hourly aggregated stats for the last N hours (UTC). Bucket key is `YYYY-MM-DDTHH`. */
246
- hourlyStats(hours: number): {
247
- date: string;
248
- executions: number;
249
- successes: number;
250
- failures: number;
251
- totalTokens: number;
252
- inputTokens: number;
253
- outputTokens: number;
254
- cacheReadTokens: number;
255
- costUsd: number;
256
- }[];
257
- }