@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
package/src/parts.ts CHANGED
@@ -51,10 +51,13 @@ import type { AnyActorRef, AnyStateMachine, StateNode, UnknownActorLogic } from
51
51
  import { isAgent, isOpenAgent, type AgentDeclaration } from "./agent.ts";
52
52
  import { argvText, isEffect, placementOf, type EffectParts, type Placement } from "./effect.ts";
53
53
  import { effectBindingLine, openPartsOf, type OpenEffectPart } from "./open-effect.ts";
54
+ import { isFailSlot } from "./fail.ts";
54
55
  import { isImageContext } from "./images.ts";
55
56
  import { isOpenBody, openBodyDeclarationOf, type OpenBodyDeclaration } from "./open-body.ts";
56
57
  import { open } from "./open.ts";
57
58
  import { repoIdentity } from "./repo-identity.ts";
59
+ import { refuseUnroutedAgentFault } from "./mechanism-routes.ts";
60
+ import { refuseLostOutput } from "./run-output.ts";
58
61
  import { userSeatOf, type Size, type UserContainer } from "./size.ts";
59
62
 
60
63
  // --- Repo Slots (ADR-0051) ---------------------------------------------------------------------
@@ -71,15 +74,103 @@ import { userSeatOf, type Size, type UserContainer } from "./size.ts";
71
74
  // meets it first, and `import { open } from "@jr2/orchestrator"` is the only spelling anyone writes.
72
75
  export { open } from "./open.ts";
73
76
 
74
- /** What a Repo Slot resolves to (GLOSSARY.md "Binding"): the url, and the base the branch
75
- * Worktree is cut from — absent, the Repo's own default branch. */
76
- export type Binding = { url: string; ref?: string };
77
+ /**
78
+ * The repository of a Repo Slot: `{ url, ref }`. `url` is the Repo's git url. `ref` is the branch
79
+ * or commit that the branch Worktree starts from; absent, the Repo's default branch. Where only a
80
+ * url is needed, a string is enough.
81
+ *
82
+ * `workspace()` and `customize()` refuse:
83
+ * - an empty `url`: ``<where>: Repo Slot "<slot>" is bound to an empty url (got <value>) — a slot
84
+ * is `open`, a url, `{ url, ref? }`, or a mapper `({ input }) => url | { url, ref? }` over the
85
+ * door (ADR-0051).``
86
+ * - an empty `ref`: the same text, with `bound with an empty ref` in place of `bound to an empty
87
+ * url`.
88
+ * - a url that names no Repo, such as a relative path: ``<where>: Repo Slot "<slot>" binds
89
+ * "<url>", which names no Repo — <reason> (ADR-0051).``
90
+ *
91
+ * @example
92
+ * ```ts
93
+ * import { jr2Setup, workspace, type Binding } from "@jr2/orchestrator";
94
+ *
95
+ * const app: Binding = { url: "https://github.com/you/app.git", ref: "release-2" };
96
+ *
97
+ * const body = jr2Setup().createMachine({
98
+ * id: "body",
99
+ * initial: "done",
100
+ * states: { done: { type: "final" } },
101
+ * });
102
+ *
103
+ * export const machine = workspace(body, {
104
+ * repos: { app },
105
+ * spec: () => ({ branch: "jr2/hotfix" }),
106
+ * });
107
+ * ```
108
+ *
109
+ * @see docs/concepts/workspaces.md
110
+ * @see docs/reference/decisions/0051-a-repo-is-a-slot-on-the-workspace-and-a-cache-on-the-node.md
111
+ */
112
+ // What a Repo Slot resolves to (GLOSSARY.md "Binding").
113
+ export type Binding = {
114
+ /** The Repo's git url. */
115
+ url: string;
116
+ /** The branch or commit that the branch Worktree starts from. Default: the Repo's default
117
+ * branch. */
118
+ ref?: string;
119
+ };
77
120
 
121
+ // Bound and open are what `jr2 up` can see; per-run is the run's business, fenced at attach by
122
+ // `git.credentials` (ADR-0051).
78
123
  /**
79
- * One Repo Slot's value: BOUND (a url, or `{ url, ref? }`), OPEN (the {@link open} sentinel —
80
- * someone downstream binds it), or PER-RUN (a mapper over the wrapper's door, so a run input — a
81
- * ticket field — decides). Bound and open are what `jr2 up` can see; per-run is the run's business,
82
- * fenced at attach by `git.credentials` (ADR-0051).
124
+ * The value of one Repo Slot in `workspace({ repos })`. One of:
125
+ * - a url, or a {@link Binding} `{ url, ref }`: the Machine names the Repo.
126
+ * - {@link open}: the Instance that registers the Machine binds it with `customize()`. `jr2 up`
127
+ * refuses a Workflow that leaves it open: ``refusing: workflow "<name>" leaves Repo Slot
128
+ * "<slot>" open — bind it where the Machine is registered: export const machine =
129
+ * customize(<import>, …) (ADR-0051)``, with the whole `customize` line to paste.
130
+ * - a function of the run input, `({ input }) => url` or a {@link Binding}: each run chooses. The
131
+ * url must match an entry of `git.credentials` in `jr2.config.ts`, or the run cannot use it.
132
+ *
133
+ * The key of the slot is a directory name under `/work`. It starts with a letter, and
134
+ * `workspace()` and `customize()` refuse a key that does not: ``<where>: Repo Slot key "<key>" is
135
+ * not a directory name — a slot becomes `/work/<slot>` and its order matters, so it starts with a
136
+ * letter and matches /^[A-Za-z][A-Za-z0-9._-]*$/ (ADR-0051).`` They refuse a value of another
137
+ * shape: ``<where>: Repo Slot "<slot>" is <what> — a slot is `open`, a url, `{ url, ref? }`, or a
138
+ * mapper `({ input }) => url | { url, ref? }` over the door (ADR-0051).``
139
+ *
140
+ * @example
141
+ * ```ts
142
+ * import { z } from "zod";
143
+ * import { jr2Setup, open, workspace, type RepoSlot, type Workspaced } from "@jr2/orchestrator";
144
+ *
145
+ * const runInput = z.object({ service: z.string() });
146
+ * type RunInput = z.infer<typeof runInput>;
147
+ *
148
+ * const service: RepoSlot<RunInput> = ({ input }) => `https://github.com/you/${input.service}.git`;
149
+ *
150
+ * const body = jr2Setup({
151
+ * types: {} as { input: Workspaced<RunInput, "service" | "docs" | "config"> },
152
+ * }).createMachine({
153
+ * id: "body",
154
+ * initial: "done",
155
+ * states: { done: { type: "final" } },
156
+ * });
157
+ *
158
+ * // A Machine for a package: the Instance that registers it binds `config`.
159
+ * export const deploy = workspace(body, {
160
+ * input: runInput,
161
+ * repos: {
162
+ * service,
163
+ * docs: "https://github.com/you/docs.git",
164
+ * config: open,
165
+ * },
166
+ * spec: ({ input }) => ({ branch: `deploy/${input.service}` }),
167
+ * });
168
+ * ```
169
+ *
170
+ * @see docs/concepts/workspaces.md
171
+ * @see docs/guides/bind-open-parts.md
172
+ * @see docs/guides/give-the-cluster-git-credentials.md
173
+ * @see docs/reference/decisions/0051-a-repo-is-a-slot-on-the-workspace-and-a-cache-on-the-node.md
83
174
  */
84
175
  export type RepoSlot<TInput = unknown> =
85
176
  | typeof open
@@ -199,8 +290,8 @@ export function sandboxPartsOf(machine: AnyStateMachine | undefined): SandboxPar
199
290
 
200
291
  /** Does this Machine COMPOSE a Sandbox — i.e. is it a `workspace()` wrapper? Distinct from
201
292
  * `sandboxPartsOf(m)` naming no image: a wrapper that names neither image still owns the two
202
- * seats, which is what `customize({ image })` retunes (ADR-0049) — and it always carries at least
203
- * one Repo Slot (ADR-0051). Also the data-plane switch, read off the walk: an Instance needs
293
+ * seats, which is what `customize({ image })` retunes (ADR-0049) — and it may carry no Repo Slot
294
+ * at all (ADR-0051). Also the data-plane switch, read off the walk: an Instance needs
204
295
  * Sandboxes exactly when a registered Machine composes one. A logic with no `config` (an Effect's,
205
296
  * ADR-0067) composes none. */
206
297
  export function composesSandbox(machine: AnyStateMachine): boolean {
@@ -492,11 +583,34 @@ export type CarriedEffect = {
492
583
  /** A push (ADR-0067, ADR-0051): the Workspace's branch to its Repo Slot's Binding. It names no
493
584
  * secret: `jr2 up` resolves its credential through `git.credentials`. */
494
585
  | { kind: "push"; slot?: string; sign: boolean; squash: boolean; force: boolean; pin: boolean; secrets: string[] }
586
+ /** A dispatch (ADR-0071): the Workflow it starts a run of, as `jr2 run` names it, whether it
587
+ * waits, and — toward another Orchestrator — the target's origin as an http target and its
588
+ * token as the one secret (placed in the Instance Effector beside the http Effects). No target:
589
+ * it runs in the Orchestrator's own process and names no secret. `input`: the slot's input
590
+ * schema as JSON Schema, what the walk compares with the callee's door; absent, the door alone
591
+ * checks. An Open target has no target and no secret yet. */
592
+ | {
593
+ kind: "dispatch";
594
+ workflow: string;
595
+ wait: boolean;
596
+ target?: { scheme: "http" | "https"; host: string; port: number };
597
+ secrets: string[];
598
+ input?: Record<string, unknown>;
599
+ open?: Array<"target">;
600
+ }
495
601
  );
496
602
 
603
+ /** One state that can fail the run (ADR-0073): it invokes a `fail()` slot. `state` is the state's
604
+ * id, `machine` the id of its Machine, `slot` the slot key it invokes, and `path` the `customize()`
605
+ * route to its Machine, as an {@link OpenSlot}'s. Static, as a Gate or an Effect is: the walk reads
606
+ * it, and `jr2 up`, `jr2 check` and the Machine doc list it. */
607
+ export type CarriedFailure = { machine: string; state: string; slot: string; path: OpenSlot["path"] };
608
+
497
609
  /** Everything the registered Machines carry that a converge or a boot must act on. */
498
610
  export type CarriedParts = {
499
611
  agents: CarriedAgent[];
612
+ /** Every state that invokes a `fail()` slot (ADR-0073), in walk order, nested Machines too. */
613
+ failures: CarriedFailure[];
500
614
  /** Every Effect slot, in walk order — one per Machine and slot key, at the first route the walk
501
615
  * reached its Machine by. The placement reads {@link placedEffectsOf}: one per route. */
502
616
  effects: CarriedEffect[];
@@ -556,17 +670,18 @@ function inlineMachines(node: StateNode<any, any>): Array<{ machine: AnyStateMac
556
670
  }
557
671
 
558
672
  /**
559
- * Refuse a Part written inline on an `invoke.src` — an `agent()`, an Effect or a `workspace()` that
673
+ * Refuse a Part written inline on an `invoke.src` — an `agent()`, an Effect, a `fail()` or a `workspace()` that
560
674
  * is no key of the Machine's `actors` (see the module comment). Thrown at build by
561
675
  * `jr2Setup.createMachine` and at load by {@link partsOf}, so a Machine built with xstate's own
562
- * `createMachine` is refused where `jr2 up` and the Orchestrator read it. A plain child Machine
563
- * written inline is not a Part: it stays walked, with no `customize()` route (its `path` is
564
- * `undefined`).
676
+ * `createMachine` is refused where `jr2 check`, `jr2 up` and the Orchestrator read it. A plain
677
+ * child Machine written inline is not a Part: it stays walked, with no `customize()` route (its
678
+ * `path` is `undefined`).
565
679
  */
566
680
  export function refuseInlineParts(machine: AnyStateMachine): void {
567
681
  const partOf = (src: unknown): { part: string; written: string } | undefined => {
568
682
  if (isAgent(src)) return { part: "an Agent", written: "agent(...)" };
569
683
  if (isEffect(src)) return { part: "an Effect", written: `${src.effect.kind}(...)` };
684
+ if (isFailSlot(src)) return { part: "a fail() Part", written: "fail()" };
570
685
  const child = asMachine(src);
571
686
  if (child && composesSandbox(child)) return { part: "a Workspace", written: "workspace(...)" };
572
687
  return undefined;
@@ -615,6 +730,7 @@ function canonical(value: unknown): string {
615
730
  */
616
731
  export function partsOf(machines: Iterable<AnyStateMachine>): CarriedParts {
617
732
  const agents: CarriedAgent[] = [];
733
+ const failures: CarriedFailure[] = [];
618
734
  const effects: CarriedEffect[] = [];
619
735
  const images: CarriedImage[] = [];
620
736
  const repos: CarriedRepo[] = [];
@@ -690,6 +806,8 @@ export function partsOf(machines: Iterable<AnyStateMachine>): CarriedParts {
690
806
  if (walked.has(machine)) return;
691
807
  walked.add(machine);
692
808
  refuseInlineParts(machine);
809
+ refuseLostOutput(machine);
810
+ refuseUnroutedAgentFault(machine);
693
811
  const parts = sandboxPartsOf(machine);
694
812
  const user = userSeatOf(parts.user);
695
813
  collectImage(parts.image);
@@ -706,6 +824,7 @@ export function partsOf(machines: Iterable<AnyStateMachine>): CarriedParts {
706
824
  });
707
825
  }
708
826
  const body = wrapperBodyOf(machine);
827
+ for (const { state, slot } of failingStatesOf(machine)) failures.push({ machine: machine.id, state, slot, path });
709
828
  for (const [name, logic] of Object.entries(machine.implementations.actors as Record<string, unknown>)) {
710
829
  if (isAgent(logic)) collectAgent(path, name, logic.definition);
711
830
  else if (isOpenBody(logic)) {
@@ -735,6 +854,7 @@ export function partsOf(machines: Iterable<AnyStateMachine>): CarriedParts {
735
854
  for (const body of noneBodies) for (const m of body.declaration.allows.models) harnessModels.add(m);
736
855
  return {
737
856
  agents,
857
+ failures,
738
858
  effects,
739
859
  images,
740
860
  repos,
@@ -817,6 +937,23 @@ export function carriedEffectOf(
817
937
  ): CarriedEffect {
818
938
  const placement = placementOf(parts);
819
939
  const openParts = openPartsOf(parts);
940
+ if (parts.kind === "dispatch") {
941
+ const input = (parts as { [DISPATCH_INPUT]?: Record<string, unknown> })[DISPATCH_INPUT];
942
+ return {
943
+ name,
944
+ path,
945
+ route,
946
+ kind: "dispatch",
947
+ placement,
948
+ workflow: parts.workflow,
949
+ wait: parts.wait,
950
+ timeoutMs: parts.timeoutMs,
951
+ ...(parts.target === undefined || parts.target === open ? {} : { target: originTarget(parts.target.url) }),
952
+ secrets: [...parts.secrets],
953
+ ...(input !== undefined ? { input } : {}),
954
+ ...(openParts.length ? { open: openParts as Array<"target"> } : {}),
955
+ };
956
+ }
820
957
  if (parts.kind === "http") {
821
958
  return {
822
959
  name,
@@ -867,6 +1004,20 @@ export function carriedEffectOf(
867
1004
  };
868
1005
  }
869
1006
 
1007
+ /** The key a dispatch's slot schema rides its parts under (dispatch-effect.ts): `Symbol.for`, so this
1008
+ * walk reads it off a Machine built by another copy of the module (ADR-0071). */
1009
+ const DISPATCH_INPUT = Symbol.for("jr2.dispatch.input");
1010
+
1011
+ /** A dispatch target's origin as the Effector's fence reads an http target: scheme, host, port. The
1012
+ * origin was checked when the slot was built, so it parses. */
1013
+ function originTarget(url: string): { scheme: "http" | "https"; host: string; port: number } {
1014
+ const u = new URL(url);
1015
+ const scheme = u.protocol === "http:" ? "http" : "https";
1016
+ // As an http target's: brackets off an IPv6 literal, lower case (http-effect.ts `targetOf`).
1017
+ const host = u.hostname.replace(/^\[|\]$/g, "").toLowerCase();
1018
+ return { scheme, host, port: u.port ? Number(u.port) : scheme === "http" ? 80 : 443 };
1019
+ }
1020
+
870
1021
  /**
871
1022
  * One Workspace a Machine composes, as its pod's Held secrets are placed (ADR-0059): what the pod
872
1023
  * names. Located like a {@link CarriedSize} — `path` is the `customize()` route to its
@@ -896,6 +1047,9 @@ export type WorkspacePod = {
896
1047
  /** Each Repo Slot's Binding url as the Machine binds it, by slot, in order; undefined for an open
897
1048
  * or per-run slot, whose url `jr2 up` cannot read. A push resolves its credential through it. */
898
1049
  bindings: Record<string, string | undefined>;
1050
+ /** The `workspace()` declares no Repo Slot (ADR-0051): it has only `/work`, which its steps
1051
+ * share. Absent for one with slots, and for an Open map, whose slots the composer names. */
1052
+ noSlot?: true;
899
1053
  };
900
1054
 
901
1055
  /**
@@ -976,6 +1130,7 @@ export function workspacePodsOf(root: AnyStateMachine): WorkspacePod[] {
976
1130
  ...(parts.effector ? { effector: { ...parts.effector } } : {}),
977
1131
  ...(parts.image !== undefined ? { image: parts.image } : {}),
978
1132
  bindings,
1133
+ ...(parts.repos !== open && Object.keys(parts.repos).length === 0 ? { noSlot: true as const } : {}),
979
1134
  });
980
1135
  }
981
1136
  const body = wrapperBodyOf(machine);
@@ -990,6 +1145,22 @@ export function workspacePodsOf(root: AnyStateMachine): WorkspacePod[] {
990
1145
  return pods;
991
1146
  }
992
1147
 
1148
+ /** Every state of `machine`'s own tree that invokes a `fail()` slot (ADR-0073), in document order,
1149
+ * with the slot key: a state that can fail the run. A child Machine's states are its own walk's. */
1150
+ export function failingStatesOf(machine: AnyStateMachine): Array<{ state: string; slot: string }> {
1151
+ const actors = machine.implementations.actors as Record<string, unknown>;
1152
+ const out: Array<{ state: string; slot: string }> = [];
1153
+ const visit = (node: StateNode<any, any>): void => {
1154
+ for (const inv of node.invoke) {
1155
+ if (typeof inv.src === "string" && isFailSlot(actors[inv.src])) out.push({ state: node.id, slot: inv.src });
1156
+ }
1157
+ const children = Object.values(node.states as Record<string, StateNode<any, any>>);
1158
+ for (const child of children.sort((a, b) => a.order - b.order)) visit(child);
1159
+ };
1160
+ visit(machine.root);
1161
+ return out;
1162
+ }
1163
+
993
1164
  /** Every machine object written inline below `node`, at any depth of its state tree, with its hop. */
994
1165
  function walkStates(node: StateNode<any, any>, visit: (machine: AnyStateMachine, hop: RouteHop) => void): void {
995
1166
  for (const { machine, hop } of inlineMachines(node)) visit(machine, hop);
package/src/party.ts CHANGED
@@ -24,9 +24,75 @@ import { vocabularyOf } from "./vocabulary.ts";
24
24
  /** The guard type `sentBy` names: dotted, so no author guard can take the name. */
25
25
  export const SENT_BY = "jr2.sentBy";
26
26
 
27
- /** A writing runs for this party's events, and for the Machine's own: `guard: sentBy("coder")`. The
28
- * id is an Agent slot, or a Gate's invoke id, of this Machine — an unknown id is refused at load. */
27
+ /**
28
+ * A guard that is true for an event that one party sent, and false for an event that another party
29
+ * sent: `guard: sentBy("coder")`. Use it where two parties may send the same event to one state,
30
+ * and the transition must run for one of them only. It is also true for an event that the Machine
31
+ * sends itself, which has no sender.
32
+ *
33
+ * It can only make a transition decline the events of other parties. It never lets a party send
34
+ * an event that the party may not send at that state: the position of the `on` key decides that.
35
+ * When the guard is false, xstate tries the next transition for the event, as for any guard. Use
36
+ * it alone, or inside `and([…])`.
37
+ *
38
+ * `createMachine` refuses an id that is not a party of the Machine: ``machine "<id>":
39
+ * sentBy("<party>") on "<event>" at "<state>" names no party of this Machine (Agent slots:
40
+ * <slots>; Gate invoke ids: <ids>)``
41
+ *
42
+ * @param id - The party: the slot key of an Agent of this Machine, or the invoke `id` of one of its
43
+ * Gates.
44
+ * @returns A named guard object, for a transition's `guard`.
45
+ *
46
+ * @example
47
+ * ```ts
48
+ * import { z } from "zod";
49
+ * import { agent, defineEvent, fail, jr2Setup, sentBy } from "@jr2/orchestrator";
50
+ *
51
+ * const done = defineEvent({
52
+ * name: "done",
53
+ * description: "Call this when the draft is ready for review.",
54
+ * input: z.object({}),
55
+ * });
56
+ *
57
+ * export const machine = jr2Setup({
58
+ * events: [done],
59
+ * actors: {
60
+ * writer: agent({
61
+ * model: "anthropic/claude-haiku-5-5",
62
+ * instructions: "You write release notes.",
63
+ * workspace: "none",
64
+ * }),
65
+ * fail: fail(),
66
+ * },
67
+ * }).createMachine({
68
+ * id: "notes",
69
+ * on: { "agent.fault": ".failed" },
70
+ * initial: "drafting",
71
+ * states: {
72
+ * drafting: {
73
+ * invoke: [
74
+ * { src: "writer", input: { prompt: "Draft the release notes." } },
75
+ * { src: "gate", id: "editor" },
76
+ * ],
77
+ * on: {
78
+ * // The writer's `done` goes to review; the editor's `done` skips it.
79
+ * done: [{ guard: sentBy("writer"), target: "review" }, { target: "published" }],
80
+ * },
81
+ * },
82
+ * review: { invoke: { src: "gate" }, on: { done: "published" } },
83
+ * published: { type: "final" },
84
+ * failed: { invoke: { src: "fail", input: { reason: "the Agent's Turn could not go on" } } },
85
+ * },
86
+ * });
87
+ * ```
88
+ *
89
+ * @see docs/concepts/the-menu.md
90
+ * @see docs/concepts/gates.md
91
+ * @see docs/reference/decisions/0015-authoring-surface-absorbs-the-mechanism.md
92
+ */
29
93
  export function sentBy<const Id extends string>(id: Id): { type: typeof SENT_BY; params: { id: Id } } {
94
+ // A NAMED guard with params, so the load walk can read it (see the module header). The id is
95
+ // refused at load by `refuseUnknownSentBy` when no Agent slot or Gate invoke id has it.
30
96
  return { type: SENT_BY, params: { id } };
31
97
  }
32
98