@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
@@ -0,0 +1,304 @@
1
+ ---
2
+ title: Answer a Gate
3
+ description: Send an event to an open Gate of a run, from the CLI, the Console, a webhook handler or a CI job.
4
+ ---
5
+
6
+ # Answer a Gate
7
+
8
+ Send an event to an open [Gate](../reference/glossary.md#gate) of a run from the CLI, the
9
+ [Console](../reference/glossary.md#console), a webhook handler or a CI job.
10
+
11
+ A run waits at a Gate until a person or a different system answers it. The Gate is open while the run is in the state
12
+ that invokes it, and it closes when the run leaves that state. An open Gate has an id, its events, and the input schema
13
+ of each event. Its `meta` is the data that the [Machine](../reference/glossary.md#machine) shows to the person or the
14
+ system that answers.
15
+
16
+ The examples on this page use the [Workflow](../reference/glossary.md#workflow) `release`. Its Gate `review` takes
17
+ `approve`, with no input, and `reject`, with a `reason`. The Workflow has no [Agent](../reference/glossary.md#agent), so
18
+ you can try the steps with no model. Save the file as `workflows/release.ts` in your
19
+ [Instance](../reference/glossary.md#instance). Then run `jr2 up`:
20
+
21
+ ```ts
22
+ import { assign } from "xstate";
23
+ import { z } from "zod";
24
+ import { defineEvent, fail, jr2Setup } from "@jr2/orchestrator";
25
+
26
+ // The two answers that the Gate takes. A person, a script or a CI job sends one of them.
27
+ const approve = defineEvent({
28
+ name: "approve",
29
+ description: "Release this version.",
30
+ input: z.object({}),
31
+ });
32
+ const reject = defineEvent({
33
+ name: "reject",
34
+ description: "Do not release this version. Say why.",
35
+ input: z.object({ reason: z.string().min(1) }),
36
+ });
37
+
38
+ type Context = { version: string; reason?: string };
39
+
40
+ export const machine = jr2Setup({
41
+ types: {} as { input: { version: string }; context: Context },
42
+ events: [approve, reject],
43
+ actors: { fail: fail() },
44
+ }).createMachine({
45
+ id: "release",
46
+ // jr2 checks each run input against this schema before the run starts.
47
+ input: z.object({ version: z.string() }),
48
+ context: ({ input }) => ({ version: input.version }),
49
+ initial: "review",
50
+ states: {
51
+ review: {
52
+ // The Gate is open while the run is in this state. Its id is the state key, "review".
53
+ // It takes the events of this state: approve and reject.
54
+ invoke: { src: "gate", input: ({ context }) => ({ meta: { version: context.version } }) },
55
+ on: {
56
+ approve: "released",
57
+ reject: { target: "rejected", actions: assign({ reason: ({ event }) => event.reason }) },
58
+ },
59
+ },
60
+ released: { type: "final" },
61
+ // A person stopped the release, and the run ends here. Not a final state: the run ends
62
+ // `failed`, with the person's reason.
63
+ rejected: { invoke: { src: "fail", input: ({ context }) => ({ reason: context.reason! }) } },
64
+ },
65
+ });
66
+ ```
67
+
68
+ In the commands, replace these values:
69
+
70
+ - `<namespace>`: the namespace of your Instance. It is the [`name`](../reference/config.md#name) in `jr2.config.ts`.
71
+ When `jr2.config.ts` sets no `name`, it is the name of the Instance folder.
72
+ - `<run id>`: the run id, or its first 4 characters or more. `jr2 run` prints the run id in the line
73
+ `run <run id> (<workflow>) — attached`.
74
+
75
+ Give each `jr2` command in the Instance folder.
76
+
77
+ ## Start a run that waits
78
+
79
+ Start a run in one terminal. `jr2 run` stays attached while the run waits at the Gate:
80
+
81
+ ```sh
82
+ jr2 run release --input '{"version":"1.4.0"}'
83
+ ```
84
+
85
+ ```text
86
+ → context <context> / namespace <namespace>
87
+ run 2319932e-02c1-4f9d-98db-3c5a410395da (release) — attached
88
+ → active "review"
89
+ ```
90
+
91
+ Your run id is different, and so are the instance id and the `assembly` hash in the next steps. Give the commands in the
92
+ next steps in a second terminal. [Start a run](start-a-run.md) gives the other ways to start a run.
93
+
94
+ ## Find the open Gate
95
+
96
+ Run [`jr2 status`](../reference/cli.md#status) with the run id:
97
+
98
+ ```sh
99
+ jr2 status 2319
100
+ ```
101
+
102
+ ```text
103
+ → context <context> / namespace <namespace>
104
+ {"runId":"2319932e-02c1-4f9d-98db-3c5a410395da","workflow":"release","instanceId":"c898d8c7-e48b-4a56-8101-7148905b6aed","status":"active","value":"review","context":{"version":"1.4.0"},"children":[],"waiting":[],"held":[],"assembly":"83858e28b054","gates":[{"gate":"review","path":["review"],"accepts":[{"name":"approve","description":"Release this version.","input":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{},"additionalProperties":false}},{"name":"reject","description":"Do not release this version. Say why.","input":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"reason":{"type":"string","minLength":1}},"required":["reason"],"additionalProperties":false}}],"acceptsNow":["approve","reject"],"meta":{"version":"1.4.0"}}]}
105
+ ```
106
+
107
+ `gates` holds each open Gate of the run, as a [`GateView`](../reference/http-api.md#type-gateview):
108
+
109
+ - `gate` is the id of the Gate. Give it in `--gate`. When the Machine gives the Gate no id, jr2 makes the id from the
110
+ path of the Gate's state. Here it is `review`, the key of the state.
111
+ - `accepts` holds each event that the Gate accepts: its `name`, its `description`, and its `input` as JSON Schema.
112
+ - `acceptsNow` holds the events that the run takes now. A guard on a transition can remove an event from this list.
113
+ - `meta` holds the data that the Machine gives to the Gate.
114
+
115
+ A run that has no open Gate has `"gates":[]`.
116
+
117
+ ## Answer from the CLI
118
+
119
+ Run [`jr2 send`](../reference/cli.md#send). Give the Gate in `--gate`, the event in `--event`, and the input of the
120
+ event as a JSON object in `--input`:
121
+
122
+ ```sh
123
+ jr2 send 2319 --gate review --event reject --input '{"reason":"The changelog is not ready."}'
124
+ ```
125
+
126
+ ```text
127
+ → context <context> / namespace <namespace>
128
+ delivered reject to gate "review" on 2319932e-02c1-4f9d-98db-3c5a410395da
129
+ ```
130
+
131
+ `jr2 send` prints `delivered` only when the run took the event. In the first terminal, the run ends. A `reject` ends the
132
+ release, so the `rejected` state invokes [`fail`](../reference/authoring-surface/fail.md) with the reason, and the run
133
+ ends `failed`. Its output is the [Failure](../reference/glossary.md#failure), and `jr2 run` exits with `1`:
134
+
135
+ ```text
136
+ → active "rejected"
137
+ → failed "rejected"
138
+ failed: The changelog is not ready.
139
+ {"runId":"2319932e-02c1-4f9d-98db-3c5a410395da","workflow":"release","instanceId":"c898d8c7-e48b-4a56-8101-7148905b6aed","status":"failed","value":"rejected","context":{"version":"1.4.0","reason":"The changelog is not ready."},"children":[],"waiting":[],"held":[],"assembly":"83858e28b054","output":{"reason":"The changelog is not ready."}}
140
+ ```
141
+
142
+ The run ended, so its Gate closed. Each example below answers a run that waits. Before each example, start a new run in
143
+ the first terminal:
144
+
145
+ ```sh
146
+ jr2 run release --input '{"version":"1.4.0"}'
147
+ ```
148
+
149
+ For an event with no input, such as `approve`, do not give `--input`:
150
+
151
+ ```sh
152
+ jr2 send <run id> --gate review --event approve
153
+ ```
154
+
155
+ ```text
156
+ → context <context> / namespace <namespace>
157
+ delivered approve to gate "review" on c099e2dc-6dd2-45da-9358-0723c8b83c68
158
+ ```
159
+
160
+ `jr2 send` prints the full run id, also when you give a prefix.
161
+
162
+ ## Answer from the Console
163
+
164
+ You need the Instance token to answer a Gate from the Console. [Open the Console](open-the-console.md) tells how to open
165
+ it and how to get the token.
166
+
167
+ 1. Open the Console.
168
+ 2. Type the Instance token in the `instance token` box in the nav.
169
+ 3. Push Enter. The badge beside the box shows `…`, then `live`.
170
+ 4. Click the `Attention` tab in the drawer on the right. It shows a card for each open Gate of the Workflow that you
171
+ selected. To see the Gates of all the Workflows, select `all workflows`. When you select no Workflow, it shows them
172
+ all.
173
+ 5. Find the card. Its top line shows `⚑` and the id of the Gate at the left. At the right, it shows the Workflow and the
174
+ first 8 characters of the run id. Below it, the card shows the `meta` of the Gate.
175
+ 6. The card has a form for each event that the Gate accepts. Fill in the form of the event that you send. A field that
176
+ has `*` after its name is necessary.
177
+ 7. Click `send` in that form.
178
+
179
+ When the run takes the event, the card goes away. When the [Orchestrator](../reference/glossary.md#orchestrator) refuses
180
+ the event, the form shows the refusal text below the `send` button.
181
+
182
+ The `⚑` badge in the nav gives the number of open Gates in all the Workflows. Click it to open the `Attention` tab.
183
+
184
+ ## Answer from a webhook or CI
185
+
186
+ A webhook handler or a CI job answers a Gate with
187
+ [`POST /runs/:runId/gates/:gate/events`](../reference/http-api.md#post-runs-runid-gates-gate-events) and the Instance
188
+ token. jr2 has no webhook receiver of its own. Your handler or job reads its own event, finds the run and the Gate, and
189
+ sends the call. The body is the event: `type` is the name of the event, and the other properties are its input.
190
+
191
+ `jr2 up` makes the Service `jr2-orchestrator` on port 4000, with no address outside the cluster. Thus a caller outside
192
+ the cluster uses a port forward, or an address that you make for the Service.
193
+
194
+ In a new terminal, forward a port to the Orchestrator. Keep this command open:
195
+
196
+ ```sh
197
+ kubectl -n <namespace> port-forward svc/jr2-orchestrator 4000:4000
198
+ ```
199
+
200
+ In a different terminal, get the Instance token into a variable:
201
+
202
+ ```sh
203
+ TOKEN=$(kubectl -n <namespace> get secret jr2-instance -o jsonpath='{.data.JR2_INSTANCE_TOKEN}' | base64 -d)
204
+ ```
205
+
206
+ Send the event. Use the full run id, because the route does not accept a prefix:
207
+
208
+ ```sh
209
+ curl -s -X POST http://localhost:4000/runs/<run id>/gates/review/events \
210
+ -H "Authorization: Bearer $TOKEN" \
211
+ -H "Content-Type: application/json" \
212
+ -d '{"type":"approve"}'
213
+ ```
214
+
215
+ ```text
216
+ {"ok":true}
217
+ ```
218
+
219
+ A webhook handler often knows a fact, such as a version, but not the run id. It can find the run from the `meta` of the
220
+ Gate. [`GET /runs`](../reference/http-api.md#get-runs) gives the live runs, and
221
+ [`GET /runs/:runId`](../reference/http-api.md#get-runs-runid) gives the open Gates of one run. This script approves the
222
+ `release` run that waits for one version. It needs `curl` and `jq`. Save it as `approve-release.sh`:
223
+
224
+ ```sh
225
+ #!/bin/sh
226
+ # Approve the release run that waits at its review Gate for one version.
227
+ # Set JR2_URL, JR2_TOKEN and VERSION before you run this script. It needs curl and jq.
228
+ set -eu
229
+
230
+ auth="Authorization: Bearer $JR2_TOKEN"
231
+
232
+ # The live runs of the release Workflow.
233
+ for run in $(curl -fsS -H "$auth" "$JR2_URL/runs" | jq -r '.[] | select(.workflow == "release") | .runId'); do
234
+ # The open Gates of the run, with their meta.
235
+ version=$(curl -fsS -H "$auth" "$JR2_URL/runs/$run" | jq -r '.gates[] | select(.gate == "review") | .meta.version')
236
+ if [ "$version" = "$VERSION" ]; then
237
+ curl -fsS -X POST -H "$auth" -H "Content-Type: application/json" \
238
+ -d '{"type":"approve"}' "$JR2_URL/runs/$run/gates/review/events"
239
+ echo
240
+ fi
241
+ done
242
+ ```
243
+
244
+ ```sh
245
+ JR2_URL=http://localhost:4000 JR2_TOKEN=$TOKEN VERSION=1.4.0 sh approve-release.sh
246
+ ```
247
+
248
+ ```text
249
+ {"ok":true}
250
+ ```
251
+
252
+ A CI job can also run `jr2 send`. With `JR2_URL` and `JR2_TOKEN`, `jr2 send` needs no Instance folder and no kubectl
253
+ context, and it accepts a prefix of the run id:
254
+
255
+ ```sh
256
+ JR2_URL=http://localhost:4000 JR2_TOKEN=$TOKEN jr2 send <run id> --gate review --event approve
257
+ ```
258
+
259
+ ```text
260
+ → http://localhost:4000
261
+ delivered approve to gate "review" on c44c6e49-452d-4150-8ce4-4d036363d2a0
262
+ ```
263
+
264
+ ## Rules
265
+
266
+ - The Orchestrator refuses a Gate that is not open on the run, with the status code `404`:
267
+ `no open gate "<gate>" on run "<run id>" (open: <gates>)`. The part `(open: <gates>)` shows only when the run has an
268
+ open Gate. When an event takes the run out of the state of the Gate, the Gate closes. Thus a second answer gets this
269
+ refusal.
270
+ - The Orchestrator refuses an event that the Gate does not accept, with the status code `400`:
271
+ `"<gate>" does not accept "<event>" (accepts: <events>)`
272
+ - The Orchestrator refuses an input that does not agree with the schema of the event, with the status code `400`:
273
+ `invalid "<event>" payload: <issues>`. `<issues>` is the list of the problems as JSON.
274
+ - The Orchestrator refuses an event that the run does not take now, with the status code `409`, and delivers nothing:
275
+ `gate "<gate>" is open, and the run does not take "<event>" now: <why> — not delivered (takes now: <events>)`. The
276
+ body also holds `acceptsNow`.
277
+ - The Orchestrator refuses a body with no `type`, with the status code `400`:
278
+ `event body must carry a string "type" (one of the gate's accepted names)`
279
+ - The Orchestrator refuses a body that holds `sender`, with the status code `400`:
280
+ `` `sender` is written by the Orchestrator on every delivered event; a caller cannot send it ``
281
+ - The Orchestrator refuses an event without the Instance token, with the status code `401`: `unauthorized`.
282
+ - The Orchestrator refuses an event with the token of a [Sandbox](../reference/glossary.md#sandbox), with the status
283
+ code `403`: `a Sandbox token cannot deliver to a gate — gates are not on the Agent's surface`. Thus an Agent cannot
284
+ answer a Gate.
285
+ - `jr2 send` prints each refusal of the Orchestrator as `error: <refusal>`, and exits with `1`. After a `404` refusal,
286
+ it also prints the version of the Instance in one more line:
287
+ ``instance: <version> (<hash>) — if it predates this CLI, `jr2 up` converges the cluster to this kit``. `<hash>` is
288
+ the hash of the current [Assembly](../reference/glossary.md#assembly).
289
+ - `jr2 send` without `--gate` sends run control, and run control accepts only `CANCEL`. For a different event, it exits
290
+ with `2`: `jr2 send: unknown event "<event>" (run control accepts: CANCEL; workflow events need --gate)`
291
+ - With `--gate`, `jr2 send` sends nothing when `--input` is not valid JSON. It exits with `2`:
292
+ `jr2 send: --input is not valid JSON`
293
+ - `jr2 send` with no run id or no `--event` sends nothing. It prints its help and exits with `2`.
294
+
295
+ ## Read next
296
+
297
+ - [Gates](../concepts/gates.md)
298
+ - [ADR-0011](../reference/decisions/0011-workflow-defined-events.md): a Gate, its events, and its `meta`.
299
+ - [ADR-0013](../reference/decisions/0013-the-agent-reaches-its-machine-through-a-container-it-cannot-read.md): why an
300
+ Agent cannot answer a Gate, and why a refused event is not delivered.
301
+ - [ADR-0032](../reference/decisions/0032-the-console-unlocks-with-the-instance-token.md): the Instance token in the
302
+ Console.
303
+ - [Start a run](start-a-run.md)
304
+ - [Watch a run](watch-a-run.md)
@@ -0,0 +1,224 @@
1
+ ---
2
+ title: "Bind a shipped Machine's Open parts"
3
+ description: Register a Machine from a package as a Workflow, and bind the parts that it leaves Open with customize().
4
+ ---
5
+
6
+ # Bind a shipped Machine's Open parts
7
+
8
+ Register a [Machine](../reference/glossary.md#machine) from a package as a
9
+ [Workflow](../reference/glossary.md#workflow), and bind the parts that it leaves [Open](../reference/glossary.md#open)
10
+ with [`customize()`](../reference/authoring-surface/customize.md).
11
+
12
+ A package does not know your [Repo](../reference/glossary.md#repo), and it cannot pay for your model. Thus a Machine in
13
+ a package marks these parts with [`open`](../reference/authoring-surface/open.md), and you bind them on the line that
14
+ registers it. [`jr2 up`](../reference/cli.md#up) refuses a Workflow with an Open part that nobody bound.
15
+
16
+ The examples on this page register [`task`](../reference/machines.md#task), the Machine that `@jr2/machines` ships.
17
+ `task` leaves two parts Open: its whole [Repo Slot](../reference/glossary.md#repo-slot) map, and the model of its
18
+ [Agent](../reference/glossary.md#agent) `coder`.
19
+
20
+ ## Install the package
21
+
22
+ Install `@jr2/machines` at the [Kit version](../reference/glossary.md#kit-version) of your
23
+ [Instance](../reference/glossary.md#instance). `<version>` is the version of `@jr2/orchestrator` in your `package.json`:
24
+
25
+ ```sh
26
+ npm install --save-exact @jr2/machines@<version>
27
+ ```
28
+
29
+ ## Find the Open parts
30
+
31
+ Register the Machine as it is. Save this file as `workflows/fix-app.ts`:
32
+
33
+ ```ts
34
+ import { task } from "@jr2/machines";
35
+
36
+ // The Machine as it is, with no part bound. jr2 up refuses this file, and prints the line that binds one part.
37
+ export const machine = task;
38
+ ```
39
+
40
+ Then run `jr2 up`. It stops before it changes the cluster. For each Open part, it prints the `customize()` line that
41
+ binds the part:
42
+
43
+ ```sh
44
+ jr2 up
45
+ ```
46
+
47
+ ```text
48
+ jr2 up — instance "my-instance" → context kind-jr2 / namespace my-instance
49
+ typecheck: tsc --noEmit (the instance's own compiler)
50
+ refusing: workflow "fix-app" leaves its Repo Slots open — bind it where the Machine is registered: export const machine = customize(<import>, { repos: { <slot>: "<url>" } }) (ADR-0051)
51
+ refusing: workflow "fix-app" leaves Agent "coder" open — bind it where the Machine is registered: export const machine = customize(<import>, { agents: { coder: { model: "<provider>/<model>" } } }) (ADR-0054)
52
+ ```
53
+
54
+ [The Reference of `@jr2/machines`](../reference/machines.md) also gives the Open parts of each Machine.
55
+
56
+ ## Bind the Open parts
57
+
58
+ Replace the file with one `customize()` call that binds the two parts. The coder works in the Repo `app`. It can read
59
+ the Repo `handbook`.
60
+
61
+ **Anthropic**
62
+
63
+ ```ts
64
+ import { customize } from "@jr2/orchestrator";
65
+ import { task } from "@jr2/machines";
66
+
67
+ const model = "anthropic/claude-haiku-5-5";
68
+
69
+ // `task` leaves two parts Open: its Repo Slots and the model of its coder. Bind the two here.
70
+ // The file name gives the Workflow its name: fix-app.
71
+ export const machine = customize(task, {
72
+ repos: {
73
+ // The first Repo Slot is the Repo that the coder works in. Its branch starts from `main`.
74
+ app: { url: "https://github.com/<you>/app.git", ref: "main" },
75
+ // The coder can read each Repo Slot after the first. A url alone uses the default branch.
76
+ handbook: "https://github.com/<you>/handbook.git",
77
+ },
78
+ // `{ model }` changes only the model. The coder keeps the instructions of `task`.
79
+ agents: { coder: { model } },
80
+ });
81
+ ```
82
+
83
+ **Local**
84
+
85
+ ```ts
86
+ import { customize } from "@jr2/orchestrator";
87
+ import { task } from "@jr2/machines";
88
+
89
+ const model = "local/qwen3.6-35b-a3b";
90
+
91
+ // `task` leaves two parts Open: its Repo Slots and the model of its coder. Bind the two here.
92
+ // The file name gives the Workflow its name: fix-app.
93
+ export const machine = customize(task, {
94
+ repos: {
95
+ // The first Repo Slot is the Repo that the coder works in. Its branch starts from `main`.
96
+ app: { url: "https://github.com/<you>/app.git", ref: "main" },
97
+ // The coder can read each Repo Slot after the first. A url alone uses the default branch.
98
+ handbook: "https://github.com/<you>/handbook.git",
99
+ },
100
+ // `{ model }` changes only the model. The coder keeps the instructions of `task`.
101
+ agents: { coder: { model } },
102
+ });
103
+ ```
104
+
105
+ Write the owner of your Repos in place of `<you>`. A private Repo needs a git credential in the cluster.
106
+ [Give the cluster git credentials](give-the-cluster-git-credentials.md) tells how.
107
+
108
+ The coder uses the model of the tab. Connect that model in `jr2.config.ts` and `.env` before you run `jr2 up`.
109
+ [Connect a model](../get-started/connect-a-model.md) tells how. Run `jr2 up` again. It converges. Then start a run with
110
+ a prompt:
111
+
112
+ ```sh
113
+ jr2 run fix-app --input '{"prompt":"Make the failing test in test/greet.test.ts pass."}'
114
+ ```
115
+
116
+ [An Agent in a Sandbox](../get-started/an-agent-in-a-sandbox.md) gives a full run of `task`, with the `review`
117
+ [Gate](../reference/glossary.md#gate).
118
+
119
+ ### A Repo Slot
120
+
121
+ The key of each Repo Slot is the name of the slot, and the directory `/work/<slot>` in the
122
+ [Sandbox](../reference/glossary.md#sandbox). The value is one of these:
123
+
124
+ - a url: `"https://github.com/<you>/handbook.git"`. The clone stays on the default branch of the Repo, and a new
125
+ [Worktree](../reference/glossary.md#worktree) branch starts from it.
126
+ - a [Binding](../reference/glossary.md#binding): `{ url, ref }`. The clone stays on `ref`, a branch, a tag or a commit,
127
+ and a new branch starts from it.
128
+ - a function of the run input: `({ input }) => url`, or `({ input }) => ({ url, ref })`. Each run chooses its Repo. The
129
+ url must agree with an entry of [`git.credentials`](../reference/config.md#git-credentials) in `jr2.config.ts`.
130
+ - `open`, to leave the slot Open for the Instance that registers your Machine.
131
+
132
+ `task` leaves the whole map Open. Thus you name every slot, and you name one slot or more. The order has the meaning
133
+ that the Machine gives it. For `task`, the first slot is the Repo that the coder works in, and the coder can read the
134
+ others. A Machine that names its slots, such as `repos: { app: open }`, takes only those keys.
135
+
136
+ ### An Agent
137
+
138
+ `agents` takes the fields of the definition of an Agent, by slot. Each field goes over the field that the author wrote.
139
+ Thus `{ model }` changes only the model, and the coder keeps the instructions of `task`. You can also change other
140
+ fields, such as `thinkingLevel` or `instructions`.
141
+ [`AgentDefinition`](../reference/authoring-surface/type-agentdefinition.md) gives the fields.
142
+
143
+ ## Bind the parts of a Machine that you compose
144
+
145
+ When your Machine invokes a packaged Machine as a child, the Open parts of the child are Open in your Machine too. Bind
146
+ them in one of two ways:
147
+
148
+ - Bind them on the import, before you put it under `actors`: `const coding = customize(task, { repos, agents })`. Then
149
+ use `coding` as the child. [Composition](../concepts/composition.md) has an example.
150
+ - Bind them on your Machine, through the slot of the child:
151
+ `customize(yours, { actors: { <slot>: { repos, agents } } })`.
152
+
153
+ `jr2 up` names the child in the refusal, and it prints the line with `actors`. For example, a Machine `outer` puts
154
+ `task` under `actors` as `coding`, and binds nothing:
155
+
156
+ ```text
157
+ …
158
+ refusing: workflow "outer" leaves its Repo Slots open (on the Machine composed as "coding") — bind it where the Machine is registered: export const machine = customize(<import>, { actors: { coding: { repos: { <slot>: "<url>" } } } }) (ADR-0051)
159
+ refusing: workflow "outer" leaves Agent "coder" open (on the Machine composed as "coding") — bind it where the Machine is registered: export const machine = customize(<import>, { actors: { coding: { agents: { coder: { model: "<provider>/<model>" } } } } }) (ADR-0054)
160
+ ```
161
+
162
+ When `task` is a child of your Machine, give it `branch` in its input. Only the root Machine of a run gets the id that
163
+ `task` makes a branch name from.
164
+
165
+ ## Bind the Open parts of an Effect
166
+
167
+ A packaged Machine can leave the url of an `http` [Effect](../reference/glossary.md#effect), the argv of a `command`, or
168
+ the name of a secret Open. Bind them with `effects`, by the slot of the Effect:
169
+ `customize(machine, { effects: { notify: { url } } })`. One object binds all the Open parts of one Effect. You bind each
170
+ part one time, to a value. No run chooses it. [`EffectBinding`](../reference/authoring-surface/type-effectbinding.md)
171
+ gives the values, and [Run a command or call a URL with an Effect](run-a-command-or-call-a-url.md) shows an Effect.
172
+
173
+ ## Rules
174
+
175
+ - `jr2 up` refuses a registered Machine that leaves a part Open. It changes nothing in the cluster:
176
+ `refusing: workflow "<name>" leaves <part> open — bind it where the Machine is registered: export const machine = customize(<import>, <binding>) (<adr>)`.
177
+ `<part>` is one of `its Repo Slots`, `Repo Slot "<slot>"`, `Agent "<slot>"`, or `the <parts> of Effect "<slot>"`,
178
+ where `<parts>` is such as `url` or `url and secret`. For a child Machine, `(on the Machine composed as "<slot>")`
179
+ comes after `open`.
180
+ - `jr2 up` refuses an Open part on a Machine that a state writes in its `invoke.src`, because no `customize()` gets to
181
+ it. Put that Machine under `actors`:
182
+ `refusing: workflow "<name>" leaves <part> open on a Machine invoked inline — no customize() reaches an actor without a slot key; declare that Machine under setup({ actors }) and bind it there (ADR-0049, <adr>)`
183
+ - The compiler refuses a key for a part that the Machine does not declare, such as an Agent slot that it does not have.
184
+ The text of the compiler is:
185
+ `Object literal may only specify known properties, and '<slot>' does not exist in type '<type>'.` Then `jr2 up` prints
186
+ `refusing: this instance does not typecheck — nothing was built and nothing was applied`.
187
+ - `customize()` refuses a slot that the compiler did not see. `jr2 up` prints the refusal as `error: <refusal>`:
188
+ - `customize(): machine "<id>" carries no Agent slot "<slot>" — its Agents are: <slots> (ADR-0049). Only declared parts can be retuned; a Machine that needs another Agent is a new Machine.`
189
+ - `customize(): machine "<id>" composes no Machine under "<slot>" — the Machines it composes are: <slots> (ADR-0049).`
190
+ - `customize(): machine "<id>" declares no Repo Slot "<slot>" — its slots are: <slots> (ADR-0051)`
191
+ - `customize(): machine "<id>" carries no Effect slot "<slot>" — its Effects are: <slots> (ADR-0067). Only declared parts can be bound.`
192
+ - `customize()` refuses an Open map that you bind with no slot:
193
+ ``customize(): machine "<id>" declares its Repo Slots open as a map — name at least one: `repos: { app: "https://…" }` (ADR-0051).``
194
+ - `customize()` refuses a Repo Slot key that is not a directory name. The key becomes `/work/<slot>`:
195
+ ``customize(): Repo Slot key "<slot>" is not a directory name — a slot becomes `/work/<slot>`, `/work/.jr2/` is reserved for jr2, and its order matters, so it starts with a letter and matches /^[A-Za-z][A-Za-z0-9._-]*$/ (ADR-0051, ADR-0075).``
196
+ - `customize()` refuses an empty url:
197
+ ``customize(): Repo Slot "<slot>" is bound to an empty url (got <value>) — a slot is `open`, a url, `{ url, ref? }`, or a mapper `({ input }) => url | { url, ref? }` over the door (ADR-0051).``
198
+ For an empty `ref`, the text says `bound with an empty ref`.
199
+ - `customize()` refuses a url that names no Repo, such as a relative path:
200
+ `customize(): Repo Slot "<slot>" binds "<url>", which names no Repo — <reason> (ADR-0051).`
201
+ - `customize()` refuses `open` or a function as the value of an Effect's part:
202
+ ``customize(): the <kind> Effect "<slot>"'s <part> is bound once, to a value — not `open` again: no run chooses an Effect's <part> (ADR-0054)``.
203
+ For a function, the text says `a function of the run` in place of `` `open` again ``.
204
+ - An Agent does not start a [Turn](../reference/glossary.md#turn) while its model is Open:
205
+ ``agent "<slot>" has an Open model — nobody bound it; bind it where the Machine is registered (`customize(<machine>, { agents: { <slot>: { model: "<provider>/<model>" } } })`), because a packaged Machine cannot pick a model on your behalf (ADR-0054)``.
206
+ `jr2 up` refuses this case first.
207
+ - `task` inside a different Machine refuses to start without `branch` in its input:
208
+ ``task: no `branch` on the door and no Instance ID to derive one from — `jr2/task-<instance id>` needs the id the host injects beside the door of the ROOT machine (ADR-0033), and this run of `task` was started by a parent Machine instead. Pass `branch` in the run input.``
209
+
210
+ ## Read next
211
+
212
+ - [Composition](../concepts/composition.md)
213
+ - [ADR-0054](../reference/decisions/0054-the-kit-ships-machines-and-a-shipped-machine-leaves-its-parts-open.md): the kit
214
+ ships Machines, and a shipped Machine leaves its parts Open.
215
+ - [ADR-0049](../reference/decisions/0049-a-machine-carries-its-parts-and-composes-by-invoke.md): a Machine carries its
216
+ parts, and `customize()` changes them.
217
+ - [ADR-0051](../reference/decisions/0051-a-repo-is-a-slot-on-the-workspace-and-a-cache-on-the-node.md): a Repo is a slot
218
+ on the `workspace()`.
219
+ - [Workspaces](../concepts/workspaces.md)
220
+ - [Publish a Machine as an npm package](publish-a-machine-as-an-npm-package.md), to leave parts Open in a Machine of
221
+ your own.
222
+ - Reference: [`customize()`](../reference/authoring-surface/customize.md),
223
+ [`Customize`](../reference/authoring-surface/type-customize.md), [`open`](../reference/authoring-surface/open.md),
224
+ [`RepoSlot`](../reference/authoring-surface/type-reposlot.md), [`task`](../reference/machines.md#task)