@jr2/orchestrator 0.4.1 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (361) hide show
  1. package/README.md +20 -2
  2. package/console/components/app.ts +2 -0
  3. package/console/components/fleet.ts +14 -1
  4. package/console/components/machine-pane.ts +41 -2
  5. package/console/main.ts +13 -1
  6. package/console/store.ts +102 -6
  7. package/console/style.css +21 -0
  8. package/docs/agents-block.md +5 -0
  9. package/docs/concepts/agents-and-turns.md +478 -0
  10. package/docs/concepts/architecture.md +243 -0
  11. package/docs/concepts/charts.md +146 -0
  12. package/docs/concepts/composition.md +357 -0
  13. package/docs/concepts/converge.md +257 -0
  14. package/docs/concepts/durable-runs.md +189 -0
  15. package/docs/concepts/effects.md +658 -0
  16. package/docs/concepts/gates.md +208 -0
  17. package/docs/concepts/machines-and-workflows.md +298 -0
  18. package/docs/concepts/pools-and-sources.md +230 -0
  19. package/docs/concepts/secrets-and-trust.md +306 -0
  20. package/docs/concepts/the-menu.md +381 -0
  21. package/docs/concepts/workspaces.md +756 -0
  22. package/docs/get-started/a-model-decides.md +563 -0
  23. package/docs/get-started/an-agent-in-a-sandbox.md +383 -0
  24. package/docs/get-started/connect-a-model.md +248 -0
  25. package/docs/get-started/create-an-instance.md +194 -0
  26. package/docs/get-started/have-your-assistant-write-a-machine.md +993 -0
  27. package/docs/get-started/install.md +130 -0
  28. package/docs/guides/add-tools-to-the-sandbox.md +308 -0
  29. package/docs/guides/answer-a-gate.md +304 -0
  30. package/docs/guides/bind-open-parts.md +224 -0
  31. package/docs/guides/cancel-a-run.md +146 -0
  32. package/docs/guides/clean-up.md +206 -0
  33. package/docs/guides/cut-a-worktree.md +560 -0
  34. package/docs/guides/fix-a-failed-converge.md +361 -0
  35. package/docs/guides/give-the-cluster-git-credentials.md +222 -0
  36. package/docs/guides/iterate-on-a-machine-on-kind.md +190 -0
  37. package/docs/guides/let-an-agent-write-a-chart.md +230 -0
  38. package/docs/guides/look-inside-a-sandbox.md +177 -0
  39. package/docs/guides/mirror-the-kit-images.md +176 -0
  40. package/docs/guides/move-from-kind-to-a-shared-cluster.md +318 -0
  41. package/docs/guides/open-the-console.md +91 -0
  42. package/docs/guides/publish-a-machine-as-an-npm-package.md +350 -0
  43. package/docs/guides/push-and-sign-a-branch.md +532 -0
  44. package/docs/guides/run-a-chart-by-name.md +270 -0
  45. package/docs/guides/run-a-command-or-call-a-url.md +587 -0
  46. package/docs/guides/run-one-worker-per-item.md +322 -0
  47. package/docs/guides/set-an-agents-access-and-dials.md +420 -0
  48. package/docs/guides/size-a-workspace.md +217 -0
  49. package/docs/guides/start-a-run-from-a-run.md +237 -0
  50. package/docs/guides/start-a-run.md +207 -0
  51. package/docs/guides/upgrade-the-kit-version.md +240 -0
  52. package/docs/guides/use-a-hosted-provider.md +214 -0
  53. package/docs/guides/use-a-local-model.md +313 -0
  54. package/docs/guides/watch-a-run.md +349 -0
  55. package/docs/guides/write-a-workflow.md +318 -0
  56. package/docs/index.md +44 -0
  57. package/docs/llms.txt +237 -0
  58. package/docs/reference/authoring-surface/agent.md +151 -0
  59. package/docs/reference/authoring-surface/answer.md +156 -0
  60. package/docs/reference/authoring-surface/arg.md +82 -0
  61. package/docs/reference/authoring-surface/basic.md +62 -0
  62. package/docs/reference/authoring-surface/bearer.md +53 -0
  63. package/docs/reference/authoring-surface/branchname.md +15 -0
  64. package/docs/reference/authoring-surface/chartschema.md +23 -0
  65. package/docs/reference/authoring-surface/chartschemafor.md +48 -0
  66. package/docs/reference/authoring-surface/command.md +206 -0
  67. package/docs/reference/authoring-surface/customize.md +64 -0
  68. package/docs/reference/authoring-surface/defineconfig.md +41 -0
  69. package/docs/reference/authoring-surface/defineevent.md +114 -0
  70. package/docs/reference/authoring-surface/dispatch.md +126 -0
  71. package/docs/reference/authoring-surface/fail.md +96 -0
  72. package/docs/reference/authoring-surface/file.md +142 -0
  73. package/docs/reference/authoring-surface/frompick.md +277 -0
  74. package/docs/reference/authoring-surface/http.md +259 -0
  75. package/docs/reference/authoring-surface/isfailure.md +58 -0
  76. package/docs/reference/authoring-surface/isready.md +14 -0
  77. package/docs/reference/authoring-surface/jr2setup.md +237 -0
  78. package/docs/reference/authoring-surface/open.md +105 -0
  79. package/docs/reference/authoring-surface/openbody.md +86 -0
  80. package/docs/reference/authoring-surface/paramsof.md +143 -0
  81. package/docs/reference/authoring-surface/pool.md +186 -0
  82. package/docs/reference/authoring-surface/push.md +130 -0
  83. package/docs/reference/authoring-surface/readyof.md +21 -0
  84. package/docs/reference/authoring-surface/secret.md +139 -0
  85. package/docs/reference/authoring-surface/sentby.md +83 -0
  86. package/docs/reference/authoring-surface/source.md +51 -0
  87. package/docs/reference/authoring-surface/text.md +62 -0
  88. package/docs/reference/authoring-surface/type-agentdeclaration.md +27 -0
  89. package/docs/reference/authoring-surface/type-agentdefinition.md +80 -0
  90. package/docs/reference/authoring-surface/type-agentlogic.md +15 -0
  91. package/docs/reference/authoring-surface/type-agentslots.md +15 -0
  92. package/docs/reference/authoring-surface/type-answeraction.md +12 -0
  93. package/docs/reference/authoring-surface/type-anyframepath.md +14 -0
  94. package/docs/reference/authoring-surface/type-anyworktreepath.md +15 -0
  95. package/docs/reference/authoring-surface/type-arg.md +19 -0
  96. package/docs/reference/authoring-surface/type-argnames.md +12 -0
  97. package/docs/reference/authoring-surface/type-bindactors.md +14 -0
  98. package/docs/reference/authoring-surface/type-binding.md +61 -0
  99. package/docs/reference/authoring-surface/type-bindingof.md +12 -0
  100. package/docs/reference/authoring-surface/type-bodyacceptsdoor.md +15 -0
  101. package/docs/reference/authoring-surface/type-bodyacceptsslots.md +17 -0
  102. package/docs/reference/authoring-surface/type-ceilings.md +41 -0
  103. package/docs/reference/authoring-surface/type-chainlink.md +19 -0
  104. package/docs/reference/authoring-surface/type-chartaction.md +46 -0
  105. package/docs/reference/authoring-surface/type-chartagent.md +28 -0
  106. package/docs/reference/authoring-surface/type-chartevent.md +20 -0
  107. package/docs/reference/authoring-surface/type-chartguard.md +20 -0
  108. package/docs/reference/authoring-surface/type-chartinvoke.md +28 -0
  109. package/docs/reference/authoring-surface/type-chartjson.md +14 -0
  110. package/docs/reference/authoring-surface/type-chartstate.md +46 -0
  111. package/docs/reference/authoring-surface/type-charttext.md +40 -0
  112. package/docs/reference/authoring-surface/type-charttransition.md +22 -0
  113. package/docs/reference/authoring-surface/type-charttransitions.md +14 -0
  114. package/docs/reference/authoring-surface/type-chartvalue.md +15 -0
  115. package/docs/reference/authoring-surface/type-childat.md +12 -0
  116. package/docs/reference/authoring-surface/type-childslots.md +12 -0
  117. package/docs/reference/authoring-surface/type-commandenv.md +15 -0
  118. package/docs/reference/authoring-surface/type-commandinput.md +20 -0
  119. package/docs/reference/authoring-surface/type-commandoptions.md +56 -0
  120. package/docs/reference/authoring-surface/type-commandoutput.md +122 -0
  121. package/docs/reference/authoring-surface/type-customize.md +111 -0
  122. package/docs/reference/authoring-surface/type-dispatchdefinition.md +39 -0
  123. package/docs/reference/authoring-surface/type-dispatchinput.md +14 -0
  124. package/docs/reference/authoring-surface/type-dispatchopenparts.md +14 -0
  125. package/docs/reference/authoring-surface/type-dispatchoutput.md +72 -0
  126. package/docs/reference/authoring-surface/type-doorlessinput.md +19 -0
  127. package/docs/reference/authoring-surface/type-duration.md +15 -0
  128. package/docs/reference/authoring-surface/type-effectbinding.md +93 -0
  129. package/docs/reference/authoring-surface/type-effectlogic.md +12 -0
  130. package/docs/reference/authoring-surface/type-envopenparts.md +14 -0
  131. package/docs/reference/authoring-surface/type-eventaudience.md +27 -0
  132. package/docs/reference/authoring-surface/type-eventdef.md +45 -0
  133. package/docs/reference/authoring-surface/type-eventfrom.md +16 -0
  134. package/docs/reference/authoring-surface/type-eventsemantics.md +26 -0
  135. package/docs/reference/authoring-surface/type-execoutcome.md +34 -0
  136. package/docs/reference/authoring-surface/type-failslot.md +14 -0
  137. package/docs/reference/authoring-surface/type-failure.md +19 -0
  138. package/docs/reference/authoring-surface/type-failureinput.md +20 -0
  139. package/docs/reference/authoring-surface/type-filebody.md +37 -0
  140. package/docs/reference/authoring-surface/type-framepath.md +14 -0
  141. package/docs/reference/authoring-surface/type-frominput.md +14 -0
  142. package/docs/reference/authoring-surface/type-hostinjectedinput.md +56 -0
  143. package/docs/reference/authoring-surface/type-httpdefinition.md +104 -0
  144. package/docs/reference/authoring-surface/type-httpfileinput.md +20 -0
  145. package/docs/reference/authoring-surface/type-httpinput.md +12 -0
  146. package/docs/reference/authoring-surface/type-httpmethod.md +14 -0
  147. package/docs/reference/authoring-surface/type-httpopenparts.md +12 -0
  148. package/docs/reference/authoring-surface/type-httpoutput.md +95 -0
  149. package/docs/reference/authoring-surface/type-httprequestparts.md +33 -0
  150. package/docs/reference/authoring-surface/type-jr2config.md +126 -0
  151. package/docs/reference/authoring-surface/type-lateroutcome.md +21 -0
  152. package/docs/reference/authoring-surface/type-lends.md +38 -0
  153. package/docs/reference/authoring-surface/type-logicat.md +12 -0
  154. package/docs/reference/authoring-surface/type-markedif.md +12 -0
  155. package/docs/reference/authoring-surface/type-mergedactors.md +12 -0
  156. package/docs/reference/authoring-surface/type-namedsecret.md +25 -0
  157. package/docs/reference/authoring-surface/type-namestart.md +77 -0
  158. package/docs/reference/authoring-surface/type-noslotworkspaceoptions.md +27 -0
  159. package/docs/reference/authoring-surface/type-notworktreekeys.md +12 -0
  160. package/docs/reference/authoring-surface/type-openbodydeclaration.md +40 -0
  161. package/docs/reference/authoring-surface/type-openbodylogic.md +14 -0
  162. package/docs/reference/authoring-surface/type-openbodyoutput.md +42 -0
  163. package/docs/reference/authoring-surface/type-openbodyslot.md +18 -0
  164. package/docs/reference/authoring-surface/type-opencommandinput.md +22 -0
  165. package/docs/reference/authoring-surface/type-openeffect.md +12 -0
  166. package/docs/reference/authoring-surface/type-openeffectslots.md +12 -0
  167. package/docs/reference/authoring-surface/type-openof.md +12 -0
  168. package/docs/reference/authoring-surface/type-opensecret.md +23 -0
  169. package/docs/reference/authoring-surface/type-opensecretmark.md +12 -0
  170. package/docs/reference/authoring-surface/type-permissivenoslotworkspaceoptions.md +26 -0
  171. package/docs/reference/authoring-surface/type-permissiveworkspaceoptions.md +27 -0
  172. package/docs/reference/authoring-surface/type-poolmachine.md +28 -0
  173. package/docs/reference/authoring-surface/type-poolnextinput.md +22 -0
  174. package/docs/reference/authoring-surface/type-poolspec.md +60 -0
  175. package/docs/reference/authoring-surface/type-pushinput.md +34 -0
  176. package/docs/reference/authoring-surface/type-pushoptions.md +79 -0
  177. package/docs/reference/authoring-surface/type-pushoutput.md +149 -0
  178. package/docs/reference/authoring-surface/type-pushwireoutput.md +12 -0
  179. package/docs/reference/authoring-surface/type-quantity.md +14 -0
  180. package/docs/reference/authoring-surface/type-reached.md +12 -0
  181. package/docs/reference/authoring-surface/type-reposlot.md +70 -0
  182. package/docs/reference/authoring-surface/type-reposlotsof.md +16 -0
  183. package/docs/reference/authoring-surface/type-sandboxoptions.md +84 -0
  184. package/docs/reference/authoring-surface/type-secret.md +25 -0
  185. package/docs/reference/authoring-surface/type-sender.md +19 -0
  186. package/docs/reference/authoring-surface/type-sentbyguards.md +12 -0
  187. package/docs/reference/authoring-surface/type-size.md +85 -0
  188. package/docs/reference/authoring-surface/type-slothandles.md +24 -0
  189. package/docs/reference/authoring-surface/type-sourcenextresult.md +17 -0
  190. package/docs/reference/authoring-surface/type-sourcespec.md +44 -0
  191. package/docs/reference/authoring-surface/type-syncstate.md +12 -0
  192. package/docs/reference/authoring-surface/type-text.md +19 -0
  193. package/docs/reference/authoring-surface/type-textpart.md +24 -0
  194. package/docs/reference/authoring-surface/type-thinkinglevel.md +39 -0
  195. package/docs/reference/authoring-surface/type-toparameterizedobject.md +14 -0
  196. package/docs/reference/authoring-surface/type-toprovidedactor.md +14 -0
  197. package/docs/reference/authoring-surface/type-unknown.md +21 -0
  198. package/docs/reference/authoring-surface/type-usercontainer.md +77 -0
  199. package/docs/reference/authoring-surface/type-withoutemptyindex.md +20 -0
  200. package/docs/reference/authoring-surface/type-workflowevent.md +46 -0
  201. package/docs/reference/authoring-surface/type-workspaceaccess.md +16 -0
  202. package/docs/reference/authoring-surface/type-workspaced.md +115 -0
  203. package/docs/reference/authoring-surface/type-workspacehandles.md +22 -0
  204. package/docs/reference/authoring-surface/type-workspacemachine.md +29 -0
  205. package/docs/reference/authoring-surface/type-workspaceof.md +13 -0
  206. package/docs/reference/authoring-surface/type-workspaceoptions.md +27 -0
  207. package/docs/reference/authoring-surface/type-worktreefound.md +16 -0
  208. package/docs/reference/authoring-surface/type-worktreeinput.md +56 -0
  209. package/docs/reference/authoring-surface/type-worktreekey.md +14 -0
  210. package/docs/reference/authoring-surface/type-worktreeoptions.md +29 -0
  211. package/docs/reference/authoring-surface/type-worktreeoutput.md +45 -0
  212. package/docs/reference/authoring-surface/type-worktreepath.md +16 -0
  213. package/docs/reference/authoring-surface/type-worktreeready.md +37 -0
  214. package/docs/reference/authoring-surface/type-worktreerefused.md +21 -0
  215. package/docs/reference/authoring-surface/workspace.md +287 -0
  216. package/docs/reference/authoring-surface/worktree.md +71 -0
  217. package/docs/reference/authoring-surface.md +217 -0
  218. package/docs/reference/cli.md +433 -0
  219. package/docs/reference/config.md +765 -0
  220. package/docs/reference/decisions/0001-operator-owned-generic-sandbox.md +114 -0
  221. package/docs/reference/decisions/0002-duplex-streaming-actor.md +117 -0
  222. package/docs/reference/decisions/0004-worktree-provisioning-model.md +130 -0
  223. package/docs/reference/decisions/0005-sandbox-pod-composition.md +240 -0
  224. package/docs/reference/decisions/0006-agent-control-surface.md +50 -0
  225. package/docs/reference/decisions/0007-durable-machine-state.md +109 -0
  226. package/docs/reference/decisions/0008-orchestrator-as-deployed-app.md +60 -0
  227. package/docs/reference/decisions/0009-cli-and-instance-interface.md +275 -0
  228. package/docs/reference/decisions/0010-bdd-acceptance-tests.md +160 -0
  229. package/docs/reference/decisions/0011-workflow-defined-events.md +141 -0
  230. package/docs/reference/decisions/0012-workspace-wrapper-machine.md +103 -0
  231. package/docs/reference/decisions/0013-the-agent-reaches-its-machine-through-a-container-it-cannot-read.md +175 -0
  232. package/docs/reference/decisions/0014-observation-is-open-run-state-is-not.md +95 -0
  233. package/docs/reference/decisions/0015-authoring-surface-absorbs-the-mechanism.md +271 -0
  234. package/docs/reference/decisions/0016-agent-turn-mechanics-are-internal.md +126 -0
  235. package/docs/reference/decisions/0017-pool-over-a-source-port.md +71 -0
  236. package/docs/reference/decisions/0018-instance-agents-are-definitions-jr2-assembles-the-harness.md +111 -0
  237. package/docs/reference/decisions/0019-one-converging-command-against-the-current-context.md +287 -0
  238. package/docs/reference/decisions/0020-private-ca-trust-is-a-named-concept.md +60 -0
  239. package/docs/reference/decisions/0021-workspace-continuity-is-a-lease-that-answers-back.md +101 -0
  240. package/docs/reference/decisions/0022-observation-is-a-level-triggered-feed.md +103 -0
  241. package/docs/reference/decisions/0023-the-harness-prints-the-conversation.md +175 -0
  242. package/docs/reference/decisions/0024-an-agents-turn-ends-with-the-state-that-asked-for-it.md +436 -0
  243. package/docs/reference/decisions/0025-cancel-ends-a-run-stop-parks-it.md +65 -0
  244. package/docs/reference/decisions/0026-a-turn-that-is-over-is-never-prompted.md +62 -0
  245. package/docs/reference/decisions/0027-the-harness-is-jr2s-own-server-flue-retires-the-wire-stays.md +245 -0
  246. package/docs/reference/decisions/0028-what-an-agent-may-do-to-the-workspace-is-part-of-its-definition.md +90 -0
  247. package/docs/reference/decisions/0029-a-menu-is-fixed-for-a-conversation-and-a-turn-is-told-its-allowed-picks.md +154 -0
  248. package/docs/reference/decisions/0030-a-snapshot-names-the-machine-it-was-written-under.md +100 -0
  249. package/docs/reference/decisions/0031-menu-only-agents-run-on-the-instance-harness.md +193 -0
  250. package/docs/reference/decisions/0032-the-console-unlocks-with-the-instance-token.md +61 -0
  251. package/docs/reference/decisions/0033-a-machine-declares-the-input-that-starts-it.md +126 -0
  252. package/docs/reference/decisions/0034-the-console-renders-with-preact-and-the-server-erases-the-types.md +57 -0
  253. package/docs/reference/decisions/0035-a-runaway-turn-is-ended-rerolled-once-then-a-fault.md +92 -0
  254. package/docs/reference/decisions/0036-a-turn-compacts-its-own-context-mid-flight.md +138 -0
  255. package/docs/reference/decisions/0037-an-instance-builds-its-sandbox-images-jr2-injects-the-harness.md +196 -0
  256. package/docs/reference/decisions/0038-jr2-up-builds-every-image-it-deploys.md +170 -0
  257. package/docs/reference/decisions/0039-image-garbage-collects-by-reachability.md +115 -0
  258. package/docs/reference/decisions/0041-a-build-the-host-already-holds-is-not-spent-again.md +64 -0
  259. package/docs/reference/decisions/0042-ready-is-not-routable-an-admission-retries-its-connection.md +142 -0
  260. package/docs/reference/decisions/0043-the-kit-is-tested-as-installed-a-local-registry-stands-in-for-npm.md +170 -0
  261. package/docs/reference/decisions/0044-kit-images-live-at-a-canonical-home-a-self-host-mirrors-it.md +85 -0
  262. package/docs/reference/decisions/0045-the-platform-joins-the-image-address-and-the-cluster-chooses-it.md +82 -0
  263. package/docs/reference/decisions/0046-a-converge-failure-carries-its-diagnosis.md +34 -0
  264. package/docs/reference/decisions/0047-the-git-ssh-key-source-is-the-users-choice.md +47 -0
  265. package/docs/reference/decisions/0048-the-orchestrator-boots-without-its-repos.md +36 -0
  266. package/docs/reference/decisions/0049-a-machine-carries-its-parts-and-composes-by-invoke.md +126 -0
  267. package/docs/reference/decisions/0050-what-code-names-config-declares-what-the-cli-names-discovery-finds.md +73 -0
  268. package/docs/reference/decisions/0051-a-repo-is-a-slot-on-the-workspace-and-a-cache-on-the-node.md +238 -0
  269. package/docs/reference/decisions/0052-a-sandbox-lands-where-an-ordinary-pod-lands-and-the-cache-follows-it.md +86 -0
  270. package/docs/reference/decisions/0053-a-fetch-inside-the-pod-asks-the-node-cache-and-the-cache-asks-the-remote.md +123 -0
  271. package/docs/reference/decisions/0054-the-kit-ships-machines-and-a-shipped-machine-leaves-its-parts-open.md +126 -0
  272. package/docs/reference/decisions/0055-a-release-is-a-pushed-tag-and-the-publish-guard-is-the-credential.md +107 -0
  273. package/docs/reference/decisions/0056-a-global-jr2-hands-off-to-the-instances-own-and-an-instance-has-one-kit-version.md +62 -0
  274. package/docs/reference/decisions/0057-a-turn-is-its-frame-its-dials-and-whether-it-continues.md +152 -0
  275. package/docs/reference/decisions/0058-a-harness-answers-the-orchestrator-alone.md +108 -0
  276. package/docs/reference/decisions/0059-a-harness-holds-stand-ins-and-the-custodian-holds-the-keys.md +427 -0
  277. package/docs/reference/decisions/0060-a-workspace-states-its-size-and-jr2-reserves-all-of-it.md +111 -0
  278. package/docs/reference/decisions/0061-a-memory-kill-ends-the-agents-processes-not-the-harness.md +83 -0
  279. package/docs/reference/decisions/0062-jr2-briefs-the-agent-on-its-seat-never-on-its-task.md +239 -0
  280. package/docs/reference/decisions/0063-the-orchestrator-watches-the-cluster.md +82 -0
  281. package/docs/reference/decisions/0064-a-workspace-waits-for-capacity.md +79 -0
  282. package/docs/reference/decisions/0065-a-persist-survives-a-crash-and-history-is-a-week.md +65 -0
  283. package/docs/reference/decisions/0066-a-model-tier-runs-a-real-model-and-a-change-to-what-it-reads-runs-the-tier.md +552 -0
  284. package/docs/reference/decisions/0067-an-effect-is-an-actor-slot-and-runs-at-most-once-unless-marked-idempotent.md +458 -0
  285. package/docs/reference/decisions/0068-an-effector-holds-an-effects-secrets-and-signs-its-wire.md +475 -0
  286. package/docs/reference/decisions/0069-the-orchestrator-is-a-kit-image-and-an-instance-publishes-its-assembly.md +180 -0
  287. package/docs/reference/decisions/0070-a-machine-lends-its-parts-to-a-chart.md +334 -0
  288. package/docs/reference/decisions/0071-a-run-starts-a-run-through-a-dispatch-effect.md +183 -0
  289. package/docs/reference/decisions/0072-the-docs-ship-inside-the-kit-and-an-instances-agents-md-indexes-them.md +144 -0
  290. package/docs/reference/decisions/0073-a-machine-fails-a-run-with-fail-and-an-uncaught-failure-ends-it-failed.md +122 -0
  291. package/docs/reference/decisions/0074-an-unrouted-mechanism-event-is-refused-at-load-and-faults-the-run.md +76 -0
  292. package/docs/reference/decisions/0075-a-machine-cuts-a-worktree-and-the-workspace-only-clones.md +295 -0
  293. package/docs/reference/decisions/0076-an-agents-control-credential-lives-only-where-no-workspace-code-runs.md +320 -0
  294. package/docs/reference/decisions/0077-jr2-requires-landlock-on-every-sandbox-node.md +79 -0
  295. package/docs/reference/decisions.md +86 -0
  296. package/docs/reference/glossary.md +687 -0
  297. package/docs/reference/http-api.md +1386 -0
  298. package/docs/reference/machines.md +189 -0
  299. package/docs/reference/mechanism-events.md +72 -0
  300. package/docs/why.md +207 -0
  301. package/package.json +5 -3
  302. package/src/actor.ts +694 -106
  303. package/src/agent.ts +114 -38
  304. package/src/ambient.ts +3 -4
  305. package/src/assembly-checks.ts +189 -7
  306. package/src/cause.ts +234 -0
  307. package/src/chart.ts +345 -46
  308. package/src/charts.ts +43 -8
  309. package/src/config.ts +440 -178
  310. package/src/custodian.lua +17 -5
  311. package/src/custodian.ts +325 -99
  312. package/src/customize.ts +199 -49
  313. package/src/dispatch-effect.ts +945 -0
  314. package/src/door-compat.ts +217 -0
  315. package/src/durability.ts +11 -4
  316. package/src/effect-checks.ts +50 -3
  317. package/src/effect.ts +641 -128
  318. package/src/effector-wire.ts +165 -13
  319. package/src/fail.ts +222 -0
  320. package/src/harness-client.ts +587 -50
  321. package/src/harness-env.ts +33 -0
  322. package/src/held-secrets.ts +125 -16
  323. package/src/holds.ts +3 -0
  324. package/src/http-effect.ts +556 -58
  325. package/src/http.ts +480 -30
  326. package/src/index.ts +74 -82
  327. package/src/instance.ts +68 -8
  328. package/src/internal.ts +85 -0
  329. package/src/kube-client.ts +6 -3
  330. package/src/machine-doc.ts +24 -7
  331. package/src/mechanism-routes.ts +168 -0
  332. package/src/model-keys.generated.ts +53 -0
  333. package/src/model-keys.ts +42 -58
  334. package/src/names.ts +19 -6
  335. package/src/notices.ts +483 -41
  336. package/src/open-body.ts +242 -40
  337. package/src/open-effect.ts +81 -8
  338. package/src/open.ts +90 -6
  339. package/src/parts.ts +213 -30
  340. package/src/party.ts +101 -2
  341. package/src/pick.ts +497 -11
  342. package/src/pool.ts +282 -50
  343. package/src/registration.ts +133 -12
  344. package/src/repo-identity.ts +7 -3
  345. package/src/repos.ts +22 -3
  346. package/src/run-host.ts +665 -45
  347. package/src/run-output.ts +38 -0
  348. package/src/sandbox-effect.ts +457 -71
  349. package/src/sandbox-kube.ts +66 -17
  350. package/src/secret-placement.ts +59 -17
  351. package/src/server.ts +3 -0
  352. package/src/setup.ts +325 -62
  353. package/src/size.ts +121 -9
  354. package/src/snapshot-store.ts +54 -10
  355. package/src/stub-harness.ts +44 -16
  356. package/src/timers.ts +14 -1
  357. package/src/tokens.ts +107 -32
  358. package/src/vocabulary.ts +88 -14
  359. package/src/wire.ts +100 -26
  360. package/src/workspace.ts +771 -238
  361. package/src/worktree.ts +249 -0
@@ -0,0 +1,587 @@
1
+ ---
2
+ title: Run a command or call a URL with an Effect
3
+ description: Run a program or call a URL as an Effect, give it input from a pick, and route on its output.
4
+ ---
5
+
6
+ # Run a command or call a URL with an Effect
7
+
8
+ Run a program in the [Workspace](../reference/glossary.md#workspace), or call a URL, as an
9
+ [Effect](../reference/glossary.md#effect), and route the [Machine](../reference/glossary.md#machine) on its output.
10
+
11
+ Put the Effect under `actors` in [`jr2Setup`](../reference/authoring-surface/jr2setup.md), beside the
12
+ [Agents](../reference/glossary.md#agent). Then invoke it by its key from a state, and route on its output in `onDone`.
13
+ In this [Workflow](../reference/glossary.md#workflow), the Machine cuts a [Worktree](../reference/glossary.md#worktree),
14
+ and a coder fixes the tests there. It picks `run_test` to run one test file with a
15
+ [`command`](../reference/authoring-surface/command.md) Effect. When it picks `finished`, an
16
+ [`http`](../reference/authoring-surface/http.md) Effect posts its summary to a URL. Save the file as
17
+ `workflows/fix-and-report.ts` in your [Instance](../reference/glossary.md#instance):
18
+
19
+ **Anthropic**
20
+
21
+ ```ts
22
+ import { z } from "zod";
23
+ import {
24
+ agent,
25
+ answer,
26
+ arg,
27
+ bearer,
28
+ command,
29
+ defineEvent,
30
+ fail,
31
+ fromPick,
32
+ http,
33
+ isReady,
34
+ jr2Setup,
35
+ secret,
36
+ workspace,
37
+ worktree,
38
+ type CommandOutput,
39
+ type Workspaced,
40
+ } from "@jr2/orchestrator";
41
+
42
+ const runTest = defineEvent({
43
+ name: "run_test",
44
+ description: "Run one test file. The answer tells if it passes.",
45
+ input: z.object({ file: z.string() }),
46
+ });
47
+ const finished = defineEvent({
48
+ name: "finished",
49
+ description: "Call this when the tests pass and you committed the fix. Say what you changed.",
50
+ input: z.object({ summary: z.string() }),
51
+ });
52
+
53
+ const runInput = z.object({ prompt: z.string(), branch: z.string() });
54
+ type BodyInput = Workspaced<z.infer<typeof runInput>, "app">;
55
+
56
+ // The Worktree that the coder and the command name.
57
+ const fixTree = (context: BodyInput) => `${context.workspace.repos.app}/fix` as const;
58
+
59
+ const passed = (output: CommandOutput): boolean => output.outcome === "exited" && output.code === 0;
60
+
61
+ const body = jr2Setup({
62
+ types: {} as { input: BodyInput; context: BodyInput },
63
+ events: [runTest, finished],
64
+ actors: {
65
+ coder: agent({
66
+ model: "anthropic/claude-haiku-5-5",
67
+ instructions: "You fix failing tests. You change no test. You commit the fix.",
68
+ }),
69
+ // Cut the Worktree: an Effect too.
70
+ cut: worktree(),
71
+ // One program, with no shell. arg("file") is one argument, from the input of the Effect.
72
+ test: command(["node", "--test", arg("file")], { timeout: "5m" }),
73
+ // A call to a fixed URL. The Effector puts the value of the secret in the header.
74
+ report: http({
75
+ method: "POST",
76
+ url: "https://hooks.example.com/jr2",
77
+ auth: bearer(secret("hook-token")),
78
+ input: z.object({ branch: z.string(), summary: z.string() }),
79
+ request: ({ branch, summary }) => ({ json: { text: `${branch}: ${summary}` } }),
80
+ }),
81
+ // Fail the run: the end for work that did not succeed.
82
+ fail: fail(),
83
+ },
84
+ }).createMachine({
85
+ id: "fix-and-report",
86
+ context: ({ input }) => input,
87
+ on: { "workspace.lost": ".lost" },
88
+ initial: "cutting",
89
+ states: {
90
+ // The Workspace only clones. The Machine cuts the Worktree that the Agent works in.
91
+ cutting: {
92
+ invoke: {
93
+ src: "cut",
94
+ input: ({ context }) => ({ path: fixTree(context), branch: context.branch }),
95
+ onDone: [{ guard: ({ event }) => isReady(event.output), target: "coding" }, { target: "notCut" }],
96
+ },
97
+ },
98
+ coding: {
99
+ invoke: {
100
+ src: "coder",
101
+ input: ({ context }) => ({ prompt: context.prompt, cwd: fixTree(context) }),
102
+ },
103
+ on: {
104
+ finished: "reporting",
105
+ // A Turn of the coder failed with no pick. Without this route, the run stays in `coding`.
106
+ "agent.fault": "failed",
107
+ },
108
+ initial: "ready",
109
+ states: {
110
+ ready: { on: { run_test: "testing" } },
111
+ testing: {
112
+ invoke: {
113
+ src: "test",
114
+ // The `file` of the pick goes to the arg("file") of the command. The Machine gives `worktree`.
115
+ input: fromPick(runTest, ({ context }) => ({ worktree: fixTree(context) })),
116
+ onDone: {
117
+ target: "ready",
118
+ // The Agent reads this text as the answer to its run_test pick.
119
+ actions: answer(({ event }) =>
120
+ passed(event.output)
121
+ ? "The test passes."
122
+ : `The test fails:\n${"tail" in event.output ? event.output.tail : event.output.reason}`,
123
+ ),
124
+ },
125
+ },
126
+ },
127
+ },
128
+ },
129
+ reporting: {
130
+ invoke: {
131
+ src: "report",
132
+ // The Agent gives `summary`. The Machine gives `branch`.
133
+ input: fromPick(finished, ({ context }) => ({ branch: context.branch })),
134
+ onDone: [
135
+ { guard: ({ event }) => event.output.outcome === "response" && event.output.status < 300, target: "done" },
136
+ { target: "notReported" },
137
+ ],
138
+ },
139
+ },
140
+ done: { type: "final" },
141
+ // Not final states: a final state means `done`. Each one fails the run, and the run ends `failed`.
142
+ notCut: { invoke: { src: "fail", input: { reason: "the Worktree was not cut" } } },
143
+ notReported: { invoke: { src: "fail", input: { reason: "the report did not go out" } } },
144
+ failed: { invoke: { src: "fail", input: { reason: "the coder could not go on" } } },
145
+ lost: { invoke: { src: "fail", input: { reason: "the Sandbox was lost" } } },
146
+ },
147
+ });
148
+
149
+ export const machine = workspace(body, {
150
+ input: runInput,
151
+ repos: { app: "https://github.com/<you>/app.git" },
152
+ });
153
+ ```
154
+
155
+ **Local**
156
+
157
+ ```ts
158
+ import { z } from "zod";
159
+ import {
160
+ agent,
161
+ answer,
162
+ arg,
163
+ bearer,
164
+ command,
165
+ defineEvent,
166
+ fail,
167
+ fromPick,
168
+ http,
169
+ isReady,
170
+ jr2Setup,
171
+ secret,
172
+ workspace,
173
+ worktree,
174
+ type CommandOutput,
175
+ type Workspaced,
176
+ } from "@jr2/orchestrator";
177
+
178
+ const runTest = defineEvent({
179
+ name: "run_test",
180
+ description: "Run one test file. The answer tells if it passes.",
181
+ input: z.object({ file: z.string() }),
182
+ });
183
+ const finished = defineEvent({
184
+ name: "finished",
185
+ description: "Call this when the tests pass and you committed the fix. Say what you changed.",
186
+ input: z.object({ summary: z.string() }),
187
+ });
188
+
189
+ const runInput = z.object({ prompt: z.string(), branch: z.string() });
190
+ type BodyInput = Workspaced<z.infer<typeof runInput>, "app">;
191
+
192
+ // The Worktree that the coder and the command name.
193
+ const fixTree = (context: BodyInput) => `${context.workspace.repos.app}/fix` as const;
194
+
195
+ const passed = (output: CommandOutput): boolean => output.outcome === "exited" && output.code === 0;
196
+
197
+ const body = jr2Setup({
198
+ types: {} as { input: BodyInput; context: BodyInput },
199
+ events: [runTest, finished],
200
+ actors: {
201
+ coder: agent({
202
+ model: "local/qwen3.6-35b-a3b",
203
+ instructions: "You fix failing tests. You change no test. You commit the fix.",
204
+ }),
205
+ // Cut the Worktree: an Effect too.
206
+ cut: worktree(),
207
+ // One program, with no shell. arg("file") is one argument, from the input of the Effect.
208
+ test: command(["node", "--test", arg("file")], { timeout: "5m" }),
209
+ // A call to a fixed URL. The Effector puts the value of the secret in the header.
210
+ report: http({
211
+ method: "POST",
212
+ url: "https://hooks.example.com/jr2",
213
+ auth: bearer(secret("hook-token")),
214
+ input: z.object({ branch: z.string(), summary: z.string() }),
215
+ request: ({ branch, summary }) => ({ json: { text: `${branch}: ${summary}` } }),
216
+ }),
217
+ // Fail the run: the end for work that did not succeed.
218
+ fail: fail(),
219
+ },
220
+ }).createMachine({
221
+ id: "fix-and-report",
222
+ context: ({ input }) => input,
223
+ on: { "workspace.lost": ".lost" },
224
+ initial: "cutting",
225
+ states: {
226
+ // The Workspace only clones. The Machine cuts the Worktree that the Agent works in.
227
+ cutting: {
228
+ invoke: {
229
+ src: "cut",
230
+ input: ({ context }) => ({ path: fixTree(context), branch: context.branch }),
231
+ onDone: [{ guard: ({ event }) => isReady(event.output), target: "coding" }, { target: "notCut" }],
232
+ },
233
+ },
234
+ coding: {
235
+ invoke: {
236
+ src: "coder",
237
+ input: ({ context }) => ({ prompt: context.prompt, cwd: fixTree(context) }),
238
+ },
239
+ on: {
240
+ finished: "reporting",
241
+ // A Turn of the coder failed with no pick. Without this route, the run stays in `coding`.
242
+ "agent.fault": "failed",
243
+ },
244
+ initial: "ready",
245
+ states: {
246
+ ready: { on: { run_test: "testing" } },
247
+ testing: {
248
+ invoke: {
249
+ src: "test",
250
+ // The `file` of the pick goes to the arg("file") of the command. The Machine gives `worktree`.
251
+ input: fromPick(runTest, ({ context }) => ({ worktree: fixTree(context) })),
252
+ onDone: {
253
+ target: "ready",
254
+ // The Agent reads this text as the answer to its run_test pick.
255
+ actions: answer(({ event }) =>
256
+ passed(event.output)
257
+ ? "The test passes."
258
+ : `The test fails:\n${"tail" in event.output ? event.output.tail : event.output.reason}`,
259
+ ),
260
+ },
261
+ },
262
+ },
263
+ },
264
+ },
265
+ reporting: {
266
+ invoke: {
267
+ src: "report",
268
+ // The Agent gives `summary`. The Machine gives `branch`.
269
+ input: fromPick(finished, ({ context }) => ({ branch: context.branch })),
270
+ onDone: [
271
+ { guard: ({ event }) => event.output.outcome === "response" && event.output.status < 300, target: "done" },
272
+ { target: "notReported" },
273
+ ],
274
+ },
275
+ },
276
+ done: { type: "final" },
277
+ // Not final states: a final state means `done`. Each one fails the run, and the run ends `failed`.
278
+ notCut: { invoke: { src: "fail", input: { reason: "the Worktree was not cut" } } },
279
+ notReported: { invoke: { src: "fail", input: { reason: "the report did not go out" } } },
280
+ failed: { invoke: { src: "fail", input: { reason: "the coder could not go on" } } },
281
+ lost: { invoke: { src: "fail", input: { reason: "the Sandbox was lost" } } },
282
+ },
283
+ });
284
+
285
+ export const machine = workspace(body, {
286
+ input: runInput,
287
+ repos: { app: "https://github.com/<you>/app.git" },
288
+ });
289
+ ```
290
+
291
+ The `coding` state routes [`agent.fault`](../reference/mechanism-events.md#agent-fault) to `failed`. jr2 sends it when a
292
+ Turn of the coder fails with no pick. Each state that invokes an Agent has a route for it, on the state or on a state
293
+ above it: `jr2 check` refuses a Machine without one. When no transition takes the event, the run ends `error`.
294
+
295
+ `notCut`, `failed`, `notReported` and `lost` are not final states. Each one invokes
296
+ [`fail`](../reference/authoring-surface/fail.md), and the run ends `failed` with its reason: a final state means `done`.
297
+ Do not throw from a promise to fail, because a throw is a defect, and the run ends `error`.
298
+
299
+ Write your GitHub user name in place of `<you>`. The Agent uses the model of the tab. `https://hooks.example.com/jr2` is
300
+ an example. Write the URL of your own service.
301
+
302
+ The `http` Effect names the [Effect secret](../reference/glossary.md#effect-secret) `hook-token`. Add it to the
303
+ [`secrets`](../reference/config.md#secrets) list of `jr2.config.ts`, beside the entries that are there:
304
+
305
+ ```ts
306
+ import { defineConfig } from "@jr2/orchestrator";
307
+
308
+ export default defineConfig({
309
+ // An Effect secret: secret("hook-token") names it. The value comes from HOOK_TOKEN in .env.
310
+ secrets: [{ name: "hook-token", value: process.env.HOOK_TOKEN }],
311
+ });
312
+ ```
313
+
314
+ The file shows only the `secrets` field. Keep the other fields and entries of your `jr2.config.ts`.
315
+
316
+ Then put the value in `.env`:
317
+
318
+ ```sh
319
+ HOOK_TOKEN=<token>
320
+ ```
321
+
322
+ `<token>` is the token of your service. It has 8 characters or more.
323
+
324
+ ## Run a command
325
+
326
+ `command(argv, options)` runs one program. `argv` is a list, and each entry is one argument. jr2 starts `argv[0]` with
327
+ no shell. An [`arg("name")`](../reference/authoring-surface/arg.md) entry is one argument that the input of the Effect
328
+ fills, whatever its characters. To use a shell, write it in the argv: `["sh", "-c", "<script>"]`.
329
+
330
+ The options:
331
+
332
+ - `timeout`: how long the program can run, such as `"90s"`, `"10m"` or `"1h"`. The default is `"10m"`. After it, jr2
333
+ kills the process group, and the outcome is `timeout`.
334
+ - `tail`: how many characters of the end of the output the Machine gets. The default is 4096.
335
+
336
+ The input of the Effect says where the program runs. Under [Repo Slots](../reference/glossary.md#repo-slot), `worktree`
337
+ is required: the path of a Worktree that a cut made, or `/work/<slot>/default`. The program starts in the root of that
338
+ folder. In a Workspace with no Repo Slot, it starts in `/work`, the folder that the steps of the Workspace share (see
339
+ [Workspaces](../concepts/workspaces.md#a-workspace-with-no-repo)). To run it in a subfolder, give the path as an
340
+ argument, such as `["node", "--test", "<dir>/test/*.test.js"]`, or write `["sh", "-c", "cd <dir> && <program>"]`.
341
+
342
+ A `command` with no Effect secret runs in the [Harness](../reference/glossary.md#harness) container of the
343
+ [Sandbox](../reference/glossary.md#sandbox), beside the [Working tools](../reference/glossary.md#working-tools) of the
344
+ Agent. It uses the tools of the [Sandbox Image](../reference/glossary.md#sandbox-image). Thus invoke it in the body of a
345
+ [`workspace()`](../reference/authoring-surface/workspace.md).
346
+
347
+ Each outcome is output for `onDone`, also a failure. Route on `outcome`
348
+ ([`CommandOutput`](../reference/authoring-surface/type-commandoutput.md)):
349
+
350
+ - `exited`, with `code` and `tail`. A test that fails is `exited` with a `code` that is not 0. A program that the
351
+ container does not have is `exited` with code 127. A bad `worktree` is `exited` with code 127 too, and `tail` gives
352
+ the reason. A bad path does not add an outcome.
353
+ - `timeout`, with `tail`.
354
+ - `killed`, with `signal` and `tail`.
355
+ - `unknown`, with `reason`: jr2 cannot tell what the program did. jr2 does not run it again.
356
+
357
+ ## Use an Effect secret in a command
358
+
359
+ A program that needs a credential gets it from the `env` option. Each value is an Effect secret, for example
360
+ `env: { NODE_AUTH_TOKEN: secret("npm-token") }`. [`secret("<name>")`](../reference/authoring-surface/secret.md) gives
361
+ the value. `secret("<name>").path` gives the path of a file that holds the value. The name is an entry of the `secrets`
362
+ list of `jr2.config.ts`, as for `hook-token`.
363
+
364
+ A `command` with an Effect secret in `env` does not run beside the Agent. It runs in the
365
+ [Sandbox Effector](../reference/glossary.md#sandbox-effector), a container that the Agent cannot reach. Its `worktree`
366
+ must be a branch Worktree that a cut made in this Sandbox, because a path alone does not name the target of a
367
+ credential. It runs against one commit of that branch, not against the live Worktree:
368
+
369
+ - By default, the commit is the tip of the branch when the Effect starts. When the Worktree holds changes that the
370
+ program did not see, its output has `dirty: true`.
371
+ - With `pin: true`, the commit is the `sha` of the input of the Effect: `{ worktree, sha: "<full commit id>" }`. Use it
372
+ for a commit that a [Gate](../reference/glossary.md#gate) approved.
373
+
374
+ The Sandbox Effector runs in the Sandbox Image, or in the image of the `effector` option of `workspace()`. Thus that
375
+ image must hold the program.
376
+
377
+ ## Call a URL
378
+
379
+ `http(definition)` makes one call to a URL. The definition fixes all of the call except what `request` makes:
380
+
381
+ - `method`: `GET`, `HEAD`, `POST`, `PUT`, `PATCH`, `DELETE` or `OPTIONS`.
382
+ - `url`: `http://` or `https://`, then a literal host. An Effect secret can be only in the path, in a
383
+ [`text`](../reference/authoring-surface/text.md) template:
384
+ `` text`https://api.example.com/bot${secret("<name>")}/send` ``.
385
+ - `auth`: the `Authorization` header. Use [`bearer(secret("<name>"))`](../reference/authoring-surface/bearer.md),
386
+ [`basic(user, password)`](../reference/authoring-surface/basic.md), or a `text` that is the full value.
387
+ - `headers`: the headers that are the same for each run. Each name is in lower case. A value is a string, a
388
+ `secret("<name>")` or a `text`.
389
+ - `input`: the zod schema of the input of the Effect. jr2 parses the input with it before the call.
390
+ - `request`: a function of the input. It gives the `path` segments that jr2 adds to the URL, and a `json` or a `text`
391
+ body. It cannot change the host, a header or an Effect secret.
392
+ - `timeout`: how long jr2 waits for the answer. The default is `"30s"`. After it, the outcome is `unknown`.
393
+ - `maxBody`: how many bytes of a text body the output keeps. The default is 65536.
394
+ - `idempotent`: `true` when a second call is safe. The default is `false`. See [Effects](../concepts/effects.md).
395
+
396
+ To send a file of a Worktree as the body, use [`file(path)`](../reference/authoring-surface/file.md) as `body`. The
397
+ input of the Effect names the Worktree, `{ worktree }`, and a cut in this Sandbox must have made it. The path is
398
+ relative to that Worktree. In a Workspace with no Repo Slot, the input has no `worktree`, and the path is relative to
399
+ `/work`. jr2 sends a file body only with `PUT`, `POST` or `PATCH`.
400
+
401
+ An `http` Effect runs in the [Instance Effector](../reference/glossary.md#instance-effector). The
402
+ [Effector](../reference/glossary.md#effector) puts the value of each Effect secret into the call. The Agent never reads
403
+ the value. You can invoke an `http` Effect in a Machine with no Workspace. An `http` Effect with a file body runs in the
404
+ Sandbox Effector, so invoke it in the body of a `workspace()`.
405
+
406
+ Each outcome is output for `onDone`. Route on `outcome`
407
+ ([`HttpOutput`](../reference/authoring-surface/type-httpoutput.md)):
408
+
409
+ - `response`, with `status`, `headers`, `contentType`, `size` and, for a text body, `body`. A 4xx or 5xx status is a
410
+ `response` too. The example goes to `done` only for a status below 300.
411
+ - `unreachable`: the call did not go out.
412
+ - `refused`: jr2 or the Effector refused the call, and sent nothing.
413
+ - `unknown`: the call can have gone out, but no answer came.
414
+
415
+ ## Give the input from a pick
416
+
417
+ The input of an Effect is the `input` of the invoke. When a pick of the Agent enters the state, the input can come from
418
+ the params of the pick:
419
+
420
+ - [`fromPick(def)`](../reference/authoring-surface/frompick.md) gives each param of the pick to the key of the same
421
+ name. In the `testing` state, the `file` of `run_test` goes to `arg("file")`.
422
+ - `fromPick(def, fill)` adds the keys that `fill` gives. In the `reporting` state, the Agent gives `summary`, and the
423
+ Machine gives `branch`. Thus the Agent cannot choose the branch in the report.
424
+ - [`paramsOf(event, def)`](../reference/authoring-surface/paramsof.md) reads the params in a plain `input` function. Use
425
+ it when the Machine changes a param before the Effect gets it.
426
+
427
+ Each param of a pick that enters an Effect's state must go somewhere: to a key of the Effect's input, to `fill`, or to
428
+ the context with `assign`. `createMachine` refuses a param that nothing reads, because the Agent gives it and nothing
429
+ uses it. The compiler does not find this error. `jr2 check` and `jr2 up` find it when they load the module. Thus when
430
+ you copy `finished` with its `summary` into a Machine that does not send or keep the summary, drop `summary` from the
431
+ `input` of the event. [Rules](#rules) gives the text of each refusal.
432
+
433
+ TypeScript checks the keys of the pick and of `fill` against the input of the Effect. When the Agent's state holds the
434
+ Effect, the Agent waits for the answer to its pick. [`answer(fn)`](../reference/authoring-surface/answer.md) sets that
435
+ answer. In the `testing` state, the Agent reads one line, or the end of the test output. Without `answer`, it reads the
436
+ `CommandOutput` of the command, as JSON.
437
+
438
+ ## What jr2 up shows
439
+
440
+ Run [`jr2 up`](../reference/cli.md#up). It reads each Effect without running it, and it shows what the Effect runs, and
441
+ where. It also shows where each Effect secret goes:
442
+
443
+ ```sh
444
+ jr2 up
445
+ ```
446
+
447
+ ```text
448
+ …
449
+ effects: workflow "fix-and-report" — what it runs outside itself (ADR-0067)
450
+ cut: worktree — 600s, in the Harness
451
+ test: command ["node","--test","<file>"] — 300s, in the Harness
452
+ report: http POST https://hooks.example.com — 30s, in the Instance Effector, secrets "hook-token"
453
+ …
454
+ failures: workflow "fix-and-report" — the states that fail the run (ADR-0073)
455
+ fix-and-report.notCut: invokes fail
456
+ fix-and-report.notReported: invokes fail
457
+ fix-and-report.failed: invokes fail
458
+ fix-and-report.lost: invokes fail
459
+ …
460
+ secret hook-token: an Effect secret in the Instance Effector (fix-and-report/report)
461
+ …
462
+ ```
463
+
464
+ `<file>` is the `arg("file")` entry. Each time is in seconds. `failures` lists each state that can end the run `failed`.
465
+
466
+ ## Rules
467
+
468
+ When you call `command()`, it refuses:
469
+
470
+ - an empty argv: `command(argv): argv is a non-empty list — each entry one argument, never shell text`
471
+ - an entry that is not a string or an `arg()`: `command(argv): an argv entry is a string or arg("name"), got <entry>`
472
+ - a timeout that is not a positive duration:
473
+ `command: timeout "<timeout>" is not a positive duration (like "90s", "10m", "1h")`
474
+ - an `env` name that is not a variable name, or that is `PATH`, `HOME` or `TMPDIR`:
475
+ `command(argv, { env }): "<name>" is not a variable the author sets — PATH, HOME and TMPDIR are the Effector's (ADR-0067)`
476
+ - `pin: true` with no Effect secret in `env`:
477
+ ``command(argv, { pin: true }) names no secret in its env: `pin` chooses the commit a credentialed command runs against in the Sandbox Effector, and a command that names no secret runs in the live Worktree (ADR-0067) — name its secret, command(argv, { env: { NAME: secret("x") }, pin: true }), or drop `pin` ``
478
+
479
+ `workspace()` refuses a body with an invoke that does not say where it works, when it can read the input:
480
+ ``workspace(): state "<state>": "<slot>" names no `<key>`, and a Workspace with Repo Slots says where each Turn and Effect works: a Worktree, or `cwd: "/work"` for a Turn (ADR-0057)``
481
+
482
+ When a `command` starts, it refuses:
483
+
484
+ - a state outside a `workspace()`. With no Effect secret in `env`:
485
+ `command "<slot>" runs in the Harness container of a Workspace, and its state is not inside a workspace() — invoke it from a Workspace's body (ADR-0067)`.
486
+ With one:
487
+ `command "<slot>" runs in the Sandbox Effector of a Workspace, and its state is not inside a workspace() — invoke it from a Workspace's body (ADR-0067)`
488
+ - no `worktree` under Repo Slots, with no Effect secret in `env`:
489
+ ``command "<slot>" runs under a Workspace with Repo Slots (<slots>) and its input names no `worktree`: say which, a Worktree that a cut gave or `<slot>/default` ``
490
+ - with an Effect secret in `env`, a Workspace with no Repo Slot:
491
+ `command "<slot>" runs under a Workspace with no Repo Slot: a command with an Effect secret runs against one commit of a Repo Slot's branch, and there is none — declare a Repo Slot, or name no secret in its env, and it runs in /work beside the Agent (ADR-0051)`
492
+ - an `arg()` with no string in the input. The angle brackets around the name are in the text, and `<type>` is `nothing`
493
+ when the input has no such key:
494
+ `command "<slot>": argv slot <<name>> has no string value in its input (got <type>) — map it in the invoke's input`
495
+ - with `pin: true`, an input `sha` that is not a full commit id:
496
+ `command "<slot>" (pin): its input's sha is not a full commit id`
497
+
498
+ When you call `http()`, it refuses:
499
+
500
+ - a method that is not in the list:
501
+ `http({ method: "<method>" }): the method is one of GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS`
502
+ - a scheme or a host that is not literal:
503
+ ``http({ url }): the url is an http:// or https:// url whose scheme and host are literal — a secret may sit only in its path, after a "/": text`https://api.example.com/bot${secret("tg")}/send` (ADR-0068)``
504
+ - an Effect secret after `?` or `#` in the URL:
505
+ ``http({ url }): secret("<name>") sits in the url's query or fragment — a secret may sit only in its path; send it in `auth` or a header instead: headers: { "x-api-key": text`${secret("...")}` } (ADR-0068)``
506
+ - a user name or a password in the URL: ``http({ url }): the url carries userinfo — use `auth` ``
507
+ - a header name that is not in lower case, or that frames or routes the request, such as `host` or `content-length`:
508
+ `http({ headers }): "<name>" is not a header an Effect sets — a lowercase name that does not frame or route the request (ADR-0068)`
509
+ - an `authorization` header beside `auth`: ``http({ headers }): "authorization" is set by `auth` — write one of them``
510
+ - a timeout that is not a positive duration: `http: timeout "<timeout>" is not a positive duration (like "30s", "2m")`
511
+ - a `maxBody` that is not a positive whole number: `http({ maxBody }): a positive number of bytes`
512
+ - a file body with a method other than `PUT`, `POST` or `PATCH`:
513
+ `http({ method: "<method>", body: file(...) }): a file body is sent with PUT, POST, PATCH (ADR-0068)`
514
+ - a `body` that is not `file()`:
515
+ ``http({ body }): a body is file(path, { segments?, contentType? }) — json and text come from `request` ``
516
+ - a `content-type` header beside the `contentType` of `file()`:
517
+ `http({ headers, body: file(path, { contentType }) }): "content-type" is set by file()'s contentType — write one of them (ADR-0067)`
518
+ - a `request` with a file body:
519
+ ``http({ body: file(...), request }): with a file body the run's part is file()'s — its path, from the input if it must be, and its `segments` — so write no `request` (ADR-0068)``
520
+ - a URL whose host is not a host: `http({ url }): "<scheme>://<host>" is not a host`
521
+
522
+ When an `http` Effect starts, it refuses an input that its `input` schema does not accept. The Effect takes its
523
+ `onError` route, and each problem is `<path>: <message>`, with `; ` between them:
524
+ `http "<slot>": its input does not match the definition's input schema — <path>: <message>`. With a file body, the text
525
+ ends after `input schema`.
526
+
527
+ An `http` Effect with a file body runs in the Sandbox Effector. When it starts, it refuses:
528
+
529
+ - a state outside a `workspace()`:
530
+ `http "<slot>" runs in the Sandbox Effector of a Workspace, and its state is not inside a workspace() — invoke it from a Workspace's body (ADR-0067)`
531
+ - no `worktree` under Repo Slots:
532
+ ``http "<slot>" reads a Worktree file, under a Workspace with Repo Slots, and its input names no `worktree` ``
533
+
534
+ A bad `worktree` is output, because a word of a run can cause it. An `http` Effect with a file body settles `refused`. A
535
+ `command` settles `exited` with code 127, with the reason in `tail`. A credentialed `command` and a file body need a
536
+ cut: `no cut made <path> in this Sandbox: cut it with worktree()`
537
+
538
+ When you call `secret()`, `bearer()` or `text`, they refuse:
539
+
540
+ - an Effect secret name with characters other than letters, digits, `.`, `_` and `-`, or that starts with `.`:
541
+ `secret("<name>"): a secret's name is letters, digits, ".", "_" and "-", and does not start with "." — it is the file the Effector reads it from (ADR-0068)`
542
+ - a `bearer()` value that is not a `secret()`: `bearer(…) takes a secret("name")`
543
+ - a `text` value that is not a `secret()` or a string: ``text`…`: a value is a secret("name") or a string, got <value>``
544
+
545
+ `createMachine` refuses:
546
+
547
+ - an Effect that you write directly in an `invoke`:
548
+ `machine "<id>": state "<state>" invokes an Effect inline — a Part is a key of actors, so it has a name that the ledger, the report and customize() share: actors: { <name>: <kind>(...) }, then invoke: { src: "<name>" }`
549
+ - a param of a pick that reaches no key of the Effect's input, and that nothing else reads:
550
+ ``machine "<id>": pick "<pick>" enters state "<state>" (Effect "<slot>") with fromPick: "<param>" is no key of the Effect's input (<keys>), and nothing else reads it — the Agent supplies it and it reaches nothing; name an argv slot for it, read it in `fill`, store it with assign, or drop it from the def``
551
+ - a key that `fill` sets and that is also a param of the pick:
552
+ ``machine "<id>": pick "<pick>" enters state "<state>" (Effect "<slot>"): `fill` sets "<param>", which is also a param of the pick — the Machine's value wins and the Agent's is dropped; rename one, or drop it from the def``
553
+ - a `fromPick` in a state that a different event enters:
554
+ `machine "<id>": state "<state>" (Effect "<slot>") reads the params of pick "<pick>" but is entered on "<event>" — that event does not carry them`
555
+ - a param of a pick that enters an Effect's state with no `fromPick`, when nothing reads it:
556
+ `machine "<id>": pick "<pick>" enters state "<state>" (Effect "<slot>"), which never reads "<param>": the Agent supplies it and nothing uses it — map it in an invoke's input, store it with assign, or drop it from the def`
557
+
558
+ [`paramsOf()`](../reference/authoring-surface/paramsof.md) refuses an event that is not the pick:
559
+ `state entered by "<event>", but its input reads the params of pick "<pick>"`
560
+
561
+ `jr2 up` refuses:
562
+
563
+ - a `command` with an Effect secret in a Workspace with no Repo Slot:
564
+ `workflow "<workflow>": command "<slot>" runs in Workspace of workflow "<workflow>", which has no Repo Slot: a command with an Effect secret runs against one commit of a Repo Slot's branch, and there is none — declare a Repo Slot, or name no secret in its env, and it runs in /work beside the Agent (ADR-0051)`
565
+ - an Effect secret that the `secrets` list does not have:
566
+ ``workflow "<workflow>": the <kind> Effect "<slot>" names secret("<name>"), which the `secrets` list does not hold — add it: secrets: [{ name: "<name>", value: process.env.<NAME> }] (ADR-0068)``
567
+ - an Effect secret with no value, for example when `HOOK_TOKEN` is not in `.env`. `<name>` is the `name` of the entry,
568
+ such as `hook-token`. Set the variable that `process.env` reads, such as `HOOK_TOKEN`:
569
+ `secrets[<i>] needs exactly one of value or valueFrom — <name> has neither, which is what an unset .env variable reads as: set <name> in .env, or reference a Secret with valueFrom: { secretKeyRef: { name, key } } (ADR-0059)`
570
+ - an Effect secret with a value shorter than 8 characters:
571
+ `secrets[<i>] (<name>) is an Effect secret shorter than 8 characters — the Effector replaces every match of a secret in what it returns, and a value this short would match ordinary text. Use the whole credential; the value itself is not shown (ADR-0068)`
572
+
573
+ ## Read next
574
+
575
+ - [Effects](../concepts/effects.md): the kinds of Effect, where each runs, and at most once.
576
+ - [Secrets and trust](../concepts/secrets-and-trust.md): who holds an Effect secret.
577
+ - [The Menu](../concepts/the-menu.md): how a pick waits for its answer.
578
+ - [Push and sign a branch](push-and-sign-a-branch.md): the `push` Effect.
579
+ - [Cut a Worktree](cut-a-worktree.md): the Worktree that a `command` runs in, and the removal of a Worktree.
580
+ - Reference: [`command`](../reference/authoring-surface/command.md),
581
+ [`CommandOptions`](../reference/authoring-surface/type-commandoptions.md),
582
+ [`http`](../reference/authoring-surface/http.md), [`secret`](../reference/authoring-surface/secret.md),
583
+ [`fromPick`](../reference/authoring-surface/frompick.md) and [`answer`](../reference/authoring-surface/answer.md).
584
+ - [ADR-0067](../reference/decisions/0067-an-effect-is-an-actor-slot-and-runs-at-most-once-unless-marked-idempotent.md):
585
+ an Effect is an actor slot, and runs at most once unless marked idempotent.
586
+ - [ADR-0068](../reference/decisions/0068-an-effector-holds-an-effects-secrets-and-signs-its-wire.md): an Effector holds
587
+ the secrets of an Effect, and signs its wire.