@jr2/orchestrator 0.4.1 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (361) 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 +478 -0
  10. package/docs/concepts/architecture.md +243 -0
  11. package/docs/concepts/charts.md +146 -0
  12. package/docs/concepts/composition.md +357 -0
  13. package/docs/concepts/converge.md +257 -0
  14. package/docs/concepts/durable-runs.md +189 -0
  15. package/docs/concepts/effects.md +658 -0
  16. package/docs/concepts/gates.md +208 -0
  17. package/docs/concepts/machines-and-workflows.md +298 -0
  18. package/docs/concepts/pools-and-sources.md +230 -0
  19. package/docs/concepts/secrets-and-trust.md +306 -0
  20. package/docs/concepts/the-menu.md +381 -0
  21. package/docs/concepts/workspaces.md +756 -0
  22. package/docs/get-started/a-model-decides.md +563 -0
  23. package/docs/get-started/an-agent-in-a-sandbox.md +383 -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 +993 -0
  27. package/docs/get-started/install.md +130 -0
  28. package/docs/guides/add-tools-to-the-sandbox.md +308 -0
  29. package/docs/guides/answer-a-gate.md +304 -0
  30. package/docs/guides/bind-open-parts.md +224 -0
  31. package/docs/guides/cancel-a-run.md +146 -0
  32. package/docs/guides/clean-up.md +206 -0
  33. package/docs/guides/cut-a-worktree.md +560 -0
  34. package/docs/guides/fix-a-failed-converge.md +361 -0
  35. package/docs/guides/give-the-cluster-git-credentials.md +222 -0
  36. package/docs/guides/iterate-on-a-machine-on-kind.md +190 -0
  37. package/docs/guides/let-an-agent-write-a-chart.md +230 -0
  38. package/docs/guides/look-inside-a-sandbox.md +177 -0
  39. package/docs/guides/mirror-the-kit-images.md +176 -0
  40. package/docs/guides/move-from-kind-to-a-shared-cluster.md +318 -0
  41. package/docs/guides/open-the-console.md +91 -0
  42. package/docs/guides/publish-a-machine-as-an-npm-package.md +350 -0
  43. package/docs/guides/push-and-sign-a-branch.md +532 -0
  44. package/docs/guides/run-a-chart-by-name.md +270 -0
  45. package/docs/guides/run-a-command-or-call-a-url.md +587 -0
  46. package/docs/guides/run-one-worker-per-item.md +322 -0
  47. package/docs/guides/set-an-agents-access-and-dials.md +420 -0
  48. package/docs/guides/size-a-workspace.md +217 -0
  49. package/docs/guides/start-a-run-from-a-run.md +237 -0
  50. package/docs/guides/start-a-run.md +207 -0
  51. package/docs/guides/upgrade-the-kit-version.md +240 -0
  52. package/docs/guides/use-a-hosted-provider.md +214 -0
  53. package/docs/guides/use-a-local-model.md +313 -0
  54. package/docs/guides/watch-a-run.md +349 -0
  55. package/docs/guides/write-a-workflow.md +318 -0
  56. package/docs/index.md +44 -0
  57. package/docs/llms.txt +237 -0
  58. package/docs/reference/authoring-surface/agent.md +151 -0
  59. package/docs/reference/authoring-surface/answer.md +156 -0
  60. package/docs/reference/authoring-surface/arg.md +82 -0
  61. package/docs/reference/authoring-surface/basic.md +62 -0
  62. package/docs/reference/authoring-surface/bearer.md +53 -0
  63. package/docs/reference/authoring-surface/branchname.md +15 -0
  64. package/docs/reference/authoring-surface/chartschema.md +23 -0
  65. package/docs/reference/authoring-surface/chartschemafor.md +48 -0
  66. package/docs/reference/authoring-surface/command.md +206 -0
  67. package/docs/reference/authoring-surface/customize.md +64 -0
  68. package/docs/reference/authoring-surface/defineconfig.md +41 -0
  69. package/docs/reference/authoring-surface/defineevent.md +114 -0
  70. package/docs/reference/authoring-surface/dispatch.md +126 -0
  71. package/docs/reference/authoring-surface/fail.md +96 -0
  72. package/docs/reference/authoring-surface/file.md +142 -0
  73. package/docs/reference/authoring-surface/frompick.md +277 -0
  74. package/docs/reference/authoring-surface/http.md +259 -0
  75. package/docs/reference/authoring-surface/isfailure.md +58 -0
  76. package/docs/reference/authoring-surface/isready.md +14 -0
  77. package/docs/reference/authoring-surface/jr2setup.md +237 -0
  78. package/docs/reference/authoring-surface/open.md +105 -0
  79. package/docs/reference/authoring-surface/openbody.md +86 -0
  80. package/docs/reference/authoring-surface/paramsof.md +143 -0
  81. package/docs/reference/authoring-surface/pool.md +186 -0
  82. package/docs/reference/authoring-surface/push.md +130 -0
  83. package/docs/reference/authoring-surface/readyof.md +21 -0
  84. package/docs/reference/authoring-surface/secret.md +139 -0
  85. package/docs/reference/authoring-surface/sentby.md +83 -0
  86. package/docs/reference/authoring-surface/source.md +51 -0
  87. package/docs/reference/authoring-surface/text.md +62 -0
  88. package/docs/reference/authoring-surface/type-agentdeclaration.md +27 -0
  89. package/docs/reference/authoring-surface/type-agentdefinition.md +80 -0
  90. package/docs/reference/authoring-surface/type-agentlogic.md +15 -0
  91. package/docs/reference/authoring-surface/type-agentslots.md +15 -0
  92. package/docs/reference/authoring-surface/type-answeraction.md +12 -0
  93. package/docs/reference/authoring-surface/type-anyframepath.md +14 -0
  94. package/docs/reference/authoring-surface/type-anyworktreepath.md +15 -0
  95. package/docs/reference/authoring-surface/type-arg.md +19 -0
  96. package/docs/reference/authoring-surface/type-argnames.md +12 -0
  97. package/docs/reference/authoring-surface/type-bindactors.md +14 -0
  98. package/docs/reference/authoring-surface/type-binding.md +61 -0
  99. package/docs/reference/authoring-surface/type-bindingof.md +12 -0
  100. package/docs/reference/authoring-surface/type-bodyacceptsdoor.md +15 -0
  101. package/docs/reference/authoring-surface/type-bodyacceptsslots.md +17 -0
  102. package/docs/reference/authoring-surface/type-ceilings.md +41 -0
  103. package/docs/reference/authoring-surface/type-chainlink.md +19 -0
  104. package/docs/reference/authoring-surface/type-chartaction.md +46 -0
  105. package/docs/reference/authoring-surface/type-chartagent.md +28 -0
  106. package/docs/reference/authoring-surface/type-chartevent.md +20 -0
  107. package/docs/reference/authoring-surface/type-chartguard.md +20 -0
  108. package/docs/reference/authoring-surface/type-chartinvoke.md +28 -0
  109. package/docs/reference/authoring-surface/type-chartjson.md +14 -0
  110. package/docs/reference/authoring-surface/type-chartstate.md +46 -0
  111. package/docs/reference/authoring-surface/type-charttext.md +40 -0
  112. package/docs/reference/authoring-surface/type-charttransition.md +22 -0
  113. package/docs/reference/authoring-surface/type-charttransitions.md +14 -0
  114. package/docs/reference/authoring-surface/type-chartvalue.md +15 -0
  115. package/docs/reference/authoring-surface/type-childat.md +12 -0
  116. package/docs/reference/authoring-surface/type-childslots.md +12 -0
  117. package/docs/reference/authoring-surface/type-commandenv.md +15 -0
  118. package/docs/reference/authoring-surface/type-commandinput.md +20 -0
  119. package/docs/reference/authoring-surface/type-commandoptions.md +56 -0
  120. package/docs/reference/authoring-surface/type-commandoutput.md +122 -0
  121. package/docs/reference/authoring-surface/type-customize.md +111 -0
  122. package/docs/reference/authoring-surface/type-dispatchdefinition.md +39 -0
  123. package/docs/reference/authoring-surface/type-dispatchinput.md +14 -0
  124. package/docs/reference/authoring-surface/type-dispatchopenparts.md +14 -0
  125. package/docs/reference/authoring-surface/type-dispatchoutput.md +72 -0
  126. package/docs/reference/authoring-surface/type-doorlessinput.md +19 -0
  127. package/docs/reference/authoring-surface/type-duration.md +15 -0
  128. package/docs/reference/authoring-surface/type-effectbinding.md +93 -0
  129. package/docs/reference/authoring-surface/type-effectlogic.md +12 -0
  130. package/docs/reference/authoring-surface/type-envopenparts.md +14 -0
  131. package/docs/reference/authoring-surface/type-eventaudience.md +27 -0
  132. package/docs/reference/authoring-surface/type-eventdef.md +45 -0
  133. package/docs/reference/authoring-surface/type-eventfrom.md +16 -0
  134. package/docs/reference/authoring-surface/type-eventsemantics.md +26 -0
  135. package/docs/reference/authoring-surface/type-execoutcome.md +34 -0
  136. package/docs/reference/authoring-surface/type-failslot.md +14 -0
  137. package/docs/reference/authoring-surface/type-failure.md +19 -0
  138. package/docs/reference/authoring-surface/type-failureinput.md +20 -0
  139. package/docs/reference/authoring-surface/type-filebody.md +37 -0
  140. package/docs/reference/authoring-surface/type-framepath.md +14 -0
  141. package/docs/reference/authoring-surface/type-frominput.md +14 -0
  142. package/docs/reference/authoring-surface/type-hostinjectedinput.md +56 -0
  143. package/docs/reference/authoring-surface/type-httpdefinition.md +104 -0
  144. package/docs/reference/authoring-surface/type-httpfileinput.md +20 -0
  145. package/docs/reference/authoring-surface/type-httpinput.md +12 -0
  146. package/docs/reference/authoring-surface/type-httpmethod.md +14 -0
  147. package/docs/reference/authoring-surface/type-httpopenparts.md +12 -0
  148. package/docs/reference/authoring-surface/type-httpoutput.md +95 -0
  149. package/docs/reference/authoring-surface/type-httprequestparts.md +33 -0
  150. package/docs/reference/authoring-surface/type-jr2config.md +126 -0
  151. package/docs/reference/authoring-surface/type-lateroutcome.md +21 -0
  152. package/docs/reference/authoring-surface/type-lends.md +38 -0
  153. package/docs/reference/authoring-surface/type-logicat.md +12 -0
  154. package/docs/reference/authoring-surface/type-markedif.md +12 -0
  155. package/docs/reference/authoring-surface/type-mergedactors.md +12 -0
  156. package/docs/reference/authoring-surface/type-namedsecret.md +25 -0
  157. package/docs/reference/authoring-surface/type-namestart.md +77 -0
  158. package/docs/reference/authoring-surface/type-noslotworkspaceoptions.md +27 -0
  159. package/docs/reference/authoring-surface/type-notworktreekeys.md +12 -0
  160. package/docs/reference/authoring-surface/type-openbodydeclaration.md +40 -0
  161. package/docs/reference/authoring-surface/type-openbodylogic.md +14 -0
  162. package/docs/reference/authoring-surface/type-openbodyoutput.md +42 -0
  163. package/docs/reference/authoring-surface/type-openbodyslot.md +18 -0
  164. package/docs/reference/authoring-surface/type-opencommandinput.md +22 -0
  165. package/docs/reference/authoring-surface/type-openeffect.md +12 -0
  166. package/docs/reference/authoring-surface/type-openeffectslots.md +12 -0
  167. package/docs/reference/authoring-surface/type-openof.md +12 -0
  168. package/docs/reference/authoring-surface/type-opensecret.md +23 -0
  169. package/docs/reference/authoring-surface/type-opensecretmark.md +12 -0
  170. package/docs/reference/authoring-surface/type-permissivenoslotworkspaceoptions.md +26 -0
  171. package/docs/reference/authoring-surface/type-permissiveworkspaceoptions.md +27 -0
  172. package/docs/reference/authoring-surface/type-poolmachine.md +28 -0
  173. package/docs/reference/authoring-surface/type-poolnextinput.md +22 -0
  174. package/docs/reference/authoring-surface/type-poolspec.md +60 -0
  175. package/docs/reference/authoring-surface/type-pushinput.md +34 -0
  176. package/docs/reference/authoring-surface/type-pushoptions.md +79 -0
  177. package/docs/reference/authoring-surface/type-pushoutput.md +149 -0
  178. package/docs/reference/authoring-surface/type-pushwireoutput.md +12 -0
  179. package/docs/reference/authoring-surface/type-quantity.md +14 -0
  180. package/docs/reference/authoring-surface/type-reached.md +12 -0
  181. package/docs/reference/authoring-surface/type-reposlot.md +70 -0
  182. package/docs/reference/authoring-surface/type-reposlotsof.md +16 -0
  183. package/docs/reference/authoring-surface/type-sandboxoptions.md +84 -0
  184. package/docs/reference/authoring-surface/type-secret.md +25 -0
  185. package/docs/reference/authoring-surface/type-sender.md +19 -0
  186. package/docs/reference/authoring-surface/type-sentbyguards.md +12 -0
  187. package/docs/reference/authoring-surface/type-size.md +85 -0
  188. package/docs/reference/authoring-surface/type-slothandles.md +24 -0
  189. package/docs/reference/authoring-surface/type-sourcenextresult.md +17 -0
  190. package/docs/reference/authoring-surface/type-sourcespec.md +44 -0
  191. package/docs/reference/authoring-surface/type-syncstate.md +12 -0
  192. package/docs/reference/authoring-surface/type-text.md +19 -0
  193. package/docs/reference/authoring-surface/type-textpart.md +24 -0
  194. package/docs/reference/authoring-surface/type-thinkinglevel.md +39 -0
  195. package/docs/reference/authoring-surface/type-toparameterizedobject.md +14 -0
  196. package/docs/reference/authoring-surface/type-toprovidedactor.md +14 -0
  197. package/docs/reference/authoring-surface/type-unknown.md +21 -0
  198. package/docs/reference/authoring-surface/type-usercontainer.md +77 -0
  199. package/docs/reference/authoring-surface/type-withoutemptyindex.md +20 -0
  200. package/docs/reference/authoring-surface/type-workflowevent.md +46 -0
  201. package/docs/reference/authoring-surface/type-workspaceaccess.md +16 -0
  202. package/docs/reference/authoring-surface/type-workspaced.md +115 -0
  203. package/docs/reference/authoring-surface/type-workspacehandles.md +22 -0
  204. package/docs/reference/authoring-surface/type-workspacemachine.md +29 -0
  205. package/docs/reference/authoring-surface/type-workspaceof.md +13 -0
  206. package/docs/reference/authoring-surface/type-workspaceoptions.md +27 -0
  207. package/docs/reference/authoring-surface/type-worktreefound.md +16 -0
  208. package/docs/reference/authoring-surface/type-worktreeinput.md +56 -0
  209. package/docs/reference/authoring-surface/type-worktreekey.md +14 -0
  210. package/docs/reference/authoring-surface/type-worktreeoptions.md +29 -0
  211. package/docs/reference/authoring-surface/type-worktreeoutput.md +45 -0
  212. package/docs/reference/authoring-surface/type-worktreepath.md +16 -0
  213. package/docs/reference/authoring-surface/type-worktreeready.md +37 -0
  214. package/docs/reference/authoring-surface/type-worktreerefused.md +21 -0
  215. package/docs/reference/authoring-surface/workspace.md +287 -0
  216. package/docs/reference/authoring-surface/worktree.md +71 -0
  217. package/docs/reference/authoring-surface.md +217 -0
  218. package/docs/reference/cli.md +433 -0
  219. package/docs/reference/config.md +765 -0
  220. package/docs/reference/decisions/0001-operator-owned-generic-sandbox.md +114 -0
  221. package/docs/reference/decisions/0002-duplex-streaming-actor.md +117 -0
  222. package/docs/reference/decisions/0004-worktree-provisioning-model.md +130 -0
  223. package/docs/reference/decisions/0005-sandbox-pod-composition.md +240 -0
  224. package/docs/reference/decisions/0006-agent-control-surface.md +50 -0
  225. package/docs/reference/decisions/0007-durable-machine-state.md +109 -0
  226. package/docs/reference/decisions/0008-orchestrator-as-deployed-app.md +60 -0
  227. package/docs/reference/decisions/0009-cli-and-instance-interface.md +275 -0
  228. package/docs/reference/decisions/0010-bdd-acceptance-tests.md +160 -0
  229. package/docs/reference/decisions/0011-workflow-defined-events.md +141 -0
  230. package/docs/reference/decisions/0012-workspace-wrapper-machine.md +103 -0
  231. package/docs/reference/decisions/0013-the-agent-reaches-its-machine-through-a-container-it-cannot-read.md +175 -0
  232. package/docs/reference/decisions/0014-observation-is-open-run-state-is-not.md +95 -0
  233. package/docs/reference/decisions/0015-authoring-surface-absorbs-the-mechanism.md +271 -0
  234. package/docs/reference/decisions/0016-agent-turn-mechanics-are-internal.md +126 -0
  235. package/docs/reference/decisions/0017-pool-over-a-source-port.md +71 -0
  236. package/docs/reference/decisions/0018-instance-agents-are-definitions-jr2-assembles-the-harness.md +111 -0
  237. package/docs/reference/decisions/0019-one-converging-command-against-the-current-context.md +287 -0
  238. package/docs/reference/decisions/0020-private-ca-trust-is-a-named-concept.md +60 -0
  239. package/docs/reference/decisions/0021-workspace-continuity-is-a-lease-that-answers-back.md +101 -0
  240. package/docs/reference/decisions/0022-observation-is-a-level-triggered-feed.md +103 -0
  241. package/docs/reference/decisions/0023-the-harness-prints-the-conversation.md +175 -0
  242. package/docs/reference/decisions/0024-an-agents-turn-ends-with-the-state-that-asked-for-it.md +436 -0
  243. package/docs/reference/decisions/0025-cancel-ends-a-run-stop-parks-it.md +65 -0
  244. package/docs/reference/decisions/0026-a-turn-that-is-over-is-never-prompted.md +62 -0
  245. package/docs/reference/decisions/0027-the-harness-is-jr2s-own-server-flue-retires-the-wire-stays.md +245 -0
  246. package/docs/reference/decisions/0028-what-an-agent-may-do-to-the-workspace-is-part-of-its-definition.md +90 -0
  247. package/docs/reference/decisions/0029-a-menu-is-fixed-for-a-conversation-and-a-turn-is-told-its-allowed-picks.md +154 -0
  248. package/docs/reference/decisions/0030-a-snapshot-names-the-machine-it-was-written-under.md +100 -0
  249. package/docs/reference/decisions/0031-menu-only-agents-run-on-the-instance-harness.md +193 -0
  250. package/docs/reference/decisions/0032-the-console-unlocks-with-the-instance-token.md +61 -0
  251. package/docs/reference/decisions/0033-a-machine-declares-the-input-that-starts-it.md +126 -0
  252. package/docs/reference/decisions/0034-the-console-renders-with-preact-and-the-server-erases-the-types.md +57 -0
  253. package/docs/reference/decisions/0035-a-runaway-turn-is-ended-rerolled-once-then-a-fault.md +92 -0
  254. package/docs/reference/decisions/0036-a-turn-compacts-its-own-context-mid-flight.md +138 -0
  255. package/docs/reference/decisions/0037-an-instance-builds-its-sandbox-images-jr2-injects-the-harness.md +196 -0
  256. package/docs/reference/decisions/0038-jr2-up-builds-every-image-it-deploys.md +170 -0
  257. package/docs/reference/decisions/0039-image-garbage-collects-by-reachability.md +115 -0
  258. package/docs/reference/decisions/0041-a-build-the-host-already-holds-is-not-spent-again.md +64 -0
  259. package/docs/reference/decisions/0042-ready-is-not-routable-an-admission-retries-its-connection.md +142 -0
  260. package/docs/reference/decisions/0043-the-kit-is-tested-as-installed-a-local-registry-stands-in-for-npm.md +170 -0
  261. package/docs/reference/decisions/0044-kit-images-live-at-a-canonical-home-a-self-host-mirrors-it.md +85 -0
  262. package/docs/reference/decisions/0045-the-platform-joins-the-image-address-and-the-cluster-chooses-it.md +82 -0
  263. package/docs/reference/decisions/0046-a-converge-failure-carries-its-diagnosis.md +34 -0
  264. package/docs/reference/decisions/0047-the-git-ssh-key-source-is-the-users-choice.md +47 -0
  265. package/docs/reference/decisions/0048-the-orchestrator-boots-without-its-repos.md +36 -0
  266. package/docs/reference/decisions/0049-a-machine-carries-its-parts-and-composes-by-invoke.md +126 -0
  267. package/docs/reference/decisions/0050-what-code-names-config-declares-what-the-cli-names-discovery-finds.md +73 -0
  268. package/docs/reference/decisions/0051-a-repo-is-a-slot-on-the-workspace-and-a-cache-on-the-node.md +238 -0
  269. package/docs/reference/decisions/0052-a-sandbox-lands-where-an-ordinary-pod-lands-and-the-cache-follows-it.md +86 -0
  270. package/docs/reference/decisions/0053-a-fetch-inside-the-pod-asks-the-node-cache-and-the-cache-asks-the-remote.md +123 -0
  271. package/docs/reference/decisions/0054-the-kit-ships-machines-and-a-shipped-machine-leaves-its-parts-open.md +126 -0
  272. package/docs/reference/decisions/0055-a-release-is-a-pushed-tag-and-the-publish-guard-is-the-credential.md +107 -0
  273. package/docs/reference/decisions/0056-a-global-jr2-hands-off-to-the-instances-own-and-an-instance-has-one-kit-version.md +62 -0
  274. package/docs/reference/decisions/0057-a-turn-is-its-frame-its-dials-and-whether-it-continues.md +152 -0
  275. package/docs/reference/decisions/0058-a-harness-answers-the-orchestrator-alone.md +108 -0
  276. package/docs/reference/decisions/0059-a-harness-holds-stand-ins-and-the-custodian-holds-the-keys.md +427 -0
  277. package/docs/reference/decisions/0060-a-workspace-states-its-size-and-jr2-reserves-all-of-it.md +111 -0
  278. package/docs/reference/decisions/0061-a-memory-kill-ends-the-agents-processes-not-the-harness.md +83 -0
  279. package/docs/reference/decisions/0062-jr2-briefs-the-agent-on-its-seat-never-on-its-task.md +239 -0
  280. package/docs/reference/decisions/0063-the-orchestrator-watches-the-cluster.md +82 -0
  281. package/docs/reference/decisions/0064-a-workspace-waits-for-capacity.md +79 -0
  282. package/docs/reference/decisions/0065-a-persist-survives-a-crash-and-history-is-a-week.md +65 -0
  283. package/docs/reference/decisions/0066-a-model-tier-runs-a-real-model-and-a-change-to-what-it-reads-runs-the-tier.md +552 -0
  284. package/docs/reference/decisions/0067-an-effect-is-an-actor-slot-and-runs-at-most-once-unless-marked-idempotent.md +458 -0
  285. package/docs/reference/decisions/0068-an-effector-holds-an-effects-secrets-and-signs-its-wire.md +475 -0
  286. package/docs/reference/decisions/0069-the-orchestrator-is-a-kit-image-and-an-instance-publishes-its-assembly.md +180 -0
  287. package/docs/reference/decisions/0070-a-machine-lends-its-parts-to-a-chart.md +334 -0
  288. package/docs/reference/decisions/0071-a-run-starts-a-run-through-a-dispatch-effect.md +183 -0
  289. package/docs/reference/decisions/0072-the-docs-ship-inside-the-kit-and-an-instances-agents-md-indexes-them.md +144 -0
  290. package/docs/reference/decisions/0073-a-machine-fails-a-run-with-fail-and-an-uncaught-failure-ends-it-failed.md +122 -0
  291. package/docs/reference/decisions/0074-an-unrouted-mechanism-event-is-refused-at-load-and-faults-the-run.md +76 -0
  292. package/docs/reference/decisions/0075-a-machine-cuts-a-worktree-and-the-workspace-only-clones.md +295 -0
  293. package/docs/reference/decisions/0076-an-agents-control-credential-lives-only-where-no-workspace-code-runs.md +320 -0
  294. package/docs/reference/decisions/0077-jr2-requires-landlock-on-every-sandbox-node.md +79 -0
  295. package/docs/reference/decisions.md +86 -0
  296. package/docs/reference/glossary.md +687 -0
  297. package/docs/reference/http-api.md +1386 -0
  298. package/docs/reference/machines.md +189 -0
  299. package/docs/reference/mechanism-events.md +72 -0
  300. package/docs/why.md +207 -0
  301. package/package.json +5 -3
  302. package/src/actor.ts +694 -106
  303. package/src/agent.ts +114 -38
  304. package/src/ambient.ts +3 -4
  305. package/src/assembly-checks.ts +189 -7
  306. package/src/cause.ts +234 -0
  307. package/src/chart.ts +345 -46
  308. package/src/charts.ts +43 -8
  309. package/src/config.ts +440 -178
  310. package/src/custodian.lua +17 -5
  311. package/src/custodian.ts +325 -99
  312. package/src/customize.ts +199 -49
  313. package/src/dispatch-effect.ts +945 -0
  314. package/src/door-compat.ts +217 -0
  315. package/src/durability.ts +11 -4
  316. package/src/effect-checks.ts +50 -3
  317. package/src/effect.ts +641 -128
  318. package/src/effector-wire.ts +165 -13
  319. package/src/fail.ts +222 -0
  320. package/src/harness-client.ts +587 -50
  321. package/src/harness-env.ts +33 -0
  322. package/src/held-secrets.ts +125 -16
  323. package/src/holds.ts +3 -0
  324. package/src/http-effect.ts +556 -58
  325. package/src/http.ts +480 -30
  326. package/src/index.ts +74 -82
  327. package/src/instance.ts +68 -8
  328. package/src/internal.ts +85 -0
  329. package/src/kube-client.ts +6 -3
  330. package/src/machine-doc.ts +24 -7
  331. package/src/mechanism-routes.ts +168 -0
  332. package/src/model-keys.generated.ts +53 -0
  333. package/src/model-keys.ts +42 -58
  334. package/src/names.ts +19 -6
  335. package/src/notices.ts +483 -41
  336. package/src/open-body.ts +242 -40
  337. package/src/open-effect.ts +81 -8
  338. package/src/open.ts +90 -6
  339. package/src/parts.ts +213 -30
  340. package/src/party.ts +101 -2
  341. package/src/pick.ts +497 -11
  342. package/src/pool.ts +282 -50
  343. package/src/registration.ts +133 -12
  344. package/src/repo-identity.ts +7 -3
  345. package/src/repos.ts +22 -3
  346. package/src/run-host.ts +665 -45
  347. package/src/run-output.ts +38 -0
  348. package/src/sandbox-effect.ts +457 -71
  349. package/src/sandbox-kube.ts +66 -17
  350. package/src/secret-placement.ts +59 -17
  351. package/src/server.ts +3 -0
  352. package/src/setup.ts +325 -62
  353. package/src/size.ts +121 -9
  354. package/src/snapshot-store.ts +54 -10
  355. package/src/stub-harness.ts +44 -16
  356. package/src/timers.ts +14 -1
  357. package/src/tokens.ts +107 -32
  358. package/src/vocabulary.ts +88 -14
  359. package/src/wire.ts +100 -26
  360. package/src/workspace.ts +771 -238
  361. package/src/worktree.ts +249 -0
package/src/customize.ts CHANGED
@@ -45,6 +45,8 @@
45
45
  // its slot MAP Open (`repos: open`, ADR-0051) declared exactly this: every slot is the composer's
46
46
  // to name, so the map they write is the declaration, not an addition to one.
47
47
 
48
+ import type { CallbackActorLogic } from "xstate";
49
+ import type { AgentRunReceiveEvent } from "./actor.ts";
48
50
  import { StateMachine, type AnyStateMachine, type InputFrom, type ProvidedActor, type UnknownActorLogic } from "xstate";
49
51
  import type { AgentLogic } from "./actor.ts";
50
52
  import { isAgent, type AgentDefinition } from "./agent.ts";
@@ -77,7 +79,7 @@ import {
77
79
  import { isEffect, type Arg } from "./effect.ts";
78
80
  import { attachLent, copyOpenBody, lentIn, openBodiesOf, openBodyDeclarationOf } from "./open-body.ts";
79
81
  import { effectChecks } from "./effect-checks.ts";
80
- import type { Text } from "./http-effect.ts";
82
+ import type { NamedSecret, Text } from "./http-effect.ts";
81
83
  import {
82
84
  binderOf,
83
85
  effectBindingShape,
@@ -116,37 +118,63 @@ type SlotsOf<M extends AnyStateMachine> =
116
118
  ? TActor
117
119
  : never;
118
120
 
119
- /** The logic a Machine declares under one slot key. */
121
+ /**
122
+ * The logic a Machine declares under one slot key.
123
+ *
124
+ * @internal
125
+ */
120
126
  type LogicAt<M extends AnyStateMachine, K extends string> = Extract<SlotsOf<M>, { src: K }>["logic"];
121
127
 
122
- /** The Agent slots — told from every other slot by their logic, which no other actor kind has. */
123
- type AgentSlots<M extends AnyStateMachine> = Extract<SlotsOf<M>, { logic: AgentLogic }>["src"];
124
-
128
+ /**
129
+ * The Agent slots — told from every other slot by their logic, which no other actor kind has.
130
+ *
131
+ * @internal
132
+ */
133
+ type AgentSlots<M extends AnyStateMachine> = Extract<
134
+ SlotsOf<M>,
135
+ { logic: CallbackActorLogic<AgentRunReceiveEvent, any> }
136
+ >["src"];
125
137
  /** The Effect slots with an Open part — told by the phantom `OpenEffect` their constructor's
126
- * overload states for an `open` url or argv, or a `secret(open)` (open-effect.ts). */
138
+ * overload states for an `open` url or argv, or a `secret(open)` (open-effect.ts).
139
+ *
140
+ * @internal
141
+ */
127
142
  type OpenEffectSlots<M extends AnyStateMachine> = Extract<SlotsOf<M>, { logic: OpenEffect<OpenEffectPart> }>["src"];
128
143
 
129
- /** What one Open part binds to: a url, an argv, a secret's name. */
144
+ /** What one Open part binds to: a url, an argv, a secret's name, a dispatch's target — another
145
+ * Orchestrator's origin and the secret that holds its Instance token, together (ADR-0071). */
130
146
  type PartBinding<P> = P extends "url"
131
147
  ? { url: string | Text }
132
148
  : P extends "argv"
133
149
  ? { argv: readonly (string | Arg)[] }
134
150
  : P extends "secret"
135
151
  ? { secret: string }
136
- : never;
152
+ : P extends "target"
153
+ ? { target: { url: string; token: NamedSecret } }
154
+ : never;
137
155
 
138
156
  /** A union of object types as their intersection: one binding object with every key. */
139
157
  type Intersected<U> = (U extends unknown ? (x: U) => void : never) extends (x: infer I) => void ? I : never;
140
158
 
141
159
  /** What one Open Effect binds to: its url, its argv or its secret — for an Effect with two Open
142
- * parts, one object with both keys, the intersection of their bindings (ADR-0054). */
160
+ * parts, one object with both keys, the intersection of their bindings (ADR-0054).
161
+ *
162
+ * @internal
163
+ */
143
164
  type BindingOf<L> = L extends OpenEffect<infer P> ? Intersected<PartBinding<P>> : never;
144
165
 
145
166
  /** The child-Machine slots: the slots composition reaches (ADR-0049 — a nested Machine is an
146
- * ordinary `invoke` of an ordinary slot). */
167
+ * ordinary `invoke` of an ordinary slot).
168
+ *
169
+ * @internal
170
+ */
147
171
  type ChildSlots<M extends AnyStateMachine> = Extract<SlotsOf<M>, { logic: AnyStateMachine }>["src"];
148
172
 
149
- /** The child Machine under one slot key, constrained so `Customize` may recurse into it. */
173
+ /**
174
+ * The child Machine under one slot key, constrained so `Customize` may recurse into it.
175
+ *
176
+ * @internal
177
+ */
150
178
  type ChildAt<M extends AnyStateMachine, K extends string> = Extract<LogicAt<M, K>, AnyStateMachine>;
151
179
 
152
180
  /**
@@ -160,6 +188,7 @@ type ChildAt<M extends AnyStateMachine, K extends string> = Extract<LogicAt<M, K
160
188
  // Each step is taken on the wrapper's MARKER (`JR2Wrapper`, parts.ts), never on a slot's spelling —
161
189
  // an author is free to name a slot `body` or `worker`, and routing through it because of the name
162
190
  // would offer the Agents of a Machine the composer never named.
191
+ /** @internal */
163
192
  type Reached<M extends AnyStateMachine> = M extends JR2Wrapper<infer TBody> ? Reached<TBody> : M;
164
193
 
165
194
  /**
@@ -167,68 +196,130 @@ type Reached<M extends AnyStateMachine> = M extends JR2Wrapper<infer TBody> ? Re
167
196
  * {@link Reached}: down through the wrappers to the first Machine that composes a Sandbox, which
168
197
  * is the one whose `JR2Repos` marker says which slots exist (ADR-0051). `never` when no wrapper on
169
198
  * the chain composes one, which is what makes `repos` unavailable there rather than `{}`.
199
+ *
200
+ * @internal
170
201
  */
171
202
  type WorkspaceOf<M extends AnyStateMachine> =
172
203
  M extends JR2Repos<any> ? M : M extends JR2Wrapper<infer TBody> ? WorkspaceOf<TBody> : never;
173
204
 
174
205
  /** The Repo Slot keys the reached `workspace()` declared. The `never` case is tested by itself,
175
206
  * because `never extends JR2Repos<infer TSlots>` is true with nothing to infer from — and an
176
- * uninferred `TSlots` widens to `string`, which would offer every key exactly where there are none. */
207
+ * uninferred `TSlots` widens to `string`, which would offer every key exactly where there are none.
208
+ *
209
+ * @internal
210
+ */
177
211
  type RepoSlotsOf<M extends AnyStateMachine> = [WorkspaceOf<M>] extends [never]
178
212
  ? never
179
213
  : WorkspaceOf<M> extends JR2Repos<infer TSlots>
180
214
  ? TSlots
181
215
  : never;
182
216
 
217
+ // What may be retuned on one Machine, mirroring the DECLARATION's own shape and recursively
218
+ // partial (ADR-0049): every key optional, every Agent override a partial definition, every child a
219
+ // `Customize` of that child. `image`/`user` are the `workspace()` options (ADR-0037, ADR-0005) and
220
+ // apply to the wrapper the chain reaches; a Machine that composes no Sandbox refuses them at build
221
+ // time, because there is nothing for them to name.
183
222
  /**
184
- * What may be retuned on one Machine, mirroring the DECLARATION's own shape and recursively
185
- * partial (ADR-0049): every key optional, every Agent override a partial definition, every child
186
- * a `Customize` of that child.
223
+ * The parts of one Machine that `customize()` can retune: its Agents, its Open Effects, the
224
+ * Machines it composes, and the Sandbox of its `workspace()`. The type comes from the Machine
225
+ * itself, so it offers only the parts that the Machine declares. A key for a part the Machine does
226
+ * not declare does not compile. The `agents`, `effects`, `actors` and `repos` keys take no value
227
+ * when the Machine has no such part. `image`, `user` and `resources` compile on every Machine, and
228
+ * `customize()` refuses them when the Machine composes no `workspace()`.
229
+ *
230
+ * Every key is optional. Write only what you change.
231
+ *
232
+ * @example
233
+ * ```ts
234
+ * import { customize, type Customize } from "@jr2/orchestrator";
235
+ * import { task } from "@jr2/machines";
236
+ *
237
+ * const parts: Customize<typeof task> = {
238
+ * repos: { app: { url: "https://github.com/you/app.git", ref: "main" } },
239
+ * agents: { coder: { model: "anthropic/claude-haiku-5-5", thinkingLevel: "high" } },
240
+ * };
241
+ *
242
+ * export const machine = customize(task, parts);
243
+ * ```
187
244
  *
188
- * `image`/`user` are the `workspace()` options (ADR-0037, ADR-0005) and apply to the wrapper the
189
- * chain reaches; a Machine that composes no Sandbox refuses them at build time, because there is
190
- * nothing for them to name.
245
+ * @see docs/guides/bind-open-parts.md
246
+ * @see docs/concepts/composition.md
247
+ * @see docs/reference/decisions/0049-a-machine-carries-its-parts-and-composes-by-invoke.md
191
248
  */
192
249
  export type Customize<M extends AnyStateMachine> = {
193
- /** Retune an Agent this Machine carries: the override is layered over the stock definition, so
194
- * `{ model }` alone keeps the instructions the author wrote — and BINDS the model when the
195
- * author left it Open (ADR-0054), which is the common consumer line for a packaged Machine. The
196
- * override is a `Partial<AgentDefinition>`, never a declaration: a composer binds, and binding
197
- * to `open` again is not a thing anyone means. A Machine carrying no Agent takes `never` rather
198
- * than `{}`: an empty object type accepts any literal, which would make the one case with
199
- * nothing to name the one case with nothing checked. */
250
+ // `{ model }` alone BINDS the model when the author left it Open (ADR-0054), which is the common
251
+ // consumer line for a packaged Machine. The override is a `Partial<AgentDefinition>`, never a
252
+ // declaration: a composer binds, and binding to `open` again is not a thing anyone means
253
+ // (ADR-0054). A Machine carrying no Agent takes `never` rather than `{}`: an empty object type
254
+ // accepts any literal, which would make the one case with nothing to name the one case with
255
+ // nothing checked.
256
+ /** Retune the Agents that this Machine carries, by slot name: `{ coder: { model } }`. Each
257
+ * override goes over the definition that the author wrote, field by field, so `{ model }` alone
258
+ * keeps the author's instructions. When the author left the model Open, this is where you bind
259
+ * it. Allowed fields: the fields of an `agent()` definition. At run time, `customize()` refuses a
260
+ * slot that holds no Agent: `customize(): machine "<id>" carries no Agent slot "<slot>" — its
261
+ * Agents are: <slots>`. */
200
262
  agents?: [AgentSlots<Reached<M>>] extends [never]
201
263
  ? never
202
264
  : { [K in AgentSlots<Reached<M>>]?: Partial<AgentDefinition> };
203
- /** Bind an Effect's Open parts (ADR-0054): `{ url }` for an http Effect (whatever its body) whose url
204
- * the package left Open, `{ argv }` for a command whose argv it left Open, `{ secret }` for an
205
- * Effect that names `secret(open)` — one object with both keys for an Effect with two, so a binding
206
- * that leaves one out does not compile. Bound once, here — a value, never a mapper over the door,
207
- * so the host is fixed before any run. Only an Effect with an Open part is offered: a part its
208
- * author fixed stays fixed. A Machine with none takes `never`, as `agents` does. */
265
+ // `{ url }` is for an http Effect whatever its body (ADR-0054); `{ target }` binds a dispatch's
266
+ // url and token as one (ADR-0071). Bound once, here — a value, never a mapper over the door, so
267
+ // the host is fixed before any run (ADR-0054). Only an Effect with an Open part is offered: a
268
+ // part its author fixed stays fixed. A Machine with none takes `never`, as `agents` does.
269
+ /** Bind the Open parts of this Machine's Effects, by slot name: `{ url }` for an `http` Effect
270
+ * whose url is Open, `{ argv }` for a `command` whose argv is Open, `{ secret }` for an Effect
271
+ * that names `secret(open)`, `{ target: { url, token: secret("<name>") } }` for a `dispatch`
272
+ * whose target is Open. For an Effect with two Open parts, one object holds both keys, and
273
+ * a binding that leaves one out does not compile. Only Effects with an Open part are offered.
274
+ * See {@link EffectBinding} for the values and the refusals. */
209
275
  effects?: [OpenEffectSlots<Reached<M>>] extends [never]
210
276
  ? never
211
277
  : { [K in OpenEffectSlots<Reached<M>>]?: BindingOf<LogicAt<Reached<M>, K>> };
212
- /** Retune a Machine this one composes — the same shape, one level down. */
278
+ /** Retune a Machine that this Machine composes, by slot name. The value has the same shape as
279
+ * these parts, one level down. At run time, `customize()` refuses a slot that holds no Machine:
280
+ * `customize(): machine "<id>" composes no Machine under "<slot>"`. */
213
281
  actors?: [ChildSlots<Reached<M>>] extends [never]
214
282
  ? never
215
283
  : { [K in ChildSlots<Reached<M>>]?: Customize<ChildAt<Reached<M>, K>> };
216
- /** The Sandbox Image (ADR-0037): a `file:` URL to a docker context this module ships, or a
217
- * registry ref. */
284
+ // The Sandbox Image (ADR-0037).
285
+ /** The Sandbox Image: a `file:` URL to a docker context that your module ships
286
+ * (`import.meta.resolve("./image")`), which `jr2 up` builds, or a registry ref. It replaces the
287
+ * image of the `workspace()`. When the Machine composes no `workspace()`, `customize()` refuses it
288
+ * at run time. */
218
289
  image?: string;
219
- /** The User Container (ADR-0005): its image in the same two shapes, or `{ image, resources }`
220
- * with its split of the Size (ADR-0060). Replaces the seat whole — split included. */
290
+ // The User Container (ADR-0005), in the same two shapes, or `{ image, resources }` with its split
291
+ // of the Size (ADR-0060). Replaces the seat whole — split included.
292
+ /** The User Container: its image, as a `file:` URL or a registry ref, or a
293
+ * {@link UserContainer} that also gives its part of the Size. It replaces the whole User
294
+ * Container, its part of the Size included. When the Machine composes no `workspace()`,
295
+ * `customize()` refuses it at run time. */
221
296
  user?: string | UserContainer;
222
- /** The Size (ADR-0060), layered field by field over the `workspace()`'s own: the composer's
223
- * Repo may be bigger than the author's. `limits.memory` and `limits.cpu`, nothing else. */
297
+ // The Size (ADR-0060), layered over the `workspace()`'s own: the composer's Repo may be bigger
298
+ // than the author's.
299
+ /** The Size, layered field by field over the Size of the `workspace()`: `{ limits: { memory } }`
300
+ * keeps the author's cpu. Only `limits.memory` and `limits.cpu`. See {@link Size}. Only for a
301
+ * Machine that composes a `workspace()`. */
224
302
  resources?: Size;
225
- /** Bind the Repo Slots the reached `workspace()` declared (ADR-0051) — an open slot to a url,
226
- * or a bound or per-run one to a different Binding; any of the three forms, so a consumer can
227
- * also bind a mapper over the wrapper's door. A slot the Machine does not declare is a compile
228
- * error, and a Machine that composes no Sandbox takes `never`, as `agents` does. A `workspace()`
229
- * that declared its map Open takes any keys — they are the composer's words, in the order the
230
- * Machine documents — and at least one, checked at the call. */
231
- repos?: [RepoSlotsOf<M>] extends [never] ? never : { [K in RepoSlotsOf<M>]?: RepoSlot<InputFrom<WorkspaceOf<M>>> };
303
+ // Any of the three slot forms, so a consumer can also bind a mapper over the wrapper's door
304
+ // (ADR-0051). A Machine that composes no Sandbox takes `never`, as `agents` does. A
305
+ // `workspace()` that declared its map Open takes any keys — they are the composer's words, in the
306
+ // order the Machine documents — and at least one, checked at the call.
307
+ /** Bind the Repo Slots of the `workspace()`, by slot name. Each value is one of these:
308
+ *
309
+ * - a url
310
+ * - a Binding `{ url, ref? }`
311
+ * - a function `({ input }) => url | { url, ref? }` over the run input
312
+ * - `open`, to leave the slot for the next composer to bind
313
+ *
314
+ * You can bind an Open slot, or give a bound or per-run slot a different Binding. A slot that
315
+ * the Machine does not declare does not compile. Some Machines, such as `task`, leave their
316
+ * whole slot map Open. Then you name every slot, and at least one. The keys are your names for
317
+ * the Repos, and the Machine says what their order means. */
318
+ // A Workspace with only optional fields can start with no input, but the wrapper gives a mapper `{}`,
319
+ // so its `input` is never `undefined`.
320
+ repos?: [RepoSlotsOf<M>] extends [never]
321
+ ? never
322
+ : { [K in RepoSlotsOf<M>]?: RepoSlot<Exclude<InputFrom<WorkspaceOf<M>>, undefined>> };
232
323
  };
233
324
 
234
325
  /** The same shape with the types erased — what the implementation walks. */
@@ -242,10 +333,55 @@ type LooseParts = {
242
333
  resources?: Size;
243
334
  };
244
335
 
336
+ // Returns a NEW Machine of the same type — the original is untouched, so two customizations of one
337
+ // import are two independent Machines (ADR-0049's `deep`/`quick`), and a run of either carries what
338
+ // it was given.
245
339
  /**
246
- * Retune the parts a Machine carries, returning a NEW Machine of the same type — the original is
247
- * untouched, so two customizations of one import are two independent Machines (ADR-0049's
248
- * `deep`/`quick`), and a run of either carries what it was given.
340
+ * Retune the parts that a Machine carries, without a change to the module that exports it. Use it
341
+ * where you register a Machine as a Workflow. It binds the parts that a packaged Machine leaves
342
+ * Open: its Repo Slots, an Agent's model, or an Effect's url, argv or secret. It also changes the
343
+ * parts that its author fixed: an Agent's instructions, the Sandbox Image, or the Size.
344
+ *
345
+ * It gives back a new Machine of the same type. The original does not change, so two
346
+ * `customize()` calls on one import give two Machines. Only the parts the Machine declares can be
347
+ * retuned. You cannot add a part: a Machine that needs another Agent is a new Machine. The types
348
+ * refuse most mistakes when you compile. At run time, `customize()` also throws:
349
+ *
350
+ * - `customize(): machine "<id>" carries no Agent slot "<slot>" — its Agents are: <slots>`
351
+ * - `customize(): machine "<id>" composes no Machine under "<slot>" — the Machines it composes are: <slots>`
352
+ * - `customize(): machine "<id>" carries no Effect slot "<slot>" — its Effects are: <slots>`
353
+ * - `customize(): machine "<id>" declares no Repo Slot "<slot>" — its slots are: <slots>`
354
+ * - `customize(): machine "<id>" declares its Repo Slots open as a map — name at least one`
355
+ * - `` customize(): `repos` say what a SANDBOX is made of, how big it is and which Repos it
356
+ * attaches, and machine "<id>" composes none `` (for `resources`, the text starts
357
+ * `` customize(): `resources` ``; for `image` or `user`, it starts `` customize(): `image`/`user` ``)
358
+ * - `customize(): machine "<id>": <errors>`, when an Effect argv that you bind fails the checks
359
+ * that the Machine passed when it was built
360
+ * - the refusals of {@link EffectBinding}, {@link RepoSlot}, {@link Size} and
361
+ * {@link UserContainer}, which start with `customize()`
362
+ *
363
+ * @param machine - The Machine to retune: one you import from a package, or one you wrote. When
364
+ * its root is a `workspace()` or a `pool()`, `customize()` reaches through to the Machine inside,
365
+ * so you never name the wrapper's own slot.
366
+ * @param parts - The parts to change. See {@link Customize}.
367
+ * @returns A new Machine of the same type, with the parts changed.
368
+ *
369
+ * @example
370
+ * ```ts
371
+ * import { customize } from "@jr2/orchestrator";
372
+ * import { task } from "@jr2/machines";
373
+ *
374
+ * export const machine = customize(task, {
375
+ * repos: { app: { url: "https://github.com/you/app.git" } },
376
+ * agents: { coder: { model: "anthropic/claude-haiku-5-5" } },
377
+ * resources: { limits: { memory: "4Gi" } },
378
+ * });
379
+ * ```
380
+ *
381
+ * @see docs/guides/bind-open-parts.md
382
+ * @see docs/concepts/composition.md
383
+ * @see docs/reference/decisions/0049-a-machine-carries-its-parts-and-composes-by-invoke.md
384
+ * @see docs/reference/decisions/0054-the-kit-ships-machines-and-a-shipped-machine-leaves-its-parts-open.md
249
385
  */
250
386
  export function customize<M extends AnyStateMachine>(machine: M, parts: Customize<M>): M {
251
387
  const { agents, effects, actors, image, user, repos, resources } = parts as LooseParts;
@@ -360,7 +496,7 @@ function retune(machine: AnyStateMachine, parts: LooseParts): AnyStateMachine {
360
496
  /**
361
497
  * Bind one Effect's Open parts (ADR-0054): the slot must be an Effect, each key of the binding one
362
498
  * of its Open parts, and each value the value that part takes — a url (a string, or a `text` with a
363
- * secret in its path), an argv, or a secret's name. A key left out leaves that part Open. The binder
499
+ * secret in its path), an argv, a secret's name, or a dispatch's target (ADR-0071). A key left out leaves that part Open. The binder
364
500
  * builds the Effect again, whole, so the bound one meets every check its constructor runs: the url's
365
501
  * literal host, the argv's entries, the secret's name. The compiler's check of the
366
502
  * invoke's input against the argv's slots does not reach it (an Open argv's input is one string per
@@ -400,6 +536,17 @@ function bindEffect(machine: AnyStateMachine, name: string, binding: EffectBindi
400
536
  `${value === open ? "`open` again" : "a function of the run"}: no run chooses an Effect's ${part} (ADR-0054)`,
401
537
  );
402
538
  }
539
+ if (part === "target") {
540
+ // The whole target is the Open part (ADR-0071): an origin and a named secret, bound together.
541
+ // The dispatch's own constructor checks the url and the name when the binder rebuilds it.
542
+ const target = value as { url?: unknown; token?: unknown } | null;
543
+ if (typeof target !== "object" || target === null || typeof target.url !== "string" || !isSecret(target.token)) {
544
+ throw new Error(
545
+ `customize(): the dispatch Effect "${name}"'s target is bound to another Orchestrator's origin and the ` +
546
+ `secret that holds its Instance token: ${effectBindingShape("target")} (ADR-0071)`,
547
+ );
548
+ }
549
+ }
403
550
  if (part === "secret" && typeof value !== "string") {
404
551
  throw new Error(
405
552
  `customize(): the ${logic.effect.kind} Effect "${name}"'s secret is bound to a secret's name, a string — ` +
@@ -410,6 +557,9 @@ function bindEffect(machine: AnyStateMachine, name: string, binding: EffectBindi
410
557
  return binder(binding);
411
558
  }
412
559
 
560
+ const isSecret = (value: unknown): boolean =>
561
+ typeof value === "object" && value !== null && typeof (value as { secret?: unknown }).secret === "string";
562
+
413
563
  /**
414
564
  * The load walk's Effect checks (ADR-0067), again, on a Machine whose Open argv this `customize()`
415
565
  * bound: at build its argv slots were unknown and every pick param counted as read; now the bound