@jr2/orchestrator 0.5.1 → 0.7.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 (350) hide show
  1. package/console/components/app.ts +55 -15
  2. package/console/components/bottom-drawer.ts +259 -0
  3. package/console/components/drawer.ts +14 -6
  4. package/console/components/fleet.ts +36 -13
  5. package/console/components/machine-pane.ts +61 -5
  6. package/console/components/nav.ts +54 -8
  7. package/console/conversation.ts +161 -0
  8. package/console/login.ts +123 -0
  9. package/console/main.ts +600 -60
  10. package/console/store.ts +611 -64
  11. package/console/style.css +231 -0
  12. package/docs/agents-block.md +2 -2
  13. package/docs/concepts/agents-and-turns.md +142 -29
  14. package/docs/concepts/architecture.md +60 -34
  15. package/docs/concepts/callers-and-hooks.md +205 -0
  16. package/docs/concepts/charts.md +13 -8
  17. package/docs/concepts/composition.md +10 -1
  18. package/docs/concepts/converge.md +7 -2
  19. package/docs/concepts/durable-runs.md +43 -16
  20. package/docs/concepts/effects.md +133 -50
  21. package/docs/concepts/gates.md +95 -25
  22. package/docs/concepts/machines-and-workflows.md +14 -4
  23. package/docs/concepts/pools-and-sources.md +193 -17
  24. package/docs/concepts/secrets-and-trust.md +186 -62
  25. package/docs/concepts/the-menu.md +14 -0
  26. package/docs/concepts/workspaces.md +135 -56
  27. package/docs/get-started/a-model-decides.md +14 -13
  28. package/docs/get-started/an-agent-in-a-sandbox.md +46 -35
  29. package/docs/get-started/connect-a-model.md +1 -1
  30. package/docs/get-started/create-an-instance.md +17 -14
  31. package/docs/get-started/have-your-assistant-write-a-machine.md +111 -40
  32. package/docs/get-started/install.md +4 -0
  33. package/docs/guides/add-tools-to-the-sandbox.md +72 -15
  34. package/docs/guides/answer-a-gate-from-a-forge.md +304 -0
  35. package/docs/guides/answer-a-gate.md +74 -37
  36. package/docs/guides/bind-open-parts.md +29 -12
  37. package/docs/guides/call-an-mcp-tool-from-a-machine.md +572 -0
  38. package/docs/guides/cancel-a-run.md +26 -16
  39. package/docs/guides/cut-a-worktree.md +560 -0
  40. package/docs/guides/fix-a-failed-converge.md +19 -7
  41. package/docs/guides/give-a-caller-a-scope.md +203 -0
  42. package/docs/guides/give-an-agent-mcp-tools.md +422 -0
  43. package/docs/guides/iterate-on-a-machine-on-kind.md +10 -9
  44. package/docs/guides/let-an-agent-write-a-chart.md +14 -7
  45. package/docs/guides/look-inside-a-sandbox.md +115 -42
  46. package/docs/guides/move-from-kind-to-a-shared-cluster.md +16 -0
  47. package/docs/guides/open-the-console.md +63 -14
  48. package/docs/guides/push-and-sign-a-branch.md +67 -21
  49. package/docs/guides/read-a-conversation.md +225 -0
  50. package/docs/guides/run-a-chart-by-name.md +17 -16
  51. package/docs/guides/run-a-command-or-call-a-url.md +84 -41
  52. package/docs/guides/run-one-worker-per-item.md +34 -27
  53. package/docs/guides/set-an-agents-access-and-dials.md +69 -22
  54. package/docs/guides/size-a-workspace.md +19 -6
  55. package/docs/guides/start-a-run-for-each-alert.md +290 -0
  56. package/docs/guides/start-a-run-from-a-run.md +18 -16
  57. package/docs/guides/start-a-run.md +24 -18
  58. package/docs/guides/steer-an-agent.md +332 -0
  59. package/docs/guides/use-a-hosted-provider.md +7 -1
  60. package/docs/guides/watch-a-run.md +146 -117
  61. package/docs/guides/write-a-hook-kind.md +238 -0
  62. package/docs/guides/write-a-tool-as-an-mcp-server.md +351 -0
  63. package/docs/guides/write-a-workflow.md +18 -8
  64. package/docs/llms.txt +110 -23
  65. package/docs/reference/authoring-surface/agent.md +35 -12
  66. package/docs/reference/authoring-surface/answer.md +20 -4
  67. package/docs/reference/authoring-surface/arg.md +28 -6
  68. package/docs/reference/authoring-surface/basic.md +1 -1
  69. package/docs/reference/authoring-surface/bearer.md +1 -1
  70. package/docs/reference/authoring-surface/branchname.md +15 -0
  71. package/docs/reference/authoring-surface/carry.md +23 -0
  72. package/docs/reference/authoring-surface/chartschema.md +1 -1
  73. package/docs/reference/authoring-surface/chartschemafor.md +1 -1
  74. package/docs/reference/authoring-surface/command.md +37 -22
  75. package/docs/reference/authoring-surface/customize.md +4 -1
  76. package/docs/reference/authoring-surface/defineconfig.md +1 -1
  77. package/docs/reference/authoring-surface/defineevent.md +1 -1
  78. package/docs/reference/authoring-surface/dispatch.md +5 -4
  79. package/docs/reference/authoring-surface/fail.md +18 -5
  80. package/docs/reference/authoring-surface/file.md +37 -17
  81. package/docs/reference/authoring-surface/frompick.md +1 -1
  82. package/docs/reference/authoring-surface/gate.md +118 -0
  83. package/docs/reference/authoring-surface/group-agents.md +15 -0
  84. package/docs/reference/authoring-surface/group-charts.md +16 -0
  85. package/docs/reference/authoring-surface/group-composition.md +25 -0
  86. package/docs/reference/authoring-surface/group-config.md +17 -0
  87. package/docs/reference/authoring-surface/group-effects.md +48 -0
  88. package/docs/reference/authoring-surface/group-failure.md +13 -0
  89. package/docs/reference/authoring-surface/group-gates.md +16 -0
  90. package/docs/reference/authoring-surface/group-machine-and-events.md +15 -0
  91. package/docs/reference/authoring-surface/group-steering.md +12 -0
  92. package/docs/reference/authoring-surface/group-types-these-signatures-name.md +137 -0
  93. package/docs/reference/authoring-surface/group-workspaces-and-repos.md +15 -0
  94. package/docs/reference/authoring-surface/http.md +109 -9
  95. package/docs/reference/authoring-surface/isfailure.md +1 -1
  96. package/docs/reference/authoring-surface/isready.md +14 -0
  97. package/docs/reference/authoring-surface/jr2setup.md +14 -4
  98. package/docs/reference/authoring-surface/mcp.md +107 -0
  99. package/docs/reference/authoring-surface/open.md +41 -8
  100. package/docs/reference/authoring-surface/openbody.md +1 -1
  101. package/docs/reference/authoring-surface/paramsof.md +23 -5
  102. package/docs/reference/authoring-surface/pool.md +79 -11
  103. package/docs/reference/authoring-surface/push.md +31 -13
  104. package/docs/reference/authoring-surface/readyof.md +21 -0
  105. package/docs/reference/authoring-surface/reread.md +19 -0
  106. package/docs/reference/authoring-surface/secret.md +26 -5
  107. package/docs/reference/authoring-surface/sentby.md +1 -1
  108. package/docs/reference/authoring-surface/skip.md +22 -0
  109. package/docs/reference/authoring-surface/source.md +59 -4
  110. package/docs/reference/authoring-surface/steer.md +93 -0
  111. package/docs/reference/authoring-surface/text.md +1 -1
  112. package/docs/reference/authoring-surface/type-agentdefinition.md +16 -3
  113. package/docs/reference/authoring-surface/type-agentmcpserver.md +54 -0
  114. package/docs/reference/authoring-surface/type-agentslots.md +4 -1
  115. package/docs/reference/authoring-surface/type-anyframepath.md +14 -0
  116. package/docs/reference/authoring-surface/type-anyworktreepath.md +15 -0
  117. package/docs/reference/authoring-surface/type-bindactors.md +14 -0
  118. package/docs/reference/authoring-surface/type-binding.md +6 -7
  119. package/docs/reference/authoring-surface/type-caller.md +40 -0
  120. package/docs/reference/authoring-surface/type-callerrecord.md +32 -0
  121. package/docs/reference/authoring-surface/type-carry.md +19 -0
  122. package/docs/reference/authoring-surface/type-chainlink.md +3 -3
  123. package/docs/reference/authoring-surface/type-commandinput.md +4 -3
  124. package/docs/reference/authoring-surface/type-commandoptions.md +0 -22
  125. package/docs/reference/authoring-surface/type-commandoutput.md +23 -5
  126. package/docs/reference/authoring-surface/type-customize.md +20 -3
  127. package/docs/reference/authoring-surface/type-delivered.md +17 -0
  128. package/docs/reference/authoring-surface/type-deliveredevent.md +18 -0
  129. package/docs/reference/authoring-surface/type-dispatchdefinition.md +4 -3
  130. package/docs/reference/authoring-surface/type-dispatchoutput.md +9 -2
  131. package/docs/reference/authoring-surface/type-doorlessinput.md +19 -0
  132. package/docs/reference/authoring-surface/type-effectbinding.md +12 -2
  133. package/docs/reference/authoring-surface/type-filebody.md +4 -8
  134. package/docs/reference/authoring-surface/type-framepath.md +14 -0
  135. package/docs/reference/authoring-surface/type-gatebinding.md +15 -0
  136. package/docs/reference/authoring-surface/type-gatehooks.md +12 -0
  137. package/docs/reference/authoring-surface/type-gatelook.md +37 -0
  138. package/docs/reference/authoring-surface/type-gateoutcome.md +32 -0
  139. package/docs/reference/authoring-surface/type-gatereply.md +19 -0
  140. package/docs/reference/authoring-surface/type-gateslot.md +21 -0
  141. package/docs/reference/authoring-surface/type-gateslotinput.md +13 -0
  142. package/docs/reference/authoring-surface/type-gateslotparts.md +18 -0
  143. package/docs/reference/authoring-surface/type-gateslots.md +12 -0
  144. package/docs/reference/authoring-surface/type-gatetypesat.md +13 -0
  145. package/docs/reference/authoring-surface/type-hostinjectedinput.md +3 -5
  146. package/docs/reference/authoring-surface/type-httpdefinition.md +6 -3
  147. package/docs/reference/authoring-surface/type-httpfileinput.md +20 -0
  148. package/docs/reference/authoring-surface/type-httpoutput.md +8 -2
  149. package/docs/reference/authoring-surface/type-jr2config.md +37 -2
  150. package/docs/reference/authoring-surface/type-lateroutcome.md +21 -0
  151. package/docs/reference/authoring-surface/type-lends.md +5 -1
  152. package/docs/reference/authoring-surface/type-lookoutput.md +14 -0
  153. package/docs/reference/authoring-surface/type-mcpcalloutput.md +78 -0
  154. package/docs/reference/authoring-surface/type-mcpnotreturned.md +42 -0
  155. package/docs/reference/authoring-surface/type-mcpoptions.md +47 -0
  156. package/docs/reference/authoring-surface/type-mcpoutput.md +50 -0
  157. package/docs/reference/authoring-surface/type-mcpreadoutput.md +53 -0
  158. package/docs/reference/authoring-surface/type-mcpremoteserver.md +50 -0
  159. package/docs/reference/authoring-surface/type-mcpserver.md +41 -0
  160. package/docs/reference/authoring-surface/type-mcpstdioserver.md +42 -0
  161. package/docs/reference/authoring-surface/type-namedsecret.md +4 -4
  162. package/docs/reference/authoring-surface/type-namestart.md +77 -0
  163. package/docs/reference/authoring-surface/type-noslotworkspaceoptions.md +1 -6
  164. package/docs/reference/authoring-surface/type-notworktreekeys.md +12 -0
  165. package/docs/reference/authoring-surface/type-openbodydeclaration.md +1 -1
  166. package/docs/reference/authoring-surface/type-openbodyoutput.md +1 -1
  167. package/docs/reference/authoring-surface/type-opencommandinput.md +7 -2
  168. package/docs/reference/authoring-surface/type-permissivenoslotworkspaceoptions.md +1 -6
  169. package/docs/reference/authoring-surface/type-permissiveworkspaceoptions.md +5 -10
  170. package/docs/reference/authoring-surface/type-poolnextinput.md +22 -0
  171. package/docs/reference/authoring-surface/type-poolspec.md +11 -6
  172. package/docs/reference/authoring-surface/type-pushinput.md +22 -3
  173. package/docs/reference/authoring-surface/type-pushoutput.md +33 -8
  174. package/docs/reference/authoring-surface/type-pushsourcespec.md +38 -0
  175. package/docs/reference/authoring-surface/type-readsourcespec.md +47 -0
  176. package/docs/reference/authoring-surface/type-reposlot.md +6 -6
  177. package/docs/reference/authoring-surface/type-reread.md +18 -0
  178. package/docs/reference/authoring-surface/type-runsconfig.md +41 -0
  179. package/docs/reference/authoring-surface/type-sandboxoptions.md +11 -4
  180. package/docs/reference/authoring-surface/type-sender.md +26 -1
  181. package/docs/reference/authoring-surface/type-sendercallerfield.md +14 -0
  182. package/docs/reference/authoring-surface/type-size.md +1 -1
  183. package/docs/reference/authoring-surface/type-skip.md +19 -0
  184. package/docs/reference/authoring-surface/type-slothandles.md +5 -13
  185. package/docs/reference/authoring-surface/type-sourcehooks.md +23 -0
  186. package/docs/reference/authoring-surface/type-sourcein.md +25 -0
  187. package/docs/reference/authoring-surface/type-sourcereply.md +18 -0
  188. package/docs/reference/authoring-surface/type-sourcespec.md +26 -17
  189. package/docs/reference/authoring-surface/type-sourceverdict.md +49 -0
  190. package/docs/reference/authoring-surface/type-standingpoolmachine.md +12 -0
  191. package/docs/reference/authoring-surface/type-standingpoolspec.md +51 -0
  192. package/docs/reference/authoring-surface/type-steerargs.md +20 -0
  193. package/docs/reference/authoring-surface/type-thinkinglevel.md +1 -1
  194. package/docs/reference/authoring-surface/type-usercontainer.md +1 -1
  195. package/docs/reference/authoring-surface/type-workspaced.md +30 -9
  196. package/docs/reference/authoring-surface/type-workspacehandles.md +5 -6
  197. package/docs/reference/authoring-surface/type-workspaceoptions.md +1 -13
  198. package/docs/reference/authoring-surface/type-worktreefound.md +16 -0
  199. package/docs/reference/authoring-surface/type-worktreeinput.md +56 -0
  200. package/docs/reference/authoring-surface/type-worktreekey.md +14 -0
  201. package/docs/reference/authoring-surface/type-worktreeoptions.md +29 -0
  202. package/docs/reference/authoring-surface/type-worktreeoutput.md +45 -0
  203. package/docs/reference/authoring-surface/type-worktreepath.md +16 -0
  204. package/docs/reference/authoring-surface/type-worktreeready.md +37 -0
  205. package/docs/reference/authoring-surface/type-worktreerefused.md +21 -0
  206. package/docs/reference/authoring-surface/workspace.md +66 -38
  207. package/docs/reference/authoring-surface/worktree.md +71 -0
  208. package/docs/reference/authoring-surface.md +88 -147
  209. package/docs/reference/cli.md +413 -74
  210. package/docs/reference/config.md +248 -6
  211. package/docs/reference/decisions/0001-operator-owned-generic-sandbox.md +10 -9
  212. package/docs/reference/decisions/0002-duplex-streaming-actor.md +81 -14
  213. package/docs/reference/decisions/0004-worktree-provisioning-model.md +27 -21
  214. package/docs/reference/decisions/0005-sandbox-pod-composition.md +39 -25
  215. package/docs/reference/decisions/0006-agent-control-surface.md +6 -3
  216. package/docs/reference/decisions/0007-durable-machine-state.md +1 -1
  217. package/docs/reference/decisions/0009-cli-and-instance-interface.md +150 -49
  218. package/docs/reference/decisions/0010-bdd-acceptance-tests.md +5 -3
  219. package/docs/reference/decisions/0011-workflow-defined-events.md +256 -12
  220. package/docs/reference/decisions/0012-workspace-wrapper-machine.md +39 -32
  221. package/docs/reference/decisions/0013-the-agent-reaches-its-machine-through-a-container-it-cannot-read.md +54 -30
  222. package/docs/reference/decisions/0014-observation-is-open-run-state-is-not.md +53 -27
  223. package/docs/reference/decisions/0015-authoring-surface-absorbs-the-mechanism.md +26 -16
  224. package/docs/reference/decisions/0016-agent-turn-mechanics-are-internal.md +9 -7
  225. package/docs/reference/decisions/0017-pool-over-a-source-port.md +226 -10
  226. package/docs/reference/decisions/0018-instance-agents-are-definitions-jr2-assembles-the-harness.md +15 -7
  227. package/docs/reference/decisions/0019-one-converging-command-against-the-current-context.md +53 -27
  228. package/docs/reference/decisions/0021-workspace-continuity-is-a-lease-that-answers-back.md +16 -2
  229. package/docs/reference/decisions/0022-observation-is-a-level-triggered-feed.md +4 -4
  230. package/docs/reference/decisions/0023-the-harness-prints-the-conversation.md +124 -43
  231. package/docs/reference/decisions/0024-an-agents-turn-ends-with-the-state-that-asked-for-it.md +36 -38
  232. package/docs/reference/decisions/0025-cancel-ends-a-run-stop-parks-it.md +10 -5
  233. package/docs/reference/decisions/0027-the-harness-is-jr2s-own-server-flue-retires-the-wire-stays.md +16 -7
  234. package/docs/reference/decisions/0028-what-an-agent-may-do-to-the-workspace-is-part-of-its-definition.md +36 -19
  235. package/docs/reference/decisions/0029-a-menu-is-fixed-for-a-conversation-and-a-turn-is-told-its-allowed-picks.md +18 -10
  236. package/docs/reference/decisions/0030-a-snapshot-names-the-machine-it-was-written-under.md +3 -2
  237. package/docs/reference/decisions/0031-menu-only-agents-run-on-the-instance-harness.md +23 -15
  238. package/docs/reference/decisions/0032-the-console-unlocks-with-a-callers-credential.md +101 -0
  239. package/docs/reference/decisions/0033-a-machine-declares-the-input-that-starts-it.md +22 -22
  240. package/docs/reference/decisions/0034-the-console-renders-with-preact-and-the-server-erases-the-types.md +6 -6
  241. package/docs/reference/decisions/0037-an-instance-builds-its-sandbox-images-jr2-injects-the-harness.md +13 -12
  242. package/docs/reference/decisions/0049-a-machine-carries-its-parts-and-composes-by-invoke.md +23 -23
  243. package/docs/reference/decisions/0050-what-code-names-config-declares-what-the-cli-names-discovery-finds.md +6 -1
  244. package/docs/reference/decisions/0051-a-repo-is-a-slot-on-the-workspace-and-a-cache-on-the-node.md +57 -46
  245. package/docs/reference/decisions/0052-a-sandbox-lands-where-an-ordinary-pod-lands-and-the-cache-follows-it.md +5 -0
  246. package/docs/reference/decisions/0053-a-fetch-inside-the-pod-asks-the-node-cache-and-the-cache-asks-the-remote.md +20 -8
  247. package/docs/reference/decisions/0054-the-kit-ships-machines-and-a-shipped-machine-leaves-its-parts-open.md +55 -40
  248. package/docs/reference/decisions/0055-a-release-is-a-pushed-tag-and-the-publish-guard-is-the-credential.md +14 -13
  249. package/docs/reference/decisions/0057-a-turn-is-its-frame-its-dials-and-whether-it-continues.md +31 -24
  250. package/docs/reference/decisions/0058-a-harness-answers-the-orchestrator-alone.md +18 -10
  251. package/docs/reference/decisions/0059-a-harness-holds-stand-ins-and-the-custodian-holds-the-keys.md +137 -86
  252. package/docs/reference/decisions/0062-jr2-briefs-the-agent-on-its-seat-never-on-its-task.md +165 -91
  253. package/docs/reference/decisions/0063-the-orchestrator-watches-the-cluster.md +7 -7
  254. package/docs/reference/decisions/0064-a-workspace-waits-for-capacity.md +2 -2
  255. package/docs/reference/decisions/0065-a-persist-survives-a-crash-and-history-is-kept-for-a-set-time.md +109 -0
  256. package/docs/reference/decisions/0066-a-model-tier-runs-a-real-model-and-a-change-to-what-it-reads-runs-the-tier.md +53 -23
  257. package/docs/reference/decisions/0067-an-effect-is-an-actor-slot-and-runs-at-most-once-unless-marked-idempotent.md +221 -153
  258. package/docs/reference/decisions/0068-an-effector-holds-an-effects-secrets-and-signs-its-wire.md +161 -96
  259. package/docs/reference/decisions/0069-the-orchestrator-is-a-kit-image-and-an-instance-publishes-its-assembly.md +32 -9
  260. package/docs/reference/decisions/0070-a-machine-lends-its-parts-to-a-chart.md +48 -33
  261. package/docs/reference/decisions/0071-a-run-starts-a-run-through-a-dispatch-effect.md +56 -30
  262. package/docs/reference/decisions/0072-the-docs-ship-inside-the-kit-and-an-instances-agents-md-indexes-them.md +35 -25
  263. package/docs/reference/decisions/0073-a-machine-fails-a-run-with-fail-and-an-uncaught-failure-ends-it-failed.md +1 -1
  264. package/docs/reference/decisions/0075-a-machine-cuts-a-worktree-and-the-workspace-only-clones.md +296 -0
  265. package/docs/reference/decisions/0076-an-agents-control-credential-lives-only-where-no-workspace-code-runs.md +347 -0
  266. package/docs/reference/decisions/0077-jr2-requires-landlock-on-every-sandbox-node.md +79 -0
  267. package/docs/reference/decisions/0078-a-caller-comes-from-one-authenticator-seam-and-acts-within-its-scopes.md +285 -0
  268. package/docs/reference/decisions/0079-an-agent-holds-mcp-tools-a-machine-calls-them-as-an-effect-and-the-machine-is-the-approval.md +198 -0
  269. package/docs/reference/decisions.md +9 -4
  270. package/docs/reference/glossary.md +138 -45
  271. package/docs/reference/hooks.md +1077 -0
  272. package/docs/reference/http-api.md +988 -123
  273. package/docs/reference/machines.md +0 -1
  274. package/docs/why.md +7 -5
  275. package/package.json +10 -3
  276. package/src/actor.ts +194 -42
  277. package/src/agent.ts +56 -6
  278. package/src/ambient.ts +3 -5
  279. package/src/assembly-checks.ts +530 -4
  280. package/src/callers.ts +245 -0
  281. package/src/chart.ts +238 -26
  282. package/src/charts.ts +9 -2
  283. package/src/config.ts +566 -7
  284. package/src/conversations.ts +453 -0
  285. package/src/custodian.lua +17 -5
  286. package/src/custodian.ts +257 -77
  287. package/src/customize.ts +154 -7
  288. package/src/dispatch-effect.ts +142 -26
  289. package/src/durability.ts +2 -0
  290. package/src/duration.ts +20 -0
  291. package/src/effect-checks.ts +52 -4
  292. package/src/effect.ts +401 -132
  293. package/src/effector-wire.ts +278 -30
  294. package/src/fail.ts +17 -4
  295. package/src/gate-brand.ts +16 -0
  296. package/src/gate.ts +634 -48
  297. package/src/harness-client.ts +84 -35
  298. package/src/harness-env.ts +33 -0
  299. package/src/held-secrets.ts +197 -39
  300. package/src/holds.ts +5 -2
  301. package/src/hook-kinds/discord.ts +92 -0
  302. package/src/hook-kinds/door.ts +107 -0
  303. package/src/hook-kinds/github.ts +89 -0
  304. package/src/hook-kinds/gitlab.ts +72 -0
  305. package/src/hook-kinds/hook.ts +7 -0
  306. package/src/hook-kinds/index.ts +465 -0
  307. package/src/hook-kinds/slack.ts +151 -0
  308. package/src/hook-kinds/webhook.ts +113 -0
  309. package/src/hooks.ts +506 -0
  310. package/src/http-effect.ts +164 -70
  311. package/src/http.ts +933 -99
  312. package/src/index.ts +30 -5
  313. package/src/instance.ts +196 -26
  314. package/src/internal.ts +23 -3
  315. package/src/kube-client.ts +6 -3
  316. package/src/machine-doc.ts +29 -5
  317. package/src/mcp-effect.ts +424 -0
  318. package/src/model-keys.ts +24 -0
  319. package/src/mount-digest.ts +41 -7
  320. package/src/names.ts +82 -7
  321. package/src/notices.ts +576 -59
  322. package/src/open-body.ts +110 -30
  323. package/src/open-effect.ts +17 -4
  324. package/src/open.ts +40 -7
  325. package/src/parts.ts +125 -35
  326. package/src/party.ts +35 -1
  327. package/src/pick.ts +43 -9
  328. package/src/pool.ts +1172 -172
  329. package/src/registration.ts +249 -17
  330. package/src/repo-identity.ts +7 -3
  331. package/src/repos.ts +20 -2
  332. package/src/run-host.ts +1614 -190
  333. package/src/run-list.ts +191 -0
  334. package/src/sandbox-effect.ts +217 -66
  335. package/src/sandbox-kube.ts +116 -21
  336. package/src/secret-placement.ts +248 -35
  337. package/src/server.ts +53 -4
  338. package/src/setup.ts +158 -38
  339. package/src/snapshot-store.ts +565 -48
  340. package/src/steer.ts +111 -0
  341. package/src/stub-harness.ts +6 -2
  342. package/src/tokens.ts +362 -46
  343. package/src/vocabulary.ts +23 -4
  344. package/src/wire.ts +27 -10
  345. package/src/workspace.ts +314 -259
  346. package/src/worktree.ts +249 -0
  347. package/docs/reference/authoring-surface/type-noslotspec.md +0 -26
  348. package/docs/reference/authoring-surface/type-workspacespec.md +0 -37
  349. package/docs/reference/decisions/0032-the-console-unlocks-with-the-instance-token.md +0 -61
  350. package/docs/reference/decisions/0065-a-persist-survives-a-crash-and-history-is-a-week.md +0 -65
@@ -1,11 +1,11 @@
1
1
  ---
2
2
  title: workspace
3
- description: "Run a body Machine in a Sandbox: a pod of its own, with a Worktree of each Repo Slot on one branch."
3
+ description: "Run a body Machine in a Sandbox: a pod of its own, with a clone of each Repo Slot."
4
4
  ---
5
5
 
6
6
  # `workspace`
7
7
 
8
- Function, in `@jr2/orchestrator/src/workspace.ts`. It is an export of `@jr2/orchestrator`, on the [Authoring surface](../authoring-surface.md) page, in Workspaces and Repos.
8
+ Function, in `@jr2/orchestrator/src/workspace.ts`. It is an export of `@jr2/orchestrator`, in the [Workspaces and Repos](group-workspaces-and-repos.md) group of the [Authoring surface](../authoring-surface.md) page.
9
9
 
10
10
  ## Overload 1
11
11
 
@@ -20,30 +20,33 @@ function workspace<
20
20
  ): WorkspaceMachine<WithoutEmptyIndex<z.infer<TSchema>>, OutputFrom<TBody>, TBody, TSlots>
21
21
  ```
22
22
 
23
- Run a body Machine in a Sandbox: a pod of its own, with a Worktree of each Repo Slot on one
24
- branch. The result is a Machine. Register it as a Workflow, or invoke it from another Machine as
23
+ Run a body Machine in a Sandbox: a pod of its own, with a clone of each Repo Slot. The result is
24
+ a Machine. Register it as a Workflow, or invoke it from another Machine as
25
25
  an actor slot.
26
26
 
27
27
  When a run enters it, the Workspace makes the Sandbox and waits for room on a node, with no
28
- deadline. It clones each Repo Slot and makes its Worktree on the `branch` that `spec` gives. Then
29
- it runs the body with the run input plus `workspace`, the handles (see [`Workspaced`](type-workspaced.md)). The
30
- Agents with Working tools and the `command` Effects in the body run in that Sandbox. An Agent
28
+ deadline. It clones each Repo Slot to `/work/<slot>/default`, on the Binding's base, and makes no
29
+ Worktree: the body cuts each Worktree that it needs with `worktree()`. A slot that is only read
30
+ needs no cut. No work happens in `default/`. Then it runs the body with the run input plus
31
+ `workspace`, the handles (see [`Workspaced`](type-workspaced.md)). The Agents with Working tools and the `command` Effects in the body run in that Sandbox. An Agent
31
32
  with `workspace: "none"` runs on the Instance Harness. When the body reaches a final state, the
32
- Workspace deletes the Sandbox, and its output is the body's output. Push the branch before
33
+ Workspace deletes the Sandbox, and its output is the body's output. Push each branch before
33
34
  then: jr2 deletes the Sandbox's commits with it.
34
35
 
36
+ The author chooses how many Agents work in a Workspace. Agents in one Worktree share git, as
37
+ people in one checkout do. Each coder that needs its own branch gets its own Worktree of the one
38
+ clone.
39
+
35
40
  Leave out `repos` for a Workspace with no Repo Slot: its Agents and `command` Effects share
36
- `/work`, as the steps of one job share a folder, and `spec` is optional and gives only
37
- `workGroup`. The body's input is then `Workspaced<RunInput, never>`. An `http` Effect sends a
38
- file of `/work` with `file(path)`. A `push`, and a `command` with an Effect secret in its `env`,
39
- need a Repo Slot, so jr2 refuses them there. jr2 deletes `/work` with the Sandbox: send what
41
+ `/work`, as the steps of one job share a folder. The body's input is then `Workspaced<RunInput, never>`. An `http` Effect sends a
42
+ file of `/work` with `file(path)`. A `worktree()`, a `push`, and a `command` with an Effect secret in its
43
+ `env`, need a Repo Slot, so jr2 refuses them there. jr2 deletes `/work` with the Sandbox: send what
40
44
  must stay before the body ends.
41
45
 
42
46
  Give each run a different branch, so that two runs do not push to one branch. Make it from a
43
47
  field of the run input, or from `instanceId` when the run input has no field that is different
44
- for each run: ``spec: ({ input }) => ({ branch: `fix/${input.instanceId}` })``. The input of
45
- `spec` holds `instanceId` with no cast, also for the door `z.object({})`. Only a root
46
- `workspace()` gets `instanceId` from jr2. A `workspace()` that a different Machine invokes gets
48
+ for each run: ``branch: `fix/${context.instanceId}` `` in the input of the cut. Add
49
+ `HostInjectedInput` to the body's input type to read it. Only a root `workspace()` gets `instanceId` from jr2. A `workspace()` that a different Machine invokes gets
47
50
  it only when its parent gives it.
48
51
 
49
52
  The Sandbox is Lost when its pod is evicted or its node goes. Then the body gets the event
@@ -67,7 +70,7 @@ It refuses, when you call it:
67
70
  - a body with its own `input`: ``workspace(): the body "<id>" declares its own run input, which
68
71
  nothing will ever serve or enforce — the wrapper feeds the body the run input PLUS the injected
69
72
  `workspace` handles, so the body's schema is not the door. Move it to the wrapper:
70
- workspace(body, { input, spec }) (ADR-0033).``
73
+ workspace(body, { input }) (ADR-0033).``
71
74
  - an empty `image`: ``workspace(): `image` must be a non-empty string (got <value>) — either a
72
75
  `file:` URL to a docker context this module ships (`import.meta.resolve("./image")`) or a
73
76
  registry ref (ADR-0037).``
@@ -77,9 +80,7 @@ It refuses, when you call it:
77
80
  `repos: { app: "https://…" }` — or `open` whole, for a map the consumer names; leave it out
78
81
  for a Workspace with no Repo Slot (ADR-0051).``
79
82
  - a bad Repo Slot name or value (see [`RepoSlot`](type-reposlot.md))
80
- - a `spec` that is not a function, or no `spec` on a Workspace with Repo Slots: ``workspace():
81
- `spec` must be a function from the run input to the spec — spec: ({ input }) => ({ branch }) —
82
- and only a Workspace with no Repo Slot may leave it out (ADR-0051).``
83
+ - a `workGroup` that is not a gid: ``workspace(): `workGroup` must be a gid (got <value>)``
83
84
  - a bad `secrets` list: ``workspace(): `secrets` must be a list of distinct names from
84
85
  jr2.config.ts's `secrets` list (got <value>) — secrets: ["JIRA_TOKEN"] (ADR-0059).``
85
86
  - a bad `effector`: ``workspace(): `effector` is { image } — a `file:` URL to a docker context
@@ -95,19 +96,16 @@ It refuses, when you call it:
95
96
  (ADR-0060)``, or the same text for `resources.limits.<key>`. The other texts are in
96
97
  [`Size`](type-size.md).
97
98
 
98
- And when a run enters it, a spec without a `branch` (or with `branch: "default"`), or with a bad
99
- `reviewSha` or `workGroup`: ``workspace spec invalid: <fields> — the spec derives from run input;
100
- does `jr2 run --input` carry every field this workflow's workspace() mapping reads?``. With no
101
- Repo Slot, a spec with a `branch` or a `reviewSha`: ``workspace spec invalid: <field> (the
102
- Workspace has no Repo Slot, so it has no branch and no review Worktree; its spec gives only
103
- workGroup) …``
99
+ And when a run enters it, a per-run Repo Slot's mapper that gives no `url`, or a bad `ref`:
100
+ ``workspace invalid: repos.<slot> mapper returned <fields> — the mapper derives from run
101
+ input; does `jr2 run --input` carry every field this workflow's workspace() slot reads?``
104
102
 
105
103
  **Parameters**
106
104
 
107
105
  - `body`: The Machine to run in the Sandbox. Its input is `Workspaced<RunInput, Slots>`.
108
106
  - `options` ([`WorkspaceOptions`](type-workspaceoptions.md) | [`NoSlotWorkspaceOptions`](type-noslotworkspaceoptions.md)): What the Sandbox is made of (`image`, `user`, `resources`, `effector`), the
109
- Repo Slots it clones (`repos`), the Held secrets it can use (`secrets`), the run input
110
- (`input`), and the function from the run input to the branch (`spec`).
107
+ Repo Slots it clones (`repos`), the Held secrets it can use (`secrets`), the pod's `fsGroup`
108
+ (`workGroup`), and the run input (`input`).
111
109
 
112
110
  **Returns**: A Machine whose input is the run input and whose output is the body's output.
113
111
 
@@ -118,8 +116,10 @@ import { z } from "zod";
118
116
  import {
119
117
  command,
120
118
  fail,
119
+ isReady,
121
120
  jr2Setup,
122
121
  workspace,
122
+ worktree,
123
123
  type CommandOutput,
124
124
  type Workspaced,
125
125
  } from "@jr2/orchestrator";
@@ -127,23 +127,36 @@ import {
127
127
  const runInput = z.object({ ticket: z.string(), repo: z.string() });
128
128
  type BodyInput = Workspaced<z.infer<typeof runInput>, "app" | "docs">;
129
129
 
130
+ // The Worktree of this run. An Agent or a command that only reads `docs` uses `/work/docs/default`.
131
+ const buildTree = (context: BodyInput) => `${context.workspace.repos.app}/build` as const;
132
+
130
133
  const passed = (output: CommandOutput): boolean =>
131
134
  output.outcome === "exited" && output.code === 0;
132
135
 
133
136
  const body = jr2Setup({
134
- types: {} as { input: BodyInput },
137
+ types: {} as { input: BodyInput; context: BodyInput },
135
138
  actors: {
136
- build: command(["npm", "run", "build"], { slot: "app" }),
139
+ cut: worktree(),
140
+ build: command(["npm", "run", "build"]),
137
141
  fail: fail(),
138
142
  },
139
143
  }).createMachine({
140
144
  id: "build",
145
+ context: ({ input }) => input,
141
146
  on: { "workspace.lost": ".lost" },
142
- initial: "building",
147
+ initial: "cutting",
143
148
  states: {
149
+ cutting: {
150
+ invoke: {
151
+ src: "cut",
152
+ input: ({ context }) => ({ path: buildTree(context), branch: `fix/${context.ticket}` }),
153
+ onDone: [{ guard: ({ event }) => isReady(event.output), target: "building" }, { target: "notCut" }],
154
+ },
155
+ },
144
156
  building: {
145
157
  invoke: {
146
158
  src: "build",
159
+ input: ({ context }) => ({ worktree: buildTree(context) }),
147
160
  onDone: [
148
161
  { guard: ({ event }) => passed(event.output), target: "built" },
149
162
  { target: "broken" },
@@ -152,6 +165,7 @@ const body = jr2Setup({
152
165
  },
153
166
  built: { type: "final" },
154
167
  broken: { invoke: { src: "fail", input: { reason: "npm run build did not pass" } } },
168
+ notCut: { invoke: { src: "fail", input: { reason: "the Worktree was not cut" } } },
155
169
  lost: { invoke: { src: "fail", input: { reason: "the Sandbox is gone" } } },
156
170
  },
157
171
  });
@@ -164,7 +178,6 @@ export const machine = workspace(body, {
164
178
  app: ({ input }) => input.repo,
165
179
  docs: { url: "https://github.com/you/docs.git", ref: "main" },
166
180
  },
167
- spec: ({ input }) => ({ branch: `fix/${input.ticket}` }),
168
181
  });
169
182
  ```
170
183
 
@@ -175,9 +188,12 @@ import { z } from "zod";
175
188
  import {
176
189
  command,
177
190
  fail,
191
+ isReady,
178
192
  jr2Setup,
179
193
  workspace,
194
+ worktree,
180
195
  type CommandOutput,
196
+ type HostInjectedInput,
181
197
  type Workspaced,
182
198
  } from "@jr2/orchestrator";
183
199
 
@@ -187,18 +203,30 @@ const passed = (output: CommandOutput): boolean =>
187
203
  // The run input has no field that is different for each run, so the branch comes from
188
204
  // `instanceId`.
189
205
  const runInput = z.object({});
206
+ type BodyInput = Workspaced<z.infer<typeof runInput> & HostInjectedInput, "app">;
207
+
208
+ const nightlyTree = (context: BodyInput) => `${context.workspace.repos.app}/nightly` as const;
190
209
 
191
210
  const body = jr2Setup({
192
- types: {} as { input: Workspaced<z.infer<typeof runInput>, "app"> },
193
- actors: { test: command(["npm", "test"], { slot: "app" }), fail: fail() },
211
+ types: {} as { input: BodyInput; context: BodyInput },
212
+ actors: { cut: worktree(), test: command(["npm", "test"]), fail: fail() },
194
213
  }).createMachine({
195
214
  id: "nightly",
215
+ context: ({ input }) => input,
196
216
  on: { "workspace.lost": ".lost" },
197
- initial: "testing",
217
+ initial: "cutting",
198
218
  states: {
219
+ cutting: {
220
+ invoke: {
221
+ src: "cut",
222
+ input: ({ context }) => ({ path: nightlyTree(context), branch: `nightly/${context.instanceId}` }),
223
+ onDone: [{ guard: ({ event }) => isReady(event.output), target: "testing" }, { target: "notCut" }],
224
+ },
225
+ },
199
226
  testing: {
200
227
  invoke: {
201
228
  src: "test",
229
+ input: ({ context }) => ({ worktree: nightlyTree(context) }),
202
230
  onDone: [
203
231
  { guard: ({ event }) => passed(event.output), target: "tested" },
204
232
  { target: "red" },
@@ -207,6 +235,7 @@ const body = jr2Setup({
207
235
  },
208
236
  tested: { type: "final" },
209
237
  red: { invoke: { src: "fail", input: { reason: "npm test did not pass" } } },
238
+ notCut: { invoke: { src: "fail", input: { reason: "the Worktree was not cut" } } },
210
239
  lost: { invoke: { src: "fail", input: { reason: "the Sandbox is gone" } } },
211
240
  },
212
241
  });
@@ -215,7 +244,6 @@ export const machine = workspace(body, {
215
244
  input: runInput,
216
245
  image: "docker.io/library/node:24",
217
246
  repos: { app: "https://github.com/you/app.git" },
218
- spec: ({ input }) => ({ branch: `fix/${input.instanceId}` }),
219
247
  });
220
248
  ```
221
249
 
@@ -234,10 +262,10 @@ export const machine = workspace(body, {
234
262
  function workspace<
235
263
  TBody extends AnyStateMachine,
236
264
  TSlots extends string = never,
237
- TInput = unknown,
265
+ TInput = DoorlessInput<TBody>,
238
266
  >(
239
267
  body: TBody & BodyAcceptsSlots<TBody, TSlots>,
240
- options: PermissiveWorkspaceOptions<TSlots, TInput> | PermissiveNoSlotWorkspaceOptions<TInput>,
268
+ options: PermissiveWorkspaceOptions<TSlots, Exclude<TInput, undefined>> | PermissiveNoSlotWorkspaceOptions,
241
269
  ): WorkspaceMachine<TInput, OutputFrom<TBody>, TBody, TSlots>
242
270
  ```
243
271
 
@@ -249,7 +277,7 @@ what it refuses.
249
277
 
250
278
  - `body`: The Machine to run in the Sandbox. Its input is the input of the Workspace plus
251
279
  `workspace`, the handles.
252
- - `options` ([`PermissiveWorkspaceOptions`](type-permissiveworkspaceoptions.md) | [`PermissiveNoSlotWorkspaceOptions`](type-permissivenoslotworkspaceoptions.md)): The options of the Sandbox, and `spec`. There is no `input`.
280
+ - `options` ([`PermissiveWorkspaceOptions`](type-permissiveworkspaceoptions.md) | [`PermissiveNoSlotWorkspaceOptions`](type-permissivenoslotworkspaceoptions.md)): The options of the Sandbox. There is no `input`.
253
281
 
254
282
  **Returns**: A Machine whose input is the run input and whose output is the body's output.
255
283
 
@@ -0,0 +1,71 @@
1
+ ---
2
+ title: worktree
3
+ description: "Make a `worktree` Effect: it cuts a Worktree of a Repo Slot, or reads the one that is there."
4
+ ---
5
+
6
+ # `worktree`
7
+
8
+ Function, in `@jr2/orchestrator/src/worktree.ts`. It is an export of `@jr2/orchestrator`, in the [Effects](group-effects.md) group of the [Authoring surface](../authoring-surface.md) page.
9
+
10
+ ```ts
11
+ function worktree(options: WorktreeOptions = {}): EffectLogic<WorktreeInput, WorktreeOutput>
12
+ ```
13
+
14
+ Make a `worktree` Effect: it cuts a Worktree of a Repo Slot, or reads the one that is there. Put it
15
+ in `actors`, and invoke it from a `workspace()` body.
16
+
17
+ With `{ path, branch, from? }`, the branch resolves in this order, after a fetch: a local branch;
18
+ `origin/<branch>`, tracked; a new branch from `from` or the Binding's base, with no upstream. With
19
+ `{ path, detach }`, the Worktree is forced to that commit and cleaned, each time. `path` is exactly
20
+ `/work/<slot>/<name>`. Each outcome is output: `ready`, `refused`, `unknown`.
21
+
22
+ `expect` says if the branch can exist: `worktree({ expect: "new" })` refuses a branch that exists,
23
+ and `worktree({ expect: "existing" })` refuses a branch that does not exist. A run cannot change it.
24
+
25
+ A cut needs a Repo Slot. Under a Workspace with no Repo Slot, `jr2 up` refuses it, and the invoke
26
+ fails with `worktree "<slot>" runs under a Workspace with no Repo Slot: a cut makes a Worktree of a
27
+ Repo Slot, and there is none — declare one: repos: { app: "<url>" } (ADR-0075)`.
28
+
29
+ **Parameters**
30
+
31
+ - `options` ([`WorktreeOptions`](type-worktreeoptions.md)): Optional. `expect`, and `timeout`, how long the fetch and the cut can take.
32
+ Default: `"10m"`.
33
+
34
+ **Returns**: The actor logic of the Effect's slot. Its output is a [`WorktreeOutput`](type-worktreeoutput.md).
35
+
36
+ **Example**
37
+
38
+ ```ts
39
+ import { fail, isReady, jr2Setup, worktree, type Workspaced } from "@jr2/orchestrator";
40
+
41
+ type BodyInput = Workspaced<{ branch: string }, "app">;
42
+ const tree = (context: BodyInput) => `${context.workspace.repos.app}/fix` as const;
43
+
44
+ export const body = jr2Setup({
45
+ types: {} as { input: BodyInput; context: BodyInput },
46
+ actors: { cut: worktree({ expect: "new" }), fail: fail() },
47
+ }).createMachine({
48
+ context: ({ input }) => input,
49
+ on: { "workspace.lost": ".notCut" },
50
+ initial: "cutting",
51
+ states: {
52
+ cutting: {
53
+ invoke: {
54
+ src: "cut",
55
+ input: ({ context }) => ({ path: tree(context), branch: context.branch }),
56
+ // The last arm has no guard: it takes `refused`, `unknown` and each later outcome.
57
+ onDone: [{ guard: ({ event }) => isReady(event.output), target: "done" }, { target: "notCut" }],
58
+ },
59
+ },
60
+ done: { type: "final" },
61
+ notCut: { invoke: { src: "fail", input: { reason: "the Worktree was not cut" } } },
62
+ },
63
+ });
64
+ ```
65
+
66
+ **See also**
67
+
68
+ - [Cut a Worktree](../../guides/cut-a-worktree.md)
69
+ - [Workspaces](../../concepts/workspaces.md)
70
+ - [Effects](../../concepts/effects.md)
71
+ - [ADR-0075: A Machine cuts a Worktree, and the Workspace only clones](../decisions/0075-a-machine-cuts-a-worktree-and-the-workspace-only-clones.md)