@jr2/orchestrator 0.4.1 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (327) hide show
  1. package/README.md +20 -2
  2. package/console/components/app.ts +2 -0
  3. package/console/components/fleet.ts +14 -1
  4. package/console/components/machine-pane.ts +41 -2
  5. package/console/main.ts +13 -1
  6. package/console/store.ts +102 -6
  7. package/console/style.css +21 -0
  8. package/docs/agents-block.md +5 -0
  9. package/docs/concepts/agents-and-turns.md +442 -0
  10. package/docs/concepts/architecture.md +230 -0
  11. package/docs/concepts/charts.md +143 -0
  12. package/docs/concepts/composition.md +357 -0
  13. package/docs/concepts/converge.md +254 -0
  14. package/docs/concepts/durable-runs.md +189 -0
  15. package/docs/concepts/effects.md +603 -0
  16. package/docs/concepts/gates.md +208 -0
  17. package/docs/concepts/machines-and-workflows.md +289 -0
  18. package/docs/concepts/pools-and-sources.md +230 -0
  19. package/docs/concepts/secrets-and-trust.md +222 -0
  20. package/docs/concepts/the-menu.md +378 -0
  21. package/docs/concepts/workspaces.md +678 -0
  22. package/docs/get-started/a-model-decides.md +563 -0
  23. package/docs/get-started/an-agent-in-a-sandbox.md +381 -0
  24. package/docs/get-started/connect-a-model.md +248 -0
  25. package/docs/get-started/create-an-instance.md +194 -0
  26. package/docs/get-started/have-your-assistant-write-a-machine.md +922 -0
  27. package/docs/get-started/install.md +126 -0
  28. package/docs/guides/add-tools-to-the-sandbox.md +295 -0
  29. package/docs/guides/answer-a-gate.md +304 -0
  30. package/docs/guides/bind-open-parts.md +223 -0
  31. package/docs/guides/cancel-a-run.md +146 -0
  32. package/docs/guides/clean-up.md +206 -0
  33. package/docs/guides/fix-a-failed-converge.md +361 -0
  34. package/docs/guides/give-the-cluster-git-credentials.md +222 -0
  35. package/docs/guides/iterate-on-a-machine-on-kind.md +190 -0
  36. package/docs/guides/let-an-agent-write-a-chart.md +226 -0
  37. package/docs/guides/look-inside-a-sandbox.md +174 -0
  38. package/docs/guides/mirror-the-kit-images.md +176 -0
  39. package/docs/guides/move-from-kind-to-a-shared-cluster.md +302 -0
  40. package/docs/guides/open-the-console.md +91 -0
  41. package/docs/guides/publish-a-machine-as-an-npm-package.md +350 -0
  42. package/docs/guides/push-and-sign-a-branch.md +486 -0
  43. package/docs/guides/run-a-chart-by-name.md +270 -0
  44. package/docs/guides/run-a-command-or-call-a-url.md +544 -0
  45. package/docs/guides/run-one-worker-per-item.md +321 -0
  46. package/docs/guides/set-an-agents-access-and-dials.md +375 -0
  47. package/docs/guides/size-a-workspace.md +204 -0
  48. package/docs/guides/start-a-run-from-a-run.md +237 -0
  49. package/docs/guides/start-a-run.md +207 -0
  50. package/docs/guides/upgrade-the-kit-version.md +240 -0
  51. package/docs/guides/use-a-hosted-provider.md +208 -0
  52. package/docs/guides/use-a-local-model.md +313 -0
  53. package/docs/guides/watch-a-run.md +326 -0
  54. package/docs/guides/write-a-workflow.md +318 -0
  55. package/docs/index.md +44 -0
  56. package/docs/llms.txt +216 -0
  57. package/docs/reference/authoring-surface/agent.md +128 -0
  58. package/docs/reference/authoring-surface/answer.md +140 -0
  59. package/docs/reference/authoring-surface/arg.md +60 -0
  60. package/docs/reference/authoring-surface/basic.md +62 -0
  61. package/docs/reference/authoring-surface/bearer.md +53 -0
  62. package/docs/reference/authoring-surface/chartschema.md +23 -0
  63. package/docs/reference/authoring-surface/chartschemafor.md +48 -0
  64. package/docs/reference/authoring-surface/command.md +191 -0
  65. package/docs/reference/authoring-surface/customize.md +64 -0
  66. package/docs/reference/authoring-surface/defineconfig.md +41 -0
  67. package/docs/reference/authoring-surface/defineevent.md +114 -0
  68. package/docs/reference/authoring-surface/dispatch.md +126 -0
  69. package/docs/reference/authoring-surface/fail.md +83 -0
  70. package/docs/reference/authoring-surface/file.md +122 -0
  71. package/docs/reference/authoring-surface/frompick.md +277 -0
  72. package/docs/reference/authoring-surface/http.md +159 -0
  73. package/docs/reference/authoring-surface/isfailure.md +58 -0
  74. package/docs/reference/authoring-surface/jr2setup.md +237 -0
  75. package/docs/reference/authoring-surface/open.md +74 -0
  76. package/docs/reference/authoring-surface/openbody.md +86 -0
  77. package/docs/reference/authoring-surface/paramsof.md +125 -0
  78. package/docs/reference/authoring-surface/pool.md +186 -0
  79. package/docs/reference/authoring-surface/push.md +112 -0
  80. package/docs/reference/authoring-surface/secret.md +118 -0
  81. package/docs/reference/authoring-surface/sentby.md +83 -0
  82. package/docs/reference/authoring-surface/source.md +51 -0
  83. package/docs/reference/authoring-surface/text.md +62 -0
  84. package/docs/reference/authoring-surface/type-agentdeclaration.md +27 -0
  85. package/docs/reference/authoring-surface/type-agentdefinition.md +80 -0
  86. package/docs/reference/authoring-surface/type-agentlogic.md +15 -0
  87. package/docs/reference/authoring-surface/type-agentslots.md +12 -0
  88. package/docs/reference/authoring-surface/type-answeraction.md +12 -0
  89. package/docs/reference/authoring-surface/type-arg.md +19 -0
  90. package/docs/reference/authoring-surface/type-argnames.md +12 -0
  91. package/docs/reference/authoring-surface/type-binding.md +62 -0
  92. package/docs/reference/authoring-surface/type-bindingof.md +12 -0
  93. package/docs/reference/authoring-surface/type-bodyacceptsdoor.md +15 -0
  94. package/docs/reference/authoring-surface/type-bodyacceptsslots.md +17 -0
  95. package/docs/reference/authoring-surface/type-ceilings.md +41 -0
  96. package/docs/reference/authoring-surface/type-chainlink.md +19 -0
  97. package/docs/reference/authoring-surface/type-chartaction.md +46 -0
  98. package/docs/reference/authoring-surface/type-chartagent.md +28 -0
  99. package/docs/reference/authoring-surface/type-chartevent.md +20 -0
  100. package/docs/reference/authoring-surface/type-chartguard.md +20 -0
  101. package/docs/reference/authoring-surface/type-chartinvoke.md +28 -0
  102. package/docs/reference/authoring-surface/type-chartjson.md +14 -0
  103. package/docs/reference/authoring-surface/type-chartstate.md +46 -0
  104. package/docs/reference/authoring-surface/type-charttext.md +40 -0
  105. package/docs/reference/authoring-surface/type-charttransition.md +22 -0
  106. package/docs/reference/authoring-surface/type-charttransitions.md +14 -0
  107. package/docs/reference/authoring-surface/type-chartvalue.md +15 -0
  108. package/docs/reference/authoring-surface/type-childat.md +12 -0
  109. package/docs/reference/authoring-surface/type-childslots.md +12 -0
  110. package/docs/reference/authoring-surface/type-commandenv.md +15 -0
  111. package/docs/reference/authoring-surface/type-commandinput.md +19 -0
  112. package/docs/reference/authoring-surface/type-commandoptions.md +78 -0
  113. package/docs/reference/authoring-surface/type-commandoutput.md +104 -0
  114. package/docs/reference/authoring-surface/type-customize.md +109 -0
  115. package/docs/reference/authoring-surface/type-dispatchdefinition.md +39 -0
  116. package/docs/reference/authoring-surface/type-dispatchinput.md +14 -0
  117. package/docs/reference/authoring-surface/type-dispatchopenparts.md +14 -0
  118. package/docs/reference/authoring-surface/type-dispatchoutput.md +65 -0
  119. package/docs/reference/authoring-surface/type-duration.md +15 -0
  120. package/docs/reference/authoring-surface/type-effectbinding.md +93 -0
  121. package/docs/reference/authoring-surface/type-effectlogic.md +12 -0
  122. package/docs/reference/authoring-surface/type-envopenparts.md +14 -0
  123. package/docs/reference/authoring-surface/type-eventaudience.md +27 -0
  124. package/docs/reference/authoring-surface/type-eventdef.md +45 -0
  125. package/docs/reference/authoring-surface/type-eventfrom.md +16 -0
  126. package/docs/reference/authoring-surface/type-eventsemantics.md +26 -0
  127. package/docs/reference/authoring-surface/type-execoutcome.md +34 -0
  128. package/docs/reference/authoring-surface/type-failslot.md +14 -0
  129. package/docs/reference/authoring-surface/type-failure.md +19 -0
  130. package/docs/reference/authoring-surface/type-failureinput.md +20 -0
  131. package/docs/reference/authoring-surface/type-filebody.md +41 -0
  132. package/docs/reference/authoring-surface/type-frominput.md +14 -0
  133. package/docs/reference/authoring-surface/type-hostinjectedinput.md +58 -0
  134. package/docs/reference/authoring-surface/type-httpdefinition.md +101 -0
  135. package/docs/reference/authoring-surface/type-httpinput.md +12 -0
  136. package/docs/reference/authoring-surface/type-httpmethod.md +14 -0
  137. package/docs/reference/authoring-surface/type-httpopenparts.md +12 -0
  138. package/docs/reference/authoring-surface/type-httpoutput.md +89 -0
  139. package/docs/reference/authoring-surface/type-httprequestparts.md +33 -0
  140. package/docs/reference/authoring-surface/type-jr2config.md +126 -0
  141. package/docs/reference/authoring-surface/type-lends.md +38 -0
  142. package/docs/reference/authoring-surface/type-logicat.md +12 -0
  143. package/docs/reference/authoring-surface/type-markedif.md +12 -0
  144. package/docs/reference/authoring-surface/type-mergedactors.md +12 -0
  145. package/docs/reference/authoring-surface/type-namedsecret.md +25 -0
  146. package/docs/reference/authoring-surface/type-noslotspec.md +26 -0
  147. package/docs/reference/authoring-surface/type-noslotworkspaceoptions.md +32 -0
  148. package/docs/reference/authoring-surface/type-openbodydeclaration.md +40 -0
  149. package/docs/reference/authoring-surface/type-openbodylogic.md +14 -0
  150. package/docs/reference/authoring-surface/type-openbodyoutput.md +42 -0
  151. package/docs/reference/authoring-surface/type-openbodyslot.md +18 -0
  152. package/docs/reference/authoring-surface/type-opencommandinput.md +17 -0
  153. package/docs/reference/authoring-surface/type-openeffect.md +12 -0
  154. package/docs/reference/authoring-surface/type-openeffectslots.md +12 -0
  155. package/docs/reference/authoring-surface/type-openof.md +12 -0
  156. package/docs/reference/authoring-surface/type-opensecret.md +23 -0
  157. package/docs/reference/authoring-surface/type-opensecretmark.md +12 -0
  158. package/docs/reference/authoring-surface/type-permissivenoslotworkspaceoptions.md +31 -0
  159. package/docs/reference/authoring-surface/type-permissiveworkspaceoptions.md +32 -0
  160. package/docs/reference/authoring-surface/type-poolmachine.md +28 -0
  161. package/docs/reference/authoring-surface/type-poolspec.md +60 -0
  162. package/docs/reference/authoring-surface/type-pushinput.md +15 -0
  163. package/docs/reference/authoring-surface/type-pushoptions.md +79 -0
  164. package/docs/reference/authoring-surface/type-pushoutput.md +124 -0
  165. package/docs/reference/authoring-surface/type-pushwireoutput.md +12 -0
  166. package/docs/reference/authoring-surface/type-quantity.md +14 -0
  167. package/docs/reference/authoring-surface/type-reached.md +12 -0
  168. package/docs/reference/authoring-surface/type-reposlot.md +70 -0
  169. package/docs/reference/authoring-surface/type-reposlotsof.md +16 -0
  170. package/docs/reference/authoring-surface/type-sandboxoptions.md +77 -0
  171. package/docs/reference/authoring-surface/type-secret.md +25 -0
  172. package/docs/reference/authoring-surface/type-sender.md +19 -0
  173. package/docs/reference/authoring-surface/type-sentbyguards.md +12 -0
  174. package/docs/reference/authoring-surface/type-size.md +85 -0
  175. package/docs/reference/authoring-surface/type-slothandles.md +32 -0
  176. package/docs/reference/authoring-surface/type-sourcenextresult.md +17 -0
  177. package/docs/reference/authoring-surface/type-sourcespec.md +44 -0
  178. package/docs/reference/authoring-surface/type-syncstate.md +12 -0
  179. package/docs/reference/authoring-surface/type-text.md +19 -0
  180. package/docs/reference/authoring-surface/type-textpart.md +24 -0
  181. package/docs/reference/authoring-surface/type-thinkinglevel.md +39 -0
  182. package/docs/reference/authoring-surface/type-toparameterizedobject.md +14 -0
  183. package/docs/reference/authoring-surface/type-toprovidedactor.md +14 -0
  184. package/docs/reference/authoring-surface/type-unknown.md +21 -0
  185. package/docs/reference/authoring-surface/type-usercontainer.md +77 -0
  186. package/docs/reference/authoring-surface/type-withoutemptyindex.md +20 -0
  187. package/docs/reference/authoring-surface/type-workflowevent.md +46 -0
  188. package/docs/reference/authoring-surface/type-workspaceaccess.md +16 -0
  189. package/docs/reference/authoring-surface/type-workspaced.md +94 -0
  190. package/docs/reference/authoring-surface/type-workspacehandles.md +23 -0
  191. package/docs/reference/authoring-surface/type-workspacemachine.md +29 -0
  192. package/docs/reference/authoring-surface/type-workspaceof.md +13 -0
  193. package/docs/reference/authoring-surface/type-workspaceoptions.md +39 -0
  194. package/docs/reference/authoring-surface/type-workspacespec.md +37 -0
  195. package/docs/reference/authoring-surface/workspace.md +259 -0
  196. package/docs/reference/authoring-surface.md +197 -0
  197. package/docs/reference/cli.md +433 -0
  198. package/docs/reference/config.md +756 -0
  199. package/docs/reference/decisions/0001-operator-owned-generic-sandbox.md +113 -0
  200. package/docs/reference/decisions/0002-duplex-streaming-actor.md +110 -0
  201. package/docs/reference/decisions/0004-worktree-provisioning-model.md +124 -0
  202. package/docs/reference/decisions/0005-sandbox-pod-composition.md +230 -0
  203. package/docs/reference/decisions/0006-agent-control-surface.md +47 -0
  204. package/docs/reference/decisions/0007-durable-machine-state.md +109 -0
  205. package/docs/reference/decisions/0008-orchestrator-as-deployed-app.md +60 -0
  206. package/docs/reference/decisions/0009-cli-and-instance-interface.md +275 -0
  207. package/docs/reference/decisions/0010-bdd-acceptance-tests.md +160 -0
  208. package/docs/reference/decisions/0011-workflow-defined-events.md +141 -0
  209. package/docs/reference/decisions/0012-workspace-wrapper-machine.md +103 -0
  210. package/docs/reference/decisions/0013-the-agent-reaches-its-machine-through-a-container-it-cannot-read.md +157 -0
  211. package/docs/reference/decisions/0014-observation-is-open-run-state-is-not.md +95 -0
  212. package/docs/reference/decisions/0015-authoring-surface-absorbs-the-mechanism.md +265 -0
  213. package/docs/reference/decisions/0016-agent-turn-mechanics-are-internal.md +124 -0
  214. package/docs/reference/decisions/0017-pool-over-a-source-port.md +69 -0
  215. package/docs/reference/decisions/0018-instance-agents-are-definitions-jr2-assembles-the-harness.md +111 -0
  216. package/docs/reference/decisions/0019-one-converging-command-against-the-current-context.md +275 -0
  217. package/docs/reference/decisions/0020-private-ca-trust-is-a-named-concept.md +60 -0
  218. package/docs/reference/decisions/0021-workspace-continuity-is-a-lease-that-answers-back.md +100 -0
  219. package/docs/reference/decisions/0022-observation-is-a-level-triggered-feed.md +103 -0
  220. package/docs/reference/decisions/0023-the-harness-prints-the-conversation.md +176 -0
  221. package/docs/reference/decisions/0024-an-agents-turn-ends-with-the-state-that-asked-for-it.md +439 -0
  222. package/docs/reference/decisions/0025-cancel-ends-a-run-stop-parks-it.md +65 -0
  223. package/docs/reference/decisions/0026-a-turn-that-is-over-is-never-prompted.md +62 -0
  224. package/docs/reference/decisions/0027-the-harness-is-jr2s-own-server-flue-retires-the-wire-stays.md +237 -0
  225. package/docs/reference/decisions/0028-what-an-agent-may-do-to-the-workspace-is-part-of-its-definition.md +89 -0
  226. package/docs/reference/decisions/0029-a-menu-is-fixed-for-a-conversation-and-a-turn-is-told-its-allowed-picks.md +154 -0
  227. package/docs/reference/decisions/0030-a-snapshot-names-the-machine-it-was-written-under.md +100 -0
  228. package/docs/reference/decisions/0031-menu-only-agents-run-on-the-instance-harness.md +190 -0
  229. package/docs/reference/decisions/0032-the-console-unlocks-with-the-instance-token.md +61 -0
  230. package/docs/reference/decisions/0033-a-machine-declares-the-input-that-starts-it.md +127 -0
  231. package/docs/reference/decisions/0034-the-console-renders-with-preact-and-the-server-erases-the-types.md +57 -0
  232. package/docs/reference/decisions/0035-a-runaway-turn-is-ended-rerolled-once-then-a-fault.md +92 -0
  233. package/docs/reference/decisions/0036-a-turn-compacts-its-own-context-mid-flight.md +138 -0
  234. package/docs/reference/decisions/0037-an-instance-builds-its-sandbox-images-jr2-injects-the-harness.md +196 -0
  235. package/docs/reference/decisions/0038-jr2-up-builds-every-image-it-deploys.md +170 -0
  236. package/docs/reference/decisions/0039-image-garbage-collects-by-reachability.md +115 -0
  237. package/docs/reference/decisions/0041-a-build-the-host-already-holds-is-not-spent-again.md +64 -0
  238. package/docs/reference/decisions/0042-ready-is-not-routable-an-admission-retries-its-connection.md +142 -0
  239. package/docs/reference/decisions/0043-the-kit-is-tested-as-installed-a-local-registry-stands-in-for-npm.md +170 -0
  240. package/docs/reference/decisions/0044-kit-images-live-at-a-canonical-home-a-self-host-mirrors-it.md +85 -0
  241. package/docs/reference/decisions/0045-the-platform-joins-the-image-address-and-the-cluster-chooses-it.md +82 -0
  242. package/docs/reference/decisions/0046-a-converge-failure-carries-its-diagnosis.md +34 -0
  243. package/docs/reference/decisions/0047-the-git-ssh-key-source-is-the-users-choice.md +47 -0
  244. package/docs/reference/decisions/0048-the-orchestrator-boots-without-its-repos.md +36 -0
  245. package/docs/reference/decisions/0049-a-machine-carries-its-parts-and-composes-by-invoke.md +126 -0
  246. package/docs/reference/decisions/0050-what-code-names-config-declares-what-the-cli-names-discovery-finds.md +73 -0
  247. package/docs/reference/decisions/0051-a-repo-is-a-slot-on-the-workspace-and-a-cache-on-the-node.md +227 -0
  248. package/docs/reference/decisions/0052-a-sandbox-lands-where-an-ordinary-pod-lands-and-the-cache-follows-it.md +81 -0
  249. package/docs/reference/decisions/0053-a-fetch-inside-the-pod-asks-the-node-cache-and-the-cache-asks-the-remote.md +111 -0
  250. package/docs/reference/decisions/0054-the-kit-ships-machines-and-a-shipped-machine-leaves-its-parts-open.md +126 -0
  251. package/docs/reference/decisions/0055-a-release-is-a-pushed-tag-and-the-publish-guard-is-the-credential.md +107 -0
  252. package/docs/reference/decisions/0056-a-global-jr2-hands-off-to-the-instances-own-and-an-instance-has-one-kit-version.md +62 -0
  253. package/docs/reference/decisions/0057-a-turn-is-its-frame-its-dials-and-whether-it-continues.md +152 -0
  254. package/docs/reference/decisions/0058-a-harness-answers-the-orchestrator-alone.md +106 -0
  255. package/docs/reference/decisions/0059-a-harness-holds-stand-ins-and-the-custodian-holds-the-keys.md +384 -0
  256. package/docs/reference/decisions/0060-a-workspace-states-its-size-and-jr2-reserves-all-of-it.md +111 -0
  257. package/docs/reference/decisions/0061-a-memory-kill-ends-the-agents-processes-not-the-harness.md +83 -0
  258. package/docs/reference/decisions/0062-jr2-briefs-the-agent-on-its-seat-never-on-its-task.md +212 -0
  259. package/docs/reference/decisions/0063-the-orchestrator-watches-the-cluster.md +83 -0
  260. package/docs/reference/decisions/0064-a-workspace-waits-for-capacity.md +79 -0
  261. package/docs/reference/decisions/0065-a-persist-survives-a-crash-and-history-is-a-week.md +65 -0
  262. package/docs/reference/decisions/0066-a-model-tier-runs-a-real-model-and-a-change-to-what-it-reads-runs-the-tier.md +550 -0
  263. package/docs/reference/decisions/0067-an-effect-is-an-actor-slot-and-runs-at-most-once-unless-marked-idempotent.md +430 -0
  264. package/docs/reference/decisions/0068-an-effector-holds-an-effects-secrets-and-signs-its-wire.md +464 -0
  265. package/docs/reference/decisions/0069-the-orchestrator-is-a-kit-image-and-an-instance-publishes-its-assembly.md +180 -0
  266. package/docs/reference/decisions/0070-a-machine-lends-its-parts-to-a-chart.md +323 -0
  267. package/docs/reference/decisions/0071-a-run-starts-a-run-through-a-dispatch-effect.md +183 -0
  268. package/docs/reference/decisions/0072-the-docs-ship-inside-the-kit-and-an-instances-agents-md-indexes-them.md +144 -0
  269. package/docs/reference/decisions/0073-a-machine-fails-a-run-with-fail-and-an-uncaught-failure-ends-it-failed.md +122 -0
  270. package/docs/reference/decisions/0074-an-unrouted-mechanism-event-is-refused-at-load-and-faults-the-run.md +76 -0
  271. package/docs/reference/decisions.md +83 -0
  272. package/docs/reference/glossary.md +648 -0
  273. package/docs/reference/http-api.md +1348 -0
  274. package/docs/reference/machines.md +190 -0
  275. package/docs/reference/mechanism-events.md +72 -0
  276. package/docs/why.md +206 -0
  277. package/package.json +5 -3
  278. package/src/actor.ts +541 -79
  279. package/src/agent.ts +114 -38
  280. package/src/ambient.ts +2 -1
  281. package/src/assembly-checks.ts +189 -7
  282. package/src/cause.ts +234 -0
  283. package/src/chart.ts +169 -37
  284. package/src/charts.ts +34 -6
  285. package/src/config.ts +430 -178
  286. package/src/custodian.ts +74 -22
  287. package/src/customize.ts +188 -46
  288. package/src/dispatch-effect.ts +945 -0
  289. package/src/door-compat.ts +217 -0
  290. package/src/durability.ts +11 -4
  291. package/src/effect.ts +341 -44
  292. package/src/effector-wire.ts +160 -11
  293. package/src/fail.ts +209 -0
  294. package/src/harness-client.ts +541 -47
  295. package/src/http-effect.ts +495 -53
  296. package/src/http.ts +427 -16
  297. package/src/index.ts +60 -82
  298. package/src/instance.ts +68 -8
  299. package/src/internal.ts +84 -0
  300. package/src/machine-doc.ts +21 -3
  301. package/src/mechanism-routes.ts +168 -0
  302. package/src/model-keys.generated.ts +53 -0
  303. package/src/model-keys.ts +18 -58
  304. package/src/notices.ts +66 -13
  305. package/src/open-body.ts +159 -23
  306. package/src/open-effect.ts +81 -8
  307. package/src/open.ts +59 -6
  308. package/src/parts.ts +184 -13
  309. package/src/party.ts +68 -2
  310. package/src/pick.ts +463 -11
  311. package/src/pool.ts +247 -36
  312. package/src/registration.ts +83 -4
  313. package/src/repos.ts +2 -1
  314. package/src/run-host.ts +565 -31
  315. package/src/run-output.ts +38 -0
  316. package/src/sandbox-effect.ts +273 -38
  317. package/src/sandbox-kube.ts +3 -1
  318. package/src/secret-placement.ts +52 -17
  319. package/src/server.ts +3 -0
  320. package/src/setup.ts +239 -56
  321. package/src/size.ts +121 -9
  322. package/src/snapshot-store.ts +54 -10
  323. package/src/stub-harness.ts +44 -16
  324. package/src/timers.ts +14 -1
  325. package/src/vocabulary.ts +69 -14
  326. package/src/wire.ts +90 -16
  327. package/src/workspace.ts +697 -175
@@ -0,0 +1,191 @@
1
+ ---
2
+ title: command
3
+ description: "Make a `command` Effect: an actor slot that runs one program in the Workspace's Sandbox when a state invokes it."
4
+ ---
5
+
6
+ # `command`
7
+
8
+ Function, in `@jr2/orchestrator/src/harness-client.ts`. It is an export of `@jr2/orchestrator`, on the [Authoring surface](../authoring-surface.md) page, in Effects.
9
+
10
+ ## Overload 1
11
+
12
+ ```ts
13
+ function command<
14
+ const A extends readonly (string | Arg)[],
15
+ const Opt extends CommandOptions = CommandOptions,
16
+ >(
17
+ argv: A,
18
+ options?: Opt,
19
+ ): EffectLogic<CommandInput<A, Opt["pin"]>, CommandOutput> & OpenOf<EnvOpenParts<Opt>>
20
+ ```
21
+
22
+ Make a `command` Effect: an actor slot that runs one program in the Workspace's Sandbox when a
23
+ state invokes it. Put it under `actors` and invoke it by its key: `actors: { tests:
24
+ command(["node", "--test"]) }`, then `invoke: { src: "tests", onDone: … }`.
25
+
26
+ `argv` is a list, never shell text: each entry is one argument. An `arg("name")` entry is filled
27
+ from the invoke's `input` (`input: { name: "…" }`), as one argument whatever its text. To use a
28
+ shell, write it: `["sh", "-c", "…"]`.
29
+
30
+ Where it runs:
31
+ - With no Effect secret in `env`, in the Harness container of the enclosing Workspace's Sandbox.
32
+ It runs in the Worktree of a Repo Slot, or in `/work` in a Workspace with no Repo Slot. The
33
+ Agent's Working tools also run in this container.
34
+ - With an Effect secret in `env`, in the Sandbox Effector, against a commit of the branch. This
35
+ is the branch tip when it starts, or with `pin: true` the commit that the invoke's `input.sha`
36
+ names. The output then says `dirty: true` when the Worktree held edits that the command did
37
+ not see.
38
+
39
+ Every outcome is output for `onDone`, never an error: `{ outcome: "exited", code, tail }`,
40
+ `{ outcome: "timeout", tail }`, `{ outcome: "killed", signal, tail }`, or `{ outcome: "unknown",
41
+ reason }` when jr2 cannot know what happened. `tail` is the end of the output stream.
42
+
43
+ After an Orchestrator restart:
44
+ - A command with no Effect secret in `env` never runs twice. jr2 attaches to it again, or settles
45
+ `unknown`.
46
+ - A command with an Effect secret in `env` runs again when the Sandbox Effector no longer holds
47
+ it. It runs against the same commit. If jr2 has no commit for it, it settles `unknown`.
48
+
49
+ When the state exits, the command stops: jr2 kills its process group. `onError` is only for a
50
+ Machine or config defect.
51
+
52
+ It refuses, when you call it:
53
+ - an empty `argv`: `command(argv): argv is a non-empty list — each entry one argument, never
54
+ shell text`
55
+ - an entry that is not a string or `arg()`: `command(argv): an argv entry is a string or
56
+ arg("name"), got <entry>`
57
+ - a `timeout` that is not a positive duration: `command: timeout "<timeout>" is not a positive
58
+ duration (like "90s", "10m", "1h")`
59
+ - an `env` name that is not a variable name, or `PATH`, `HOME` or `TMPDIR`: ``command(argv, {
60
+ env }): "<name>" is not a variable the author sets — PATH, HOME and TMPDIR are the Effector's
61
+ (ADR-0067)``
62
+ - `pin: true` with no Effect secret in `env`: ``command(argv, { pin: true }) names no secret in
63
+ its env: `pin` chooses the commit a credentialed command runs against in the Sandbox
64
+ Effector, and a command that names no secret runs in the live Worktree (ADR-0067) — name its
65
+ secret, command(argv, { env: { NAME: secret("x") }, pin: true }), or drop `pin` ``
66
+
67
+ And when it starts, with no Effect secret in `env`:
68
+ - outside a `workspace()`: `command "<slot>" runs in the Harness container of a Workspace, and
69
+ its state is not inside a workspace() — invoke it from a Workspace's body (ADR-0067)`
70
+ - no `slot` under a Workspace with more than one Repo Slot: `command "<slot>" runs under a
71
+ Workspace carrying more than one Repo Slot (<slots>) and names none — say which Worktree it
72
+ runs in: command(argv, { slot: "<slot>" }) (ADR-0051)`
73
+ - a `slot` that the Workspace does not have: `command "<slot>" names Repo Slot "<name>", which
74
+ its Workspace does not carry (<slots>)`
75
+ - an `arg()` with no string in `input`: `command "<slot>": argv slot <<name>> has no string
76
+ value in its input (got <type>) — map it in the invoke's input`. The angle brackets around the
77
+ arg's name are in the text: `argv slot <file>`. `<type>` is `nothing` when `input` has no such
78
+ field, or the type of its value, such as `number`.
79
+
80
+ And when it starts, with an Effect secret in `env`:
81
+ - outside a `workspace()`: `command "<slot>" runs in the Sandbox Effector of a Workspace, and its
82
+ state is not inside a workspace() — invoke it from a Workspace's body (ADR-0067)`
83
+ - no `slot` under a Workspace with more than one Repo Slot: `command "<slot>" runs under a
84
+ Workspace carrying more than one Repo Slot (<slots>) — say which: { slot: "<slot>" }
85
+ (ADR-0051)`
86
+ - a Workspace with no Repo Slot: `command "<slot>" runs under a Workspace with no Repo Slot: a
87
+ command with an Effect secret runs against one commit of a Repo Slot's branch, and there is
88
+ none — declare a Repo Slot, or name no secret in its env, and it runs in /work beside the Agent
89
+ (ADR-0051)`. `jr2 up` refuses it first, with the same reason
90
+ - a `slot` that the Workspace does not have: `command "<slot>" names Repo Slot "<name>", which
91
+ its Workspace does not carry (<slots>)`
92
+ - `pin: true` and an `input.sha` that is not a full commit id: `command "<slot>" (pin): its
93
+ input's sha is not a full commit id`
94
+ - an `arg()` with no string in `input`: the same text as above.
95
+
96
+ **Parameters**
97
+
98
+ - `argv`: The program and its arguments: strings and `arg("name")` entries. Or `open`, in a
99
+ Machine that you publish as a package, for the Instance that registers it to bind with
100
+ `customize()`.
101
+ - `options` ([`CommandOptions`](type-commandoptions.md)): Optional. `slot`: the Repo Slot whose Worktree the command runs in; needed only
102
+ where the Workspace has more than one. `timeout`: `"90s"`, `"10m"` or `"1h"`, default
103
+ `"10m"`; when it expires, the output is `timeout`. `tail`: how many characters of the end of
104
+ the output stream to keep, default 4096. `env`: environment variables. Each value is
105
+ `secret("name")` for the value of an Effect secret, or `secret("name").path` for the path of a
106
+ file that holds it. `pin`: `true` to run against the commit in `input.sha`. Use `pin` only
107
+ with an Effect secret in `env`.
108
+
109
+ **Returns**: The actor logic of the Effect's slot. Its output is a `CommandOutput`.
110
+
111
+ **Example**
112
+
113
+ ```ts
114
+ import { z } from "zod";
115
+ import { arg, command, fail, jr2Setup, workspace, type Workspaced } from "@jr2/orchestrator";
116
+
117
+ const runInput = z.object({ branch: z.string() });
118
+ type BodyInput = Workspaced<z.infer<typeof runInput>, "app">;
119
+
120
+ const body = jr2Setup({
121
+ types: {} as { input: BodyInput },
122
+ actors: {
123
+ tests: command(["node", "--test", arg("file")], { timeout: "5m" }),
124
+ fail: fail(),
125
+ },
126
+ }).createMachine({
127
+ id: "check",
128
+ on: { "workspace.lost": ".lost" },
129
+ initial: "testing",
130
+ states: {
131
+ testing: {
132
+ invoke: {
133
+ src: "tests",
134
+ input: { file: "test/greet.test.js" },
135
+ onDone: [
136
+ {
137
+ guard: ({ event }) => event.output.outcome === "exited" && event.output.code === 0,
138
+ target: "passed",
139
+ },
140
+ { target: "failed" },
141
+ ],
142
+ },
143
+ },
144
+ passed: { type: "final" },
145
+ // Not final states: each one fails the run, and the run ends `failed`.
146
+ failed: { invoke: { src: "fail", input: { reason: "the test did not pass" } } },
147
+ lost: { invoke: { src: "fail", input: { reason: "the Sandbox is gone" } } },
148
+ },
149
+ });
150
+
151
+ export const machine = workspace(body, {
152
+ input: runInput,
153
+ repos: { app: "https://github.com/you/app.git" },
154
+ spec: ({ input }) => ({ branch: input.branch }),
155
+ });
156
+ ```
157
+
158
+ **See also**
159
+
160
+ - [Effects](../../concepts/effects.md)
161
+ - [Run a command or call a URL with an Effect](../../guides/run-a-command-or-call-a-url.md)
162
+ - [ADR-0067: An Effect is an actor slot, and runs at most once unless marked idempotent](../decisions/0067-an-effect-is-an-actor-slot-and-runs-at-most-once-unless-marked-idempotent.md)
163
+ - [ADR-0068: An Effector holds an Effect's secrets and signs its wire](../decisions/0068-an-effector-holds-an-effects-secrets-and-signs-its-wire.md)
164
+
165
+ ## Overload 2
166
+
167
+ ```ts
168
+ function command<
169
+ const Opt extends CommandOptions = CommandOptions,
170
+ >(
171
+ argv: typeof open,
172
+ options?: Opt,
173
+ ): EffectLogic<OpenCommandInput<Opt["pin"]>, CommandOutput> & OpenEffect<"argv" | EnvOpenParts<Opt>>
174
+ ```
175
+
176
+ Make a `command` Effect whose argv is Open: `command(open, options)`, in a Machine that you
177
+ publish as a package. The Instance that registers the Machine binds the argv one time:
178
+ `customize(machine, { effects: { <slot>: { argv } } })`. `command` tells the rest, and
179
+ what it refuses.
180
+
181
+ **Parameters**
182
+
183
+ - `argv`: `open`.
184
+ - `options` ([`CommandOptions`](type-commandoptions.md)): Optional. The same options as for a written argv.
185
+
186
+ **Returns**: The actor logic of the Effect's slot. Its output is a `CommandOutput`.
187
+
188
+ **See also**
189
+
190
+ - [Bind a shipped Machine's Open parts](../../guides/bind-open-parts.md)
191
+ - [ADR-0054: The kit ships Machines, and a shipped Machine leaves its parts Open](../decisions/0054-the-kit-ships-machines-and-a-shipped-machine-leaves-its-parts-open.md)
@@ -0,0 +1,64 @@
1
+ ---
2
+ title: customize
3
+ description: Retune the parts that a Machine carries, without a change to the module that exports it.
4
+ ---
5
+
6
+ # `customize`
7
+
8
+ Function, in `@jr2/orchestrator/src/customize.ts`. It is an export of `@jr2/orchestrator`, on the [Authoring surface](../authoring-surface.md) page, in Composition.
9
+
10
+ ```ts
11
+ function customize<M extends AnyStateMachine>(machine: M, parts: Customize<M>): M
12
+ ```
13
+
14
+ Retune the parts that a Machine carries, without a change to the module that exports it. Use it
15
+ where you register a Machine as a Workflow. It binds the parts that a packaged Machine leaves
16
+ Open: its Repo Slots, an Agent's model, or an Effect's url, argv or secret. It also changes the
17
+ parts that its author fixed: an Agent's instructions, the Sandbox Image, or the Size.
18
+
19
+ It gives back a new Machine of the same type. The original does not change, so two
20
+ `customize()` calls on one import give two Machines. Only the parts the Machine declares can be
21
+ retuned. You cannot add a part: a Machine that needs another Agent is a new Machine. The types
22
+ refuse most mistakes when you compile. At run time, `customize()` also throws:
23
+
24
+ - `customize(): machine "<id>" carries no Agent slot "<slot>" — its Agents are: <slots>`
25
+ - `customize(): machine "<id>" composes no Machine under "<slot>" — the Machines it composes are: <slots>`
26
+ - `customize(): machine "<id>" carries no Effect slot "<slot>" — its Effects are: <slots>`
27
+ - `customize(): machine "<id>" declares no Repo Slot "<slot>" — its slots are: <slots>`
28
+ - `customize(): machine "<id>" declares its Repo Slots open as a map — name at least one`
29
+ - `` customize(): `repos` say what a SANDBOX is made of, how big it is and which Repos it
30
+ attaches, and machine "<id>" composes none `` (for `resources`, the text starts
31
+ `` customize(): `resources` ``; for `image` or `user`, it starts `` customize(): `image`/`user` ``)
32
+ - `customize(): machine "<id>": <errors>`, when an Effect argv that you bind fails the checks
33
+ that the Machine passed when it was built
34
+ - the refusals of [`EffectBinding`](type-effectbinding.md), [`RepoSlot`](type-reposlot.md), [`Size`](type-size.md) and
35
+ [`UserContainer`](type-usercontainer.md), which start with `customize()`
36
+
37
+ **Parameters**
38
+
39
+ - `machine`: The Machine to retune: one you import from a package, or one you wrote. When
40
+ its root is a `workspace()` or a `pool()`, `customize()` reaches through to the Machine inside,
41
+ so you never name the wrapper's own slot.
42
+ - `parts`: The parts to change. See [`Customize`](type-customize.md).
43
+
44
+ **Returns**: A new Machine of the same type, with the parts changed.
45
+
46
+ **Example**
47
+
48
+ ```ts
49
+ import { customize } from "@jr2/orchestrator";
50
+ import { task } from "@jr2/machines";
51
+
52
+ export const machine = customize(task, {
53
+ repos: { app: { url: "https://github.com/you/app.git" } },
54
+ agents: { coder: { model: "anthropic/claude-haiku-5-5" } },
55
+ resources: { limits: { memory: "4Gi" } },
56
+ });
57
+ ```
58
+
59
+ **See also**
60
+
61
+ - [Bind a shipped Machine's Open parts](../../guides/bind-open-parts.md)
62
+ - [Composition](../../concepts/composition.md)
63
+ - [ADR-0049: A Machine carries its parts and composes by invoke](../decisions/0049-a-machine-carries-its-parts-and-composes-by-invoke.md)
64
+ - [ADR-0054: The kit ships Machines, and a shipped Machine leaves its parts Open](../decisions/0054-the-kit-ships-machines-and-a-shipped-machine-leaves-its-parts-open.md)
@@ -0,0 +1,41 @@
1
+ ---
2
+ title: defineConfig
3
+ description: "Declare the config of an Instance: the default export of `jr2.config.ts`."
4
+ ---
5
+
6
+ # `defineConfig`
7
+
8
+ Function, in `@jr2/orchestrator/src/config.ts`. It is an export of `@jr2/orchestrator`, on the [Authoring surface](../authoring-surface.md) page, in Config.
9
+
10
+ ```ts
11
+ function defineConfig(c: JR2Config): JR2Config
12
+ ```
13
+
14
+ Declare the config of an Instance: the default export of `jr2.config.ts`. It gives back the
15
+ object that you pass. Its only work is to check that object against [`JR2Config`](type-jr2config.md) where you
16
+ write it, at every depth, a misspelled key included. `jr2 up` typechecks the file before it
17
+ converges.
18
+
19
+ **Parameters**
20
+
21
+ - `c`: The Instance's config. See [`JR2Config`](type-jr2config.md) for every field.
22
+
23
+ **Returns**: The same object.
24
+
25
+ **Example**
26
+
27
+ ```ts
28
+ import { defineConfig } from "@jr2/orchestrator";
29
+
30
+ export default defineConfig({
31
+ name: "my-instance",
32
+ secrets: [{ name: "ANTHROPIC_API_KEY", value: process.env.ANTHROPIC_API_KEY }],
33
+ git: { credentials: [{ match: "github.com/you/", token: "GITHUB_TOKEN" }] },
34
+ });
35
+ ```
36
+
37
+ **See also**
38
+
39
+ - [jr2.config.ts](../config.md)
40
+ - [Create an Instance](../../get-started/create-an-instance.md)
41
+ - [ADR-0050: What code names, config declares; what the CLI names, discovery finds](../decisions/0050-what-code-names-config-declares-what-the-cli-names-discovery-finds.md)
@@ -0,0 +1,114 @@
1
+ ---
2
+ title: defineEvent
3
+ description: "Define one workflow event: an event that an Agent or the caller of a Gate may send into your Machine."
4
+ ---
5
+
6
+ # `defineEvent`
7
+
8
+ Function, in `src/define-event.ts` of `@jr2/agent-protocol`, a dependency of `@jr2/orchestrator`. It is an export of `@jr2/orchestrator`, on the [Authoring surface](../authoring-surface.md) page, in Machine and events.
9
+
10
+ ```ts
11
+ function defineEvent<const Name extends string, Input extends z.ZodObject>(def: {
12
+ name: Name;
13
+ description?: string;
14
+ input: Input;
15
+ semantics?: EventSemantics;
16
+ audience?: EventAudience;
17
+ }): EventDef<Name, Input>
18
+ ```
19
+
20
+ Define one workflow event: an event that an Agent or the caller of a Gate may send into your
21
+ Machine. Give the result to `jr2Setup({ events })`, and write its name as an `on` key on the
22
+ states that take it. An Agent sees each event it may send as one tool on its Menu.
23
+
24
+ It gives back a frozen [`EventDef`](type-eventdef.md) and registers nothing. Each Machine whose `jr2Setup`
25
+ lists the event takes it. A Machine that does not list it does not take it.
26
+
27
+ Give an event only the params that the Machine reads. When a pick enters a state that invokes an
28
+ Effect, `createMachine` refuses each param of the pick that nothing reads: the input of the
29
+ Effect, an `assign`, or the `fill` of `fromPick`. The compiler does not find this error.
30
+ `jr2 check` and `jr2 up` find it when they load the module. Thus when you copy a `finish` event with a `summary`
31
+ and nothing uses the summary, drop `summary` from the `input`, or store it with `assign`.
32
+
33
+ It refuses:
34
+ - a name with a character other than a letter, a digit, `_` or `-`:
35
+ `defineEvent: invalid name "<name>" — must match /^[a-zA-Z0-9_-]+$/ (it becomes an MCP tool
36
+ name and an xstate event type)`
37
+ - an `input` with a `sender` field:
38
+ ``defineEvent: "<name>" declares `sender` in its input — the Orchestrator writes that field
39
+ on every delivered event (who sent it); name the payload field something else``
40
+ - an `output` field:
41
+ ``defineEvent: "<name>" declares an `output`, which is retired — every pick is answered when
42
+ the work it started is done, and the answer is the Machine's, not the def's``. With
43
+ `semantics: "deferred"`, the text says ``declares `deferred` `` in place of
44
+ ``declares an `output` ``.
45
+
46
+ **Parameters**
47
+
48
+ - `def`: The event: its `name`, its `input` schema, and optionally its `description`,
49
+ `semantics` and `audience`.
50
+
51
+ - `name`: `Name`
52
+
53
+ The event's name: the `on` key that takes it, and the name of its tool on the Agent's Menu.
54
+ Letters, digits, `_` and `-` only.
55
+ - `description` (optional): `string`
56
+
57
+ What the event means, and when to send it. An Agent's model reads it as the tool's
58
+ description. Make it true at every state that takes the event.
59
+ - `input`: `Input`
60
+
61
+ The schema of the payload: a flat `z.object`. Use `z.object({})` for an event with no
62
+ payload. Do not name a field `sender`: jr2 writes that field.
63
+ - `semantics` (optional): [`EventSemantics`](type-eventsemantics.md)
64
+
65
+ How the sender gets its answer. Default: `"ack"`, the only value `createMachine` accepts.
66
+ - `audience` (optional): [`EventAudience`](type-eventaudience.md)
67
+
68
+ Who may send the event: `"agent"`, `"external"` or `"any"`. Default: unset, and the state of
69
+ each `on` key decides (see [`EventAudience`](type-eventaudience.md)).
70
+
71
+ **Returns**: The event, as plain data to list in `jr2Setup({ events })`.
72
+
73
+ **Example**
74
+
75
+ ```ts
76
+ import { z } from "zod";
77
+ import { agent, defineEvent, fail, jr2Setup } from "@jr2/orchestrator";
78
+
79
+ const done = defineEvent({
80
+ name: "done",
81
+ description: "Call this when the summary is written.",
82
+ input: z.object({ summary: z.string() }),
83
+ });
84
+
85
+ export const machine = jr2Setup({
86
+ events: [done],
87
+ actors: {
88
+ writer: agent({
89
+ model: "anthropic/claude-haiku-5-5",
90
+ instructions: "You write short summaries.",
91
+ workspace: "none",
92
+ }),
93
+ fail: fail(),
94
+ },
95
+ }).createMachine({
96
+ id: "summary",
97
+ on: { "agent.fault": ".failed" },
98
+ initial: "writing",
99
+ states: {
100
+ writing: {
101
+ invoke: { src: "writer", input: { prompt: "Summarize the release notes in one line." } },
102
+ on: { done: "finished" },
103
+ },
104
+ finished: { type: "final" },
105
+ failed: { invoke: { src: "fail", input: { reason: "the Agent's Turn could not go on" } } },
106
+ },
107
+ });
108
+ ```
109
+
110
+ **See also**
111
+
112
+ - [Write a Workflow](../../guides/write-a-workflow.md)
113
+ - [The Menu](../../concepts/the-menu.md)
114
+ - [ADR-0011: Control events are workflow-defined and delivered by closure, not routed](../decisions/0011-workflow-defined-events.md)
@@ -0,0 +1,126 @@
1
+ ---
2
+ title: dispatch
3
+ description: "Make a `dispatch` Effect: it starts a run of a Workflow."
4
+ ---
5
+
6
+ # `dispatch`
7
+
8
+ Function, in `@jr2/orchestrator/src/dispatch-effect.ts`. It is an export of `@jr2/orchestrator`, on the [Authoring surface](../authoring-surface.md) page, in Effects.
9
+
10
+ ```ts
11
+ function dispatch<
12
+ S extends z.ZodObject | undefined = undefined,
13
+ const T extends DispatchDefinition<S>["target"] = undefined,
14
+ >(
15
+ workflow: string,
16
+ def?: DispatchDefinition<S> & { target?: T },
17
+ ): EffectLogic<DispatchInput<S>, DispatchOutput> & OpenOf<DispatchOpenParts<T>>
18
+ ```
19
+
20
+ Make a `dispatch` Effect: it starts a run of a Workflow. Put it in `actors`, and invoke it from a
21
+ state: `actors: { triage: dispatch("triage", { input }) }`. The input of the invoke is the run
22
+ input of the new run, as `jr2 run --input` gives it.
23
+
24
+ The new run is a run of its own, with its own id, its own Workspaces and its own `CANCEL`. Its
25
+ record names this run as the run that dispatched it. A `CANCEL` of this run does not end it.
26
+
27
+ With no `target`, the run starts in this Orchestrator, under the current Assembly. With
28
+ `target: { url, token }`, it starts on the Orchestrator at `url`, and the Effect runs in the
29
+ Instance Effector. Every outcome is output ([`DispatchOutput`](type-dispatchoutput.md)): `started`, `settled`,
30
+ `refused`, `unreachable` or `unknown`. Each start carries a key, so a start that jr2 sends again
31
+ after a restart starts no second run.
32
+
33
+ It refuses:
34
+ - a name that is not a Workflow name: ``dispatch("<name>"): the Workflow is named as `jr2 run`
35
+ names it — a Machine's filename stem ("review"), or "<wrapper>/<name>" for a named Chart:
36
+ lowercase letters, digits and "-" (ADR-0071)``
37
+ - a `wait` that is not a boolean: `dispatch("<name>", { wait }): wait is true or false — a slot
38
+ that needs both declares two`
39
+ - an `input` that is not a `z.object()`: `dispatch("<name>", { input }): the input is a
40
+ z.object(...) — the run's body is a JSON object (ADR-0071)`
41
+ - a `timeout` that is not a duration: `dispatch("<name>"): timeout "<timeout>" is not a positive
42
+ duration (like "30s", "10m", "1h")`
43
+ - a `target` url that is not an origin: `dispatch("<name>", { target }): "<url>" is not an
44
+ origin — write the scheme and the host, with a port if it is not the scheme's, and no path,
45
+ query or userinfo`, then two examples
46
+ - `secret(open)` in a target: `dispatch("<name>", { target }): secret(open) in a target — the
47
+ target is the Open part, not its secret`, then the fix
48
+
49
+ `jr2 up` refuses a dispatch with no target whose Workflow the Assembly does not have, and an
50
+ `input` schema that the input of that Workflow does not take.
51
+
52
+ **Parameters**
53
+
54
+ - `workflow`: The Workflow to start, as `jr2 run` names it: `"triage"`, or
55
+ `"<wrapper>/<name>"` for a named Chart.
56
+ - `def`: Optional. Each field tells what it does.
57
+
58
+ - `input` (optional): `S`
59
+
60
+ A zod schema of the run input of the Workflow. It types the `input` of the invoke and
61
+ `fromPick`, and `jr2 up` compares it with the input that the Workflow declares. Without it,
62
+ only the Workflow checks the input.
63
+ - `wait` (optional): `boolean`
64
+
65
+ `true`: end when the new run ends (`settled`). `false`, the default: end when the
66
+ Orchestrator accepts the run (`started`).
67
+ - `timeout` (optional): [`Duration`](type-duration.md)
68
+
69
+ How long the Effect waits: by default 30s for the start, and 10m with `wait`.
70
+ - `target` (optional): `{ url: string; token: NamedSecret; } | typeof open`
71
+
72
+ A different Orchestrator: `url` is its origin, and `token` is the secret that holds its
73
+ Instance token. Or `open`, which the composer binds with `customize(<import>, { effects: {
74
+ <slot>: { target: { url, token } } } })`. Without it, the run starts in this Orchestrator.
75
+
76
+ **Returns**: An Effect, for `actors`.
77
+
78
+ **Example**
79
+
80
+ ```ts
81
+ import { assign } from "xstate";
82
+ import { z } from "zod";
83
+ import { defineEvent, dispatch, jr2Setup } from "@jr2/orchestrator";
84
+
85
+ const triageInput = z.object({ request: z.string() });
86
+
87
+ const report = defineEvent({
88
+ name: "report",
89
+ description: "Report a request. A run of triage starts for it.",
90
+ input: triageInput,
91
+ });
92
+
93
+ export const machine = jr2Setup({
94
+ types: {} as { context: { request: string } },
95
+ events: [report],
96
+ // `wait: true`: the Effect ends when the run of triage ends.
97
+ actors: { triage: dispatch("triage", { input: triageInput, wait: true }) },
98
+ }).createMachine({
99
+ id: "intake",
100
+ context: { request: "" },
101
+ initial: "listening",
102
+ states: {
103
+ listening: {
104
+ invoke: { src: "gate" },
105
+ on: { report: { target: "starting", actions: assign({ request: ({ event }) => event.request }) } },
106
+ },
107
+ starting: {
108
+ invoke: {
109
+ src: "triage",
110
+ input: ({ context }) => ({ request: context.request }),
111
+ onDone: [
112
+ { guard: ({ event }) => event.output.outcome === "settled", target: "done" },
113
+ { target: "listening" },
114
+ ],
115
+ },
116
+ },
117
+ done: { type: "final" },
118
+ },
119
+ });
120
+ ```
121
+
122
+ **See also**
123
+
124
+ - [Start a run from a run](../../guides/start-a-run-from-a-run.md)
125
+ - [Effects](../../concepts/effects.md)
126
+ - [ADR-0071: A run starts a run through a `dispatch` Effect](../decisions/0071-a-run-starts-a-run-through-a-dispatch-effect.md)
@@ -0,0 +1,83 @@
1
+ ---
2
+ title: fail
3
+ description: "Fail the run: the Part a Machine invokes to end work that did not succeed."
4
+ ---
5
+
6
+ # `fail`
7
+
8
+ Function, in `@jr2/orchestrator/src/fail.ts`. It is an export of `@jr2/orchestrator`, on the [Authoring surface](../authoring-surface.md) page, in Failure.
9
+
10
+ ```ts
11
+ function fail(): FailSlot
12
+ ```
13
+
14
+ Fail the run: the Part a Machine invokes to end work that did not succeed. Put it in `actors`
15
+ under a name, and invoke it from any state, at any depth: `actors: { fail: fail() }`, then
16
+ `invoke: { src: "fail", input: { reason } }`.
17
+
18
+ The input is `{ reason: string; detail?: unknown }`. `reason` is text for a person, and it must
19
+ not be empty. `detail` is optional JSON for a machine reader.
20
+
21
+ The Failure goes up from the state that invokes `fail`, through each parent Machine, as an error
22
+ does. An `onError` on the way catches it; [`isFailure`](isfailure.md) tells it from a defect. When no state
23
+ catches it, the run ends `failed`: its output is `{ reason, detail }`, and `jr2 run` exits 1. A
24
+ `workspace()` that a Failure goes through deletes its Sandbox first.
25
+
26
+ To fail, invoke `fail`. Do not throw from a promise to fail: a throw is a defect, and the run
27
+ ends `error`. A final state means `done`: do not use one for work that did not succeed. To keep
28
+ the work for a person to read, wait at a Gate before the state that fails.
29
+
30
+ It refuses an input that is not a Failure's, and the run ends `error`: ``fail: the input must be
31
+ { reason: string; detail?: unknown } with a reason that is not empty (got <value>) — invoke:
32
+ { src: "fail", input: { reason: "the tests failed" } } (ADR-0073)``.
33
+
34
+ **Returns**: The actor logic of the slot.
35
+
36
+ **Example**
37
+
38
+ ```ts
39
+ import { z } from "zod";
40
+ import { command, fail, jr2Setup, workspace, type Workspaced } from "@jr2/orchestrator";
41
+
42
+ const runInput = z.object({ branch: z.string() });
43
+
44
+ const body = jr2Setup({
45
+ types: {} as { input: Workspaced<z.infer<typeof runInput>, "app"> },
46
+ actors: {
47
+ tests: command(["npm", "test"], { timeout: "15m" }),
48
+ fail: fail(),
49
+ },
50
+ }).createMachine({
51
+ id: "check",
52
+ on: { "workspace.lost": ".lost" },
53
+ initial: "testing",
54
+ states: {
55
+ testing: {
56
+ invoke: {
57
+ src: "tests",
58
+ onDone: [
59
+ {
60
+ guard: ({ event }) => event.output.outcome === "exited" && event.output.code === 0,
61
+ target: "passed",
62
+ },
63
+ { target: "failing" },
64
+ ],
65
+ },
66
+ },
67
+ // Not a final state: the run ends `failed`, and the Workspace deletes the Sandbox.
68
+ failing: { invoke: { src: "fail", input: { reason: "npm test did not pass" } } },
69
+ passed: { type: "final" },
70
+ lost: { invoke: { src: "fail", input: { reason: "the Sandbox is gone" } } },
71
+ },
72
+ });
73
+
74
+ export const machine = workspace(body, {
75
+ input: runInput,
76
+ repos: { app: "https://github.com/you/app.git" },
77
+ spec: ({ input }) => ({ branch: input.branch }),
78
+ });
79
+ ```
80
+
81
+ **See also**
82
+
83
+ - [ADR-0073: A Machine fails a run with `fail()`, and an uncaught Failure ends it `failed`](../decisions/0073-a-machine-fails-a-run-with-fail-and-an-uncaught-failure-ends-it-failed.md)