@jr2/orchestrator 0.4.1 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (327) hide show
  1. package/README.md +20 -2
  2. package/console/components/app.ts +2 -0
  3. package/console/components/fleet.ts +14 -1
  4. package/console/components/machine-pane.ts +41 -2
  5. package/console/main.ts +13 -1
  6. package/console/store.ts +102 -6
  7. package/console/style.css +21 -0
  8. package/docs/agents-block.md +5 -0
  9. package/docs/concepts/agents-and-turns.md +442 -0
  10. package/docs/concepts/architecture.md +230 -0
  11. package/docs/concepts/charts.md +143 -0
  12. package/docs/concepts/composition.md +357 -0
  13. package/docs/concepts/converge.md +254 -0
  14. package/docs/concepts/durable-runs.md +189 -0
  15. package/docs/concepts/effects.md +603 -0
  16. package/docs/concepts/gates.md +208 -0
  17. package/docs/concepts/machines-and-workflows.md +289 -0
  18. package/docs/concepts/pools-and-sources.md +230 -0
  19. package/docs/concepts/secrets-and-trust.md +222 -0
  20. package/docs/concepts/the-menu.md +378 -0
  21. package/docs/concepts/workspaces.md +678 -0
  22. package/docs/get-started/a-model-decides.md +563 -0
  23. package/docs/get-started/an-agent-in-a-sandbox.md +381 -0
  24. package/docs/get-started/connect-a-model.md +248 -0
  25. package/docs/get-started/create-an-instance.md +194 -0
  26. package/docs/get-started/have-your-assistant-write-a-machine.md +922 -0
  27. package/docs/get-started/install.md +126 -0
  28. package/docs/guides/add-tools-to-the-sandbox.md +295 -0
  29. package/docs/guides/answer-a-gate.md +304 -0
  30. package/docs/guides/bind-open-parts.md +223 -0
  31. package/docs/guides/cancel-a-run.md +146 -0
  32. package/docs/guides/clean-up.md +206 -0
  33. package/docs/guides/fix-a-failed-converge.md +361 -0
  34. package/docs/guides/give-the-cluster-git-credentials.md +222 -0
  35. package/docs/guides/iterate-on-a-machine-on-kind.md +190 -0
  36. package/docs/guides/let-an-agent-write-a-chart.md +226 -0
  37. package/docs/guides/look-inside-a-sandbox.md +174 -0
  38. package/docs/guides/mirror-the-kit-images.md +176 -0
  39. package/docs/guides/move-from-kind-to-a-shared-cluster.md +302 -0
  40. package/docs/guides/open-the-console.md +91 -0
  41. package/docs/guides/publish-a-machine-as-an-npm-package.md +350 -0
  42. package/docs/guides/push-and-sign-a-branch.md +486 -0
  43. package/docs/guides/run-a-chart-by-name.md +270 -0
  44. package/docs/guides/run-a-command-or-call-a-url.md +544 -0
  45. package/docs/guides/run-one-worker-per-item.md +321 -0
  46. package/docs/guides/set-an-agents-access-and-dials.md +375 -0
  47. package/docs/guides/size-a-workspace.md +204 -0
  48. package/docs/guides/start-a-run-from-a-run.md +237 -0
  49. package/docs/guides/start-a-run.md +207 -0
  50. package/docs/guides/upgrade-the-kit-version.md +240 -0
  51. package/docs/guides/use-a-hosted-provider.md +208 -0
  52. package/docs/guides/use-a-local-model.md +313 -0
  53. package/docs/guides/watch-a-run.md +326 -0
  54. package/docs/guides/write-a-workflow.md +318 -0
  55. package/docs/index.md +44 -0
  56. package/docs/llms.txt +216 -0
  57. package/docs/reference/authoring-surface/agent.md +128 -0
  58. package/docs/reference/authoring-surface/answer.md +140 -0
  59. package/docs/reference/authoring-surface/arg.md +60 -0
  60. package/docs/reference/authoring-surface/basic.md +62 -0
  61. package/docs/reference/authoring-surface/bearer.md +53 -0
  62. package/docs/reference/authoring-surface/chartschema.md +23 -0
  63. package/docs/reference/authoring-surface/chartschemafor.md +48 -0
  64. package/docs/reference/authoring-surface/command.md +191 -0
  65. package/docs/reference/authoring-surface/customize.md +64 -0
  66. package/docs/reference/authoring-surface/defineconfig.md +41 -0
  67. package/docs/reference/authoring-surface/defineevent.md +114 -0
  68. package/docs/reference/authoring-surface/dispatch.md +126 -0
  69. package/docs/reference/authoring-surface/fail.md +83 -0
  70. package/docs/reference/authoring-surface/file.md +122 -0
  71. package/docs/reference/authoring-surface/frompick.md +277 -0
  72. package/docs/reference/authoring-surface/http.md +159 -0
  73. package/docs/reference/authoring-surface/isfailure.md +58 -0
  74. package/docs/reference/authoring-surface/jr2setup.md +237 -0
  75. package/docs/reference/authoring-surface/open.md +74 -0
  76. package/docs/reference/authoring-surface/openbody.md +86 -0
  77. package/docs/reference/authoring-surface/paramsof.md +125 -0
  78. package/docs/reference/authoring-surface/pool.md +186 -0
  79. package/docs/reference/authoring-surface/push.md +112 -0
  80. package/docs/reference/authoring-surface/secret.md +118 -0
  81. package/docs/reference/authoring-surface/sentby.md +83 -0
  82. package/docs/reference/authoring-surface/source.md +51 -0
  83. package/docs/reference/authoring-surface/text.md +62 -0
  84. package/docs/reference/authoring-surface/type-agentdeclaration.md +27 -0
  85. package/docs/reference/authoring-surface/type-agentdefinition.md +80 -0
  86. package/docs/reference/authoring-surface/type-agentlogic.md +15 -0
  87. package/docs/reference/authoring-surface/type-agentslots.md +12 -0
  88. package/docs/reference/authoring-surface/type-answeraction.md +12 -0
  89. package/docs/reference/authoring-surface/type-arg.md +19 -0
  90. package/docs/reference/authoring-surface/type-argnames.md +12 -0
  91. package/docs/reference/authoring-surface/type-binding.md +62 -0
  92. package/docs/reference/authoring-surface/type-bindingof.md +12 -0
  93. package/docs/reference/authoring-surface/type-bodyacceptsdoor.md +15 -0
  94. package/docs/reference/authoring-surface/type-bodyacceptsslots.md +17 -0
  95. package/docs/reference/authoring-surface/type-ceilings.md +41 -0
  96. package/docs/reference/authoring-surface/type-chainlink.md +19 -0
  97. package/docs/reference/authoring-surface/type-chartaction.md +46 -0
  98. package/docs/reference/authoring-surface/type-chartagent.md +28 -0
  99. package/docs/reference/authoring-surface/type-chartevent.md +20 -0
  100. package/docs/reference/authoring-surface/type-chartguard.md +20 -0
  101. package/docs/reference/authoring-surface/type-chartinvoke.md +28 -0
  102. package/docs/reference/authoring-surface/type-chartjson.md +14 -0
  103. package/docs/reference/authoring-surface/type-chartstate.md +46 -0
  104. package/docs/reference/authoring-surface/type-charttext.md +40 -0
  105. package/docs/reference/authoring-surface/type-charttransition.md +22 -0
  106. package/docs/reference/authoring-surface/type-charttransitions.md +14 -0
  107. package/docs/reference/authoring-surface/type-chartvalue.md +15 -0
  108. package/docs/reference/authoring-surface/type-childat.md +12 -0
  109. package/docs/reference/authoring-surface/type-childslots.md +12 -0
  110. package/docs/reference/authoring-surface/type-commandenv.md +15 -0
  111. package/docs/reference/authoring-surface/type-commandinput.md +19 -0
  112. package/docs/reference/authoring-surface/type-commandoptions.md +78 -0
  113. package/docs/reference/authoring-surface/type-commandoutput.md +104 -0
  114. package/docs/reference/authoring-surface/type-customize.md +109 -0
  115. package/docs/reference/authoring-surface/type-dispatchdefinition.md +39 -0
  116. package/docs/reference/authoring-surface/type-dispatchinput.md +14 -0
  117. package/docs/reference/authoring-surface/type-dispatchopenparts.md +14 -0
  118. package/docs/reference/authoring-surface/type-dispatchoutput.md +65 -0
  119. package/docs/reference/authoring-surface/type-duration.md +15 -0
  120. package/docs/reference/authoring-surface/type-effectbinding.md +93 -0
  121. package/docs/reference/authoring-surface/type-effectlogic.md +12 -0
  122. package/docs/reference/authoring-surface/type-envopenparts.md +14 -0
  123. package/docs/reference/authoring-surface/type-eventaudience.md +27 -0
  124. package/docs/reference/authoring-surface/type-eventdef.md +45 -0
  125. package/docs/reference/authoring-surface/type-eventfrom.md +16 -0
  126. package/docs/reference/authoring-surface/type-eventsemantics.md +26 -0
  127. package/docs/reference/authoring-surface/type-execoutcome.md +34 -0
  128. package/docs/reference/authoring-surface/type-failslot.md +14 -0
  129. package/docs/reference/authoring-surface/type-failure.md +19 -0
  130. package/docs/reference/authoring-surface/type-failureinput.md +20 -0
  131. package/docs/reference/authoring-surface/type-filebody.md +41 -0
  132. package/docs/reference/authoring-surface/type-frominput.md +14 -0
  133. package/docs/reference/authoring-surface/type-hostinjectedinput.md +58 -0
  134. package/docs/reference/authoring-surface/type-httpdefinition.md +101 -0
  135. package/docs/reference/authoring-surface/type-httpinput.md +12 -0
  136. package/docs/reference/authoring-surface/type-httpmethod.md +14 -0
  137. package/docs/reference/authoring-surface/type-httpopenparts.md +12 -0
  138. package/docs/reference/authoring-surface/type-httpoutput.md +89 -0
  139. package/docs/reference/authoring-surface/type-httprequestparts.md +33 -0
  140. package/docs/reference/authoring-surface/type-jr2config.md +126 -0
  141. package/docs/reference/authoring-surface/type-lends.md +38 -0
  142. package/docs/reference/authoring-surface/type-logicat.md +12 -0
  143. package/docs/reference/authoring-surface/type-markedif.md +12 -0
  144. package/docs/reference/authoring-surface/type-mergedactors.md +12 -0
  145. package/docs/reference/authoring-surface/type-namedsecret.md +25 -0
  146. package/docs/reference/authoring-surface/type-noslotspec.md +26 -0
  147. package/docs/reference/authoring-surface/type-noslotworkspaceoptions.md +32 -0
  148. package/docs/reference/authoring-surface/type-openbodydeclaration.md +40 -0
  149. package/docs/reference/authoring-surface/type-openbodylogic.md +14 -0
  150. package/docs/reference/authoring-surface/type-openbodyoutput.md +42 -0
  151. package/docs/reference/authoring-surface/type-openbodyslot.md +18 -0
  152. package/docs/reference/authoring-surface/type-opencommandinput.md +17 -0
  153. package/docs/reference/authoring-surface/type-openeffect.md +12 -0
  154. package/docs/reference/authoring-surface/type-openeffectslots.md +12 -0
  155. package/docs/reference/authoring-surface/type-openof.md +12 -0
  156. package/docs/reference/authoring-surface/type-opensecret.md +23 -0
  157. package/docs/reference/authoring-surface/type-opensecretmark.md +12 -0
  158. package/docs/reference/authoring-surface/type-permissivenoslotworkspaceoptions.md +31 -0
  159. package/docs/reference/authoring-surface/type-permissiveworkspaceoptions.md +32 -0
  160. package/docs/reference/authoring-surface/type-poolmachine.md +28 -0
  161. package/docs/reference/authoring-surface/type-poolspec.md +60 -0
  162. package/docs/reference/authoring-surface/type-pushinput.md +15 -0
  163. package/docs/reference/authoring-surface/type-pushoptions.md +79 -0
  164. package/docs/reference/authoring-surface/type-pushoutput.md +124 -0
  165. package/docs/reference/authoring-surface/type-pushwireoutput.md +12 -0
  166. package/docs/reference/authoring-surface/type-quantity.md +14 -0
  167. package/docs/reference/authoring-surface/type-reached.md +12 -0
  168. package/docs/reference/authoring-surface/type-reposlot.md +70 -0
  169. package/docs/reference/authoring-surface/type-reposlotsof.md +16 -0
  170. package/docs/reference/authoring-surface/type-sandboxoptions.md +77 -0
  171. package/docs/reference/authoring-surface/type-secret.md +25 -0
  172. package/docs/reference/authoring-surface/type-sender.md +19 -0
  173. package/docs/reference/authoring-surface/type-sentbyguards.md +12 -0
  174. package/docs/reference/authoring-surface/type-size.md +85 -0
  175. package/docs/reference/authoring-surface/type-slothandles.md +32 -0
  176. package/docs/reference/authoring-surface/type-sourcenextresult.md +17 -0
  177. package/docs/reference/authoring-surface/type-sourcespec.md +44 -0
  178. package/docs/reference/authoring-surface/type-syncstate.md +12 -0
  179. package/docs/reference/authoring-surface/type-text.md +19 -0
  180. package/docs/reference/authoring-surface/type-textpart.md +24 -0
  181. package/docs/reference/authoring-surface/type-thinkinglevel.md +39 -0
  182. package/docs/reference/authoring-surface/type-toparameterizedobject.md +14 -0
  183. package/docs/reference/authoring-surface/type-toprovidedactor.md +14 -0
  184. package/docs/reference/authoring-surface/type-unknown.md +21 -0
  185. package/docs/reference/authoring-surface/type-usercontainer.md +77 -0
  186. package/docs/reference/authoring-surface/type-withoutemptyindex.md +20 -0
  187. package/docs/reference/authoring-surface/type-workflowevent.md +46 -0
  188. package/docs/reference/authoring-surface/type-workspaceaccess.md +16 -0
  189. package/docs/reference/authoring-surface/type-workspaced.md +94 -0
  190. package/docs/reference/authoring-surface/type-workspacehandles.md +23 -0
  191. package/docs/reference/authoring-surface/type-workspacemachine.md +29 -0
  192. package/docs/reference/authoring-surface/type-workspaceof.md +13 -0
  193. package/docs/reference/authoring-surface/type-workspaceoptions.md +39 -0
  194. package/docs/reference/authoring-surface/type-workspacespec.md +37 -0
  195. package/docs/reference/authoring-surface/workspace.md +259 -0
  196. package/docs/reference/authoring-surface.md +197 -0
  197. package/docs/reference/cli.md +433 -0
  198. package/docs/reference/config.md +756 -0
  199. package/docs/reference/decisions/0001-operator-owned-generic-sandbox.md +113 -0
  200. package/docs/reference/decisions/0002-duplex-streaming-actor.md +110 -0
  201. package/docs/reference/decisions/0004-worktree-provisioning-model.md +124 -0
  202. package/docs/reference/decisions/0005-sandbox-pod-composition.md +230 -0
  203. package/docs/reference/decisions/0006-agent-control-surface.md +47 -0
  204. package/docs/reference/decisions/0007-durable-machine-state.md +109 -0
  205. package/docs/reference/decisions/0008-orchestrator-as-deployed-app.md +60 -0
  206. package/docs/reference/decisions/0009-cli-and-instance-interface.md +275 -0
  207. package/docs/reference/decisions/0010-bdd-acceptance-tests.md +160 -0
  208. package/docs/reference/decisions/0011-workflow-defined-events.md +141 -0
  209. package/docs/reference/decisions/0012-workspace-wrapper-machine.md +103 -0
  210. package/docs/reference/decisions/0013-the-agent-reaches-its-machine-through-a-container-it-cannot-read.md +157 -0
  211. package/docs/reference/decisions/0014-observation-is-open-run-state-is-not.md +95 -0
  212. package/docs/reference/decisions/0015-authoring-surface-absorbs-the-mechanism.md +265 -0
  213. package/docs/reference/decisions/0016-agent-turn-mechanics-are-internal.md +124 -0
  214. package/docs/reference/decisions/0017-pool-over-a-source-port.md +69 -0
  215. package/docs/reference/decisions/0018-instance-agents-are-definitions-jr2-assembles-the-harness.md +111 -0
  216. package/docs/reference/decisions/0019-one-converging-command-against-the-current-context.md +275 -0
  217. package/docs/reference/decisions/0020-private-ca-trust-is-a-named-concept.md +60 -0
  218. package/docs/reference/decisions/0021-workspace-continuity-is-a-lease-that-answers-back.md +100 -0
  219. package/docs/reference/decisions/0022-observation-is-a-level-triggered-feed.md +103 -0
  220. package/docs/reference/decisions/0023-the-harness-prints-the-conversation.md +176 -0
  221. package/docs/reference/decisions/0024-an-agents-turn-ends-with-the-state-that-asked-for-it.md +439 -0
  222. package/docs/reference/decisions/0025-cancel-ends-a-run-stop-parks-it.md +65 -0
  223. package/docs/reference/decisions/0026-a-turn-that-is-over-is-never-prompted.md +62 -0
  224. package/docs/reference/decisions/0027-the-harness-is-jr2s-own-server-flue-retires-the-wire-stays.md +237 -0
  225. package/docs/reference/decisions/0028-what-an-agent-may-do-to-the-workspace-is-part-of-its-definition.md +89 -0
  226. package/docs/reference/decisions/0029-a-menu-is-fixed-for-a-conversation-and-a-turn-is-told-its-allowed-picks.md +154 -0
  227. package/docs/reference/decisions/0030-a-snapshot-names-the-machine-it-was-written-under.md +100 -0
  228. package/docs/reference/decisions/0031-menu-only-agents-run-on-the-instance-harness.md +190 -0
  229. package/docs/reference/decisions/0032-the-console-unlocks-with-the-instance-token.md +61 -0
  230. package/docs/reference/decisions/0033-a-machine-declares-the-input-that-starts-it.md +127 -0
  231. package/docs/reference/decisions/0034-the-console-renders-with-preact-and-the-server-erases-the-types.md +57 -0
  232. package/docs/reference/decisions/0035-a-runaway-turn-is-ended-rerolled-once-then-a-fault.md +92 -0
  233. package/docs/reference/decisions/0036-a-turn-compacts-its-own-context-mid-flight.md +138 -0
  234. package/docs/reference/decisions/0037-an-instance-builds-its-sandbox-images-jr2-injects-the-harness.md +196 -0
  235. package/docs/reference/decisions/0038-jr2-up-builds-every-image-it-deploys.md +170 -0
  236. package/docs/reference/decisions/0039-image-garbage-collects-by-reachability.md +115 -0
  237. package/docs/reference/decisions/0041-a-build-the-host-already-holds-is-not-spent-again.md +64 -0
  238. package/docs/reference/decisions/0042-ready-is-not-routable-an-admission-retries-its-connection.md +142 -0
  239. package/docs/reference/decisions/0043-the-kit-is-tested-as-installed-a-local-registry-stands-in-for-npm.md +170 -0
  240. package/docs/reference/decisions/0044-kit-images-live-at-a-canonical-home-a-self-host-mirrors-it.md +85 -0
  241. package/docs/reference/decisions/0045-the-platform-joins-the-image-address-and-the-cluster-chooses-it.md +82 -0
  242. package/docs/reference/decisions/0046-a-converge-failure-carries-its-diagnosis.md +34 -0
  243. package/docs/reference/decisions/0047-the-git-ssh-key-source-is-the-users-choice.md +47 -0
  244. package/docs/reference/decisions/0048-the-orchestrator-boots-without-its-repos.md +36 -0
  245. package/docs/reference/decisions/0049-a-machine-carries-its-parts-and-composes-by-invoke.md +126 -0
  246. package/docs/reference/decisions/0050-what-code-names-config-declares-what-the-cli-names-discovery-finds.md +73 -0
  247. package/docs/reference/decisions/0051-a-repo-is-a-slot-on-the-workspace-and-a-cache-on-the-node.md +227 -0
  248. package/docs/reference/decisions/0052-a-sandbox-lands-where-an-ordinary-pod-lands-and-the-cache-follows-it.md +81 -0
  249. package/docs/reference/decisions/0053-a-fetch-inside-the-pod-asks-the-node-cache-and-the-cache-asks-the-remote.md +111 -0
  250. package/docs/reference/decisions/0054-the-kit-ships-machines-and-a-shipped-machine-leaves-its-parts-open.md +126 -0
  251. package/docs/reference/decisions/0055-a-release-is-a-pushed-tag-and-the-publish-guard-is-the-credential.md +107 -0
  252. package/docs/reference/decisions/0056-a-global-jr2-hands-off-to-the-instances-own-and-an-instance-has-one-kit-version.md +62 -0
  253. package/docs/reference/decisions/0057-a-turn-is-its-frame-its-dials-and-whether-it-continues.md +152 -0
  254. package/docs/reference/decisions/0058-a-harness-answers-the-orchestrator-alone.md +106 -0
  255. package/docs/reference/decisions/0059-a-harness-holds-stand-ins-and-the-custodian-holds-the-keys.md +384 -0
  256. package/docs/reference/decisions/0060-a-workspace-states-its-size-and-jr2-reserves-all-of-it.md +111 -0
  257. package/docs/reference/decisions/0061-a-memory-kill-ends-the-agents-processes-not-the-harness.md +83 -0
  258. package/docs/reference/decisions/0062-jr2-briefs-the-agent-on-its-seat-never-on-its-task.md +212 -0
  259. package/docs/reference/decisions/0063-the-orchestrator-watches-the-cluster.md +83 -0
  260. package/docs/reference/decisions/0064-a-workspace-waits-for-capacity.md +79 -0
  261. package/docs/reference/decisions/0065-a-persist-survives-a-crash-and-history-is-a-week.md +65 -0
  262. package/docs/reference/decisions/0066-a-model-tier-runs-a-real-model-and-a-change-to-what-it-reads-runs-the-tier.md +550 -0
  263. package/docs/reference/decisions/0067-an-effect-is-an-actor-slot-and-runs-at-most-once-unless-marked-idempotent.md +430 -0
  264. package/docs/reference/decisions/0068-an-effector-holds-an-effects-secrets-and-signs-its-wire.md +464 -0
  265. package/docs/reference/decisions/0069-the-orchestrator-is-a-kit-image-and-an-instance-publishes-its-assembly.md +180 -0
  266. package/docs/reference/decisions/0070-a-machine-lends-its-parts-to-a-chart.md +323 -0
  267. package/docs/reference/decisions/0071-a-run-starts-a-run-through-a-dispatch-effect.md +183 -0
  268. package/docs/reference/decisions/0072-the-docs-ship-inside-the-kit-and-an-instances-agents-md-indexes-them.md +144 -0
  269. package/docs/reference/decisions/0073-a-machine-fails-a-run-with-fail-and-an-uncaught-failure-ends-it-failed.md +122 -0
  270. package/docs/reference/decisions/0074-an-unrouted-mechanism-event-is-refused-at-load-and-faults-the-run.md +76 -0
  271. package/docs/reference/decisions.md +83 -0
  272. package/docs/reference/glossary.md +648 -0
  273. package/docs/reference/http-api.md +1348 -0
  274. package/docs/reference/machines.md +190 -0
  275. package/docs/reference/mechanism-events.md +72 -0
  276. package/docs/why.md +206 -0
  277. package/package.json +5 -3
  278. package/src/actor.ts +541 -79
  279. package/src/agent.ts +114 -38
  280. package/src/ambient.ts +2 -1
  281. package/src/assembly-checks.ts +189 -7
  282. package/src/cause.ts +234 -0
  283. package/src/chart.ts +169 -37
  284. package/src/charts.ts +34 -6
  285. package/src/config.ts +430 -178
  286. package/src/custodian.ts +74 -22
  287. package/src/customize.ts +188 -46
  288. package/src/dispatch-effect.ts +945 -0
  289. package/src/door-compat.ts +217 -0
  290. package/src/durability.ts +11 -4
  291. package/src/effect.ts +341 -44
  292. package/src/effector-wire.ts +160 -11
  293. package/src/fail.ts +209 -0
  294. package/src/harness-client.ts +541 -47
  295. package/src/http-effect.ts +495 -53
  296. package/src/http.ts +427 -16
  297. package/src/index.ts +60 -82
  298. package/src/instance.ts +68 -8
  299. package/src/internal.ts +84 -0
  300. package/src/machine-doc.ts +21 -3
  301. package/src/mechanism-routes.ts +168 -0
  302. package/src/model-keys.generated.ts +53 -0
  303. package/src/model-keys.ts +18 -58
  304. package/src/notices.ts +66 -13
  305. package/src/open-body.ts +159 -23
  306. package/src/open-effect.ts +81 -8
  307. package/src/open.ts +59 -6
  308. package/src/parts.ts +184 -13
  309. package/src/party.ts +68 -2
  310. package/src/pick.ts +463 -11
  311. package/src/pool.ts +247 -36
  312. package/src/registration.ts +83 -4
  313. package/src/repos.ts +2 -1
  314. package/src/run-host.ts +565 -31
  315. package/src/run-output.ts +38 -0
  316. package/src/sandbox-effect.ts +273 -38
  317. package/src/sandbox-kube.ts +3 -1
  318. package/src/secret-placement.ts +52 -17
  319. package/src/server.ts +3 -0
  320. package/src/setup.ts +239 -56
  321. package/src/size.ts +121 -9
  322. package/src/snapshot-store.ts +54 -10
  323. package/src/stub-harness.ts +44 -16
  324. package/src/timers.ts +14 -1
  325. package/src/vocabulary.ts +69 -14
  326. package/src/wire.ts +90 -16
  327. package/src/workspace.ts +697 -175
@@ -0,0 +1,190 @@
1
+ ---
2
+ title: Iterate on a Machine on kind
3
+ description: Change a Machine, converge the change into your kind cluster, and run it again.
4
+ ---
5
+
6
+ # Iterate on a Machine on kind
7
+
8
+ Change a [Machine](../reference/glossary.md#machine), converge the change into your kind cluster, and run it again.
9
+
10
+ kind runs a Kubernetes cluster on your computer, and jr2 uses it as its local cluster. The loop has three steps: edit
11
+ the file, run [`jr2 up`](../reference/cli.md#up), and run the [Workflow](../reference/glossary.md#workflow). The
12
+ [Orchestrator](../reference/glossary.md#orchestrator) runs only the Machines that the last `jr2 up` gave it. Thus a
13
+ change that you save does nothing until you converge it.
14
+
15
+ The examples on this page use the kind cluster `jr2` and the [Instance](../reference/glossary.md#instance) `my-instance`
16
+ from [Get started](../get-started/install.md). They change `ping`, the Workflow that `jr2 init` writes. It needs no
17
+ model.
18
+
19
+ ## Change the Machine
20
+
21
+ Open `workflows/ping.ts`. In the line of the `respond` actor, change `` `pong: ${input.message}` `` to
22
+ `` `pong, again: ${input.message}` ``. Save the file.
23
+
24
+ To find the errors before you converge, run [`jr2 check`](../reference/cli.md#check). `jr2 up` runs the same check
25
+ first:
26
+
27
+ ```sh
28
+ jr2 check
29
+ ```
30
+
31
+ It typechecks the Instance, loads each Workflow and walks its Machine, with no cluster. It prints the typecheck, the
32
+ `effects:` lines, the `seats:` lines and the `failures:` lines, and then `check: passed`. When it refuses, it gives the
33
+ line that `jr2 up` gives, and exits with `1`. `npm run typecheck` runs only the compiler, so it does not find a refusal
34
+ that occurs when a module loads. The checks of `git.credentials` and of the images need the cluster, so only `jr2 up`
35
+ does them.
36
+
37
+ ## Converge the change
38
+
39
+ Run `jr2 up` in the Instance folder:
40
+
41
+ ```sh
42
+ jr2 up
43
+ ```
44
+
45
+ For an Instance that has only `ping`, the output is:
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
+ agents: (none) (carried by 1 workflow machine(s))
51
+ assembly: staging
52
+ assembly: 0adf5bff234d (kit v<version>; 1 workflow(s): ping)
53
+ …
54
+ sandbox images: skipped (no registered Machine composes a Sandbox)
55
+ …
56
+ orchestrator: applying (image ghcr.io/snapwich/jr2-orchestrator:<version>)
57
+ orchestrator: waiting for rollout
58
+ orchestrator: verified — 1 pod(s) running ghcr.io/snapwich/jr2-orchestrator:<version>
59
+ instance effector: none (no Effect is placed there)
60
+ assembly: publishing 0adf5bff234d (current is ba71fa27f37f)
61
+ assembly: 0adf5bff234d is current — workflows: ping
62
+ swept nothing — every labeled image is named by a live root
63
+ converged — `jr2 run <workflow>` when ready
64
+ ```
65
+
66
+ `0adf5bff234d` is the hash of the new [Assembly](../reference/glossary.md#assembly), and `ba71fa27f37f` is the hash of
67
+ the Assembly that was current. Your hashes can be different. `<version>` is the
68
+ [Kit version](../reference/glossary.md#kit-version). The hash changed, because the Workflow changed. Thus `jr2 up`
69
+ published the new Assembly to the [Orchestrator](../reference/glossary.md#orchestrator). The image of the Orchestrator
70
+ did not change, so its pod did not start again. Your output has more lines when your Machines use a model, a
71
+ [Sandbox](../reference/glossary.md#sandbox) or an [Effect](../reference/glossary.md#effect).
72
+
73
+ `jr2 up` says `converged` only when the Orchestrator made the new Assembly current. When it stops with `refusing:`, the
74
+ Assembly that was current stays current. In both cases, fix the cause, then run `jr2 up` again.
75
+ [Fix a failed converge](fix-a-failed-converge.md) gives each refusal and its fix.
76
+
77
+ ## Run it again
78
+
79
+ Run the Workflow:
80
+
81
+ ```sh
82
+ jr2 run ping --input '{"message":"hi"}'
83
+ ```
84
+
85
+ ```text
86
+ → context kind-jr2 / namespace my-instance
87
+ run 7df09f94-d26d-44c3-ba1e-0279f16ccacb (ping) — attached
88
+ → done "done"
89
+ {"runId":"7df09f94-d26d-44c3-ba1e-0279f16ccacb","workflow":"ping","instanceId":"b2ec6504-553e-495a-a8be-62715c6d8595","status":"done","value":"done","context":{"message":"hi","reply":"pong, again: hi"},"children":[],"waiting":[],"held":[],"assembly":"0adf5bff234d"}
90
+ ```
91
+
92
+ Your run id and your instance id are different. The `reply` comes from the new Machine, and `assembly` is the hash of
93
+ the new Assembly.
94
+
95
+ The pod of the Orchestrator did not start again, so the port forward of the [Console](../reference/glossary.md#console)
96
+ stays open. Load the page again. Then the Console draws the new Machine. [Open the Console](open-the-console.md) gives
97
+ the command for the port forward.
98
+
99
+ ## Why a repeated jr2 up is fast
100
+
101
+ `jr2 up` does the full converge each time, but it builds a Sandbox Image only when its folder changed, and it publishes
102
+ the Assembly only when its hash changed. It never builds a Kit image, such as the image of the Orchestrator: the cluster
103
+ pulls each one at the Kit version. [Converge](../concepts/converge.md#the-images) tells why. You see it in these lines:
104
+
105
+ - `(fresh — build skipped; --force to rebuild anyway)`: the tag of a
106
+ [Sandbox Image](../reference/glossary.md#sandbox-image) did not change, so `jr2 up` did not build it.
107
+ - `(host-built — build skipped; --force to rebuild)`: your computer holds the Sandbox Image with that tag, so `jr2 up`
108
+ did not build it.
109
+ - `(current — publish skipped)`: the Orchestrator already has the Assembly with this hash.
110
+
111
+ A second `jr2 up` with no change builds nothing and publishes nothing:
112
+
113
+ ```text
114
+ …
115
+ assembly: 0adf5bff234d (current — publish skipped)
116
+ swept nothing — every labeled image is named by a live root
117
+ converged — `jr2 run <workflow>` when ready
118
+ ```
119
+
120
+ To build all the images again, run `jr2 up --force`. It builds an image again also when its tag did not change. It also
121
+ sends the Assembly again, and the Orchestrator answers that the Assembly did not change.
122
+
123
+ ## The runs that are live when you converge
124
+
125
+ A publish does not start the pod of the Orchestrator again. A run that is live keeps the Assembly that it started under.
126
+ Thus it continues on the old Machine, to its end, also after a restart. A run that waits at a
127
+ [Gate](../reference/glossary.md#gate) still waits there, and its Sandbox stays. A `jr2 run` that is attached stays
128
+ attached. Each new run uses the new Machine.
129
+
130
+ [`jr2 status`](../reference/cli.md#status), with no run id, shows each Assembly that a live run holds:
131
+
132
+ ```sh
133
+ jr2 status
134
+ ```
135
+
136
+ In this output, a run of the Workflow `rollout` from [Write a Workflow](write-a-workflow.md) waits at its Gate. It
137
+ started before the last `jr2 up`:
138
+
139
+ ```text
140
+ → context kind-jr2 / namespace my-instance
141
+ assembly: a44731886e21 (kit v<version>, current), 0 live runs hold it
142
+ assembly: 3a3fa3c403f9 (kit v<version>), 1 live run holds it
143
+ data plane: yes
144
+ ```
145
+
146
+ The Orchestrator removes the old Assembly when the last run that holds it ends. `data plane: yes` tells that the
147
+ Orchestrator runs in a cluster, so it can make Sandboxes.
148
+
149
+ A live run cannot continue when the Orchestrator cannot read its Assembly: the volume lost it, or it is for a different
150
+ Kit version. Then the Orchestrator keeps the run with the status `drifted`, and `jr2 status <run id>` gives the reason.
151
+ [Upgrade the Kit version](upgrade-the-kit-version.md) tells when this occurs.
152
+
153
+ ## Rules
154
+
155
+ - `jr2 up` changes nothing in the cluster when the Instance does not typecheck:
156
+ `refusing: this instance does not typecheck — nothing was built and nothing was applied`. The output of the compiler
157
+ follows, one line for each error.
158
+ - `jr2 up` changes nothing in the cluster when a registered Machine has an [Open](../reference/glossary.md#open) part
159
+ that nobody bound. It prints the line that binds it:
160
+ `refusing: workflow "<name>" leaves <part> open — bind it where the Machine is registered: export const machine = customize(<import>, <binding>) (<adr>)`.
161
+ [Bind a shipped Machine's Open parts](bind-open-parts.md) tells how.
162
+ - `jr2 up` prints an error in a Workflow module as `error: <message>`, and exits with `1`. It changes nothing in the
163
+ cluster. [Write a Workflow](write-a-workflow.md) gives each error.
164
+ - `jr2 up` refuses when kubectl has no current context:
165
+ ``error: no kube context — `kind create cluster` (or point kubectl at one), then re-run `jr2 up` ``
166
+ - `jr2 up` loads the Sandbox Images into the nodes only on a kind cluster: a context whose name starts with `kind-`. For
167
+ a different context with no [`registry`](../reference/config.md#registry), it builds nothing:
168
+ ``error: context <context> is not a kind cluster and no `registry` is configured — set `registry` in jr2.config.ts (from env) so the image can be pushed (ADR-0019)``
169
+ - The Orchestrator refuses an Assembly that fails its checks. `jr2 up` prints the reason and the lines of the report,
170
+ and the Assembly that was current stays current:
171
+ `refusing: the Orchestrator refused Assembly <hash> (HTTP <status>): <error> — the previous Assembly is still current`
172
+
173
+ ## Read next
174
+
175
+ - [Converge](../concepts/converge.md)
176
+ - [Durable runs](../concepts/durable-runs.md): the Machine shape and drift.
177
+ - [ADR-0019](../reference/decisions/0019-one-converging-command-against-the-current-context.md): one converging command
178
+ against the current context.
179
+ - [ADR-0069](../reference/decisions/0069-the-orchestrator-is-a-kit-image-and-an-instance-publishes-its-assembly.md): a
180
+ publish loads the Assembly with no restart, and a run keeps its Assembly.
181
+ - [ADR-0038](../reference/decisions/0038-jr2-up-builds-every-image-it-deploys.md): `jr2 up` builds each image that the
182
+ cluster runs, with a content hash as its tag.
183
+ - [ADR-0041](../reference/decisions/0041-a-build-the-host-already-holds-is-not-spent-again.md): a build that your
184
+ computer holds is not done again.
185
+ - [ADR-0050](../reference/decisions/0050-what-code-names-config-declares-what-the-cli-names-discovery-finds.md): the
186
+ typecheck is the first step of `jr2 up`.
187
+ - [Write a Workflow](write-a-workflow.md)
188
+ - [Move from kind to a shared cluster](move-from-kind-to-a-shared-cluster.md)
189
+ - Reference: [`jr2 up`](../reference/cli.md#up), [`jr2 run`](../reference/cli.md#run),
190
+ [`jr2 status`](../reference/cli.md#status)
@@ -0,0 +1,226 @@
1
+ ---
2
+ title: Let an Agent write a Chart
3
+ description: Write a Chart wrapper whose planner Agent writes a Chart, runs it, and corrects it.
4
+ ---
5
+
6
+ # Let an Agent write a Chart
7
+
8
+ Write a [Chart wrapper](../reference/glossary.md#chart-wrapper) whose planner [Agent](../reference/glossary.md#agent)
9
+ writes a [Chart](../reference/glossary.md#chart) and runs it.
10
+
11
+ This example is `workflows/plan.ts`. The planner reads the task, and it picks `run_chart` with a Chart. The Chart runs
12
+ in the [Open body](../reference/glossary.md#open-body) `body`. It can use the Agent `writer` and the
13
+ [Gate](../reference/glossary.md#gate), and it can add its own Agents with the model of the tab. When the door refuses
14
+ the Chart, the planner gets the report as the answer to its pick, and it can pick again:
15
+
16
+ ```ts
17
+ import { assign } from "xstate";
18
+ import { z } from "zod";
19
+ import {
20
+ agent,
21
+ chartSchemaFor,
22
+ defineEvent,
23
+ fail,
24
+ fromPick,
25
+ jr2Setup,
26
+ openBody,
27
+ type OpenBodyDeclaration,
28
+ type OpenBodyOutput,
29
+ } from "@jr2/orchestrator";
30
+ ```
31
+
32
+ The model of the tab:
33
+
34
+ **Anthropic**
35
+
36
+ ```ts
37
+ const model = "anthropic/claude-haiku-5-5";
38
+ ```
39
+
40
+ **Local**
41
+
42
+ ```ts
43
+ const model = "local/qwen3.6-35b-a3b";
44
+ ```
45
+
46
+ The Open body and the pick:
47
+
48
+ ```ts
49
+ // What a Chart can use. A Chart names these parts by their slot keys, and nothing else.
50
+ const declaration: OpenBodyDeclaration = {
51
+ // The Agent `writer`, and the Gate, so that a Chart can ask a person.
52
+ lends: { agents: ["writer"], gate: true },
53
+ // A Chart can add its own Agents, with this model and with no Sandbox.
54
+ allows: { models: [model], workspace: ["none"] },
55
+ // The limits of one run of a Chart.
56
+ ceilings: { turns: 12, wallClock: "30m", transitions: 500, fanOut: 2, size: 65536 },
57
+ };
58
+ ```
59
+
60
+ ```ts
61
+ // The pick of the planner. Its parameter is a Chart, in the grammar of this Open body.
62
+ const runChart = defineEvent({
63
+ name: "run_chart",
64
+ description: "Run this Chart. Its outcome is the answer to this call.",
65
+ input: z.object({ chart: chartSchemaFor(declaration) }),
66
+ });
67
+ ```
68
+
69
+ The Machine:
70
+
71
+ ```ts
72
+ export const machine = jr2Setup({
73
+ types: {} as { context: Context; input: Input },
74
+ events: [runChart],
75
+ actors: {
76
+ planner: agent({
77
+ model,
78
+ workspace: "none",
79
+ instructions: "You plan work as a Chart. You write the Chart, and you run it with run_chart.",
80
+ }),
81
+ writer: agent({
82
+ model,
83
+ workspace: "none",
84
+ instructions: "You write clear, short text for engineers.",
85
+ }),
86
+ body: openBody(declaration),
87
+ fail: fail(),
88
+ },
89
+ }).createMachine({
90
+ id: "plan",
91
+ input: z.object({ task: z.string() }),
92
+ context: ({ input }) => ({ task: input.task }),
93
+ on: { "agent.fault": ".failed" },
94
+ initial: "planning",
95
+ states: {
96
+ planning: {
97
+ invoke: {
98
+ src: "planner",
99
+ input: ({ context }) => ({
100
+ prompt: `Write a Chart for this task, and pick run_chart with it: ${context.task}`,
101
+ continue: true,
102
+ }),
103
+ },
104
+ initial: "ready",
105
+ states: {
106
+ ready: { on: { run_chart: "running" } },
107
+ running: {
108
+ // The Chart of the pick runs here. The task goes into the input of the Chart.
109
+ invoke: {
110
+ src: "body",
111
+ input: fromPick(runChart, ({ context }: { context: Context }) => ({ task: context.task })),
112
+ onDone: [
113
+ {
114
+ guard: ({ event }) => outcome(event.output) === "done",
115
+ target: "#plan.done",
116
+ actions: assign({ result: ({ event }) => event.output as OpenBodyOutput }),
117
+ },
118
+ // A refusal or a ceiling goes back to the planner, as the answer to its pick.
119
+ { target: "ready", actions: assign({ result: ({ event }) => event.output as OpenBodyOutput }) },
120
+ ],
121
+ },
122
+ },
123
+ },
124
+ },
125
+ done: { type: "final" },
126
+ failed: { invoke: { src: "fail", input: { reason: "the Agent's Turn could not go on" } } },
127
+ },
128
+ output: ({ context }) => context.result,
129
+ });
130
+ ```
131
+
132
+ ## Read the example
133
+
134
+ - [`openBody(declaration)`](../reference/authoring-surface/openbody.md) is the slot that the Chart binds. Its
135
+ declaration lends the Agent `writer` and the Gate, lets a Chart add Agents with `model` and no Sandbox, and sets the
136
+ ceilings. [Charts](../concepts/charts.md#the-open-body) tells what each part does.
137
+ - The pick `run_chart` has one parameter, `chart`. Its schema is
138
+ [`chartSchemaFor(declaration)`](../reference/authoring-surface/chartschemafor.md): the Chart grammar with the names of
139
+ this Open body. The model gets it as the parameters of its tool.
140
+ - The state `running` is below the state of the planner. Thus the pick is
141
+ [outstanding](../reference/glossary.md#outstanding) while the Chart runs, and the Turn of the planner stays open.
142
+ - [`fromPick`](../reference/authoring-surface/frompick.md) gives the Chart of the pick to the Open body, and adds
143
+ `task`. The Chart reads it as `{{input.task}}`.
144
+ - The Open body ends with an [`OpenBodyOutput`](../reference/authoring-surface/type-openbodyoutput.md). `done` goes to
145
+ the final state. `refused` and `ceiling` go back to `ready`, where jr2 answers the pick with the output. The planner
146
+ reads the report, and it can pick `run_chart` again.
147
+
148
+ ## Run it
149
+
150
+ Run [`jr2 up`](../reference/cli.md#up). The planner and `writer` are Menu-only Agents, so `jr2 up` converges the
151
+ [Instance Harness](../reference/glossary.md#instance-harness). It also puts the key of each model in `allows.models` on
152
+ the Instance Harness, because a Chart can add an Agent with that model. Then start a run:
153
+
154
+ ```sh
155
+ jr2 run plan --input '{"task":"Write the release notes for the greet CLI, and ask a person to approve them."}'
156
+ ```
157
+
158
+ Open the run in the [Console](../reference/glossary.md#console). After the planner picks `run_chart`, the Console draws
159
+ the Chart inside `running`. The Chart of each run is different, because the planner writes it.
160
+
161
+ When the door refuses a Chart, the answer to the pick holds the report. The log of the
162
+ [Instance Harness](../reference/glossary.md#instance-harness) shows each answer. Replace `<namespace>` with the
163
+ namespace of your Instance, and `<run id>` with the full run id. The log holds the lines of each run of a Menu-only
164
+ Agent, and the first `grep` keeps the lines of your run:
165
+
166
+ ```sh
167
+ kubectl -n <namespace> logs statefulset/jr2-instance-harness -c harness | grep -F '[<run id>/' | grep -F '[run_chart answer]'
168
+ ```
169
+
170
+ For example, in one run with the model of each tab, the first Chart of the planner gave a prompt to the Gate. The door
171
+ refused it:
172
+
173
+ ```text
174
+ [planner] [<run id>/root/planner] [run_chart answer] Delivered "run_chart" to the workflow (delivery ede62e99-7596-41fe-bda3-c6dcc194517f). The workflow took it and is back in the state that asked for this turn. Its answer: the output of `body`: {"outcome":"refused","report":["states.approve.invoke.input.prompt: a Gate's input takes gate and meta only; `gate` is the kit's Gate, which waits for an outside answer (a human, a webhook), not an Agent's Turn"]}. Your turn is not over. Allowed now: `mcp__jr2__run_chart`.
175
+ ```
176
+
177
+ The planner writes a different Chart in each run. Thus your report can be different, and the door can accept the first
178
+ Chart. Your delivery id is different. After a refusal, the planner can pick `run_chart` again with a corrected Chart.
179
+
180
+ When the Chart gets to its Gate, the run waits. `jr2 status <run id>` gives the id of the Gate, such as
181
+ `0.plan.planning.running.approve`, and the events that it takes. [Answer a Gate](answer-a-gate.md) tells how to answer
182
+ it. Then the Chart ends, and the run ends with the status `done`.
183
+
184
+ ## Rules
185
+
186
+ - [`openBody()`](../reference/authoring-surface/openbody.md) refuses a declaration that is not correct, with one line
187
+ for each problem. The refusal starts with `openBody: `, then each problem, separated by `; `. For example:
188
+ - `lends.<kind>: an Open body lends agents, effects, machines, guards, actions, delays, gate and fail only`
189
+ - `allows.workspace: "<value>" is not a Workspace access (write, read, none)`
190
+ - `ceilings.<ceiling>: missing; an Open body states every ceiling`
191
+ - `ceilings.<ceiling>: <value> is not a positive integer`
192
+ - `ceilings.wallClock: <value> is not a positive duration (like "90s", "10m", "2h")`
193
+ - `ceilings.size: <value> is more than 1048576 bytes (1 MiB)`
194
+ - `createMachine` refuses a lent name that the Machine does not have. The refusal starts with
195
+ `machine "<id>": Open body "<slot>": `, then each problem:
196
+ - `lends.<kind>: "<name>" is no actor slot of this Machine; its actors: <slots>`
197
+ - `lends.<kind>: "<name>" is not an Agent slot (agent(...))`, or `is not an Effect slot`, or `is not a Machine`
198
+ - `lends.<kind>: "<name>" is no <guard, action or delay> of this Machine; its <kind>: <names>`
199
+ - `lends.<kind>: "<name>" is the Open body itself`
200
+ - The door refuses a Chart, and gives one line for each problem. Each line starts with the path in the Chart. For
201
+ example:
202
+ - `<path>: "<name>" is not a lent actor or an Agent of this Chart; lent: <names>; kit: <gate, fail or none>; minted: <names>`
203
+ - `<path>: "<name>" is not a lent guard; lent guards: <names> (and jr2.sentBy with params { id }, and jr2.failure)`
204
+ - `<path>.type: "<name>" is not a generic or a lent action; generic: set, append, increment, clear; lent: <names>`
205
+ - ``<path>: <reference> is supplied by nothing: it is not in the initial `context`, and no `set`, `append` or `increment` writes it``,
206
+ then what a write supplies
207
+ - `<path>: "<reference>" is not a reference: it starts at context, event or input (a reference is a path, never an expression)`
208
+ - The door then compiles the Chart as the Open body does. A line of this last check starts with `(chart):`, and names a
209
+ state by its [xstate](https://xstate.js.org) id (for example `body.writing`), not by its path in the Chart.
210
+ - A refusal is output, not an error: the Open body ends with `{ outcome: "refused", report }`. A Chart wrapper that
211
+ routes `onDone` back to the state of the pick gives the report to the planner.
212
+ - When the Turn of an Agent of the Chart cannot go on, and no transition of the Chart takes
213
+ [`agent.fault`](../reference/mechanism-events.md#agent-fault), the Open body sends the event, unchanged, to this
214
+ wrapper. The wrapper's root route takes it, as it takes the fault of `planner`, so the run ends `failed`.
215
+ - A Chart that gets to a ceiling stops, and the Open body ends with `{ outcome: "ceiling", ceiling, detail }`.
216
+
217
+ ## Read next
218
+
219
+ - [Charts](../concepts/charts.md)
220
+ - [The Menu](../concepts/the-menu.md): how a pick waits for its answer.
221
+ - [Run a Chart by name](run-a-chart-by-name.md)
222
+ - Reference: [`openBody`](../reference/authoring-surface/openbody.md),
223
+ [`OpenBodyDeclaration`](../reference/authoring-surface/type-openbodydeclaration.md),
224
+ [`chartSchemaFor`](../reference/authoring-surface/chartschemafor.md),
225
+ [`fromPick`](../reference/authoring-surface/frompick.md)
226
+ - [ADR-0070](../reference/decisions/0070-a-machine-lends-its-parts-to-a-chart.md): a Machine lends its parts to a Chart.
@@ -0,0 +1,174 @@
1
+ ---
2
+ title: Look inside a Sandbox
3
+ description: Open a shell in the Sandbox of a run, and read the branch that its Agent works on.
4
+ ---
5
+
6
+ # Look inside a Sandbox
7
+
8
+ Open a shell in the [Sandbox](../reference/glossary.md#sandbox) of a run, and read the branch that its
9
+ [Agent](../reference/glossary.md#agent) works on.
10
+
11
+ A [Workspace](../reference/glossary.md#workspace) of the run makes the Sandbox, and deletes it when the body of the
12
+ Workspace gets to its final state or fails. The [Rules](#rules) give the cases in which the Sandbox stays. The Sandbox
13
+ is a pod. Its `harness` container runs the [Harness](../reference/glossary.md#harness), and the Agent's
14
+ [Working tools](../reference/glossary.md#working-tools) run in it. When you use `kubectl exec`, you get a shell in the
15
+ same container. An Agent that has only the [Menu](../reference/glossary.md#menu) has no Sandbox. To read its
16
+ conversation, see [Watch a run](watch-a-run.md).
17
+
18
+ In the commands on this page, replace these values:
19
+
20
+ - `<namespace>`: the namespace of your [Instance](../reference/glossary.md#instance). It is the
21
+ [`name`](../reference/config.md#name) in `jr2.config.ts`. When `jr2.config.ts` sets no `name`, it is the name of the
22
+ Instance folder.
23
+ - `<run id>`: the full run id. [`jr2 run`](../reference/cli.md#run) prints it in the line
24
+ `run <run id> (<workflow>) — attached`. [`jr2 runs`](../reference/cli.md#runs) prints the `runId` of each live run. A
25
+ prefix does not work here, because `kubectl` does not know the run ids.
26
+
27
+ Give each `jr2` command in the Instance folder.
28
+
29
+ ## Find the Sandbox
30
+
31
+ The label `jr2.dev/run` on each Sandbox holds the full id of its run:
32
+
33
+ ```sh
34
+ kubectl -n <namespace> get sandboxes -l jr2.dev/run=<run id>
35
+ ```
36
+
37
+ ```text
38
+ NAME PHASE ENDPOINT AGE
39
+ ws-a1322024-x-2-h8pgwk Ready http://ws-a1322024-x-2-h8pgwk.my-instance.svc:8080 16s
40
+ ```
41
+
42
+ - `NAME` is the name of the Sandbox, here `ws-a1322024-x-2-h8pgwk`. Your name is different. It starts with `ws-`, then
43
+ the first 8 characters of the run id. The pod has the same name. In the commands below, write it in place of
44
+ `<sandbox>`.
45
+ - A run that has two Workspaces at the same time has two rows.
46
+ - `PHASE` is `Pending` until the pod is ready and its node has a fresh cache of each Repo. Then it is `Ready`. It is
47
+ `Lost` when the pod is gone, and a `Lost` Sandbox does not get a new pod. A delete removes the Sandbox at once, so you
48
+ seldom see the phase `Terminating`.
49
+ - When the run has no Sandbox now, `kubectl` prints `No resources found in <namespace> namespace.`
50
+ - When a [Workflow](../reference/glossary.md#workflow) puts `branch` and `worktree` in the `meta` of a
51
+ [Gate](../reference/glossary.md#gate), as the `review` Gate of [`task`](../reference/machines.md#task) does,
52
+ [`jr2 status <run id>`](../reference/cli.md#status) prints them in `gates`. Give this command on your computer, not in
53
+ the Sandbox. Then you can copy the Worktree from the status.
54
+
55
+ ## Open a shell
56
+
57
+ ```sh
58
+ kubectl -n <namespace> exec -it <sandbox> -c harness -- bash
59
+ ```
60
+
61
+ The default [Sandbox Image](../reference/glossary.md#sandbox-image) that [`jr2 init`](../reference/cli.md#init) writes
62
+ starts from `node:24-slim`, which has `bash`. If your Sandbox Image has no `bash`, use `sh`.
63
+
64
+ ## Find the Worktree
65
+
66
+ Each [Repo Slot](../reference/glossary.md#repo-slot) of the Workspace has a folder in `/work`. In it, `default` is a
67
+ clone of the [Repo](../reference/glossary.md#repo), and the [Worktree](../reference/glossary.md#worktree) of the branch
68
+ is beside it. To show the folders of the Repo Slots, use this command:
69
+
70
+ ```sh
71
+ ls /work
72
+ ```
73
+
74
+ Replace `<Repo Slot>` with the name of a slot, such as `target`:
75
+
76
+ ```sh
77
+ git -C /work/<Repo Slot>/default worktree list
78
+ ```
79
+
80
+ For the slot `target` of a run of `task`, the output is:
81
+
82
+ ```text
83
+ /work/target/default 1e40403 [main]
84
+ /work/target/jr2-task-0cbdb607-48dc-4eab-9469-f8e41f2b0025 1e40403 [jr2/task-0cbdb607-48dc-4eab-9469-f8e41f2b0025]
85
+ ```
86
+
87
+ The first line is the clone, on the default branch of the Repo. The second line is the Worktree of the branch. Your
88
+ commits and your instance id are different.
89
+
90
+ - In the commands below, `<branch>` is the name of the branch, and `<worktree>` is the folder of its Worktree. The
91
+ folder is the name of the branch, with each `/` changed to `-`. For example, the branch `jr2/task-<instance id>` has
92
+ the Worktree `/work/target/jr2-task-<instance id>`.
93
+ - A Workspace that has a commit to review has one more Worktree, `/work/<Repo Slot>/<worktree>-review`. It holds that
94
+ commit, with no branch.
95
+ - The attach makes the folders and the Worktrees after the Sandbox is `Ready`. Until then, `/work` has no folder for the
96
+ Repo Slot.
97
+
98
+ ## Read the branch
99
+
100
+ Go into the Worktree:
101
+
102
+ ```sh
103
+ cd /work/<Repo Slot>/<worktree>
104
+ ```
105
+
106
+ Show the files that the Agent changed and did not commit:
107
+
108
+ ```sh
109
+ git status
110
+ ```
111
+
112
+ Show the commits of the branch, newest first. The history of its base comes after them:
113
+
114
+ ```sh
115
+ git log --oneline
116
+ ```
117
+
118
+ Show the changes in the last commit:
119
+
120
+ ```sh
121
+ git show --stat HEAD
122
+ ```
123
+
124
+ You can also give one command, with no shell:
125
+
126
+ ```sh
127
+ kubectl -n <namespace> exec <sandbox> -c harness -- git -C /work/<Repo Slot>/<worktree> log --oneline
128
+ ```
129
+
130
+ ## Push the branch
131
+
132
+ The Agent has no credential to push with. To keep its commits after the Sandbox goes, push the branch from the Worktree.
133
+ Replace `<branch>` with the name of the branch:
134
+
135
+ ```sh
136
+ git push origin <branch>
137
+ ```
138
+
139
+ `origin` fetches through the [Repo cache](../concepts/architecture.md#the-repo-cache) of the node, and pushes to the
140
+ Repo. When the Repo url starts with `https://`, `git push` asks for a user name and a password. Give your user name.
141
+ Give a token that can push to the Repo as the password.
142
+
143
+ A [Machine](../reference/glossary.md#machine) can also push the branch with an
144
+ [Effect](../reference/glossary.md#effect). See [Push and sign a branch](push-and-sign-a-branch.md).
145
+
146
+ > **Caution**
147
+ >
148
+ > The Agent works in the same files as your shell, so it sees each change that you make there. When the Sandbox goes, a
149
+ > commit that you did not push goes with it.
150
+
151
+ ## Rules
152
+
153
+ - The Workspace deletes its Sandbox when its body gets to its final state. When the body of each Workspace of the run
154
+ has got to its final state, no Sandbox has the label of the run.
155
+ - A run that a Machine fails deletes its Sandboxes, as a final state does. See
156
+ [Fail the run](write-a-workflow.md#fail-the-run). To keep the work, wait at a [Gate](../reference/glossary.md#gate)
157
+ before the state that fails.
158
+ - A Workspace that its parent stops after Placing, for example with an `after` on the state that holds it, does not
159
+ delete its Sandbox. The [operator](../concepts/architecture.md#the-operator) deletes it 30 minutes after the last
160
+ renewal of its [Lease](../reference/glossary.md#lease).
161
+ - [`jr2 send`](../reference/cli.md#send) `<run id> --event CANCEL` deletes the Sandboxes of the run. To keep them, add
162
+ `--keep`. See [Cancel a run](cancel-a-run.md).
163
+ - A run that faults keeps its Sandboxes. After a fault, and after a CANCEL with `--keep`, nothing renews the Lease of
164
+ its Workspace. The operator deletes the Sandbox 30 minutes after the last renewal.
165
+ - A Workspace in [Placing](../reference/glossary.md#placing) deletes its Sandbox at once, also after a fault and after a
166
+ CANCEL with `--keep`. Its Sandbox has no node yet, so it has nothing to look inside.
167
+
168
+ ## Read next
169
+
170
+ - [Workspaces](../concepts/workspaces.md)
171
+ - [ADR-0004](../reference/decisions/0004-worktree-provisioning-model.md): the clone and the Worktree.
172
+ - [ADR-0005](../reference/decisions/0005-sandbox-pod-composition.md): the containers of a Sandbox.
173
+ - [ADR-0012](../reference/decisions/0012-workspace-wrapper-machine.md): when a Workspace deletes its Sandbox.
174
+ - [Watch a run](watch-a-run.md)