@shipfox/api-workflows 11.0.0 → 12.1.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 (346) hide show
  1. package/.turbo/turbo-build.log +8 -8
  2. package/CHANGELOG.md +107 -0
  3. package/README.md +75 -0
  4. package/dist/core/agent-defaults.d.ts +2 -1
  5. package/dist/core/agent-defaults.d.ts.map +1 -1
  6. package/dist/core/agent-defaults.js.map +1 -1
  7. package/dist/core/checkout.d.ts +7 -21
  8. package/dist/core/checkout.d.ts.map +1 -1
  9. package/dist/core/checkout.js +122 -41
  10. package/dist/core/checkout.js.map +1 -1
  11. package/dist/core/entities/job-execution.d.ts +8 -0
  12. package/dist/core/entities/job-execution.d.ts.map +1 -1
  13. package/dist/core/entities/job-execution.js +13 -1
  14. package/dist/core/entities/job-execution.js.map +1 -1
  15. package/dist/core/entities/job-listener-event.d.ts +2 -0
  16. package/dist/core/entities/job-listener-event.d.ts.map +1 -1
  17. package/dist/core/entities/job-listener-event.js.map +1 -1
  18. package/dist/core/entities/step.d.ts +13 -3
  19. package/dist/core/entities/step.d.ts.map +1 -1
  20. package/dist/core/entities/step.js +6 -0
  21. package/dist/core/entities/step.js.map +1 -1
  22. package/dist/core/entities/workflow-run-attempt.d.ts +1 -0
  23. package/dist/core/entities/workflow-run-attempt.d.ts.map +1 -1
  24. package/dist/core/entities/workflow-run-attempt.js.map +1 -1
  25. package/dist/core/entities/workflow-run.d.ts +17 -0
  26. package/dist/core/entities/workflow-run.d.ts.map +1 -1
  27. package/dist/core/entities/workflow-run.js.map +1 -1
  28. package/dist/core/errors.d.ts +9 -2
  29. package/dist/core/errors.d.ts.map +1 -1
  30. package/dist/core/errors.js +10 -5
  31. package/dist/core/errors.js.map +1 -1
  32. package/dist/core/job-execution.d.ts.map +1 -1
  33. package/dist/core/job-execution.js +14 -8
  34. package/dist/core/job-execution.js.map +1 -1
  35. package/dist/core/job-transition/decide-job-activation.d.ts +1 -0
  36. package/dist/core/job-transition/decide-job-activation.d.ts.map +1 -1
  37. package/dist/core/job-transition/decide-job-activation.js +1 -0
  38. package/dist/core/job-transition/decide-job-activation.js.map +1 -1
  39. package/dist/core/job-transition/derive-job-success.d.ts +1 -0
  40. package/dist/core/job-transition/derive-job-success.d.ts.map +1 -1
  41. package/dist/core/job-transition/derive-job-success.js +5 -8
  42. package/dist/core/job-transition/derive-job-success.js.map +1 -1
  43. package/dist/core/listener-execution-materialization.d.ts +6 -3
  44. package/dist/core/listener-execution-materialization.d.ts.map +1 -1
  45. package/dist/core/listener-execution-materialization.js +44 -6
  46. package/dist/core/listener-execution-materialization.js.map +1 -1
  47. package/dist/core/resolve-trigger-reference.d.ts +11 -0
  48. package/dist/core/resolve-trigger-reference.d.ts.map +1 -0
  49. package/dist/core/resolve-trigger-reference.js +39 -0
  50. package/dist/core/resolve-trigger-reference.js.map +1 -0
  51. package/dist/core/run-workflow.d.ts +1 -0
  52. package/dist/core/run-workflow.d.ts.map +1 -1
  53. package/dist/core/run-workflow.js +1 -0
  54. package/dist/core/run-workflow.js.map +1 -1
  55. package/dist/core/step-config/agent.d.ts +1 -2
  56. package/dist/core/step-config/agent.d.ts.map +1 -1
  57. package/dist/core/step-config/agent.js +22 -7
  58. package/dist/core/step-config/agent.js.map +1 -1
  59. package/dist/core/step-config/assemble-run-context.d.ts +19 -8
  60. package/dist/core/step-config/assemble-run-context.d.ts.map +1 -1
  61. package/dist/core/step-config/assemble-run-context.js +51 -19
  62. package/dist/core/step-config/assemble-run-context.js.map +1 -1
  63. package/dist/core/step-config/complete-step-dispatch-config.d.ts.map +1 -1
  64. package/dist/core/step-config/complete-step-dispatch-config.js +72 -4
  65. package/dist/core/step-config/complete-step-dispatch-config.js.map +1 -1
  66. package/dist/core/step-config/index.d.ts +1 -0
  67. package/dist/core/step-config/index.d.ts.map +1 -1
  68. package/dist/core/step-config/index.js +1 -0
  69. package/dist/core/step-config/index.js.map +1 -1
  70. package/dist/core/step-config/materialize-job-execution-steps.d.ts +1 -1
  71. package/dist/core/step-config/materialize-job-execution-steps.d.ts.map +1 -1
  72. package/dist/core/step-config/materialize-job-execution-steps.js +49 -8
  73. package/dist/core/step-config/materialize-job-execution-steps.js.map +1 -1
  74. package/dist/core/step-config/materialize-workflow-model.d.ts +3 -3
  75. package/dist/core/step-config/materialize-workflow-model.d.ts.map +1 -1
  76. package/dist/core/step-config/materialize-workflow-model.js +9 -5
  77. package/dist/core/step-config/materialize-workflow-model.js.map +1 -1
  78. package/dist/core/step-config/resolve-job-execution-name.d.ts +3 -3
  79. package/dist/core/step-config/resolve-job-execution-name.d.ts.map +1 -1
  80. package/dist/core/step-config/resolve-job-execution-name.js +24 -13
  81. package/dist/core/step-config/resolve-job-execution-name.js.map +1 -1
  82. package/dist/core/step-config/resolve-step-config.d.ts.map +1 -1
  83. package/dist/core/step-config/resolve-step-config.js +174 -9
  84. package/dist/core/step-config/resolve-step-config.js.map +1 -1
  85. package/dist/core/step-config/resolve-workflow-run-name.d.ts +19 -0
  86. package/dist/core/step-config/resolve-workflow-run-name.d.ts.map +1 -0
  87. package/dist/core/step-config/resolve-workflow-run-name.js +73 -0
  88. package/dist/core/step-config/resolve-workflow-run-name.js.map +1 -0
  89. package/dist/core/step-transition/decide-step-transition.js.map +1 -1
  90. package/dist/core/step-transition/evaluate-gate.d.ts +2 -1
  91. package/dist/core/step-transition/evaluate-gate.d.ts.map +1 -1
  92. package/dist/core/step-transition/evaluate-gate.js +5 -3
  93. package/dist/core/step-transition/evaluate-gate.js.map +1 -1
  94. package/dist/core/workflow-run-creation.d.ts +3 -0
  95. package/dist/core/workflow-run-creation.d.ts.map +1 -1
  96. package/dist/core/workflow-run-creation.js +22 -7
  97. package/dist/core/workflow-run-creation.js.map +1 -1
  98. package/dist/db/db.d.ts +278 -10
  99. package/dist/db/db.d.ts.map +1 -1
  100. package/dist/db/db.js +2 -0
  101. package/dist/db/db.js.map +1 -1
  102. package/dist/db/index.d.ts +3 -2
  103. package/dist/db/index.d.ts.map +1 -1
  104. package/dist/db/index.js +2 -1
  105. package/dist/db/index.js.map +1 -1
  106. package/dist/db/job-listener-events.d.ts +2 -0
  107. package/dist/db/job-listener-events.d.ts.map +1 -1
  108. package/dist/db/job-listener-events.js +1 -0
  109. package/dist/db/job-listener-events.js.map +1 -1
  110. package/dist/db/job-listeners.d.ts +2 -0
  111. package/dist/db/job-listeners.d.ts.map +1 -1
  112. package/dist/db/job-listeners.js +81 -21
  113. package/dist/db/job-listeners.js.map +1 -1
  114. package/dist/db/schema/job-executions.d.ts +3 -3
  115. package/dist/db/schema/job-executions.d.ts.map +1 -1
  116. package/dist/db/schema/job-executions.js +8 -4
  117. package/dist/db/schema/job-executions.js.map +1 -1
  118. package/dist/db/schema/job-listener-events.d.ts +20 -0
  119. package/dist/db/schema/job-listener-events.d.ts.map +1 -1
  120. package/dist/db/schema/job-listener-events.js +2 -0
  121. package/dist/db/schema/job-listener-events.js.map +1 -1
  122. package/dist/db/schema/step-attempts.js +2 -2
  123. package/dist/db/schema/step-attempts.js.map +1 -1
  124. package/dist/db/schema/steps.d.ts +4 -2
  125. package/dist/db/schema/steps.d.ts.map +1 -1
  126. package/dist/db/schema/steps.js +1 -1
  127. package/dist/db/schema/steps.js.map +1 -1
  128. package/dist/db/schema/workflow-run-attempts.d.ts +21 -2
  129. package/dist/db/schema/workflow-run-attempts.d.ts.map +1 -1
  130. package/dist/db/schema/workflow-run-attempts.js +2 -0
  131. package/dist/db/schema/workflow-run-attempts.js.map +1 -1
  132. package/dist/db/schema/workflow-run-counters.d.ts +43 -0
  133. package/dist/db/schema/workflow-run-counters.d.ts.map +1 -0
  134. package/dist/db/schema/workflow-run-counters.js +10 -0
  135. package/dist/db/schema/workflow-run-counters.js.map +1 -0
  136. package/dist/db/schema/workflow-runs.d.ts +54 -1
  137. package/dist/db/schema/workflow-runs.d.ts.map +1 -1
  138. package/dist/db/schema/workflow-runs.js +10 -2
  139. package/dist/db/schema/workflow-runs.js.map +1 -1
  140. package/dist/db/workflow-runs/job-executions.d.ts.map +1 -1
  141. package/dist/db/workflow-runs/job-executions.js +35 -14
  142. package/dist/db/workflow-runs/job-executions.js.map +1 -1
  143. package/dist/db/workflow-runs/jobs.d.ts +2 -0
  144. package/dist/db/workflow-runs/jobs.d.ts.map +1 -1
  145. package/dist/db/workflow-runs/jobs.js +9 -5
  146. package/dist/db/workflow-runs/jobs.js.map +1 -1
  147. package/dist/db/workflow-runs/queries.d.ts +51 -0
  148. package/dist/db/workflow-runs/queries.d.ts.map +1 -1
  149. package/dist/db/workflow-runs/queries.js +82 -2
  150. package/dist/db/workflow-runs/queries.js.map +1 -1
  151. package/dist/db/workflow-runs/run-create.d.ts +1 -0
  152. package/dist/db/workflow-runs/run-create.d.ts.map +1 -1
  153. package/dist/db/workflow-runs/run-create.js +159 -32
  154. package/dist/db/workflow-runs/run-create.js.map +1 -1
  155. package/dist/db/workflow-runs/run-rerun.d.ts.map +1 -1
  156. package/dist/db/workflow-runs/run-rerun.js +13 -5
  157. package/dist/db/workflow-runs/run-rerun.js.map +1 -1
  158. package/dist/db/workflow-runs/shared.d.ts +1 -0
  159. package/dist/db/workflow-runs/shared.d.ts.map +1 -1
  160. package/dist/db/workflow-runs/shared.js +2 -1
  161. package/dist/db/workflow-runs/shared.js.map +1 -1
  162. package/dist/db/workflow-runs/steps.js +3 -3
  163. package/dist/db/workflow-runs/steps.js.map +1 -1
  164. package/dist/db/workflow-runs.d.ts +4 -3
  165. package/dist/db/workflow-runs.d.ts.map +1 -1
  166. package/dist/db/workflow-runs.js +3 -2
  167. package/dist/db/workflow-runs.js.map +1 -1
  168. package/dist/metrics/instance.d.ts +1 -0
  169. package/dist/metrics/instance.d.ts.map +1 -1
  170. package/dist/metrics/instance.js +9 -0
  171. package/dist/metrics/instance.js.map +1 -1
  172. package/dist/presentation/dto/checkout-token.d.ts +1 -0
  173. package/dist/presentation/dto/checkout-token.d.ts.map +1 -1
  174. package/dist/presentation/dto/checkout-token.js +1 -0
  175. package/dist/presentation/dto/checkout-token.js.map +1 -1
  176. package/dist/presentation/dto/index.d.ts +1 -1
  177. package/dist/presentation/dto/index.d.ts.map +1 -1
  178. package/dist/presentation/dto/index.js +1 -1
  179. package/dist/presentation/dto/index.js.map +1 -1
  180. package/dist/presentation/dto/step.d.ts.map +1 -1
  181. package/dist/presentation/dto/step.js +2 -2
  182. package/dist/presentation/dto/step.js.map +1 -1
  183. package/dist/presentation/dto/workflow-run.d.ts +3 -1
  184. package/dist/presentation/dto/workflow-run.d.ts.map +1 -1
  185. package/dist/presentation/dto/workflow-run.js +34 -0
  186. package/dist/presentation/dto/workflow-run.js.map +1 -1
  187. package/dist/presentation/inter-module.d.ts.map +1 -1
  188. package/dist/presentation/inter-module.js +31 -3
  189. package/dist/presentation/inter-module.js.map +1 -1
  190. package/dist/presentation/routes/checkout-token.d.ts +1 -1
  191. package/dist/presentation/routes/checkout-token.d.ts.map +1 -1
  192. package/dist/presentation/routes/checkout-token.js +32 -20
  193. package/dist/presentation/routes/checkout-token.js.map +1 -1
  194. package/dist/presentation/routes/leased-step.d.ts +2 -0
  195. package/dist/presentation/routes/leased-step.d.ts.map +1 -1
  196. package/dist/presentation/routes/leased-step.js +2 -1
  197. package/dist/presentation/routes/leased-step.js.map +1 -1
  198. package/dist/presentation/routes/list-runs.d.ts.map +1 -1
  199. package/dist/presentation/routes/list-runs.js +9 -3
  200. package/dist/presentation/routes/list-runs.js.map +1 -1
  201. package/dist/presentation/routes/project-access.d.ts +1 -0
  202. package/dist/presentation/routes/project-access.d.ts.map +1 -1
  203. package/dist/presentation/routes/report-step.d.ts.map +1 -1
  204. package/dist/presentation/routes/report-step.js +9 -2
  205. package/dist/presentation/routes/report-step.js.map +1 -1
  206. package/dist/presentation/subscribers/on-job-steps-settled.js +1 -1
  207. package/dist/presentation/subscribers/on-job-steps-settled.js.map +1 -1
  208. package/dist/presentation/subscribers/on-runner-job-claimed.d.ts.map +1 -1
  209. package/dist/presentation/subscribers/on-runner-job-claimed.js +21 -0
  210. package/dist/presentation/subscribers/on-runner-job-claimed.js.map +1 -1
  211. package/dist/temporal/activities/index.d.ts.map +1 -1
  212. package/dist/temporal/activities/index.js +2 -1
  213. package/dist/temporal/activities/index.js.map +1 -1
  214. package/dist/temporal/activities/orchestration-activities.d.ts +1 -0
  215. package/dist/temporal/activities/orchestration-activities.d.ts.map +1 -1
  216. package/dist/temporal/activities/orchestration-activities.js.map +1 -1
  217. package/dist/temporal/constants.d.ts +1 -0
  218. package/dist/temporal/constants.d.ts.map +1 -1
  219. package/dist/temporal/constants.js +1 -0
  220. package/dist/temporal/constants.js.map +1 -1
  221. package/dist/temporal/index.d.ts +1 -1
  222. package/dist/temporal/index.d.ts.map +1 -1
  223. package/dist/temporal/index.js +1 -1
  224. package/dist/temporal/index.js.map +1 -1
  225. package/dist/temporal/workflows/index.bundle.js +82 -43
  226. package/dist/temporal/workflows/index.d.ts +1 -1
  227. package/dist/temporal/workflows/index.d.ts.map +1 -1
  228. package/dist/temporal/workflows/index.js +1 -1
  229. package/dist/temporal/workflows/index.js.map +1 -1
  230. package/dist/temporal/workflows/job-execution-orchestration.d.ts +5 -0
  231. package/dist/temporal/workflows/job-execution-orchestration.d.ts.map +1 -1
  232. package/dist/temporal/workflows/job-execution-orchestration.js +77 -43
  233. package/dist/temporal/workflows/job-execution-orchestration.js.map +1 -1
  234. package/dist/temporal/workflows/test-env.d.ts +5 -1
  235. package/dist/temporal/workflows/test-env.d.ts.map +1 -1
  236. package/dist/temporal/workflows/test-env.js +32 -11
  237. package/dist/temporal/workflows/test-env.js.map +1 -1
  238. package/dist/tsconfig.test.tsbuildinfo +1 -1
  239. package/drizzle/0000_initial.sql +14 -2
  240. package/drizzle/0001_windy_sunfire.sql +1 -0
  241. package/drizzle/meta/0000_snapshot.json +93 -1
  242. package/drizzle/meta/0001_snapshot.json +1711 -0
  243. package/drizzle/meta/_journal.json +2 -2
  244. package/package.json +19 -19
  245. package/src/core/agent-defaults.ts +2 -1
  246. package/src/core/checkout.test.ts +378 -67
  247. package/src/core/checkout.ts +142 -59
  248. package/src/core/entities/job-execution.test.ts +21 -0
  249. package/src/core/entities/job-execution.ts +24 -0
  250. package/src/core/entities/job-listener-event.ts +3 -0
  251. package/src/core/entities/step.ts +15 -3
  252. package/src/core/entities/workflow-run-attempt.ts +1 -0
  253. package/src/core/entities/workflow-run.ts +16 -0
  254. package/src/core/errors.ts +21 -7
  255. package/src/core/job-execution.ts +27 -4
  256. package/src/core/job-transition/decide-job-activation.test.ts +4 -0
  257. package/src/core/job-transition/decide-job-activation.ts +2 -0
  258. package/src/core/job-transition/derive-job-success.test.ts +12 -0
  259. package/src/core/job-transition/derive-job-success.ts +6 -9
  260. package/src/core/listener-execution-materialization.test.ts +2 -0
  261. package/src/core/listener-execution-materialization.ts +57 -11
  262. package/src/core/resolve-trigger-reference.test.ts +160 -0
  263. package/src/core/resolve-trigger-reference.ts +53 -0
  264. package/src/core/run-workflow.ts +2 -0
  265. package/src/core/step-config/agent.ts +29 -12
  266. package/src/core/step-config/assemble-run-context.test.ts +149 -6
  267. package/src/core/step-config/assemble-run-context.ts +87 -25
  268. package/src/core/step-config/complete-step-dispatch-config.test.ts +125 -2
  269. package/src/core/step-config/complete-step-dispatch-config.ts +83 -1
  270. package/src/core/step-config/index.ts +7 -0
  271. package/src/core/step-config/materialize-job-execution-steps.test.ts +250 -1
  272. package/src/core/step-config/materialize-job-execution-steps.ts +57 -10
  273. package/src/core/step-config/materialize-workflow-model.test.ts +212 -4
  274. package/src/core/step-config/materialize-workflow-model.ts +33 -28
  275. package/src/core/step-config/resolve-job-execution-name.test.ts +37 -15
  276. package/src/core/step-config/resolve-job-execution-name.ts +30 -15
  277. package/src/core/step-config/resolve-step-config.ts +175 -10
  278. package/src/core/step-config/resolve-workflow-run-name.test.ts +115 -0
  279. package/src/core/step-config/resolve-workflow-run-name.ts +108 -0
  280. package/src/core/step-transition/decide-step-transition.ts +2 -2
  281. package/src/core/step-transition/evaluate-gate.test.ts +8 -0
  282. package/src/core/step-transition/evaluate-gate.ts +8 -1
  283. package/src/core/workflow-run-creation.test.ts +7 -4
  284. package/src/core/workflow-run-creation.ts +13 -7
  285. package/src/db/db.ts +2 -0
  286. package/src/db/index.ts +6 -0
  287. package/src/db/job-listener-events.test.ts +19 -0
  288. package/src/db/job-listener-events.ts +3 -0
  289. package/src/db/job-listeners.test.ts +187 -5
  290. package/src/db/job-listeners.ts +122 -30
  291. package/src/db/schema/job-executions.ts +12 -5
  292. package/src/db/schema/job-listener-events.ts +3 -0
  293. package/src/db/schema/step-attempts.ts +2 -2
  294. package/src/db/schema/steps.ts +2 -1
  295. package/src/db/schema/workflow-run-attempts.ts +2 -0
  296. package/src/db/schema/workflow-run-counters.ts +13 -0
  297. package/src/db/schema/workflow-runs.ts +11 -2
  298. package/src/db/workflow-runs/job-executions.ts +37 -15
  299. package/src/db/workflow-runs/jobs.ts +17 -4
  300. package/src/db/workflow-runs/queries.test.ts +206 -0
  301. package/src/db/workflow-runs/queries.ts +146 -2
  302. package/src/db/workflow-runs/run-create.test.ts +606 -8
  303. package/src/db/workflow-runs/run-create.ts +185 -40
  304. package/src/db/workflow-runs/run-rerun.test.ts +61 -2
  305. package/src/db/workflow-runs/run-rerun.ts +15 -5
  306. package/src/db/workflow-runs/shared.ts +2 -0
  307. package/src/db/workflow-runs/steps.ts +3 -3
  308. package/src/db/workflow-runs.ts +7 -0
  309. package/src/metrics/instance.ts +14 -0
  310. package/src/presentation/dto/checkout-token.test.ts +19 -9
  311. package/src/presentation/dto/checkout-token.ts +2 -1
  312. package/src/presentation/dto/index.ts +1 -1
  313. package/src/presentation/dto/job.test.ts +9 -0
  314. package/src/presentation/dto/step.test.ts +12 -0
  315. package/src/presentation/dto/step.ts +5 -2
  316. package/src/presentation/dto/workflow-run.ts +44 -2
  317. package/src/presentation/inter-module.test.ts +165 -0
  318. package/src/presentation/inter-module.ts +38 -4
  319. package/src/presentation/routes/checkout-token.test.ts +357 -142
  320. package/src/presentation/routes/checkout-token.ts +56 -26
  321. package/src/presentation/routes/get-run.test.ts +2 -0
  322. package/src/presentation/routes/get-step-secrets.test.ts +7 -2
  323. package/src/presentation/routes/leased-step.ts +9 -1
  324. package/src/presentation/routes/list-runs.test.ts +57 -0
  325. package/src/presentation/routes/list-runs.ts +8 -3
  326. package/src/presentation/routes/report-step.test.ts +25 -0
  327. package/src/presentation/routes/report-step.ts +10 -2
  328. package/src/presentation/subscribers/on-job-steps-settled.ts +1 -1
  329. package/src/presentation/subscribers/on-runner-job-claimed.test.ts +49 -0
  330. package/src/presentation/subscribers/on-runner-job-claimed.ts +22 -0
  331. package/src/temporal/activities/index.ts +1 -0
  332. package/src/temporal/activities/orchestration-activities.ts +1 -0
  333. package/src/temporal/constants.ts +1 -0
  334. package/src/temporal/index.ts +1 -0
  335. package/src/temporal/workflows/index.ts +1 -0
  336. package/src/temporal/workflows/job-execution-orchestration.test.ts +142 -6
  337. package/src/temporal/workflows/job-execution-orchestration.ts +99 -50
  338. package/src/temporal/workflows/run-orchestration.test.ts +1 -1
  339. package/src/temporal/workflows/test-env.ts +50 -13
  340. package/test/factories/project.ts +2 -0
  341. package/test/factories/workflow-model.ts +80 -26
  342. package/test/factories/workflow-run.ts +4 -1
  343. package/test/fixtures/agent-inter-module.ts +2 -1
  344. package/test/fixtures/job-with-steps.ts +1 -1
  345. package/tsconfig.build.tsbuildinfo +1 -1
  346. package/drizzle/0001_agent_tool_materialization.sql +0 -1
@@ -1,3 +1,4 @@
1
+ import {getWorkflowPredicateContextRoots} from '@shipfox/expression';
1
2
  import type {JobExecution} from '#core/entities/job-execution.js';
2
3
  import type {Step, StepAttempt} from '#core/entities/step.js';
3
4
  import {
@@ -19,7 +20,9 @@ const date = new Date('2026-06-30T12:00:00.000Z');
19
20
  describe('assembleWorkflowRunContext', () => {
20
21
  const run = {
21
22
  id: 'run-1',
23
+ number: 1,
22
24
  name: 'Build',
25
+ workflowName: 'Build',
23
26
  definitionId: 'def-1',
24
27
  projectId: 'proj-1',
25
28
  workspaceId: 'workspace-1',
@@ -39,15 +42,26 @@ describe('assembleWorkflowRunContext', () => {
39
42
  });
40
43
 
41
44
  expect(context).toEqual({
45
+ workflow: {
46
+ id: 'def-1',
47
+ name: 'Build',
48
+ },
42
49
  run: {
43
50
  id: 'run-1',
51
+ number: 1,
44
52
  name: 'Build',
45
- definition_id: 'def-1',
46
53
  project_id: 'proj-1',
47
54
  workspace_id: 'workspace-1',
48
55
  created_at: run.createdAt,
49
56
  },
50
- trigger: {source: 'github', event: 'push'},
57
+ trigger: {
58
+ source: 'github',
59
+ event: 'push',
60
+ project: null,
61
+ repository: null,
62
+ ref: null,
63
+ commit: null,
64
+ },
51
65
  event: {ref: 'refs/heads/main'},
52
66
  inputs: {deploy: true},
53
67
  });
@@ -76,7 +90,9 @@ describe('assembleWorkflowRunContext', () => {
76
90
  describe('assembleCreationContext', () => {
77
91
  const run = {
78
92
  id: 'run-1',
93
+ number: 1,
79
94
  name: 'Build',
95
+ workflowName: 'Build',
80
96
  definitionId: 'def-1',
81
97
  projectId: 'proj-1',
82
98
  workspaceId: 'workspace-1',
@@ -109,12 +125,44 @@ describe('assembleCreationContext', () => {
109
125
  }),
110
126
  });
111
127
  });
128
+
129
+ it('exposes the normalized trigger reference on the trigger root', () => {
130
+ const context = assembleWorkflowRunContext({
131
+ run: {
132
+ ...run,
133
+ triggerReference: {
134
+ project: {id: 'project-1'},
135
+ repository: 'acme/api',
136
+ ref: 'refs/pull/42/head',
137
+ commit: 'a'.repeat(40),
138
+ actor: 'octocat',
139
+ },
140
+ },
141
+ triggerPayload: {
142
+ source: 'github',
143
+ event: 'pull_request',
144
+ deliveryId: 'delivery-1',
145
+ data: {},
146
+ },
147
+ });
148
+
149
+ expect(context.trigger).toEqual({
150
+ source: 'github',
151
+ event: 'pull_request',
152
+ project: {id: 'project-1'},
153
+ repository: 'acme/api',
154
+ ref: 'refs/pull/42/head',
155
+ commit: 'a'.repeat(40),
156
+ });
157
+ });
112
158
  });
113
159
 
114
160
  describe('assembleExecutionCreationContext', () => {
115
161
  const run = {
116
162
  id: 'run-1',
163
+ number: 1,
117
164
  name: 'Build',
165
+ workflowName: 'Build',
118
166
  definitionId: 'def-1',
119
167
  projectId: 'proj-1',
120
168
  workspaceId: 'workspace-1',
@@ -140,8 +188,9 @@ describe('assembleExecutionCreationContext', () => {
140
188
  data: {ref: 'refs/heads/main'},
141
189
  },
142
190
  inputs: {deploy: true},
143
- jobId: 'job-1',
191
+ job: {id: 'job-1', key: 'build', name: 'Build'},
144
192
  sequence: 2,
193
+ nameOverride: null,
145
194
  executionName: 'Build #2',
146
195
  status: 'pending',
147
196
  triggerEvents: [
@@ -150,6 +199,10 @@ describe('assembleExecutionCreationContext', () => {
150
199
  event: 'deployment',
151
200
  delivery_id: 'delivery-2',
152
201
  received_at: '2026-06-30T12:01:00.000Z',
202
+ project: null,
203
+ repository: null,
204
+ ref: null,
205
+ commit: null,
153
206
  data: {environment: 'prod'},
154
207
  },
155
208
  ],
@@ -191,12 +244,17 @@ describe('assembleExecutionCreationContext', () => {
191
244
  event: 'deployment',
192
245
  delivery_id: 'delivery-2',
193
246
  received_at: '2026-06-30T12:01:00.000Z',
247
+ project: null,
248
+ repository: null,
249
+ ref: null,
250
+ commit: null,
194
251
  data: {environment: 'prod'},
195
252
  },
196
253
  ],
197
254
  outputs: {},
198
255
  },
199
256
  ],
257
+ job: {key: 'build', name: 'Build'},
200
258
  execution: {
201
259
  index: 1,
202
260
  name: 'Build #2',
@@ -209,6 +267,10 @@ describe('assembleExecutionCreationContext', () => {
209
267
  event: 'deployment',
210
268
  delivery_id: 'delivery-2',
211
269
  received_at: '2026-06-30T12:01:00.000Z',
270
+ project: null,
271
+ repository: null,
272
+ ref: null,
273
+ commit: null,
212
274
  data: {environment: 'prod'},
213
275
  },
214
276
  ],
@@ -222,7 +284,9 @@ describe('assembleExecutionCreationContext', () => {
222
284
  describe('assembleJobActivationContext', () => {
223
285
  const run = {
224
286
  id: 'run-1',
287
+ number: 1,
225
288
  name: 'Build',
289
+ workflowName: 'Build',
226
290
  definitionId: 'def-1',
227
291
  projectId: 'proj-1',
228
292
  workspaceId: 'workspace-1',
@@ -259,6 +323,9 @@ describe('assembleJobActivationContext', () => {
259
323
  ],
260
324
  });
261
325
 
326
+ expect(Object.keys(context.values).sort()).toEqual(
327
+ [...getWorkflowPredicateContextRoots('job.if')].sort(),
328
+ );
262
329
  expect(context).toEqual({
263
330
  site: 'job-activation',
264
331
  values: {
@@ -320,6 +387,7 @@ describe('assembleJobActivationContext', () => {
320
387
  executions: [],
321
388
  },
322
389
  ],
390
+ vars: {},
323
391
  },
324
392
  });
325
393
  });
@@ -328,7 +396,9 @@ describe('assembleJobActivationContext', () => {
328
396
  describe('listener filter snapshots', () => {
329
397
  const run = {
330
398
  id: 'run-1',
399
+ number: 1,
331
400
  name: 'Build',
401
+ workflowName: 'Build',
332
402
  definitionId: 'def-1',
333
403
  projectId: 'proj-1',
334
404
  workspaceId: 'workspace-1',
@@ -348,7 +418,7 @@ describe('listener filter snapshots', () => {
348
418
  source: 'github',
349
419
  event: 'pull_request',
350
420
  filter:
351
- 'jobs.build.outputs.pr_number == event.pull_request.number && inputs.environment == "prod" && trigger.event == "pull_request" && run.id != "" && job.key == "await"',
421
+ 'jobs.build.outputs.pr_number == event.pull_request.number && inputs.environment == "prod" && trigger.event == "pull_request" && workflow.name != "" && run.id != "" && job.key == "await" && vars.ENABLED == "true"',
352
422
  },
353
423
  ],
354
424
  until: null,
@@ -358,6 +428,7 @@ describe('listener filter snapshots', () => {
358
428
  run,
359
429
  triggerPayload,
360
430
  inputs: {environment: 'prod'},
431
+ vars: {ENABLED: 'true'},
361
432
  plan,
362
433
  dependencyJobs: [
363
434
  {
@@ -374,10 +445,19 @@ describe('listener filter snapshots', () => {
374
445
  const [matcher] = applyListenerFilterSnapshots(plan.on, context);
375
446
 
376
447
  expect(matcher?.filter_snapshot).toEqual({
448
+ workflow: {id: 'def-1', name: 'Build'},
377
449
  run: expect.objectContaining({id: 'run-1', name: 'Build'}),
378
- trigger: {source: 'github', event: 'pull_request'},
450
+ trigger: {
451
+ source: 'github',
452
+ event: 'pull_request',
453
+ project: null,
454
+ repository: null,
455
+ ref: null,
456
+ commit: null,
457
+ },
379
458
  inputs: {environment: 'prod'},
380
459
  job: {key: 'await'},
460
+ vars: {ENABLED: 'true'},
381
461
  jobs: {
382
462
  build: expect.objectContaining({
383
463
  key: 'build',
@@ -387,10 +467,40 @@ describe('listener filter snapshots', () => {
387
467
  }),
388
468
  },
389
469
  });
470
+ expect(Object.keys(matcher?.filter_snapshot ?? {}).sort()).toEqual(
471
+ getWorkflowPredicateContextRoots('listener.on')
472
+ .filter((root) => root !== 'event')
473
+ .sort(),
474
+ );
390
475
  expect(matcher?.filter_snapshot).not.toHaveProperty('event');
391
476
  expect(matcher?.filter_snapshot?.jobs).not.toHaveProperty('review');
392
477
  });
393
478
 
479
+ it('snapshots vars for listener filters', () => {
480
+ const plan = planListenerFilterSnapshots({
481
+ on: [
482
+ {
483
+ source: 'github',
484
+ event: 'pull_request',
485
+ filter: 'vars.ENABLED == "true"',
486
+ },
487
+ ],
488
+ until: null,
489
+ });
490
+ const context = assembleListenerSnapshotContext({
491
+ job: {key: 'await'},
492
+ run,
493
+ triggerPayload,
494
+ vars: {ENABLED: 'true'},
495
+ plan,
496
+ dependencyJobs: [],
497
+ });
498
+
499
+ const [matcher] = applyListenerFilterSnapshots(plan.on, context);
500
+
501
+ expect(matcher?.filter_snapshot).toEqual({vars: {ENABLED: 'true'}});
502
+ });
503
+
394
504
  it('omits snapshots for event-only filters and malformed filters', () => {
395
505
  const plan = planListenerFilterSnapshots({
396
506
  on: [
@@ -525,6 +635,9 @@ describe('assembleStepDispatchContext', () => {
525
635
  jobExecution: execution,
526
636
  });
527
637
 
638
+ expect(Object.keys(context.values).sort()).toEqual(
639
+ [...getWorkflowPredicateContextRoots('step.if')].sort(),
640
+ );
528
641
  expect(context).toEqual({
529
642
  site: 'step-dispatch',
530
643
  values: {
@@ -541,11 +654,16 @@ describe('assembleStepDispatchContext', () => {
541
654
  event: 'push',
542
655
  delivery_id: 'delivery-1',
543
656
  received_at: '2026-06-30T12:00:00.000Z',
657
+ project: null,
658
+ repository: null,
659
+ ref: null,
660
+ commit: null,
544
661
  data: {ref: 'refs/heads/main'},
545
662
  },
546
663
  ],
547
664
  outputs: {},
548
665
  },
666
+ jobs: {},
549
667
  step: {
550
668
  attempt: 2n,
551
669
  is_retry: true,
@@ -568,6 +686,7 @@ describe('assembleStepDispatchContext', () => {
568
686
  test: {status: 'pending', attempts: []},
569
687
  running: {status: 'running', attempts: []},
570
688
  },
689
+ vars: {},
571
690
  },
572
691
  });
573
692
  });
@@ -811,9 +930,13 @@ describe('assembleGateContext', () => {
811
930
  it('wraps the reported step result with the step-report site', () => {
812
931
  const context = assembleGateContext({status: 'failed', exitCode: 1});
813
932
 
933
+ expect(Object.keys(context.values).sort()).toEqual(
934
+ [...getWorkflowPredicateContextRoots('step.success')].sort(),
935
+ );
814
936
  expect(context).toEqual({
815
937
  site: 'step-report',
816
938
  values: {
939
+ vars: {},
817
940
  step: {
818
941
  exit_code: 1n,
819
942
  status: 'failed',
@@ -845,11 +968,16 @@ describe('assembleJobResolutionContext', () => {
845
968
  jobExecution({sequence: 1, name: 'Second', status: 'succeeded', finishedAt: date}),
846
969
  ];
847
970
 
848
- const context = assembleJobResolutionContext(executions);
971
+ const context = assembleJobResolutionContext({executions, jobs: []});
849
972
 
973
+ expect(Object.keys(context.values).sort()).toEqual(
974
+ [...getWorkflowPredicateContextRoots('job.success')].sort(),
975
+ );
850
976
  expect(context).toEqual({
851
977
  site: 'job-resolution',
852
978
  values: {
979
+ jobs: {},
980
+ vars: {},
853
981
  executions: [
854
982
  {
855
983
  index: 0,
@@ -863,6 +991,10 @@ describe('assembleJobResolutionContext', () => {
863
991
  event: 'push',
864
992
  delivery_id: 'delivery-1',
865
993
  received_at: '2026-06-30T12:00:00.000Z',
994
+ project: null,
995
+ repository: null,
996
+ ref: null,
997
+ commit: null,
866
998
  data: {ref: 'refs/heads/main'},
867
999
  },
868
1000
  ],
@@ -880,6 +1012,10 @@ describe('assembleJobResolutionContext', () => {
880
1012
  event: 'push',
881
1013
  delivery_id: 'delivery-1',
882
1014
  received_at: '2026-06-30T12:00:00.000Z',
1015
+ project: null,
1016
+ repository: null,
1017
+ ref: null,
1018
+ commit: null,
883
1019
  data: {ref: 'refs/heads/main'},
884
1020
  },
885
1021
  ],
@@ -894,7 +1030,9 @@ describe('assembleJobResolutionContext', () => {
894
1030
  describe('assembleExecutionResolutionContext', () => {
895
1031
  const run = {
896
1032
  id: 'run-1',
1033
+ number: 1,
897
1034
  name: 'Build',
1035
+ workflowName: 'Build',
898
1036
  definitionId: 'def-1',
899
1037
  projectId: 'proj-1',
900
1038
  workspaceId: 'workspace-1',
@@ -995,6 +1133,7 @@ function jobExecution(overrides: Partial<JobExecution> = {}): JobExecution {
995
1133
  id: 'exec-1',
996
1134
  jobId: 'job-1',
997
1135
  sequence: 2,
1136
+ nameOverride: 'Deploy',
998
1137
  name: 'Deploy',
999
1138
  runner: null,
1000
1139
  status: 'running',
@@ -1005,6 +1144,10 @@ function jobExecution(overrides: Partial<JobExecution> = {}): JobExecution {
1005
1144
  event: 'push',
1006
1145
  delivery_id: 'delivery-1',
1007
1146
  received_at: '2026-06-30T12:00:00.000Z',
1147
+ project: null,
1148
+ repository: null,
1149
+ ref: null,
1150
+ commit: null,
1008
1151
  data: {ref: 'refs/heads/main'},
1009
1152
  },
1010
1153
  ],
@@ -1,12 +1,18 @@
1
1
  import {
2
2
  analyzeContextRootKeyAccess,
3
3
  extractExactContextRoots,
4
+ getWorkflowPredicateContextRoots,
4
5
  type WorkflowExpressionEvaluationContext,
6
+ type WorkflowPredicateContextRoot,
5
7
  } from '@shipfox/expression';
6
8
  import type {Job, JobListeningTrigger} from '#core/entities/job.js';
7
9
  import type {JobExecution} from '#core/entities/job-execution.js';
8
10
  import type {Step, StepAttempt, StepStatus} from '#core/entities/step.js';
9
- import type {TriggerPayload, WorkflowRun} from '#core/entities/workflow-run.js';
11
+ import type {
12
+ TriggerPayload,
13
+ WorkflowRun,
14
+ WorkflowRunTriggerReference,
15
+ } from '#core/entities/workflow-run.js';
10
16
  import type {WorkflowEvaluationContext} from './workflow-evaluation-context.js';
11
17
 
12
18
  export interface JobContextInput {
@@ -17,8 +23,15 @@ export interface JobContextInput {
17
23
  export interface AssembleWorkflowRunContextParams {
18
24
  readonly run: Pick<
19
25
  WorkflowRun,
20
- 'id' | 'name' | 'definitionId' | 'projectId' | 'workspaceId' | 'createdAt'
21
- >;
26
+ | 'id'
27
+ | 'number'
28
+ | 'name'
29
+ | 'workflowName'
30
+ | 'definitionId'
31
+ | 'projectId'
32
+ | 'workspaceId'
33
+ | 'createdAt'
34
+ > & {readonly triggerReference?: WorkflowRunTriggerReference | null | undefined};
22
35
  readonly triggerPayload: TriggerPayload;
23
36
  readonly inputs?: Record<string, unknown> | null | undefined;
24
37
  readonly vars?: Record<string, string> | undefined;
@@ -27,11 +40,16 @@ export interface AssembleWorkflowRunContextParams {
27
40
  export function assembleWorkflowRunContext(
28
41
  params: AssembleWorkflowRunContextParams,
29
42
  ): WorkflowExpressionEvaluationContext {
43
+ const triggerReference = params.run.triggerReference;
30
44
  return {
45
+ workflow: {
46
+ id: params.run.definitionId,
47
+ name: params.run.workflowName,
48
+ },
31
49
  run: {
32
50
  id: params.run.id,
51
+ number: params.run.number,
33
52
  name: params.run.name,
34
- definition_id: params.run.definitionId,
35
53
  project_id: params.run.projectId,
36
54
  workspace_id: params.run.workspaceId,
37
55
  created_at: params.run.createdAt,
@@ -39,6 +57,10 @@ export function assembleWorkflowRunContext(
39
57
  trigger: {
40
58
  source: params.triggerPayload.source,
41
59
  event: params.triggerPayload.event,
60
+ project: triggerReference?.project ?? null,
61
+ repository: triggerReference?.repository ?? null,
62
+ ref: triggerReference?.ref ?? null,
63
+ commit: triggerReference?.commit ?? null,
42
64
  },
43
65
  event: 'data' in params.triggerPayload ? params.triggerPayload.data : null,
44
66
  inputs: params.inputs ?? null,
@@ -56,8 +78,9 @@ export function assembleCreationContext(
56
78
  }
57
79
 
58
80
  export interface AssembleExecutionCreationContextParams extends AssembleWorkflowRunContextParams {
59
- readonly jobId: string;
81
+ readonly job: Pick<Job, 'id' | 'key' | 'name'>;
60
82
  readonly sequence: number;
83
+ readonly nameOverride: string | null;
61
84
  readonly executionName: string;
62
85
  readonly status: JobExecution['status'];
63
86
  readonly triggerEvents: readonly JobExecution['triggerEvents'][number][];
@@ -68,9 +91,10 @@ export function assembleExecutionCreationContext(
68
91
  params: AssembleExecutionCreationContextParams,
69
92
  ): WorkflowEvaluationContext {
70
93
  const execution: JobExecution = {
71
- id: `${params.jobId}:${params.sequence}`,
72
- jobId: params.jobId,
94
+ id: `${params.job.id}:${params.sequence}`,
95
+ jobId: params.job.id,
73
96
  sequence: params.sequence,
97
+ nameOverride: params.nameOverride,
74
98
  name: params.executionName,
75
99
  runner: null,
76
100
  status: params.status,
@@ -92,6 +116,7 @@ export function assembleExecutionCreationContext(
92
116
  values: {
93
117
  ...assembleWorkflowRunContext(params),
94
118
  ...executions,
119
+ job: {key: params.job.key, name: params.job.name ?? params.job.key},
95
120
  execution: executionValues.at(-1),
96
121
  },
97
122
  };
@@ -142,11 +167,13 @@ export function assembleJobActivationContext(
142
167
  ...assembleWorkflowRunContext(params),
143
168
  ...assembleJobsContext(params.jobs),
144
169
  needs: params.jobs.map(assembleJobContext),
170
+ vars: params.vars ?? {},
145
171
  },
146
172
  };
147
173
  }
148
174
 
149
- type ListenerSnapshotRoot = 'run' | 'trigger' | 'inputs' | 'job' | 'jobs';
175
+ type ListenerPredicateField = 'listener.on' | 'listener.until';
176
+ type ListenerSnapshotRoot = Exclude<WorkflowPredicateContextRoot<ListenerPredicateField>, 'event'>;
150
177
 
151
178
  export interface MatcherSnapshotPlan {
152
179
  readonly matcher: JobListeningTrigger;
@@ -167,14 +194,17 @@ export function planListenerFilterSnapshots(params: {
167
194
  }): ListenerSnapshotPlan {
168
195
  const roots = new Set<ListenerSnapshotRoot>();
169
196
  const jobKeys = new Set<string>();
170
- const on = params.on.map((matcher) => planMatcherFilterSnapshot(matcher, roots, jobKeys));
197
+ const on = params.on.map((matcher) =>
198
+ planMatcherFilterSnapshot('listener.on', matcher, roots, jobKeys),
199
+ );
171
200
  const until = (params.until ?? []).map((matcher) =>
172
- planMatcherFilterSnapshot(matcher, roots, jobKeys),
201
+ planMatcherFilterSnapshot('listener.until', matcher, roots, jobKeys),
173
202
  );
174
203
  return {on, until, roots, jobKeys};
175
204
  }
176
205
 
177
206
  function planMatcherFilterSnapshot(
207
+ field: ListenerPredicateField,
178
208
  matcher: JobListeningTrigger,
179
209
  allRoots: Set<ListenerSnapshotRoot>,
180
210
  allJobKeys: Set<string>,
@@ -183,9 +213,9 @@ function planMatcherFilterSnapshot(
183
213
 
184
214
  let roots: ListenerSnapshotRoot[];
185
215
  try {
186
- roots = extractExactContextRoots(matcher.filter)
187
- .filter((root) => root !== 'event')
188
- .filter(isListenerSnapshotRoot);
216
+ roots = extractExactContextRoots(matcher.filter).filter((root) =>
217
+ isListenerSnapshotRoot(field, root),
218
+ );
189
219
  } catch {
190
220
  return {matcher, roots: new Set(), jobKeys: new Set()};
191
221
  }
@@ -205,27 +235,40 @@ function planMatcherFilterSnapshot(
205
235
  return {matcher, roots: new Set(roots), jobKeys};
206
236
  }
207
237
 
208
- function isListenerSnapshotRoot(root: string): root is ListenerSnapshotRoot {
238
+ function isListenerSnapshotRoot(
239
+ field: ListenerPredicateField,
240
+ root: string,
241
+ ): root is ListenerSnapshotRoot {
209
242
  return (
210
- root === 'run' || root === 'trigger' || root === 'inputs' || root === 'job' || root === 'jobs'
243
+ root !== 'event' &&
244
+ getWorkflowPredicateContextRoots(field).includes(
245
+ root as WorkflowPredicateContextRoot<ListenerPredicateField>,
246
+ )
211
247
  );
212
248
  }
213
249
 
214
250
  export function assembleListenerSnapshotContext(params: {
215
- readonly job: Pick<Job, 'key'>;
251
+ readonly job: Pick<Job, 'key'> & Partial<Pick<Job, 'name'>>;
216
252
  readonly run: AssembleWorkflowRunContextParams['run'];
217
253
  readonly triggerPayload: TriggerPayload;
218
254
  readonly inputs?: Record<string, unknown> | null | undefined;
255
+ readonly vars?: Record<string, string> | undefined;
219
256
  readonly plan: ListenerSnapshotPlan;
220
257
  readonly dependencyJobs: readonly JobContextInput[];
221
258
  }): WorkflowExpressionEvaluationContext {
222
259
  const context: Record<string, unknown> = {};
223
- if (params.plan.roots.has('run') || params.plan.roots.has('trigger')) {
260
+ if (
261
+ params.plan.roots.has('workflow') ||
262
+ params.plan.roots.has('run') ||
263
+ params.plan.roots.has('trigger')
264
+ ) {
224
265
  const runContext = assembleWorkflowRunContext({
225
266
  run: params.run,
226
267
  triggerPayload: params.triggerPayload,
227
268
  inputs: params.inputs,
269
+ vars: params.vars,
228
270
  });
271
+ if (params.plan.roots.has('workflow')) context.workflow = runContext.workflow;
229
272
  if (params.plan.roots.has('run')) context.run = runContext.run;
230
273
  if (params.plan.roots.has('trigger')) context.trigger = runContext.trigger;
231
274
  }
@@ -233,8 +276,14 @@ export function assembleListenerSnapshotContext(params: {
233
276
  if (params.plan.roots.has('inputs')) {
234
277
  context.inputs = params.inputs ?? null;
235
278
  }
279
+ if (params.plan.roots.has('vars')) {
280
+ context.vars = params.vars ?? {};
281
+ }
236
282
  if (params.plan.roots.has('job')) {
237
- context.job = {key: params.job.key};
283
+ context.job = {
284
+ key: params.job.key,
285
+ ...(params.job.name === undefined ? {} : {name: params.job.name ?? params.job.key}),
286
+ };
238
287
  }
239
288
  if (params.plan.roots.has('jobs')) {
240
289
  context.jobs = requestedJobsContext(params.dependencyJobs, params.plan.jobKeys);
@@ -376,6 +425,7 @@ export function assembleStepDispatchContext(params: {
376
425
  readonly targetStepId: string;
377
426
  readonly jobExecution?: JobExecution;
378
427
  readonly jobs?: readonly JobContextInput[];
428
+ readonly vars?: Record<string, string> | undefined;
379
429
  }): WorkflowEvaluationContext {
380
430
  const targetStep = params.steps.find((step) => step.id === params.targetStepId);
381
431
  const stepAttemptContext = buildStepAttemptContext(params);
@@ -392,7 +442,8 @@ export function assembleStepDispatchContext(params: {
392
442
  return {
393
443
  site: 'step-dispatch',
394
444
  values: {
395
- ...(params.jobs === undefined ? {} : assembleJobsContext(params.jobs)),
445
+ vars: params.vars ?? {},
446
+ ...assembleJobsContext(params.jobs ?? []),
396
447
  ...(params.jobExecution === undefined
397
448
  ? {}
398
449
  : {
@@ -479,10 +530,12 @@ export function assembleGateContext(params: {
479
530
  readonly status: StepStatus;
480
531
  readonly exitCode: number | null;
481
532
  readonly output?: Record<string, unknown> | null | undefined;
533
+ readonly vars?: Record<string, string> | undefined;
482
534
  }): WorkflowEvaluationContext {
483
535
  return {
484
536
  site: 'step-report',
485
537
  values: {
538
+ vars: params.vars ?? {},
486
539
  step: {
487
540
  ...(params.exitCode === null ? {} : {exit_code: BigInt(params.exitCode)}),
488
541
  status: params.status,
@@ -492,12 +545,18 @@ export function assembleGateContext(params: {
492
545
  };
493
546
  }
494
547
 
495
- export function assembleJobResolutionContext(
496
- executions: readonly JobExecution[],
497
- ): WorkflowEvaluationContext {
548
+ export function assembleJobResolutionContext(params: {
549
+ readonly executions: readonly JobExecution[];
550
+ readonly jobs: readonly JobContextInput[];
551
+ readonly vars?: Record<string, string> | undefined;
552
+ }): WorkflowEvaluationContext {
498
553
  return {
499
554
  site: 'job-resolution',
500
- values: assembleExecutionsContext(executions),
555
+ values: {
556
+ ...assembleExecutionsContext(params.executions),
557
+ ...assembleJobsContext(params.jobs),
558
+ vars: params.vars ?? {},
559
+ },
501
560
  };
502
561
  }
503
562
 
@@ -506,7 +565,7 @@ export function assembleExecutionResolutionContext(params: {
506
565
  readonly triggerPayload: TriggerPayload;
507
566
  readonly inputs?: Record<string, unknown> | null | undefined;
508
567
  readonly vars?: Record<string, string> | undefined;
509
- readonly job: Pick<Job, 'key'>;
568
+ readonly job: Pick<Job, 'key'> & Partial<Pick<Job, 'name'>>;
510
569
  readonly jobExecution: JobExecution;
511
570
  readonly executions: readonly JobExecution[];
512
571
  readonly steps: readonly Step[];
@@ -528,7 +587,10 @@ export function assembleExecutionResolutionContext(params: {
528
587
  params.jobExecution,
529
588
  executionIndex < 0 ? params.jobExecution.sequence - 1 : executionIndex,
530
589
  ),
531
- job: {key: params.job.key},
590
+ job: {
591
+ key: params.job.key,
592
+ ...(params.job.name === undefined ? {} : {name: params.job.name ?? params.job.key}),
593
+ },
532
594
  steps: assembleStepsContext({steps: params.steps, attempts: params.attempts}),
533
595
  },
534
596
  };