@relayflows/sdk 2.0.29 → 2.0.31

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 (393) hide show
  1. package/dist/agent-artifacts.d.ts.map +1 -1
  2. package/dist/agent-artifacts.js +2 -9
  3. package/dist/agent-artifacts.js.map +1 -1
  4. package/dist/agent-cwd.d.ts +69 -0
  5. package/dist/agent-cwd.d.ts.map +1 -0
  6. package/dist/agent-cwd.js +140 -0
  7. package/dist/agent-cwd.js.map +1 -0
  8. package/dist/artifact-scan-policy.d.ts +35 -0
  9. package/dist/artifact-scan-policy.d.ts.map +1 -0
  10. package/dist/artifact-scan-policy.js +49 -0
  11. package/dist/artifact-scan-policy.js.map +1 -0
  12. package/dist/authored-completion-record.d.ts +35 -0
  13. package/dist/authored-completion-record.d.ts.map +1 -0
  14. package/dist/authored-completion-record.js +92 -0
  15. package/dist/authored-completion-record.js.map +1 -0
  16. package/dist/authored-completion.d.ts +99 -0
  17. package/dist/authored-completion.d.ts.map +1 -0
  18. package/dist/authored-completion.js +184 -0
  19. package/dist/authored-completion.js.map +1 -0
  20. package/dist/authored-flow-error.d.ts +13 -1
  21. package/dist/authored-flow-error.d.ts.map +1 -1
  22. package/dist/authored-flow-error.js +12 -0
  23. package/dist/authored-flow-error.js.map +1 -1
  24. package/dist/authored-flow-executor.d.ts +7 -30
  25. package/dist/authored-flow-executor.d.ts.map +1 -1
  26. package/dist/authored-flow-executor.js +64 -48
  27. package/dist/authored-flow-executor.js.map +1 -1
  28. package/dist/authored-human.d.ts.map +1 -1
  29. package/dist/authored-human.js +1 -3
  30. package/dist/authored-human.js.map +1 -1
  31. package/dist/authored-node-entry.js +4 -1
  32. package/dist/authored-node-entry.js.map +1 -1
  33. package/dist/authored-node-runner.d.ts +9 -1
  34. package/dist/authored-node-runner.d.ts.map +1 -1
  35. package/dist/authored-node-runner.js +92 -17
  36. package/dist/authored-node-runner.js.map +1 -1
  37. package/dist/authored-root.d.ts +5 -0
  38. package/dist/authored-root.d.ts.map +1 -1
  39. package/dist/authored-root.js +20 -2
  40. package/dist/authored-root.js.map +1 -1
  41. package/dist/authored-step-output.d.ts +35 -10
  42. package/dist/authored-step-output.d.ts.map +1 -1
  43. package/dist/authored-step-output.js +108 -40
  44. package/dist/authored-step-output.js.map +1 -1
  45. package/dist/authored-verdict.d.ts +28 -0
  46. package/dist/authored-verdict.d.ts.map +1 -0
  47. package/dist/authored-verdict.js +79 -0
  48. package/dist/authored-verdict.js.map +1 -0
  49. package/dist/authored-worker-step.d.ts +5 -2
  50. package/dist/authored-worker-step.d.ts.map +1 -1
  51. package/dist/authored-worker-step.js +48 -11
  52. package/dist/authored-worker-step.js.map +1 -1
  53. package/dist/bundle-extensions.d.ts.map +1 -1
  54. package/dist/bundle-extensions.js +4 -7
  55. package/dist/bundle-extensions.js.map +1 -1
  56. package/dist/bundle.d.ts.map +1 -1
  57. package/dist/bundle.js +41 -7
  58. package/dist/bundle.js.map +1 -1
  59. package/dist/canonical.d.ts.map +1 -1
  60. package/dist/canonical.js +18 -6
  61. package/dist/canonical.js.map +1 -1
  62. package/dist/cli/check-worker-surface.d.ts +27 -0
  63. package/dist/cli/check-worker-surface.d.ts.map +1 -0
  64. package/dist/cli/check-worker-surface.js +63 -0
  65. package/dist/cli/check-worker-surface.js.map +1 -0
  66. package/dist/cli/check.d.ts +19 -2
  67. package/dist/cli/check.d.ts.map +1 -1
  68. package/dist/cli/check.js +12 -4
  69. package/dist/cli/check.js.map +1 -1
  70. package/dist/cli/cloud-format.d.ts +9 -0
  71. package/dist/cli/cloud-format.d.ts.map +1 -0
  72. package/dist/cli/cloud-format.js +77 -0
  73. package/dist/cli/cloud-format.js.map +1 -0
  74. package/dist/cli/cloud-live.d.ts +39 -0
  75. package/dist/cli/cloud-live.d.ts.map +1 -0
  76. package/dist/cli/cloud-live.js +325 -0
  77. package/dist/cli/cloud-live.js.map +1 -0
  78. package/dist/cli/cloud-read.d.ts +3 -7
  79. package/dist/cli/cloud-read.d.ts.map +1 -1
  80. package/dist/cli/cloud-read.js +14 -266
  81. package/dist/cli/cloud-read.js.map +1 -1
  82. package/dist/cli/cloud-refusal.d.ts +39 -0
  83. package/dist/cli/cloud-refusal.d.ts.map +1 -0
  84. package/dist/cli/cloud-refusal.js +95 -0
  85. package/dist/cli/cloud-refusal.js.map +1 -0
  86. package/dist/cli/cloud-status-view.d.ts +7 -0
  87. package/dist/cli/cloud-status-view.d.ts.map +1 -0
  88. package/dist/cli/cloud-status-view.js +214 -0
  89. package/dist/cli/cloud-status-view.js.map +1 -0
  90. package/dist/cli/direct-run.d.ts.map +1 -1
  91. package/dist/cli/direct-run.js +16 -2
  92. package/dist/cli/direct-run.js.map +1 -1
  93. package/dist/cli/hn-monitor.d.ts +0 -13
  94. package/dist/cli/hn-monitor.d.ts.map +1 -1
  95. package/dist/cli/hn-monitor.js +2 -1
  96. package/dist/cli/hn-monitor.js.map +1 -1
  97. package/dist/cli/local-agent-remedy.d.ts +80 -0
  98. package/dist/cli/local-agent-remedy.d.ts.map +1 -0
  99. package/dist/cli/local-agent-remedy.js +116 -0
  100. package/dist/cli/local-agent-remedy.js.map +1 -0
  101. package/dist/cli/observer-session.d.ts +41 -0
  102. package/dist/cli/observer-session.d.ts.map +1 -0
  103. package/dist/cli/observer-session.js +78 -0
  104. package/dist/cli/observer-session.js.map +1 -0
  105. package/dist/cli/run.d.ts +30 -2
  106. package/dist/cli/run.d.ts.map +1 -1
  107. package/dist/cli/run.js +186 -24
  108. package/dist/cli/run.js.map +1 -1
  109. package/dist/cli/status.d.ts +9 -0
  110. package/dist/cli/status.d.ts.map +1 -1
  111. package/dist/cli/status.js +31 -2
  112. package/dist/cli/status.js.map +1 -1
  113. package/dist/cli/step-evidence.d.ts +90 -0
  114. package/dist/cli/step-evidence.d.ts.map +1 -0
  115. package/dist/cli/step-evidence.js +259 -0
  116. package/dist/cli/step-evidence.js.map +1 -0
  117. package/dist/cli/step-failure.d.ts +14 -4
  118. package/dist/cli/step-failure.d.ts.map +1 -1
  119. package/dist/cli/step-failure.js +41 -76
  120. package/dist/cli/step-failure.js.map +1 -1
  121. package/dist/cli-commands.d.ts +6 -0
  122. package/dist/cli-commands.d.ts.map +1 -1
  123. package/dist/cli-commands.js +2 -0
  124. package/dist/cli-commands.js.map +1 -1
  125. package/dist/cli.d.ts +10 -0
  126. package/dist/cli.d.ts.map +1 -1
  127. package/dist/cli.js +53 -42
  128. package/dist/cli.js.map +1 -1
  129. package/dist/cloud-read.d.ts +15 -0
  130. package/dist/cloud-read.d.ts.map +1 -1
  131. package/dist/cloud-read.js +20 -1
  132. package/dist/cloud-read.js.map +1 -1
  133. package/dist/cloud-run-record.d.ts +27 -0
  134. package/dist/cloud-run-record.d.ts.map +1 -0
  135. package/dist/cloud-run-record.js +56 -0
  136. package/dist/cloud-run-record.js.map +1 -0
  137. package/dist/cloud-run.d.ts +2 -9
  138. package/dist/cloud-run.d.ts.map +1 -1
  139. package/dist/cloud-run.js +3 -20
  140. package/dist/cloud-run.js.map +1 -1
  141. package/dist/communication/local.d.ts.map +1 -1
  142. package/dist/communication/local.js +2 -1
  143. package/dist/communication/local.js.map +1 -1
  144. package/dist/communication/worker.d.ts +1 -1
  145. package/dist/communication/worker.d.ts.map +1 -1
  146. package/dist/communication/worker.js +13 -5
  147. package/dist/communication/worker.js.map +1 -1
  148. package/dist/compile.d.ts.map +1 -1
  149. package/dist/compile.js +28 -6
  150. package/dist/compile.js.map +1 -1
  151. package/dist/direct-input.d.ts.map +1 -1
  152. package/dist/direct-input.js +21 -1
  153. package/dist/direct-input.js.map +1 -1
  154. package/dist/failure-kinds.d.ts +96 -6
  155. package/dist/failure-kinds.d.ts.map +1 -1
  156. package/dist/failure-kinds.js +29 -2
  157. package/dist/failure-kinds.js.map +1 -1
  158. package/dist/flow-extension-compat.d.ts.map +1 -1
  159. package/dist/flow-extension-compat.js +26 -8
  160. package/dist/flow-extension-compat.js.map +1 -1
  161. package/dist/flow-extension-loader.d.ts +7 -0
  162. package/dist/flow-extension-loader.d.ts.map +1 -1
  163. package/dist/flow-extension-loader.js +48 -22
  164. package/dist/flow-extension-loader.js.map +1 -1
  165. package/dist/flow-requirements.d.ts.map +1 -1
  166. package/dist/flow-requirements.js +24 -9
  167. package/dist/flow-requirements.js.map +1 -1
  168. package/dist/fs-descriptor.d.ts +17 -0
  169. package/dist/fs-descriptor.d.ts.map +1 -0
  170. package/dist/fs-descriptor.js +96 -0
  171. package/dist/fs-descriptor.js.map +1 -0
  172. package/dist/gate-contract.d.ts +7 -0
  173. package/dist/gate-contract.d.ts.map +1 -1
  174. package/dist/gate-contract.js +6 -1
  175. package/dist/gate-contract.js.map +1 -1
  176. package/dist/helper-preflight.d.ts.map +1 -1
  177. package/dist/helper-preflight.js +10 -3
  178. package/dist/helper-preflight.js.map +1 -1
  179. package/dist/helper-reference.d.ts +25 -0
  180. package/dist/helper-reference.d.ts.map +1 -0
  181. package/dist/helper-reference.js +129 -0
  182. package/dist/helper-reference.js.map +1 -0
  183. package/dist/hosted-base-snapshot.d.ts +25 -0
  184. package/dist/hosted-base-snapshot.d.ts.map +1 -0
  185. package/dist/hosted-base-snapshot.js +278 -0
  186. package/dist/hosted-base-snapshot.js.map +1 -0
  187. package/dist/hosted-extension-declarations.d.ts +10 -0
  188. package/dist/hosted-extension-declarations.d.ts.map +1 -0
  189. package/dist/hosted-extension-declarations.js +272 -0
  190. package/dist/hosted-extension-declarations.js.map +1 -0
  191. package/dist/hosted-extension-isolation.d.ts +82 -0
  192. package/dist/hosted-extension-isolation.d.ts.map +1 -0
  193. package/dist/hosted-extension-isolation.js +322 -0
  194. package/dist/hosted-extension-isolation.js.map +1 -0
  195. package/dist/hosted-extension-manifest.d.ts +9 -0
  196. package/dist/hosted-extension-manifest.d.ts.map +1 -0
  197. package/dist/hosted-extension-manifest.js +235 -0
  198. package/dist/hosted-extension-manifest.js.map +1 -0
  199. package/dist/hosted-extension-protocol.d.ts +16 -0
  200. package/dist/hosted-extension-protocol.d.ts.map +1 -0
  201. package/dist/hosted-extension-protocol.js +224 -0
  202. package/dist/hosted-extension-protocol.js.map +1 -0
  203. package/dist/hosted-extension-runtime.d.ts +30 -0
  204. package/dist/hosted-extension-runtime.d.ts.map +1 -0
  205. package/dist/hosted-extension-runtime.js +167 -0
  206. package/dist/hosted-extension-runtime.js.map +1 -0
  207. package/dist/hosted-extension-sandbox-source.d.ts +9 -0
  208. package/dist/hosted-extension-sandbox-source.d.ts.map +1 -0
  209. package/dist/hosted-extension-sandbox-source.js +95 -0
  210. package/dist/hosted-extension-sandbox-source.js.map +1 -0
  211. package/dist/hosted-extension-sandbox.d.ts +39 -0
  212. package/dist/hosted-extension-sandbox.d.ts.map +1 -0
  213. package/dist/hosted-extension-sandbox.js +418 -0
  214. package/dist/hosted-extension-sandbox.js.map +1 -0
  215. package/dist/hosted-project.d.ts +3 -0
  216. package/dist/hosted-project.d.ts.map +1 -0
  217. package/dist/hosted-project.js +19 -0
  218. package/dist/hosted-project.js.map +1 -0
  219. package/dist/hosted-promise-safety.d.ts +12 -0
  220. package/dist/hosted-promise-safety.d.ts.map +1 -0
  221. package/dist/hosted-promise-safety.js +63 -0
  222. package/dist/hosted-promise-safety.js.map +1 -0
  223. package/dist/index.d.ts +3 -1
  224. package/dist/index.d.ts.map +1 -1
  225. package/dist/index.js +2 -0
  226. package/dist/index.js.map +1 -1
  227. package/dist/intrinsic-array.d.ts +3 -0
  228. package/dist/intrinsic-array.d.ts.map +1 -0
  229. package/dist/intrinsic-array.js +14 -0
  230. package/dist/intrinsic-array.js.map +1 -0
  231. package/dist/journal-client.d.ts +3 -1
  232. package/dist/journal-client.d.ts.map +1 -1
  233. package/dist/journal-client.js +17 -2
  234. package/dist/journal-client.js.map +1 -1
  235. package/dist/journal-projection.d.ts +16 -0
  236. package/dist/journal-projection.d.ts.map +1 -0
  237. package/dist/journal-projection.js +108 -0
  238. package/dist/journal-projection.js.map +1 -0
  239. package/dist/json-value.d.ts +6 -1
  240. package/dist/json-value.d.ts.map +1 -1
  241. package/dist/json-value.js +155 -36
  242. package/dist/json-value.js.map +1 -1
  243. package/dist/llm-worker.d.ts +9 -0
  244. package/dist/llm-worker.d.ts.map +1 -1
  245. package/dist/llm-worker.js +16 -2
  246. package/dist/llm-worker.js.map +1 -1
  247. package/dist/local-agent.d.ts +1 -1
  248. package/dist/local-agent.d.ts.map +1 -1
  249. package/dist/local-agent.js +4 -3
  250. package/dist/local-agent.js.map +1 -1
  251. package/dist/named-gate-lowering.js +35 -5
  252. package/dist/named-gate-lowering.js.map +1 -1
  253. package/dist/named-gate-preflight.d.ts +27 -0
  254. package/dist/named-gate-preflight.d.ts.map +1 -0
  255. package/dist/named-gate-preflight.js +47 -0
  256. package/dist/named-gate-preflight.js.map +1 -0
  257. package/dist/named-gates.d.ts +1 -1
  258. package/dist/named-gates.d.ts.map +1 -1
  259. package/dist/named-gates.js +3 -0
  260. package/dist/named-gates.js.map +1 -1
  261. package/dist/observer-link.d.ts +7 -0
  262. package/dist/observer-link.d.ts.map +1 -1
  263. package/dist/observer-link.js +3 -1
  264. package/dist/observer-link.js.map +1 -1
  265. package/dist/plugin-store.d.ts +8 -2
  266. package/dist/plugin-store.d.ts.map +1 -1
  267. package/dist/plugin-store.js +233 -56
  268. package/dist/plugin-store.js.map +1 -1
  269. package/dist/preflight.d.ts.map +1 -1
  270. package/dist/preflight.js +7 -0
  271. package/dist/preflight.js.map +1 -1
  272. package/dist/protocol.d.ts +2 -0
  273. package/dist/protocol.d.ts.map +1 -1
  274. package/dist/redact.d.ts +42 -0
  275. package/dist/redact.d.ts.map +1 -1
  276. package/dist/redact.js +128 -0
  277. package/dist/redact.js.map +1 -1
  278. package/dist/run-projection.d.ts +83 -0
  279. package/dist/run-projection.d.ts.map +1 -0
  280. package/dist/run-projection.js +199 -0
  281. package/dist/run-projection.js.map +1 -0
  282. package/dist/semver-range.d.ts.map +1 -1
  283. package/dist/semver-range.js +27 -15
  284. package/dist/semver-range.js.map +1 -1
  285. package/dist/shell-word.d.ts +19 -0
  286. package/dist/shell-word.d.ts.map +1 -0
  287. package/dist/shell-word.js +23 -0
  288. package/dist/shell-word.js.map +1 -0
  289. package/dist/spec.d.ts +52 -3
  290. package/dist/spec.d.ts.map +1 -1
  291. package/dist/spec.js.map +1 -1
  292. package/dist/step-fields.d.ts +1 -1
  293. package/dist/step-fields.js +1 -1
  294. package/dist/step-fields.js.map +1 -1
  295. package/dist/steps-green.d.ts +27 -0
  296. package/dist/steps-green.d.ts.map +1 -0
  297. package/dist/steps-green.js +164 -0
  298. package/dist/steps-green.js.map +1 -0
  299. package/dist/validate.d.ts.map +1 -1
  300. package/dist/validate.js +39 -8
  301. package/dist/validate.js.map +1 -1
  302. package/dist/worker-lease.d.ts +8 -1
  303. package/dist/worker-lease.d.ts.map +1 -1
  304. package/dist/worker-lease.js +34 -4
  305. package/dist/worker-lease.js.map +1 -1
  306. package/dist/worker.d.ts +8 -0
  307. package/dist/worker.d.ts.map +1 -1
  308. package/dist/worker.js +17 -9
  309. package/dist/worker.js.map +1 -1
  310. package/package.json +3 -7
  311. package/src/agent-artifacts.ts +2 -10
  312. package/src/agent-cwd.ts +139 -0
  313. package/src/artifact-scan-policy.ts +51 -0
  314. package/src/authored-completion-record.ts +119 -0
  315. package/src/authored-completion.ts +203 -0
  316. package/src/authored-flow-error.ts +13 -1
  317. package/src/authored-flow-executor.ts +101 -59
  318. package/src/authored-human.ts +1 -4
  319. package/src/authored-node-entry.ts +4 -1
  320. package/src/authored-node-runner.ts +96 -22
  321. package/src/authored-root.ts +20 -2
  322. package/src/authored-step-output.ts +139 -42
  323. package/src/authored-verdict.ts +87 -0
  324. package/src/authored-worker-step.ts +60 -12
  325. package/src/bundle-extensions.ts +6 -5
  326. package/src/bundle.ts +52 -7
  327. package/src/canonical.ts +20 -6
  328. package/src/cli/check-worker-surface.ts +66 -0
  329. package/src/cli/check.ts +35 -4
  330. package/src/cli/cloud-format.ts +82 -0
  331. package/src/cli/cloud-live.ts +366 -0
  332. package/src/cli/cloud-read.ts +13 -282
  333. package/src/cli/cloud-refusal.ts +113 -0
  334. package/src/cli/cloud-status-view.ts +213 -0
  335. package/src/cli/direct-run.ts +19 -2
  336. package/src/cli/hn-monitor.ts +2 -1
  337. package/src/cli/local-agent-remedy.ts +160 -0
  338. package/src/cli/observer-session.ts +107 -0
  339. package/src/cli/run.ts +233 -28
  340. package/src/cli/status.ts +59 -3
  341. package/src/cli/step-evidence.ts +310 -0
  342. package/src/cli/step-failure.ts +57 -81
  343. package/src/cli-commands.ts +2 -0
  344. package/src/cli.ts +64 -44
  345. package/src/cloud-read.ts +25 -1
  346. package/src/cloud-run-record.ts +64 -0
  347. package/src/cloud-run.ts +5 -24
  348. package/src/communication/local.ts +2 -1
  349. package/src/communication/worker.ts +13 -5
  350. package/src/compile.ts +28 -6
  351. package/src/direct-input.ts +22 -1
  352. package/src/failure-kinds.ts +104 -2
  353. package/src/flow-extension-compat.ts +32 -7
  354. package/src/flow-extension-loader.ts +56 -21
  355. package/src/flow-requirements.ts +24 -9
  356. package/src/fs-descriptor.ts +127 -0
  357. package/src/gate-contract.ts +13 -1
  358. package/src/helper-preflight.ts +10 -3
  359. package/src/helper-reference.ts +130 -0
  360. package/src/hosted-base-snapshot.ts +351 -0
  361. package/src/hosted-extension-declarations.ts +387 -0
  362. package/src/hosted-extension-isolation.ts +457 -0
  363. package/src/hosted-extension-manifest.ts +249 -0
  364. package/src/hosted-extension-protocol.ts +262 -0
  365. package/src/hosted-extension-runtime.ts +266 -0
  366. package/src/hosted-extension-sandbox-source.ts +94 -0
  367. package/src/hosted-extension-sandbox.ts +489 -0
  368. package/src/hosted-project.ts +18 -0
  369. package/src/hosted-promise-safety.ts +68 -0
  370. package/src/index.ts +20 -0
  371. package/src/intrinsic-array.ts +14 -0
  372. package/src/journal-client.ts +19 -2
  373. package/src/journal-projection.ts +106 -0
  374. package/src/json-value.ts +184 -32
  375. package/src/llm-worker.ts +16 -2
  376. package/src/local-agent.ts +4 -2
  377. package/src/named-gate-lowering.ts +35 -5
  378. package/src/named-gate-preflight.ts +47 -0
  379. package/src/named-gates.ts +3 -0
  380. package/src/observer-link.ts +10 -1
  381. package/src/plugin-store.ts +323 -56
  382. package/src/preflight.ts +7 -0
  383. package/src/protocol.ts +2 -0
  384. package/src/redact.ts +111 -0
  385. package/src/run-projection.ts +247 -0
  386. package/src/semver-range.ts +39 -14
  387. package/src/shell-word.ts +24 -0
  388. package/src/spec.ts +54 -3
  389. package/src/step-fields.ts +1 -1
  390. package/src/steps-green.ts +168 -0
  391. package/src/validate.ts +35 -8
  392. package/src/worker-lease.ts +35 -5
  393. package/src/worker.ts +27 -11
@@ -0,0 +1,41 @@
1
+ /**
2
+ * The observer half of `flows run` / `flows resume`: once the run id is known,
3
+ * project the run into its `wf-<runId>` channel and mint a read-only link
4
+ * scoped to that channel, so the link opens on this run's step graph instead
5
+ * of an arbitrary workspace channel. The link is printed on stderr the moment
6
+ * it exists, so a human can follow the run live, and again after `RUN`.
7
+ *
8
+ * Best-effort throughout: no workspace key means no session, and a projection
9
+ * or mint failure is a labeled stderr line. The run never depends on it.
10
+ */
11
+ import type { CliIo } from '../cli.js';
12
+ import type { JournalEvent } from '../journal-reader.js';
13
+ import { type MintObserverOptions } from '../observer-link.js';
14
+ import type { ProgressEvent } from '../progress.js';
15
+ import { type ProjectionFetch } from '../run-projection.js';
16
+ import type { RunReport } from './run.js';
17
+ type MintOutcome = {
18
+ observerUrl?: string;
19
+ warning?: string;
20
+ };
21
+ export interface ObserverSession {
22
+ /** YAML runs: every entry `run.start {watch}` / `run.watch` pushes. */
23
+ onJournalEntry(entry: JournalEvent): void;
24
+ /** Authored runs: the root's id and name, known once it is admitted. */
25
+ onRunStarted(run: {
26
+ runId: string;
27
+ flow: string;
28
+ resumed?: boolean;
29
+ }): void;
30
+ /** Authored runs: step transitions from the body's executor. */
31
+ onProgress(event: ProgressEvent): void;
32
+ /** Close the projection from the final report and settle the link. */
33
+ finish(report: RunReport): Promise<MintOutcome> | undefined;
34
+ }
35
+ export interface ObserverSessionDeps {
36
+ fetch?: ProjectionFetch;
37
+ mint?: (options: MintObserverOptions) => Promise<MintOutcome>;
38
+ }
39
+ export declare function createObserverSession(command: 'run' | 'resume', io: CliIo, env?: NodeJS.ProcessEnv, deps?: ObserverSessionDeps): ObserverSession | undefined;
40
+ export {};
41
+ //# sourceMappingURL=observer-session.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"observer-session.d.ts","sourceRoot":"","sources":["../../src/cli/observer-session.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,WAAW,CAAC;AAEvC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,EAA2C,KAAK,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AACxG,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,EACmD,KAAK,eAAe,EAC7E,MAAM,sBAAsB,CAAC;AAC9B,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAE1C,KAAK,WAAW,GAAG;IAAE,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAK9D,MAAM,WAAW,eAAe;IAC9B,uEAAuE;IACvE,cAAc,CAAC,KAAK,EAAE,YAAY,GAAG,IAAI,CAAC;IAC1C,wEAAwE;IACxE,YAAY,CAAC,GAAG,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,IAAI,CAAC;IAC5E,gEAAgE;IAChE,UAAU,CAAC,KAAK,EAAE,aAAa,GAAG,IAAI,CAAC;IACvC,sEAAsE;IACtE,MAAM,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC,GAAG,SAAS,CAAC;CAC7D;AAED,MAAM,WAAW,mBAAmB;IAClC,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,mBAAmB,KAAK,OAAO,CAAC,WAAW,CAAC,CAAC;CAC/D;AAED,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,KAAK,GAAG,QAAQ,EACzB,EAAE,EAAE,KAAK,EACT,GAAG,GAAE,MAAM,CAAC,UAAwB,EACpC,IAAI,GAAE,mBAAwB,GAC7B,eAAe,GAAG,SAAS,CA2D7B"}
@@ -0,0 +1,78 @@
1
+ /**
2
+ * The observer half of `flows run` / `flows resume`: once the run id is known,
3
+ * project the run into its `wf-<runId>` channel and mint a read-only link
4
+ * scoped to that channel, so the link opens on this run's step graph instead
5
+ * of an arbitrary workspace channel. The link is printed on stderr the moment
6
+ * it exists, so a human can follow the run live, and again after `RUN`.
7
+ *
8
+ * Best-effort throughout: no workspace key means no session, and a projection
9
+ * or mint failure is a labeled stderr line. The run never depends on it.
10
+ */
11
+ import { createJournalProjector } from '../journal-projection.js';
12
+ import { mintObserverUrl, resolveObserverLinkEnv } from '../observer-link.js';
13
+ import { createRunProjection, runChannelName, } from '../run-projection.js';
14
+ /** Bounded so an unreachable Relaycast cannot hold the CLI open. */
15
+ const DRAIN_GRACE_MS = 5_000;
16
+ export function createObserverSession(command, io, env = process.env, deps = {}) {
17
+ const link = resolveObserverLinkEnv(env);
18
+ if (link.suppressed || link.workspaceKey === undefined)
19
+ return undefined;
20
+ const workspaceKey = link.workspaceKey;
21
+ const mint = deps.mint ?? mintObserverUrl;
22
+ const liveSinceMs = command === 'resume' ? Date.now() : 0;
23
+ let projection;
24
+ let minted;
25
+ let rootRunId;
26
+ const mintFor = (runId) => minted ??= mint({
27
+ workspaceKey,
28
+ channel: runChannelName(runId),
29
+ ...(link.baseUrl === undefined ? {} : { baseUrl: link.baseUrl }),
30
+ ...(link.dashboardUrl === undefined ? {} : { dashboardUrl: link.dashboardUrl }),
31
+ }).catch((error) => ({ warning: error instanceof Error ? error.message : 'unknown mint error' }));
32
+ const open = (run) => {
33
+ if (projection !== undefined)
34
+ return projection;
35
+ rootRunId = run.runId;
36
+ projection = createRunProjection({
37
+ workspaceKey,
38
+ ...(link.baseUrl === undefined ? {} : { baseUrl: link.baseUrl }),
39
+ ...(deps.fetch === undefined ? {} : { fetch: deps.fetch }),
40
+ diagnostic: message => io.stderr(`[observer] ${message}`),
41
+ }, run);
42
+ void mintFor(run.runId).then(outcome => {
43
+ if (outcome.observerUrl !== undefined)
44
+ io.stderr(`Observer: ${outcome.observerUrl}`);
45
+ });
46
+ return projection;
47
+ };
48
+ const project = createJournalProjector(run => open({ ...run, ...(liveSinceMs > 0 ? { resumed: true } : {}) }), liveSinceMs);
49
+ return {
50
+ onJournalEntry(entry) {
51
+ try {
52
+ project(entry);
53
+ }
54
+ catch (error) {
55
+ io.stderr(`[observer] could not project journal entry ${entry.seq}: ${error instanceof Error ? error.message : String(error)}`);
56
+ }
57
+ },
58
+ onRunStarted: run => { open(run); },
59
+ onProgress(event) { projection?.step(event); },
60
+ finish(report) {
61
+ const runId = rootRunId ?? report.runId;
62
+ if (runId === undefined)
63
+ return undefined;
64
+ if (projection === undefined) {
65
+ io.stderr('[observer] this run was not projected (the daemon did not stream its journal); '
66
+ + 'the observer link opens an empty channel');
67
+ }
68
+ projection?.finish({
69
+ status: report.status === 'parked' ? 'parked' : report.completionReason === 'canceled' ? 'canceled'
70
+ : report.ok ? 'completed' : 'failed',
71
+ ...(report.completionReason === undefined ? {} : { completionReason: report.completionReason }),
72
+ });
73
+ const drained = projection?.close(DRAIN_GRACE_MS) ?? Promise.resolve();
74
+ return drained.then(() => mintFor(runId));
75
+ },
76
+ };
77
+ }
78
+ //# sourceMappingURL=observer-session.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"observer-session.js","sourceRoot":"","sources":["../../src/cli/observer-session.ts"],"names":[],"mappings":"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"}
package/dist/cli/run.d.ts CHANGED
@@ -1,11 +1,12 @@
1
1
  import { AuthoredFlowExecutionError, AuthoredHumanParked, type AuthoredHumanWait } from '../authored-flow-error.js';
2
2
  import type { ProgressEvent } from '../progress.js';
3
+ import type { JournalEvent } from '../journal-reader.js';
3
4
  import { type EnsureDaemonOptions } from '../daemon-lifecycle.js';
4
- import type { RunFailureKind, RunWarningKind, StepFailedDetails } from '../failure-kinds.js';
5
+ import type { ParkCause, RunFailureKind, RunWarningKind, StepFailedDetails } from '../failure-kinds.js';
5
6
  import { JournalClient } from '../journal-client.js';
6
7
  import type { RunCompletionReason, RunOutcome, RunStatus } from '../protocol.js';
7
8
  import type { StepType } from '../spec.js';
8
- import type { LoweredCompletionReason } from '../authored-flow-executor.js';
9
+ import { type LoweredCompletionReason } from '../authored-completion.js';
9
10
  import { type CheckReport } from './check.js';
10
11
  export type RunExitCode = 0 | 1 | 2 | 3;
11
12
  export type RunCommand = 'run' | 'resume' | 'answer';
@@ -28,6 +29,13 @@ export interface RunReport {
28
29
  socketPath?: string;
29
30
  status?: RunStatus;
30
31
  completionReason?: RunCompletionReason;
32
+ /**
33
+ * What the body passed to `done(reason, { detail })`, normalized: redacted,
34
+ * trimmed, and bounded to 2,000 code points. Absent for every one-argument
35
+ * call, so an existing report keeps its exact shape — and absent on the
36
+ * paths where no authored body declared the outcome at all.
37
+ */
38
+ completionDetail?: string;
31
39
  completedSteps?: number;
32
40
  reuse?: {
33
41
  fromRunId: string;
@@ -35,6 +43,17 @@ export interface RunReport {
35
43
  executedSteps: number;
36
44
  };
37
45
  parkedStep?: ParkedStep;
46
+ /**
47
+ * Why an exit-3 park happened, when classification established it.
48
+ *
49
+ * Carried structurally so a consumer — including this package's own authored
50
+ * boundaries — can tell "nothing is attached to run this step" from "the
51
+ * kernel is waiting for a human to recover it" without matching on the
52
+ * rendered message. Absent means the cause was not established, never
53
+ * `worker_unavailable` by default: recommending a worker for a `needs_human`
54
+ * park is the wrong answer, and guessing it is worse than saying nothing.
55
+ */
56
+ parkCause?: ParkCause;
38
57
  /** The open `f.human` question a parked authored run is waiting on. */
39
58
  humanWait?: AuthoredHumanWait;
40
59
  /** `flows answer` only: the answer it recorded. */
@@ -67,6 +86,14 @@ export interface RunLifecycleOptions {
67
86
  onPtyReady?: (path: string) => void;
68
87
  reuseFromRunId?: string;
69
88
  onProgress?: (event: ProgressEvent) => void;
89
+ /** Stream the run's journal entries while it runs (YAML runs, via `run.start {watch}` / `run.watch`). */
90
+ onJournalEntry?: (entry: JournalEvent) => void;
91
+ /** An authored root was admitted: its id is known before its body runs. */
92
+ onRunStarted?: (run: {
93
+ runId: string;
94
+ flow: string;
95
+ resumed?: boolean;
96
+ }) => void;
70
97
  localAgent?: boolean;
71
98
  /** `--agent-capacity`: the local workers' concurrency; the default is `DEFAULT_LOCAL_AGENT_CAPACITY`. */
72
99
  agentCapacity?: number;
@@ -129,6 +156,7 @@ export declare function authoredHumanParked(command: RunCommand, base: CheckRepo
129
156
  export declare function authoredCompletion(command: RunCommand, base: RunReport, socketPath: string, result: {
130
157
  name: string;
131
158
  completionReason: LoweredCompletionReason;
159
+ completionDetail?: string;
132
160
  journalSteps: readonly unknown[];
133
161
  }, runId: string | undefined): RunExecution;
134
162
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../src/cli/run.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../src/cli/run.ts"],"names":[],"mappings":"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"}
package/dist/cli/run.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { onWorkerFailure } from '../worker-lease.js';
1
2
  import { communicationInstruction } from '../communication/spec.js';
2
3
  import { checkCommunicationEnvironment, CommunicationEnvironmentError } from '../communication/preflight.js';
3
4
  import { parseHumanRecipient } from '../human-to.js';
@@ -12,11 +13,13 @@ import { socketPathFor } from '../daemon-connection.js';
12
13
  import { ensureDaemon } from '../daemon-lifecycle.js';
13
14
  import { isAuthoredFlowPath } from '../direct-input.js';
14
15
  import { daemonRefusal } from './daemon-refusal.js';
16
+ import { authoredInput, authoredWorkerRemedy, localAgentRemedy, } from './local-agent-remedy.js';
15
17
  import { inspectionHint, renderInspection, renderStepEvidence, stepFailureDetails } from './step-failure.js';
16
18
  import { JournalClient, JournalProtocolError } from '../journal-client.js';
17
19
  import { attachLocalAgent } from '../local-agent.js';
18
20
  import { LlmWorker } from '../llm-worker.js';
19
21
  import { readAuthoredRootMetadata, resumeDurableAuthoredFlow } from '../authored-root.js';
22
+ import { singleLineCompletionDetail, } from '../authored-completion.js';
20
23
  import { DEFAULT_LOCAL_AGENT_CAPACITY } from '../worker-slots.js';
21
24
  import { checkFlow, } from './check.js';
22
25
  export async function runFlow(path, dataDir, options = {}) {
@@ -60,7 +63,9 @@ async function executeCheckedFlow(checked, dataDir, options) {
60
63
  const { attachCommunicationWorkers } = await import('../communication/local.js');
61
64
  communicationWorkers = await attachCommunicationWorkers(spec, socketPath, dataDir);
62
65
  }
63
- const outcome = await client.runStart(spec, options.reuseFromRunId);
66
+ if (options.onJournalEntry !== undefined)
67
+ client.on('entry', options.onJournalEntry);
68
+ const outcome = await startWatched(client, spec, options);
64
69
  const execution = await classifyOutcome(client, 'run', outcome, base, socketPath, { ...options, dataDir });
65
70
  if (options.reuseFromRunId !== undefined) {
66
71
  execution.report.reuse = await reuseSummary(client, outcome.run_id, options.reuseFromRunId);
@@ -81,6 +86,8 @@ async function executeCheckedFlow(checked, dataDir, options) {
81
86
  return protocolFailure('run', base, socketPath, communicationWorkers?.failure ?? localAgent?.failure ?? error);
82
87
  }
83
88
  finally {
89
+ if (options.onJournalEntry !== undefined)
90
+ client.off('entry', options.onJournalEntry);
84
91
  try {
85
92
  await communicationWorkers?.close();
86
93
  }
@@ -94,6 +101,26 @@ async function executeCheckedFlow(checked, dataDir, options) {
94
101
  }
95
102
  }
96
103
  }
104
+ /**
105
+ * `run.start`, streaming the run's entries to `onJournalEntry` when one is
106
+ * given. A daemon that predates `watch` refuses the field while decoding,
107
+ * before any run exists, so starting again without it is the same request
108
+ * minus the observation — never a second run.
109
+ */
110
+ async function startWatched(client, spec, options) {
111
+ const onEntry = options.onJournalEntry;
112
+ if (onEntry === undefined)
113
+ return client.runStart(spec, options.reuseFromRunId);
114
+ try {
115
+ return await client.runStart(spec, options.reuseFromRunId, undefined, true);
116
+ }
117
+ catch (error) {
118
+ if (!(error instanceof JournalProtocolError) || error.code !== 'bad_request'
119
+ || !/unknown field `watch`/.test(error.message))
120
+ throw error;
121
+ return await client.runStart(spec, options.reuseFromRunId);
122
+ }
123
+ }
97
124
  export async function resumeFlow(runId, dataDir, options = {}) {
98
125
  const socketPath = socketFor(dataDir);
99
126
  const base = emptyReport('resume');
@@ -104,16 +131,32 @@ export async function resumeFlow(runId, dataDir, options = {}) {
104
131
  let communicationWorkers;
105
132
  let authoredAgent;
106
133
  let authoredLlm;
134
+ let llmFailure;
107
135
  let authoredLlmClient;
136
+ // Hoisted so the catch below can build the authored park remedy from the same
137
+ // metadata this resume was admitted against — the journal is the only place
138
+ // the flow path and the original `--input` survive a process boundary.
139
+ let authoredRoot;
108
140
  const workerCapacity = options.agentCapacity ?? DEFAULT_LOCAL_AGENT_CAPACITY;
109
141
  try {
110
- const authoredRoot = await readAuthoredRootMetadata(client, runId);
142
+ authoredRoot = await readAuthoredRootMetadata(client, runId);
111
143
  if (authoredRoot !== undefined) {
144
+ // Both worker-surface mismatches are refusals, not protocol failures.
145
+ // They used to throw bare `Error`s, which landed on `protocol_error`
146
+ // ("RUN <id> unknown") and told nobody what to do instead; and the
147
+ // second one is the exact complaint this change answers — `--local-agent`
148
+ // accepted on a run that cannot grow one is worse than rejected, because
149
+ // the run parks again with a message that has not changed.
112
150
  if (authoredRoot.localAgentStream !== undefined && !options.localAgent) {
113
- throw new Error('authored root requires --local-agent to resume its pinned worker surface');
151
+ return localAgentRefusal(base, runId, socketPath, `Run "${runId}" was started with a local agent worker surface, so resuming it needs the same flag.`
152
+ + ` To continue this run: ${resumeCommand(runId, dataDir, true)}.`);
114
153
  }
115
154
  if (authoredRoot.localAgentStream === undefined && options.localAgent) {
116
- throw new Error('authored root was started without a local agent worker surface');
155
+ return localAgentRefusal(base, runId, socketPath, `Run "${runId}" was started without a local agent worker surface:`
156
+ + ' --local-agent is admitted at run start; start a new run.'
157
+ + localAgentRemedy(authoredWorkerRemedy('worker_unavailable', false, {
158
+ path: authoredRoot.flowPath, input: authoredInputArgument(authoredRoot), dataDir,
159
+ })));
117
160
  }
118
161
  if (options.localAgent) {
119
162
  authoredAgent = await attachLocalAgent(client, dataDir, options.onPtyReady, authoredRoot.localAgentStream, workerCapacity);
@@ -121,6 +164,10 @@ export async function resumeFlow(runId, dataDir, options = {}) {
121
164
  await authoredLlmClient.connect();
122
165
  await authoredLlmClient.hello('flows-authored-resume-llm');
123
166
  authoredLlm = new LlmWorker(authoredLlmClient, `${authoredAgent.stream}-llm`, workerCapacity);
167
+ authoredLlm.on('error', onWorkerFailure('resume-llm', error => {
168
+ llmFailure = error;
169
+ client.close();
170
+ }));
124
171
  await authoredLlm.attach();
125
172
  }
126
173
  const result = await resumeDurableAuthoredFlow(runId, client, {
@@ -146,6 +193,13 @@ export async function resumeFlow(runId, dataDir, options = {}) {
146
193
  communicationWorkers = await attachCommunicationWorkers(spec, socketPath, dataDir);
147
194
  }
148
195
  }
196
+ const onEntry = options.onJournalEntry;
197
+ if (onEntry !== undefined) {
198
+ client.on('entry', onEntry);
199
+ // Observation never decides a resume: a watch the daemon refuses leaves
200
+ // the run unprojected, and the resume below reports the run's own fate.
201
+ await client.runWatch(runId).catch(() => client.off('entry', onEntry));
202
+ }
149
203
  let outcome = await client.runResume(runId, options.allowHumanInfluenced);
150
204
  if (await resumeHelperEffect(client, runId, dataDir)) {
151
205
  outcome = await client.runResume(runId, options.allowHumanInfluenced);
@@ -178,11 +232,38 @@ export async function resumeFlow(runId, dataDir, options = {}) {
178
232
  if (error instanceof AuthoredFlowExecutionError && (error.code === 'step_failed' || error.code === 'gate_failed')) {
179
233
  return authoredStepFailure('resume', base, socketPath, error, runId);
180
234
  }
235
+ // An authored resume that parks for want of a worker is a park, reported
236
+ // like the run path's — and with the same remedy, because an authored root
237
+ // admits its worker at run start: resuming again cannot attach one, so the
238
+ // only honest instruction is a new run carrying the same `--input`.
239
+ // `runId` here is the CHILD run holding the evidence; the root this resume
240
+ // named stays separate, so `flows` can still collect it.
241
+ if (error instanceof AuthoredFlowExecutionError && (error.code === 'agent_parked' || error.code === 'llm_parked')) {
242
+ return {
243
+ exitCode: 3,
244
+ report: {
245
+ ...base,
246
+ ok: false,
247
+ runId: error.runId ?? runId,
248
+ rootRunId: runId,
249
+ socketPath,
250
+ status: 'parked',
251
+ parkCause: error.parkCause,
252
+ diagnostics: [...base.diagnostics, {
253
+ severity: 'parked',
254
+ kind: 'run_parked',
255
+ message: error.message + localAgentRemedy(authoredWorkerRemedy(error.parkCause, options.localAgent === true, { path: authoredRoot?.flowPath, input: authoredInputArgument(authoredRoot), dataDir })),
256
+ }],
257
+ },
258
+ };
259
+ }
181
260
  if (error instanceof AuthoredHumanParked) {
182
261
  return authoredHumanParked('resume', base, socketPath, error, { dataDir, localAgent: options.localAgent === true });
183
262
  }
184
263
  if (!(error instanceof JournalProtocolError) || error.code !== 'run_not_found') {
185
- return protocolFailure('resume', base, socketPath, error, runId);
264
+ const cause = error instanceof AuthoredFlowExecutionError
265
+ ? error : llmFailure ?? authoredAgent?.failure ?? error;
266
+ return protocolFailure('resume', base, socketPath, cause, runId);
186
267
  }
187
268
  return {
188
269
  exitCode: 2,
@@ -200,6 +281,8 @@ export async function resumeFlow(runId, dataDir, options = {}) {
200
281
  }
201
282
  finally {
202
283
  try {
284
+ if (options.onJournalEntry !== undefined)
285
+ client.off('entry', options.onJournalEntry);
203
286
  await communicationWorkers?.close();
204
287
  await authoredLlm?.close();
205
288
  authoredLlmClient?.close();
@@ -210,6 +293,42 @@ export async function resumeFlow(runId, dataDir, options = {}) {
210
293
  }
211
294
  }
212
295
  }
296
+ /**
297
+ * A `--local-agent` mismatch, refused before the resume touches the journal.
298
+ *
299
+ * Exit 2 and `ok` left false by `emptyReport`: nothing ran, so this is the same
300
+ * shape as every other pre-journal refusal on this surface (docs/SURFACE.md §5).
301
+ * It returns rather than throwing so no worker is attached on the way out.
302
+ */
303
+ function localAgentRefusal(base, runId, socketPath, message) {
304
+ return {
305
+ exitCode: 2,
306
+ report: { ...base, runId, socketPath,
307
+ diagnostics: [...base.diagnostics, { severity: 'refusal', kind: 'local_agent_unavailable', message }] },
308
+ };
309
+ }
310
+ /**
311
+ * The `--input` argument a new run of this authored root would have to repeat,
312
+ * rendered back from the journaled metadata.
313
+ *
314
+ * `absent` when the root recorded no input, and also when the recorded input is
315
+ * something `JSON.stringify` cannot render — the remedy formatter then says an
316
+ * input is required instead of printing a command that would be refused as
317
+ * `input_invalid`. What it must never do is substitute `{}`: that is a
318
+ * different invocation of the flow than the one that parked.
319
+ *
320
+ * Unlike `runDirectFlow`, this side has only the decoded value: the journal
321
+ * records the input, not the `--input` word that carried it, so a run started
322
+ * from a file comes back as inline JSON. `authoredInput` is what keeps that
323
+ * honest about its own size — a recorded input can be larger than a shell
324
+ * argument even when the file that supplied it was unremarkable.
325
+ */
326
+ function authoredInputArgument(metadata) {
327
+ if (metadata === undefined || !metadata.inputPresent)
328
+ return { kind: 'absent' };
329
+ const rendered = JSON.stringify(metadata.input);
330
+ return authoredInput(typeof rendered === 'string' ? rendered : undefined);
331
+ }
213
332
  /**
214
333
  * A step that ran and failed, reported as the run failure it is.
215
334
  *
@@ -302,8 +421,18 @@ export function authoredCompletion(command, base, socketPath, result, runId) {
302
421
  ...fromBase(command, base),
303
422
  ...(runId === undefined ? {} : { runId }),
304
423
  socketPath,
424
+ ...(result.completionDetail === undefined ? {} : { completionDetail: result.completionDetail }),
305
425
  completedSteps: result.journalSteps.length,
306
426
  };
427
+ // Two spellings of the same fact, on purpose. `detail` is the structured
428
+ // one — the `StepFailedDetails` key the diagnostic already declares, here
429
+ // describing the AUTHOR's verdict rather than the daemon's account of a
430
+ // failing step — and keeps the body's own line breaks. `said` is the same
431
+ // text folded onto one line for the message, because Cloud renders a run's
432
+ // `error` through a view that elides the middle of a long one.
433
+ const detail = result.completionDetail;
434
+ const evidence = detail === undefined ? {} : { detail };
435
+ const said = detail === undefined ? '' : singleLineCompletionDetail(detail);
307
436
  switch (result.completionReason) {
308
437
  case 'success':
309
438
  return {
@@ -317,7 +446,9 @@ export function authoredCompletion(command, base, socketPath, result, runId) {
317
446
  ...common, ok: true, status: 'completed', completionReason: 'success',
318
447
  diagnostics: [...base.diagnostics, {
319
448
  severity: 'declined', kind: 'run_declined',
320
- message: 'Flow deliberately chose not to act on this input.',
449
+ ...evidence,
450
+ message: 'Flow deliberately chose not to act on this input.'
451
+ + (detail === undefined ? '' : ` ${said}`),
321
452
  }],
322
453
  },
323
454
  };
@@ -328,7 +459,9 @@ export function authoredCompletion(command, base, socketPath, result, runId) {
328
459
  ...common, ok: false, status: 'parked',
329
460
  diagnostics: [...base.diagnostics, {
330
461
  severity: 'parked', kind: 'run_parked',
331
- message: `Flow "${result.name}" needs_human; see the journal for accumulated blockers.`,
462
+ ...evidence,
463
+ message: `Flow "${result.name}" needs_human; see the journal for accumulated blockers.`
464
+ + (detail === undefined ? '' : ` ${said}`),
332
465
  }],
333
466
  },
334
467
  };
@@ -344,9 +477,16 @@ export function authoredCompletion(command, base, socketPath, result, runId) {
344
477
  ...common, ok: false, status: 'failed', completionReason: 'step_failed',
345
478
  diagnostics: [...base.diagnostics, {
346
479
  severity: 'failure', kind: 'step_failed',
347
- message: `Flow "${result.name}" declared done("step_failed"): its own checks did not pass. `
348
- + 'No step failed, so there is no step-level evidence to inspect; the journal holds '
349
- + 'every step the flow ran before it decided.',
480
+ ...evidence,
481
+ // With a detail, the flow's own account REPLACES the generic
482
+ // sentence: "no step-level evidence to inspect" is the only thing
483
+ // there is to say when the body said nothing, and saying it
484
+ // beside a real explanation would bury the explanation.
485
+ message: detail === undefined
486
+ ? `Flow "${result.name}" declared done("step_failed"): its own checks did not pass. `
487
+ + 'No step failed, so there is no step-level evidence to inspect; the journal holds '
488
+ + 'every step the flow ran before it decided.'
489
+ : `Flow "${result.name}" declared done("step_failed"): ${said}`,
350
490
  }],
351
491
  },
352
492
  };
@@ -540,31 +680,51 @@ export async function classifyOutcome(client, command, outcome, base, socketPath
540
680
  report: {
541
681
  ...report,
542
682
  parkedStep,
683
+ parkCause: needsHuman ? 'needs_human' : 'worker_unavailable',
543
684
  diagnostics: [...report.diagnostics, {
544
685
  severity: 'parked',
545
686
  kind: 'run_parked',
546
687
  message: needsHuman
547
688
  ? `Run "${current.run_id}" parked at step "${parkedStep.id}" (${parkedStep.type}): waiting for human recovery after the worker attempt failed.`
548
689
  : `Run "${current.run_id}" parked at step "${parkedStep.id}" (${parkedStep.type}): no worker is attached for step type "${parkedStep.type}".`
549
- // Only suggest the `--local-agent` remedy for YAML flows.
550
- // Authored TS flows require `--input`; the bare command below
551
- // would be refused (Cursor Bugbot flagged as LOW on flows#293).
552
- // For TS we omit the hint rather than fabricate a syntactically
553
- // valid but semantically wrong command — the direct-run refusal
554
- // for TS already names its own missing --input.
555
- + (command === 'run'
556
- && parkedStep.type === 'agent'
557
- && !options.localAgent
558
- && base.path !== undefined
559
- && !isAuthoredFlowPath(base.path)
560
- ? ` To start a new run with a local agent worker: flows run --local-agent '${base.path.replace(/'/g, "'\\''")}'. Declared workspace or stream surfaces require a worker that holds their pins.`
561
- : ''),
690
+ + localAgentRemedy(declarativeWorkerRemedy(command, current.run_id, parkedStep, base, options)),
562
691
  }],
563
692
  },
564
693
  };
565
694
  }
566
695
  return protocolFailure(command, base, socketPath, new Error(`relayflowd returned status ${current.status} without a classifiable completion`), current.run_id);
567
696
  }
697
+ /**
698
+ * Which remedy a worker park gets from the declarative classifier.
699
+ *
700
+ * An authored `.flow.ts` is deliberately SILENT here, and the suppression is
701
+ * tested first on purpose. Its remedy is a new run carrying the same `--input`,
702
+ * an argument this function does not have; `runDirectFlow` and `resumeFlow`
703
+ * render it once at the authored boundary where the input (or the journaled
704
+ * metadata holding it) is in hand. `classifyOutcome` also runs once per
705
+ * authored `f.agent` CHILD run, so answering here as well would append a
706
+ * remedy to every child message on the way out — and, on resume, a second
707
+ * contradictory one after the attached-worker branch below.
708
+ *
709
+ * `llm` parks get nothing, unchanged: the declarative verbs attach an
710
+ * agent-only worker (local-agent.ts advertises `['agent']`), so `--local-agent`
711
+ * is not a remedy for an `llm` step outside the authored path, which attaches
712
+ * an `LlmWorker` of its own.
713
+ */
714
+ function declarativeWorkerRemedy(command, runId, parkedStep, base, options) {
715
+ const dataDir = options.dataDir;
716
+ if (parkedStep.type !== 'agent')
717
+ return { kind: 'none' };
718
+ if (base.path !== undefined && isAuthoredFlowPath(base.path))
719
+ return { kind: 'none' };
720
+ if (options.localAgent === true)
721
+ return { kind: 'attached' };
722
+ if (command === 'resume')
723
+ return { kind: 'spec-resume', runId, dataDir };
724
+ if (command === 'run' && base.path !== undefined)
725
+ return { kind: 'spec-run', path: base.path, dataDir };
726
+ return { kind: 'none' };
727
+ }
568
728
  // Bound on re-polling a run that reports `running` with no identifiable step.
569
729
  // 40 x 50ms = 2s, far longer than the sub-second window observed in #179, and
570
730
  // short enough that a genuinely stuck run still reports rather than hangs.
@@ -593,6 +753,8 @@ async function inspectOutOfBandStep(client, runId) {
593
753
  ...(runningStep !== undefined ? { runningStep } : {}),
594
754
  };
595
755
  }
756
+ // Match kernel/relayflowd/src/server/client.rs: allow the lease sweep to dispatch a retry.
757
+ const LEASE_SWEEP_GRACE_MS = 5_000;
596
758
  async function waitForRunningStep(client, runId, runningStep, options) {
597
759
  let leaseDeadlineMs = runningStep.leaseDeadlineMs;
598
760
  if (!Number.isFinite(leaseDeadlineMs)) {
@@ -606,7 +768,7 @@ async function waitForRunningStep(client, runId, runningStep, options) {
606
768
  });
607
769
  while (true) {
608
770
  throwIfCanceled(options.signal, runningStep.id);
609
- const remainingMs = leaseDeadlineMs - Date.now();
771
+ const remainingMs = leaseDeadlineMs + LEASE_SWEEP_GRACE_MS - Date.now();
610
772
  if (remainingMs <= 0) {
611
773
  throw new Error(`worker lease for step "${runningStep.id}" expired at ${leaseDeadlineMs} without completion`);
612
774
  }