@stigmer/runner 3.40.0 → 3.41.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 (278) hide show
  1. package/README.md +3 -1
  2. package/dist/.build-fingerprint +1 -1
  3. package/dist/__test-utils__/execution-record-fixture.d.ts +2 -1
  4. package/dist/__test-utils__/execution-record-fixture.js.map +1 -1
  5. package/dist/activities/call-agent.js +1 -1
  6. package/dist/activities/discover-mcp-server.d.ts +7 -1
  7. package/dist/activities/discover-mcp-server.js +13 -29
  8. package/dist/activities/discover-mcp-server.js.map +1 -1
  9. package/dist/activities/execute-cursor/__test-utils__/fold.d.ts +4 -2
  10. package/dist/activities/execute-cursor/__test-utils__/fold.js +3 -4
  11. package/dist/activities/execute-cursor/__test-utils__/fold.js.map +1 -1
  12. package/dist/activities/execute-cursor/__test-utils__/hermetic-cursor.js +1 -0
  13. package/dist/activities/execute-cursor/__test-utils__/hermetic-cursor.js.map +1 -1
  14. package/dist/activities/execute-cursor/approval-policy.d.ts +1 -29
  15. package/dist/activities/execute-cursor/approval-policy.js +11 -35
  16. package/dist/activities/execute-cursor/approval-policy.js.map +1 -1
  17. package/dist/activities/execute-cursor/boundary-rows.js +4 -4
  18. package/dist/activities/execute-cursor/boundary-rows.js.map +1 -1
  19. package/dist/activities/execute-cursor/translator.d.ts +12 -17
  20. package/dist/activities/execute-cursor/translator.js +13 -30
  21. package/dist/activities/execute-cursor/translator.js.map +1 -1
  22. package/dist/activities/execute-cursor/turn-stream.js +4 -2
  23. package/dist/activities/execute-cursor/turn-stream.js.map +1 -1
  24. package/dist/activities/execute-deep-agent/__test-utils__/hermetic-deep-agent.d.ts +11 -1
  25. package/dist/activities/execute-deep-agent/__test-utils__/hermetic-deep-agent.js +22 -3
  26. package/dist/activities/execute-deep-agent/__test-utils__/hermetic-deep-agent.js.map +1 -1
  27. package/dist/activities/execute-deep-agent/inline-publisher.d.ts +33 -2
  28. package/dist/activities/execute-deep-agent/inline-publisher.js +33 -7
  29. package/dist/activities/execute-deep-agent/inline-publisher.js.map +1 -1
  30. package/dist/activities/execute-deep-agent/platform-route.d.ts +48 -13
  31. package/dist/activities/execute-deep-agent/platform-route.js +87 -19
  32. package/dist/activities/execute-deep-agent/platform-route.js.map +1 -1
  33. package/dist/activities/execute-deep-agent/prompt-builder.d.ts +70 -35
  34. package/dist/activities/execute-deep-agent/prompt-builder.js +70 -55
  35. package/dist/activities/execute-deep-agent/prompt-builder.js.map +1 -1
  36. package/dist/activities/execute-deep-agent/streaming-side-effects.d.ts +20 -3
  37. package/dist/activities/execute-deep-agent/streaming-side-effects.js +26 -4
  38. package/dist/activities/execute-deep-agent/streaming-side-effects.js.map +1 -1
  39. package/dist/activities/execute-deep-agent/translator.d.ts +5 -4
  40. package/dist/activities/execute-deep-agent/translator.js +5 -4
  41. package/dist/activities/execute-deep-agent/translator.js.map +1 -1
  42. package/dist/activities/execute-deep-agent/turn-settle.js +6 -6
  43. package/dist/activities/execute-deep-agent/turn-settle.js.map +1 -1
  44. package/dist/activities/execute-deep-agent/turn-setup.d.ts +18 -13
  45. package/dist/activities/execute-deep-agent/turn-setup.js +42 -36
  46. package/dist/activities/execute-deep-agent/turn-setup.js.map +1 -1
  47. package/dist/activities/execute-deep-agent/turn-stream.d.ts +10 -6
  48. package/dist/activities/execute-deep-agent/turn-stream.js +6 -16
  49. package/dist/activities/execute-deep-agent/turn-stream.js.map +1 -1
  50. package/dist/activities/execute-deep-agent/turn.d.ts +4 -1
  51. package/dist/activities/execute-deep-agent/turn.js +15 -6
  52. package/dist/activities/execute-deep-agent/turn.js.map +1 -1
  53. package/dist/activities/workflow-event-activities.js +2 -0
  54. package/dist/activities/workflow-event-activities.js.map +1 -1
  55. package/dist/config.d.ts +9 -0
  56. package/dist/config.js +2 -0
  57. package/dist/config.js.map +1 -1
  58. package/dist/exit-backstop.d.ts +64 -0
  59. package/dist/exit-backstop.js +79 -0
  60. package/dist/exit-backstop.js.map +1 -0
  61. package/dist/harness/terminal-table.d.ts +12 -5
  62. package/dist/harness/terminal-table.js +13 -13
  63. package/dist/harness/terminal-table.js.map +1 -1
  64. package/dist/harness/transcript/builder.d.ts +21 -0
  65. package/dist/harness/transcript/builder.js +53 -31
  66. package/dist/harness/transcript/builder.js.map +1 -1
  67. package/dist/harness/transcript/events.d.ts +22 -26
  68. package/dist/harness/transcript/events.js +6 -5
  69. package/dist/harness/transcript/events.js.map +1 -1
  70. package/dist/harness/turn-context.d.ts +3 -1
  71. package/dist/harness/turn-context.js +5 -3
  72. package/dist/harness/turn-context.js.map +1 -1
  73. package/dist/main.js +10 -4
  74. package/dist/main.js.map +1 -1
  75. package/dist/middleware/cost-advisory.d.ts +6 -3
  76. package/dist/middleware/cost-advisory.js +6 -3
  77. package/dist/middleware/cost-advisory.js.map +1 -1
  78. package/dist/middleware/execution-budget.d.ts +22 -7
  79. package/dist/middleware/execution-budget.js +57 -35
  80. package/dist/middleware/execution-budget.js.map +1 -1
  81. package/dist/middleware/index.d.ts +10 -7
  82. package/dist/middleware/index.js +10 -7
  83. package/dist/middleware/index.js.map +1 -1
  84. package/dist/middleware/types.d.ts +6 -1
  85. package/dist/runner-manager.js +3 -2
  86. package/dist/runner-manager.js.map +1 -1
  87. package/dist/runner.d.ts +25 -0
  88. package/dist/runner.js +41 -14
  89. package/dist/runner.js.map +1 -1
  90. package/dist/shared/approval-policy.d.ts +23 -13
  91. package/dist/shared/approval-policy.js +47 -14
  92. package/dist/shared/approval-policy.js.map +1 -1
  93. package/dist/shared/caller-identity.d.ts +4 -5
  94. package/dist/shared/caller-identity.js +4 -5
  95. package/dist/shared/caller-identity.js.map +1 -1
  96. package/dist/shared/channel-attachment.js +3 -2
  97. package/dist/shared/channel-attachment.js.map +1 -1
  98. package/dist/shared/connect-backfill.d.ts +2 -1
  99. package/dist/shared/connect-backfill.js +2 -2
  100. package/dist/shared/connect-backfill.js.map +1 -1
  101. package/dist/shared/mcp-resolver.d.ts +10 -1
  102. package/dist/shared/mcp-resolver.js +11 -2
  103. package/dist/shared/mcp-resolver.js.map +1 -1
  104. package/dist/shared/memory-attachment.js +3 -2
  105. package/dist/shared/memory-attachment.js.map +1 -1
  106. package/dist/shared/model-error.d.ts +25 -3
  107. package/dist/shared/model-error.js +78 -10
  108. package/dist/shared/model-error.js.map +1 -1
  109. package/dist/shared/platform-server-address.d.ts +71 -0
  110. package/dist/shared/platform-server-address.js +103 -0
  111. package/dist/shared/platform-server-address.js.map +1 -0
  112. package/dist/shared/prompt-sections.d.ts +6 -28
  113. package/dist/shared/prompt-sections.js +6 -35
  114. package/dist/shared/prompt-sections.js.map +1 -1
  115. package/dist/shared/skill-resolver.d.ts +2 -3
  116. package/dist/shared/skill-resolver.js +2 -3
  117. package/dist/shared/skill-resolver.js.map +1 -1
  118. package/dist/shared/synthesized-attachment.d.ts +0 -5
  119. package/dist/shared/synthesized-attachment.js +0 -12
  120. package/dist/shared/synthesized-attachment.js.map +1 -1
  121. package/dist/shared/tool-rounds.d.ts +51 -23
  122. package/dist/shared/tool-rounds.js +67 -24
  123. package/dist/shared/tool-rounds.js.map +1 -1
  124. package/dist/shared/workspace/platform-dir.d.ts +15 -0
  125. package/dist/shared/workspace/platform-dir.js +18 -1
  126. package/dist/shared/workspace/platform-dir.js.map +1 -1
  127. package/dist/shared/workspace/sources/git.js +13 -6
  128. package/dist/shared/workspace/sources/git.js.map +1 -1
  129. package/dist/shared/workspace/stigmer-link.d.ts +21 -14
  130. package/dist/shared/workspace/stigmer-link.js +91 -29
  131. package/dist/shared/workspace/stigmer-link.js.map +1 -1
  132. package/dist/tools/url-guard.d.ts +5 -1
  133. package/dist/tools/url-guard.js +9 -2
  134. package/dist/tools/url-guard.js.map +1 -1
  135. package/dist/worker.d.ts +11 -2
  136. package/dist/worker.js +1 -1
  137. package/dist/worker.js.map +1 -1
  138. package/dist/workflow-engine/tasks/human-input.d.ts +16 -0
  139. package/dist/workflow-engine/tasks/human-input.js +79 -37
  140. package/dist/workflow-engine/tasks/human-input.js.map +1 -1
  141. package/dist/workflow-engine/types.d.ts +14 -4
  142. package/dist/workflow-engine/types.js.map +1 -1
  143. package/dist/workflows/call-agent-orchestrator.d.ts +13 -0
  144. package/dist/workflows/call-agent-orchestrator.js.map +1 -1
  145. package/dist/workflows/engine-core.d.ts +25 -0
  146. package/dist/workflows/engine-core.js.map +1 -1
  147. package/dist/workflows/execute-from-execution.d.ts +3 -0
  148. package/dist/workflows/execute-from-execution.js.map +1 -1
  149. package/dist/workflows/human-input-orchestrator.d.ts +9 -12
  150. package/dist/workflows/human-input-orchestrator.js +12 -44
  151. package/dist/workflows/human-input-orchestrator.js.map +1 -1
  152. package/package.json +5 -5
  153. package/src/__test-utils__/config-fixture.ts +1 -0
  154. package/src/__test-utils__/execution-record-fixture.ts +2 -1
  155. package/src/__test-utils__/harness-contract/runtime-contract.ts +5 -3
  156. package/src/__test-utils__/test-gate.ts +8 -0
  157. package/src/__tests__/exit-backstop.test.ts +91 -0
  158. package/src/__tests__/golden-e2e.test.ts +80 -62
  159. package/src/__tests__/history-encryption-e2e.test.ts +51 -27
  160. package/src/__tests__/runner.test.ts +60 -2
  161. package/src/activities/__tests__/classify-tool-approvals.test.ts +1 -0
  162. package/src/activities/__tests__/discover-mcp-server.hang.test.ts +5 -1
  163. package/src/activities/__tests__/discover-mcp-server.test.ts +90 -49
  164. package/src/activities/__tests__/workflow-event-activities.test.ts +28 -7
  165. package/src/activities/call-agent.ts +1 -1
  166. package/src/activities/discover-mcp-server.ts +27 -37
  167. package/src/activities/execute-cursor/__test-utils__/fold.ts +6 -4
  168. package/src/activities/execute-cursor/__test-utils__/hermetic-cursor.ts +1 -0
  169. package/src/activities/execute-cursor/__tests__/approval-gate.test.ts +4 -29
  170. package/src/activities/execute-cursor/__tests__/hermetic/bypassed-tool-call.test.ts +120 -0
  171. package/src/activities/execute-cursor/__tests__/hermetic/file-review-capture.test.ts +5 -5
  172. package/src/activities/execute-cursor/__tests__/hermetic/goldens/file-review-capture.status.json +0 -2
  173. package/src/activities/execute-cursor/__tests__/hermetic/goldens/resolution-error.status.json +1 -1
  174. package/src/activities/execute-cursor/__tests__/hermetic/goldens/shell-output-delta.error-delta.status.json +0 -3
  175. package/src/activities/execute-cursor/__tests__/hermetic/goldens/shell-output-delta.output-first.status.json +0 -2
  176. package/src/activities/execute-cursor/__tests__/hermetic/goldens/shell-output-delta.status.json +0 -2
  177. package/src/activities/execute-cursor/__tests__/hermetic/goldens/stall.status.json +0 -2
  178. package/src/activities/execute-cursor/__tests__/hermetic/goldens/unattributed-hook-block.status.json +0 -3
  179. package/src/activities/execute-cursor/__tests__/hermetic/shell-output-delta.test.ts +9 -7
  180. package/src/activities/execute-cursor/__tests__/hermetic/thrown-error-arms.test.ts +6 -1
  181. package/src/activities/execute-cursor/__tests__/hitl-resume-history.test.ts +8 -11
  182. package/src/activities/execute-cursor/__tests__/sequential-gate-resume.test.ts +1 -3
  183. package/src/activities/execute-cursor/__tests__/translator.test.ts +68 -15
  184. package/src/activities/execute-cursor/approval-policy.ts +11 -36
  185. package/src/activities/execute-cursor/boundary-rows.ts +3 -3
  186. package/src/activities/execute-cursor/translator.ts +15 -32
  187. package/src/activities/execute-cursor/turn-stream.ts +4 -1
  188. package/src/activities/execute-deep-agent/__test-utils__/hermetic-deep-agent.ts +33 -2
  189. package/src/activities/execute-deep-agent/__tests__/adapter.test.ts +1 -0
  190. package/src/activities/execute-deep-agent/__tests__/goldens/system-prompt.build-from-plan.prompt.md +1 -27
  191. package/src/activities/execute-deep-agent/__tests__/goldens/system-prompt.everything.prompt.md +26 -30
  192. package/src/activities/execute-deep-agent/__tests__/goldens/system-prompt.plan-mode.prompt.md +1 -26
  193. package/src/activities/execute-deep-agent/__tests__/goldens/user-message.everything.md +36 -0
  194. package/src/activities/execute-deep-agent/__tests__/hermetic/file-review-capture.test.ts +4 -0
  195. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/file-review-capture.status.json +1 -1
  196. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/inline-artifact.turn1.status.json +1 -1
  197. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/inline-artifact.turn2.status.json +1 -1
  198. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/recursion-limit.persisted.status.json +8 -73
  199. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/resolution-error.status.json +1 -1
  200. package/src/activities/execute-deep-agent/__tests__/hermetic/inline-artifact-across-gate.test.ts +17 -0
  201. package/src/activities/execute-deep-agent/__tests__/hermetic/recursion-limit.test.ts +86 -26
  202. package/src/activities/execute-deep-agent/__tests__/hermetic/resolution-error.test.ts +9 -5
  203. package/src/activities/execute-deep-agent/__tests__/hermetic/thrown-turn-drains-publishes.test.ts +159 -0
  204. package/src/activities/execute-deep-agent/__tests__/inline-publisher.test.ts +84 -0
  205. package/src/activities/execute-deep-agent/__tests__/platform-route.test.ts +47 -10
  206. package/src/activities/execute-deep-agent/__tests__/prompt-builder.test.ts +127 -199
  207. package/src/activities/execute-deep-agent/__tests__/prompt-goldens.test.ts +31 -26
  208. package/src/activities/execute-deep-agent/__tests__/streaming-side-effects.test.ts +34 -0
  209. package/src/activities/execute-deep-agent/__tests__/turn-stream.test.ts +13 -5
  210. package/src/activities/execute-deep-agent/inline-publisher.ts +47 -7
  211. package/src/activities/execute-deep-agent/platform-route.ts +109 -20
  212. package/src/activities/execute-deep-agent/prompt-builder.ts +104 -92
  213. package/src/activities/execute-deep-agent/streaming-side-effects.ts +27 -4
  214. package/src/activities/execute-deep-agent/translator.ts +5 -4
  215. package/src/activities/execute-deep-agent/turn-settle.ts +6 -6
  216. package/src/activities/execute-deep-agent/turn-setup.ts +43 -38
  217. package/src/activities/execute-deep-agent/turn-stream.ts +15 -22
  218. package/src/activities/execute-deep-agent/turn.ts +16 -7
  219. package/src/activities/workflow-event-activities.ts +2 -0
  220. package/src/config.ts +11 -0
  221. package/src/exit-backstop.ts +97 -0
  222. package/src/harness/README.md +5 -5
  223. package/src/harness/terminal-table.ts +13 -13
  224. package/src/harness/transcript/__tests__/builder.test.ts +93 -21
  225. package/src/harness/transcript/builder.ts +53 -30
  226. package/src/harness/transcript/events.ts +22 -27
  227. package/src/harness/turn-context.ts +5 -3
  228. package/src/main.ts +9 -5
  229. package/src/middleware/__tests__/execution-budget.test.ts +181 -103
  230. package/src/middleware/cost-advisory.ts +6 -3
  231. package/src/middleware/execution-budget.ts +60 -34
  232. package/src/middleware/index.ts +10 -7
  233. package/src/middleware/types.ts +6 -1
  234. package/src/runner-manager.ts +3 -2
  235. package/src/runner.ts +57 -15
  236. package/src/shared/__tests__/approval-policy.test.ts +41 -0
  237. package/src/shared/__tests__/artifact-storage.test.ts +1 -0
  238. package/src/shared/__tests__/connect-backfill.test.ts +15 -11
  239. package/src/shared/__tests__/mcp-resolver.test.ts +72 -10
  240. package/src/shared/__tests__/model-error.test.ts +71 -3
  241. package/src/shared/__tests__/platform-server-address.test.ts +122 -0
  242. package/src/shared/__tests__/prompt-sections.test.ts +2 -54
  243. package/src/shared/__tests__/tool-rounds.test.ts +64 -14
  244. package/src/shared/approval-policy.ts +57 -14
  245. package/src/shared/caller-identity.ts +4 -5
  246. package/src/shared/channel-attachment.ts +2 -2
  247. package/src/shared/connect-backfill.ts +5 -1
  248. package/src/shared/mcp-resolver.ts +11 -1
  249. package/src/shared/memory-attachment.ts +2 -2
  250. package/src/shared/model-error.ts +87 -9
  251. package/src/shared/platform-server-address.ts +123 -0
  252. package/src/shared/prompt-sections.ts +6 -55
  253. package/src/shared/skill-resolver.ts +2 -3
  254. package/src/shared/synthesized-attachment.ts +0 -12
  255. package/src/shared/tool-rounds.ts +70 -24
  256. package/src/shared/workspace/__tests__/git-source.test.ts +11 -5
  257. package/src/shared/workspace/__tests__/stigmer-link.test.ts +107 -10
  258. package/src/shared/workspace/platform-dir.ts +19 -1
  259. package/src/shared/workspace/sources/git.ts +14 -8
  260. package/src/shared/workspace/stigmer-link.ts +99 -29
  261. package/src/tools/__tests__/url-guard.test.ts +19 -1
  262. package/src/tools/url-guard.ts +9 -1
  263. package/src/worker.ts +12 -2
  264. package/src/workflow-engine/__tests__/golden-execution.test.ts +2 -1
  265. package/src/workflow-engine/__tests__/loader.test.ts +1 -1
  266. package/src/workflow-engine/__tests__/tasks/human-input.test.ts +133 -57
  267. package/src/workflow-engine/tasks/human-input.ts +92 -42
  268. package/src/workflow-engine/types.ts +16 -4
  269. package/src/workflows/call-agent-orchestrator.ts +7 -0
  270. package/src/workflows/engine-core.ts +18 -0
  271. package/src/workflows/execute-from-execution.ts +2 -1
  272. package/src/workflows/human-input-orchestrator.ts +15 -56
  273. package/dist/shared/skill-relevance.d.ts +0 -65
  274. package/dist/shared/skill-relevance.js +0 -175
  275. package/dist/shared/skill-relevance.js.map +0 -1
  276. package/src/activities/execute-deep-agent/__tests__/goldens/system-prompt.skills-below-threshold.prompt.md +0 -146
  277. package/src/shared/__tests__/skill-relevance.test.ts +0 -292
  278. package/src/shared/skill-relevance.ts +0 -222
@@ -2,27 +2,25 @@
2
2
  * Human input orchestrator — Temporal workflow-layer HITL signal handler.
3
3
  *
4
4
  * Registers a signal handler for the human_input task, then blocks until
5
- * either the signal arrives or the timeout fires. Timeout behavior is
6
- * determined by the `onTimeout` policy:
7
- * - "fail": throws an error
8
- * - "approve": returns auto-approved output
9
- * - "deny": returns auto-denied output
10
- * - "escalate": returns the "escalate" outcome — by the outcome-by-name
11
- * contract (stigmer/stigmer#781) the loader guarantees the gate declares
12
- * an outcome with that exact name and a `then` branch, so the executor's
13
- * ordinary outcome routing takes the escalation path.
5
+ * either the signal arrives or the timeout fires, and reports which one
6
+ * happened: the reviewer's payload, or a timeout. It applies no timeout
7
+ * policy. What a timeout means (fail the task, or resolve the gate to a
8
+ * declared outcome) is decided in the kernel (`workflow-engine/tasks/
9
+ * human-input.ts`), which also logs how the approval ended, so the two
10
+ * cannot drift apart across layers.
14
11
  *
15
12
  * Signal payload shape:
16
- * { outcome, form_data?, reviewer, reviewer_actor?, responded_at }
13
+ * { outcome, form_data?, comment?, reviewer, reviewer_actor?, responded_at }
17
14
  *
18
15
  * TEMPORAL SANDBOX: This file runs inside the deterministic workflow isolate.
19
16
  */
20
17
  import { defineSignal, setHandler, condition } from "@temporalio/workflow";
18
+ const TIMED_OUT = { timedOut: true };
21
19
  /**
22
20
  * Orchestrates a human_input task — blocks until signal or timeout.
23
21
  */
24
22
  export async function orchestrateHumanInput(config) {
25
- const { signalName, timeoutSeconds, onTimeout } = config;
23
+ const { signalName, timeoutSeconds } = config;
26
24
  let payload;
27
25
  let received = false;
28
26
  const signal = defineSignal(signalName);
@@ -31,43 +29,13 @@ export async function orchestrateHumanInput(config) {
31
29
  received = true;
32
30
  });
33
31
  if (timeoutSeconds > 0) {
34
- const timeoutMs = timeoutSeconds * 1000;
35
- const completed = await condition(() => received, timeoutMs);
36
- if (!completed) {
37
- return handleTimeout(signalName, onTimeout);
38
- }
32
+ const completed = await condition(() => received, timeoutSeconds * 1000);
33
+ if (!completed)
34
+ return TIMED_OUT;
39
35
  }
40
36
  else {
41
37
  await condition(() => received);
42
38
  }
43
39
  return payload;
44
40
  }
45
- function handleTimeout(signalName, policy) {
46
- switch (policy) {
47
- case "approve":
48
- return {
49
- outcome: "approve",
50
- auto_resolved: true,
51
- reason: "timeout",
52
- };
53
- case "deny":
54
- return {
55
- outcome: "deny",
56
- auto_resolved: true,
57
- reason: "timeout",
58
- };
59
- case "escalate":
60
- // The outcome word IS the declared outcome's name (loader-enforced),
61
- // so no positional remapping happens downstream — the executor's name
62
- // lookup routes the escalation branch directly.
63
- return {
64
- outcome: "escalate",
65
- auto_resolved: true,
66
- reason: "timeout",
67
- };
68
- case "fail":
69
- default:
70
- throw new Error(`human_input task timed out waiting for signal '${signalName}'`);
71
- }
72
- }
73
41
  //# sourceMappingURL=human-input-orchestrator.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"human-input-orchestrator.js","sourceRoot":"","sources":["../../src/workflows/human-input-orchestrator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAQ3E;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,MAAiC;IAEjC,MAAM,EAAE,UAAU,EAAE,cAAc,EAAE,SAAS,EAAE,GAAG,MAAM,CAAC;IAEzD,IAAI,OAAqC,CAAC;IAC1C,IAAI,QAAQ,GAAG,KAAK,CAAC;IAErB,MAAM,MAAM,GAAG,YAAY,CAAqB,UAAU,CAAC,CAAC;IAC5D,UAAU,CAAC,MAAM,EAAE,CAAC,IAAsB,EAAE,EAAE;QAC5C,OAAO,GAAG,IAAI,CAAC;QACf,QAAQ,GAAG,IAAI,CAAC;IAClB,CAAC,CAAC,CAAC;IAEH,IAAI,cAAc,GAAG,CAAC,EAAE,CAAC;QACvB,MAAM,SAAS,GAAG,cAAc,GAAG,IAAI,CAAC;QACxC,MAAM,SAAS,GAAG,MAAM,SAAS,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;QAE7D,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,OAAO,aAAa,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC;QAC9C,CAAC;IACH,CAAC;SAAM,CAAC;QACN,MAAM,SAAS,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,CAAC;IAClC,CAAC;IAED,OAAO,OAAQ,CAAC;AAClB,CAAC;AAED,SAAS,aAAa,CACpB,UAAkB,EAClB,MAA+B;IAE/B,QAAQ,MAAM,EAAE,CAAC;QACf,KAAK,SAAS;YACZ,OAAO;gBACL,OAAO,EAAE,SAAS;gBAClB,aAAa,EAAE,IAAI;gBACnB,MAAM,EAAE,SAAS;aAClB,CAAC;QAEJ,KAAK,MAAM;YACT,OAAO;gBACL,OAAO,EAAE,MAAM;gBACf,aAAa,EAAE,IAAI;gBACnB,MAAM,EAAE,SAAS;aAClB,CAAC;QAEJ,KAAK,UAAU;YACb,qEAAqE;YACrE,sEAAsE;YACtE,gDAAgD;YAChD,OAAO;gBACL,OAAO,EAAE,UAAU;gBACnB,aAAa,EAAE,IAAI;gBACnB,MAAM,EAAE,SAAS;aAClB,CAAC;QAEJ,KAAK,MAAM,CAAC;QACZ;YACE,MAAM,IAAI,KAAK,CACb,kDAAkD,UAAU,GAAG,CAChE,CAAC;IACN,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"human-input-orchestrator.js","sourceRoot":"","sources":["../../src/workflows/human-input-orchestrator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAS3E,MAAM,SAAS,GAAsB,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;AAExD;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,MAAiC;IAEjC,MAAM,EAAE,UAAU,EAAE,cAAc,EAAE,GAAG,MAAM,CAAC;IAE9C,IAAI,OAAqC,CAAC;IAC1C,IAAI,QAAQ,GAAG,KAAK,CAAC;IAErB,MAAM,MAAM,GAAG,YAAY,CAAqB,UAAU,CAAC,CAAC;IAC5D,UAAU,CAAC,MAAM,EAAE,CAAC,IAAsB,EAAE,EAAE;QAC5C,OAAO,GAAG,IAAI,CAAC;QACf,QAAQ,GAAG,IAAI,CAAC;IAClB,CAAC,CAAC,CAAC;IAEH,IAAI,cAAc,GAAG,CAAC,EAAE,CAAC;QACvB,MAAM,SAAS,GAAG,MAAM,SAAS,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,cAAc,GAAG,IAAI,CAAC,CAAC;QACzE,IAAI,CAAC,SAAS;YAAE,OAAO,SAAS,CAAC;IACnC,CAAC;SAAM,CAAC;QACN,MAAM,SAAS,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,CAAC;IAClC,CAAC;IAED,OAAO,OAAQ,CAAC;AAClB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stigmer/runner",
3
- "version": "3.40.0",
3
+ "version": "3.41.0",
4
4
  "description": "Embeddable Temporal worker for the Stigmer AI agent platform — handles agent execution, workflow orchestration, and MCP server management",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -109,10 +109,10 @@
109
109
  "@opentelemetry/sdk-metrics": "^2.0.0",
110
110
  "@opentelemetry/sdk-trace-base": "^2.0.0",
111
111
  "@opentelemetry/sdk-trace-node": "^2.0.0",
112
- "@stigmer/outbound": "3.40.0",
113
- "@stigmer/protos": "3.40.0",
114
- "@stigmer/temporal-codecs": "3.40.0",
115
- "@stigmer/zip-structure": "3.40.0",
112
+ "@stigmer/outbound": "3.41.0",
113
+ "@stigmer/protos": "3.41.0",
114
+ "@stigmer/temporal-codecs": "3.41.0",
115
+ "@stigmer/zip-structure": "3.41.0",
116
116
  "@temporalio/activity": "1.16.2",
117
117
  "@temporalio/common": "1.16.2",
118
118
  "@temporalio/interceptors-opentelemetry": "1.16.2",
@@ -45,6 +45,7 @@ export function testConfig(overrides: Partial<Config> = {}): Config {
45
45
  stigmerBackendEndpoint: INERT_ENDPOINT,
46
46
  stigmerTokenRef: { current: null },
47
47
  mcpBridgeEndpoint: null,
48
+ mcpPublicEndpoint: null,
48
49
  cursorApiKey: "",
49
50
  workspaceRootDir: join(tmpdir(), "stigmer-runner-test-workspaces"),
50
51
  mode: "local",
@@ -65,7 +65,8 @@ export interface ExecutionRecordOptions {
65
65
  readonly maxCostUsd?: number;
66
66
  /**
67
67
  * `ExecutionConfig.max_tool_rounds`: the hard tool-round budget the engine
68
- * enforces (native: LangGraph's `recursionLimit`, `shared/tool-rounds.ts`).
68
+ * enforces (native: the execution budget middleware's round count,
69
+ * `shared/tool-rounds.ts`).
69
70
  * Omitted or 0 = unlimited, the proto's default. Clamped to the floor of 10
70
71
  * by the runner, so a scenario that wants the limit reached scripts a model
71
72
  * that keeps calling tools (`repeatLast`).
@@ -482,7 +482,7 @@ export async function assertNonExecutingDecisionSettlesSkipped(
482
482
  *
483
483
  * The execution SETS the budget it exhausts: the record carries the smallest
484
484
  * valid `max_tool_rounds` (an unbounded execution has no limit to reach — on
485
- * native `resolveRecursionLimit(0)` is unlimited, and the first run of this
485
+ * native `resolveToolRoundLimit(0)` is unlimited, and the first run of this
486
486
  * arm against it spun until the test timed out). The fake
487
487
  * exhausts whatever budget it is given; a real engine spins its cheapest
488
488
  * ungated tool until the graph stops it.
@@ -877,8 +877,10 @@ export async function assertResolutionErrorFailsBeforeEngine(harness: RuntimeCon
877
877
  expect(slimOf(subject, invocation).phase).toBe("EXECUTION_FAILED");
878
878
  expect(driver.record.persistedPhases, `${subject.name}: nothing was persisted before the failure`).toEqual([ExecutionPhase.EXECUTION_FAILED]);
879
879
  const final = finalStatusOf(harness, driver);
880
- expect(final.error).toBe("Execution failed: [Error] runtime fault injected at getAgent");
881
- expect(systemMessages(final)).toEqual([TERMINAL_COPY.internalFailure.row, "Error details: [Error] runtime fault injected at getAgent"]);
880
+ // One grammar for a FAILED `status.error` (stigmer#1122): the described
881
+ // fault, unframed, exactly what the details row carries.
882
+ expect(final.error).toBe("[Error] runtime fault injected at getAgent");
883
+ expect(systemMessages(final)).toEqual([TERMINAL_COPY.internalFailure.row, `Error details: ${final.error}`]);
882
884
  expect(driver.record.setupProgress).toEqual(["Fetching execution", "Resolving agent blueprint"]);
883
885
  expect(driver.record.sessionUpdates).toHaveLength(0);
884
886
  return { driver, invocations: [invocation], final };
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Whether this run is a test gate: `STIGMER_TEST_GATE=1`, set by the CI lanes
3
+ * and the local gates. A gate provides every dependency a suite needs, so a
4
+ * suite that would skip because a dependency is missing (the Temporal test
5
+ * server cannot boot, say) fails there instead. Outside a gate the same suite
6
+ * skips by name with its reason.
7
+ */
8
+ export const IN_TEST_GATE = process.env.STIGMER_TEST_GATE === "1";
@@ -0,0 +1,91 @@
1
+ import { afterEach, describe, expect, it, vi } from "vitest";
2
+ import { EXIT_BACKSTOP_MS, armExitBackstop, describeResources } from "../exit-backstop.js";
3
+
4
+ /**
5
+ * The exit backstop's contract (exit-backstop.ts): it never holds the loop,
6
+ * it stays silent before its bound, and at the bound it names what is still
7
+ * alive and exits 0, once. The real-process behaviour (a healthy runner
8
+ * exits in milliseconds, a leaked handle is cut at the bound) is proven
9
+ * against the built runner and by the execution conformance harness's
10
+ * slow-exit line; these pin the logic.
11
+ */
12
+
13
+ afterEach(() => {
14
+ vi.useRealTimers();
15
+ });
16
+
17
+ function arm(overrides: { boundMs?: number; resources?: string[] } = {}) {
18
+ const exit = vi.fn<(code: number) => void>();
19
+ const log = vi.fn<(line: string) => void>();
20
+ const timer = armExitBackstop({
21
+ boundMs: overrides.boundMs,
22
+ exit,
23
+ log,
24
+ activeResources: () => overrides.resources ?? ["TCPSocketWrap", "Timeout", "TCPSocketWrap"],
25
+ });
26
+ return { exit, log, timer };
27
+ }
28
+
29
+ describe("armExitBackstop", () => {
30
+ it("does not hold the event loop", () => {
31
+ const { timer } = arm();
32
+ try {
33
+ expect(timer.hasRef()).toBe(false);
34
+ } finally {
35
+ clearTimeout(timer);
36
+ }
37
+ });
38
+
39
+ it("stays silent before the bound", () => {
40
+ vi.useFakeTimers();
41
+ const { exit, log } = arm();
42
+
43
+ vi.advanceTimersByTime(EXIT_BACKSTOP_MS - 1);
44
+
45
+ expect(exit).not.toHaveBeenCalled();
46
+ expect(log).not.toHaveBeenCalled();
47
+ });
48
+
49
+ it("at the bound, names what is still alive and exits 0, once", () => {
50
+ vi.useFakeTimers();
51
+ const { exit, log } = arm();
52
+
53
+ vi.advanceTimersByTime(EXIT_BACKSTOP_MS);
54
+ vi.advanceTimersByTime(EXIT_BACKSTOP_MS);
55
+
56
+ expect(log).toHaveBeenCalledTimes(1);
57
+ expect(log.mock.calls[0]?.[0]).toBe(
58
+ `[runner] Process still alive ${EXIT_BACKSTOP_MS}ms after shutdown; forcing exit. ` +
59
+ "Active resources: TCPSocketWrap×2, Timeout×1",
60
+ );
61
+ expect(exit).toHaveBeenCalledTimes(1);
62
+ expect(exit).toHaveBeenCalledWith(0);
63
+ });
64
+
65
+ it("honours an explicit bound", () => {
66
+ vi.useFakeTimers();
67
+ const { exit } = arm({ boundMs: 250 });
68
+
69
+ vi.advanceTimersByTime(249);
70
+ expect(exit).not.toHaveBeenCalled();
71
+ vi.advanceTimersByTime(1);
72
+ expect(exit).toHaveBeenCalledWith(0);
73
+ });
74
+
75
+ it("keeps the bound above the conformance harness's 2 s slow-exit line", () => {
76
+ // Below it, the harness would stop reporting the very leaks this cuts.
77
+ expect(EXIT_BACKSTOP_MS).toBeGreaterThan(2_000);
78
+ });
79
+ });
80
+
81
+ describe("describeResources", () => {
82
+ it("groups and sorts, so the same leak reads the same on every exit", () => {
83
+ expect(describeResources(["Timeout", "TCPSocketWrap", "PipeWrap", "TCPSocketWrap"])).toBe(
84
+ "PipeWrap×1, TCPSocketWrap×2, Timeout×1",
85
+ );
86
+ });
87
+
88
+ it("says so when Node reports nothing", () => {
89
+ expect(describeResources([])).toBe("none reported");
90
+ });
91
+ });
@@ -7,14 +7,21 @@
7
7
  * - Expression evaluation via local activities (jq-wasm)
8
8
  * - Timer handling (sleep/wait)
9
9
  *
10
- * Prerequisites:
11
- * - @temporalio/testing ephemeral server binary (installed via npm)
12
- * - Temporal CLI (`temporal`) on PATH
10
+ * Prerequisites: none beyond `npm install`. `TestWorkflowEnvironment.createTimeSkipping()`
11
+ * downloads and runs Temporal's own test server, which skips a timer as soon as
12
+ * the workflow waits on it, so the goldens that wait minutes (#16 wait-delay,
13
+ * #21 retry-backoff) finish inside the per-test budget.
13
14
  *
14
15
  * The workflow-engine uses `deepClone` from `clone.ts` which falls
15
16
  * back to JSON round-trip when `structuredClone` is unavailable in
16
- * the Temporal deterministic V8 sandbox. Tests are skipped if the
17
- * environment can't start a Temporal test server.
17
+ * the Temporal deterministic V8 sandbox.
18
+ *
19
+ * Only one failure skips: the Temporal test server cannot boot (no network
20
+ * for the download, say). Each golden then skips by name with the boot
21
+ * error. Anything after the boot (the worker, the workflow bundle, a
22
+ * golden itself) fails. The suite once swallowed every error and returned
23
+ * early from each test, which vitest counts as a pass, so it reported
24
+ * sixteen passes without running a golden (stigmer#1300).
18
25
  *
19
26
  * Run with: npx vitest run src/__tests__/golden-e2e.test.ts
20
27
  */
@@ -24,8 +31,9 @@ import { readFileSync } from "node:fs";
24
31
  import { join, dirname } from "node:path";
25
32
  import { fileURLToPath } from "node:url";
26
33
  import { loadWorkflowFromYaml } from "../workflow-engine/loader.js";
34
+ import { IN_TEST_GATE } from "../__test-utils__/test-gate.js";
27
35
  import { evaluateExpressionBatch } from "../workflow-engine/expression.js";
28
- import type { ExecuteServerlessWorkflowInput } from "../workflows/engine-core.js";
36
+ import type { EngineActivities, ExecuteServerlessWorkflowInput } from "../workflows/engine-core.js";
29
37
  import type { WorkflowModel } from "../workflow-engine/types.js";
30
38
  import { INLINE_MODEL_WORKFLOW_TYPE } from "../__test-utils__/workflows/inline-model.js";
31
39
 
@@ -48,7 +56,8 @@ type Worker = import("@temporalio/worker").Worker;
48
56
  let env: TestWorkflowEnvironment | null = null;
49
57
  let worker: Worker | null = null;
50
58
  let workerRunPromise: Promise<void> | null = null;
51
- let envReady = false;
59
+ /** Why the Temporal test server could not boot; `null` once it has. */
60
+ let bootError: string | null = "not attempted";
52
61
 
53
62
  function createMockActivities() {
54
63
  return {
@@ -81,7 +90,12 @@ function createMockActivities() {
81
90
  ClearWorkflowApprovalStatus: async (): Promise<void> => {},
82
91
  UpdateWorkflowFileReviewStatus: async (): Promise<void> => {},
83
92
  GetAwaitingFileReviewChangeSetIds: async (): Promise<string[]> => [],
84
- };
93
+ GetAgentExecutionProgress: async (): Promise<null> => null,
94
+ ResetEventSequence: async (): Promise<number> => 0,
95
+ EmitWorkflowEvents: async (): Promise<void> => {},
96
+ LoadRecoveryContext: async (): Promise<unknown[]> => [],
97
+ PromoteTaskOutput: async (): Promise<void> => {},
98
+ } satisfies Record<keyof EngineActivities, unknown>;
85
99
  }
86
100
 
87
101
  async function runGoldenWorkflow(model: WorkflowModel, workflowInput: unknown = null): Promise<unknown> {
@@ -96,34 +110,36 @@ async function runGoldenWorkflow(model: WorkflowModel, workflowInput: unknown =
96
110
  taskQueue: TASK_QUEUE,
97
111
  workflowId: `golden-e2e-${Date.now()}-${Math.random().toString(36).slice(2)}`,
98
112
  args: [input],
99
- workflowExecutionTimeout: "30s",
113
+ // Workflow time, which the test server skips through: #16 alone waits 96s of
114
+ // timers. Real time stays bounded by vitest's per-test timeout.
115
+ workflowExecutionTimeout: "10m",
100
116
  });
101
117
  }
102
118
 
103
119
  describe("Golden E2E — Temporal TestWorkflowEnvironment", () => {
104
120
  beforeAll(async () => {
121
+ const { TestWorkflowEnvironment: TWE } = await import("@temporalio/testing");
122
+ const { Worker: W } = await import("@temporalio/worker");
123
+
105
124
  try {
106
- const { TestWorkflowEnvironment: TWE } = await import("@temporalio/testing");
107
- const { Worker: W } = await import("@temporalio/worker");
108
-
109
- env = await TWE.createLocal();
110
- worker = await W.create({
111
- connection: env.nativeConnection,
112
- taskQueue: TASK_QUEUE,
113
- workflowsPath: WORKFLOWS_PATH,
114
- activities: createMockActivities(),
115
- });
116
- workerRunPromise = worker.run();
117
-
118
- // Smoke test: execute simplest workflow to verify sandbox compatibility
119
- const smokeModel = loadWorkflowFromYaml(loadGolden("01-operation-basic.yaml"));
120
- await runGoldenWorkflow(smokeModel);
121
- envReady = true;
125
+ env = await TWE.createTimeSkipping();
122
126
  } catch (err: unknown) {
123
- const msg = err instanceof Error ? err.message : String(err);
124
- console.warn(`Temporal E2E smoke test failed (tests will be skipped): ${msg}`);
125
- envReady = false;
127
+ // Inside a gate the test server is a provided dependency: not booting is a failure.
128
+ if (IN_TEST_GATE) throw err;
129
+ bootError = err instanceof Error ? err.message : String(err);
130
+ console.warn(`Temporal test server cannot boot; every golden skips: ${bootError}`);
131
+ return;
126
132
  }
133
+ bootError = null;
134
+
135
+ // Past the boot, a failure is the suite's to report, not to skip.
136
+ worker = await W.create({
137
+ connection: env.nativeConnection,
138
+ taskQueue: TASK_QUEUE,
139
+ workflowsPath: WORKFLOWS_PATH,
140
+ activities: createMockActivities(),
141
+ });
142
+ workerRunPromise = worker.run();
127
143
  }, 60_000);
128
144
 
129
145
  afterAll(async () => {
@@ -135,117 +151,119 @@ describe("Golden E2E — Temporal TestWorkflowEnvironment", () => {
135
151
  }, 30_000);
136
152
 
137
153
  // ─────────────────────────────────────────────────────────────────
138
- // Each test skips gracefully if the Temporal test server
139
- // cannot start or the smoke test fails.
154
+ // Each golden skips by name when the test server could not boot.
140
155
  // ─────────────────────────────────────────────────────────────────
141
156
 
142
- it("#01 operation-basic — sequential set tasks", async () => {
143
- if (!envReady) return;
157
+ it("#01 operation-basic — sequential set tasks", async (testCtx) => {
158
+ if (bootError !== null) return testCtx.skip(`Temporal test server cannot boot: ${bootError}`);
144
159
  const model = loadWorkflowFromYaml(loadGolden("01-operation-basic.yaml"));
145
160
  const result = await runGoldenWorkflow(model);
146
161
  expect(result).toEqual({ workflow_completed: true });
147
162
  });
148
163
 
149
- it("#14 try-catch-raise — error handling pipeline", async () => {
150
- if (!envReady) return;
164
+ it("#14 try-catch-raise — error handling pipeline", async (testCtx) => {
165
+ if (bootError !== null) return testCtx.skip(`Temporal test server cannot boot: ${bootError}`);
151
166
  const model = loadWorkflowFromYaml(loadGolden("14-try-catch-raise.yaml"));
152
167
  const result = await runGoldenWorkflow(model);
153
168
  expect(result).toEqual({ phase: "completed" });
154
169
  });
155
170
 
156
- it("#15 fork-parallel — non-compete branches", async () => {
157
- if (!envReady) return;
171
+ it("#15 fork-parallel — non-compete branches", async (testCtx) => {
172
+ if (bootError !== null) return testCtx.skip(`Temporal test server cannot boot: ${bootError}`);
158
173
  const model = loadWorkflowFromYaml(loadGolden("15-fork-parallel.yaml"));
159
174
  const result = await runGoldenWorkflow(model);
160
175
  expect(result).toBeDefined();
161
176
  });
162
177
 
163
- it("#02 switch-conditional — HTTP + conditional branching", async () => {
164
- if (!envReady) return;
178
+ it("#02 switch-conditional — HTTP + conditional branching", async (testCtx) => {
179
+ if (bootError !== null) return testCtx.skip(`Temporal test server cannot boot: ${bootError}`);
165
180
  const model = loadWorkflowFromYaml(loadGolden("02-switch-conditional.yaml"));
166
181
  const result = await runGoldenWorkflow(model);
167
182
  expect(result).toBeDefined();
168
183
  });
169
184
 
170
- it("#03 foreach-loop — iteration with HTTP calls", async () => {
171
- if (!envReady) return;
185
+ it("#03 foreach-loop — iteration with HTTP calls", async (testCtx) => {
186
+ if (bootError !== null) return testCtx.skip(`Temporal test server cannot boot: ${bootError}`);
172
187
  const model = loadWorkflowFromYaml(loadGolden("03-foreach-loop.yaml"));
173
188
  const result = await runGoldenWorkflow(model, { items: ["a", "b", "c"] });
174
189
  expect(result).toBeDefined();
175
190
  });
176
191
 
177
- it("#04 parallel-concurrent — fork with HTTP branches", async () => {
178
- if (!envReady) return;
192
+ it("#04 parallel-concurrent — fork with HTTP branches", async (testCtx) => {
193
+ if (bootError !== null) return testCtx.skip(`Temporal test server cannot boot: ${bootError}`);
179
194
  const model = loadWorkflowFromYaml(loadGolden("04-parallel-concurrent.yaml"));
180
195
  const result = await runGoldenWorkflow(model);
181
196
  expect(result).toBeDefined();
182
197
  });
183
198
 
184
- it("#06 sleep-delay — wait + HTTP calls", async () => {
185
- if (!envReady) return;
199
+ it("#06 sleep-delay — wait + HTTP calls", async (testCtx) => {
200
+ if (bootError !== null) return testCtx.skip(`Temporal test server cannot boot: ${bootError}`);
186
201
  const model = loadWorkflowFromYaml(loadGolden("06-sleep-delay.yaml"));
187
202
  const result = await runGoldenWorkflow(model);
188
203
  expect(result).toBeDefined();
189
204
  });
190
205
 
191
- it("#07 inject-transform — expressions + HTTP", async () => {
192
- if (!envReady) return;
206
+ it("#07 inject-transform — expressions + HTTP", async (testCtx) => {
207
+ if (bootError !== null) return testCtx.skip(`Temporal test server cannot boot: ${bootError}`);
193
208
  const model = loadWorkflowFromYaml(loadGolden("07-inject-transform.yaml"));
194
209
  const result = await runGoldenWorkflow(model, { a: 10, b: 20 });
195
210
  expect(result).toBeDefined();
196
211
  });
197
212
 
198
- it("#08 error-retry — try/catch with HTTP", async () => {
199
- if (!envReady) return;
213
+ it("#08 error-retry — try/catch with HTTP", async (testCtx) => {
214
+ if (bootError !== null) return testCtx.skip(`Temporal test server cannot boot: ${bootError}`);
200
215
  const model = loadWorkflowFromYaml(loadGolden("08-error-retry.yaml"));
201
216
  const result = await runGoldenWorkflow(model);
202
217
  expect(result).toBeDefined();
203
218
  });
204
219
 
205
- it("#11 claimcheck-large-payload — sequential HTTP calls", async () => {
206
- if (!envReady) return;
220
+ it("#11 claimcheck-large-payload — sequential HTTP calls", async (testCtx) => {
221
+ if (bootError !== null) return testCtx.skip(`Temporal test server cannot boot: ${bootError}`);
207
222
  const model = loadWorkflowFromYaml(loadGolden("11-claimcheck-large-payload.yaml"));
208
223
  const result = await runGoldenWorkflow(model);
209
224
  expect(result).toBeDefined();
210
225
  });
211
226
 
212
- it("#12 claimcheck-between-steps — HTTP chain", async () => {
213
- if (!envReady) return;
227
+ it("#12 claimcheck-between-steps — HTTP chain", async (testCtx) => {
228
+ if (bootError !== null) return testCtx.skip(`Temporal test server cannot boot: ${bootError}`);
214
229
  const model = loadWorkflowFromYaml(loadGolden("12-claimcheck-between-steps.yaml"));
215
230
  const result = await runGoldenWorkflow(model);
216
231
  expect(result).toBeDefined();
217
232
  });
218
233
 
219
- it("#16 wait-delay — timer durations", async () => {
220
- if (!envReady) return;
234
+ it("#16 wait-delay — timer durations", async (testCtx) => {
235
+ if (bootError !== null) return testCtx.skip(`Temporal test server cannot boot: ${bootError}`);
221
236
  const model = loadWorkflowFromYaml(loadGolden("16-wait-delay.yaml"));
222
237
  const result = await runGoldenWorkflow(model);
223
238
  expect(result).toEqual({ completed: true });
224
239
  });
225
240
 
226
- it("#18 run-task — script + shell + workflow", async () => {
227
- if (!envReady) return;
241
+ // quarantined: stigmer#1322 — `run.workflow` starts its child by the workflow's
242
+ // name, which no worker registers; the kind is refused at save until that issue
243
+ // lands, and this golden is its end-to-end reproduction.
244
+ it.skip("#18 run-task — script + shell + workflow", async (testCtx) => {
245
+ if (bootError !== null) return testCtx.skip(`Temporal test server cannot boot: ${bootError}`);
228
246
  const model = loadWorkflowFromYaml(loadGolden("18-run-task.yaml"));
229
247
  const result = await runGoldenWorkflow(model);
230
248
  expect(result).toEqual({ all_runs_done: true });
231
249
  });
232
250
 
233
- it("#19 emit-event — CloudEvents envelope", async () => {
234
- if (!envReady) return;
251
+ it("#19 emit-event — CloudEvents envelope", async (testCtx) => {
252
+ if (bootError !== null) return testCtx.skip(`Temporal test server cannot boot: ${bootError}`);
235
253
  const model = loadWorkflowFromYaml(loadGolden("19-emit-event.yaml"));
236
254
  const result = await runGoldenWorkflow(model);
237
255
  expect(result).toEqual({ events_emitted: true });
238
256
  });
239
257
 
240
- it("#21 retry-backoff — catch-level retry", async () => {
241
- if (!envReady) return;
258
+ it("#21 retry-backoff — catch-level retry", async (testCtx) => {
259
+ if (bootError !== null) return testCtx.skip(`Temporal test server cannot boot: ${bootError}`);
242
260
  const model = loadWorkflowFromYaml(loadGolden("21-retry-backoff.yaml"));
243
261
  const result = await runGoldenWorkflow(model);
244
262
  expect(result).toEqual({ phase: "completed" });
245
263
  });
246
264
 
247
- it("#23 notification — webhook notification", async () => {
248
- if (!envReady) return;
265
+ it("#23 notification — webhook notification", async (testCtx) => {
266
+ if (bootError !== null) return testCtx.skip(`Temporal test server cannot boot: ${bootError}`);
249
267
  const model = loadWorkflowFromYaml(loadGolden("23-notification.yaml"));
250
268
  const result = await runGoldenWorkflow(model);
251
269
  expect(result).toEqual({ notifications_sent: true });