@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,1348 @@
1
+ ---
2
+ title: HTTP API
3
+ description: "Every route of the Orchestrator's HTTP API, by access band, and the types of its bodies and answers."
4
+ ---
5
+
6
+ # HTTP API
7
+
8
+ The Orchestrator's HTTP API: what the `jr2` CLI, the Console, a webhook and the Harness call. Each route is in one access band, by the credential it asks for ([ADR-0014](decisions/0014-observation-is-open-run-state-is-not.md)). Send a token as `Authorization: Bearer <token>`. An error answer is `{ error }`, with the status the route gives. A path segment `:name` is a parameter; `:name{regex}` is a parameter that must match the regex.
9
+
10
+ Bands: [Open](#band-open), [Authenticated](#band-authenticated), [Instance token only](#band-instanceonly), [Publish token only](#band-publishonly). The types the bodies and answers name are in [Types](#types).
11
+
12
+ <a id="band-open"></a>
13
+
14
+ ## Open
15
+
16
+ No token. Structure and observation: no run context, and no control.
17
+
18
+ <a id="get-healthz"></a>
19
+
20
+ ### `GET /healthz`
21
+
22
+ - Summary: Liveness, and what this instance is: its Kit version and image content hash.
23
+ - Response: { ok: true, version, hash? }
24
+ - Stream: no
25
+ - Decisions: [ADR-0009](decisions/0009-cli-and-instance-interface.md), [ADR-0019](decisions/0019-one-converging-command-against-the-current-context.md)
26
+
27
+ <a id="get-readyz"></a>
28
+
29
+ ### `GET /readyz`
30
+
31
+ - Summary: Readiness.
32
+ - Response: { ready: true }
33
+ - Stream: no
34
+ - Decisions: [ADR-0009](decisions/0009-cli-and-instance-interface.md)
35
+
36
+ <a id="get-workflows"></a>
37
+
38
+ ### `GET /workflows`
39
+
40
+ - Summary: The Workflows a run can start, each with its origin, and each Chart wrapper's named Charts in its entry. A named Chart that cannot run now says why.
41
+ - Response: [`WorkflowListing`](#type-workflowlisting)[]
42
+ - Stream: no
43
+ - Decisions: [ADR-0014](decisions/0014-observation-is-open-run-state-is-not.md), [ADR-0070](decisions/0070-a-machine-lends-its-parts-to-a-chart.md)
44
+
45
+ <a id="get-assembly"></a>
46
+
47
+ ### `GET /assembly`
48
+
49
+ - Summary: The current Assembly and the Assemblies that live runs hold.
50
+ - Response: [`AssemblyView`](#type-assemblyview)
51
+ - Stream: no
52
+ - Decisions: [ADR-0069](decisions/0069-the-orchestrator-is-a-kit-image-and-an-instance-publishes-its-assembly.md)
53
+
54
+ <a id="get-workflows-wrapper-chart-schema"></a>
55
+
56
+ ### `GET /workflows/:wrapper/chart-schema`
57
+
58
+ - Summary: The Chart grammar, narrowed to the Open body of one Chart wrapper.
59
+ - Response: JSON Schema
60
+ - Stream: no
61
+ - Decisions: [ADR-0070](decisions/0070-a-machine-lends-its-parts-to-a-chart.md)
62
+
63
+ <a id="get-workflows-name-runs-runid-machine"></a>
64
+
65
+ ### `GET /workflows/:name/runs/:runId/machine`
66
+
67
+ - Summary: The Machine that a run binds, with each bound Chart compiled in, which the Console draws.
68
+ - Response: [`MachineDoc`](#type-machinedoc)
69
+ - Stream: no
70
+ - Decisions: [ADR-0070](decisions/0070-a-machine-lends-its-parts-to-a-chart.md)
71
+
72
+ <a id="get"></a>
73
+
74
+ ### `GET /`
75
+
76
+ - Summary: The Console page to a browser; a 404 to a JSON caller.
77
+ - Response: text/html (the Console shell)
78
+ - Stream: no
79
+ - Decisions: [ADR-0032](decisions/0032-the-console-unlocks-with-the-instance-token.md)
80
+
81
+ <a id="get-workflows-name"></a>
82
+
83
+ ### `GET /workflows/:name`
84
+
85
+ - Summary: The Console page to a browser; to a JSON caller, the workflow and its declared input schema.
86
+ - Response: { name, machineId, input: JSON Schema | null }, or text/html
87
+ - Stream: no
88
+ - Decisions: [ADR-0032](decisions/0032-the-console-unlocks-with-the-instance-token.md), [ADR-0033](decisions/0033-a-machine-declares-the-input-that-starts-it.md)
89
+
90
+ <a id="get-workflows-name-machine"></a>
91
+
92
+ ### `GET /workflows/:name/machine`
93
+
94
+ - Summary: The registered template Machine's structure, which the Console draws.
95
+ - Response: [`MachineDoc`](#type-machinedoc)
96
+ - Stream: no
97
+ - Decisions: [ADR-0014](decisions/0014-observation-is-open-run-state-is-not.md)
98
+
99
+ <a id="get-workflows-name-runs"></a>
100
+
101
+ ### `GET /workflows/:name/runs`
102
+
103
+ - Summary: The live runs of one workflow, as observations: identity and state value, no context.
104
+ - Response: [`RunObservation`](#type-runobservation)[]
105
+ - Stream: no
106
+ - Decisions: [ADR-0014](decisions/0014-observation-is-open-run-state-is-not.md)
107
+
108
+ <a id="get-workflows-name-events"></a>
109
+
110
+ ### `GET /workflows/:name/events`
111
+
112
+ - Summary: The activity of every run of one workflow, as observations, on one connection.
113
+ - Response: SSE: runs, status, emit (type only), retry, gone
114
+ - Stream: yes: Server-Sent Events
115
+ - Decisions: [ADR-0014](decisions/0014-observation-is-open-run-state-is-not.md), [ADR-0022](decisions/0022-observation-is-a-level-triggered-feed.md)
116
+
117
+ <a id="get-workflows-name-runs-runid-events"></a>
118
+
119
+ ### `GET /workflows/:name/runs/:runId/events`
120
+
121
+ - Summary: One live run's activity, as observations, until it settles.
122
+ - Response: SSE: status, emit (type only), retry
123
+ - Stream: yes: Server-Sent Events
124
+ - Decisions: [ADR-0014](decisions/0014-observation-is-open-run-state-is-not.md), [ADR-0022](decisions/0022-observation-is-a-level-triggered-feed.md)
125
+
126
+ <a id="get-assets-style-css"></a>
127
+
128
+ ### `GET /assets/style.css`
129
+
130
+ - Summary: The Console's stylesheet.
131
+ - Response: text/css
132
+ - Stream: no
133
+ - Decisions: [ADR-0032](decisions/0032-the-console-unlocks-with-the-instance-token.md)
134
+
135
+ <a id="get-assets-elk-js"></a>
136
+
137
+ ### `GET /assets/elk.js`
138
+
139
+ - Summary: The Console's graph layout library (the elkjs bundle).
140
+ - Response: text/javascript
141
+ - Stream: no
142
+ - Decisions: [ADR-0032](decisions/0032-the-console-unlocks-with-the-instance-token.md)
143
+
144
+ <a id="get-assets-file"></a>
145
+
146
+ ### `GET /assets/:file{[\w.-]+\.ts}`
147
+
148
+ - Summary: A Console source module, with its types erased.
149
+ - Response: text/javascript
150
+ - Stream: no
151
+ - Decisions: [ADR-0034](decisions/0034-the-console-renders-with-preact-and-the-server-erases-the-types.md)
152
+
153
+ <a id="get-assets-components-file"></a>
154
+
155
+ ### `GET /assets/components/:file{[\w.-]+\.ts}`
156
+
157
+ - Summary: A Console view module, with its types erased.
158
+ - Response: text/javascript
159
+ - Stream: no
160
+ - Decisions: [ADR-0034](decisions/0034-the-console-renders-with-preact-and-the-server-erases-the-types.md)
161
+
162
+ <a id="get-assets-vendor-file"></a>
163
+
164
+ ### `GET /assets/vendor/:file`
165
+
166
+ - Summary: Preact's browser ESM, which the Console's import map names.
167
+ - Response: text/javascript
168
+ - Stream: no
169
+ - Decisions: [ADR-0034](decisions/0034-the-console-renders-with-preact-and-the-server-erases-the-types.md)
170
+
171
+ <a id="band-authenticated"></a>
172
+
173
+ ## Authenticated
174
+
175
+ Any token jr2 minted: the Instance token, or a Sandbox token. A Sandbox token reaches only what its own Sandbox owns.
176
+
177
+ <a id="get-agents-instanceid-surface"></a>
178
+
179
+ ### `GET /agents/:instanceId/surface`
180
+
181
+ - Summary: An Agent's Menu and this Turn's Allowed picks. A Sandbox token reads only its own Sandbox's.
182
+ - Response: [`AgentSurfaceView`](#type-agentsurfaceview)
183
+ - Stream: no
184
+ - Decisions: [ADR-0013](decisions/0013-the-agent-reaches-its-machine-through-a-container-it-cannot-read.md), [ADR-0029](decisions/0029-a-menu-is-fixed-for-a-conversation-and-a-turn-is-told-its-allowed-picks.md)
185
+
186
+ <a id="post-agents-instanceid-events"></a>
187
+
188
+ ### `POST /agents/:instanceId/events`
189
+
190
+ - Summary: Deliver an Agent's pick into the state that invoked it.
191
+ - Body: { type, ...payload }, checked against the pick's input schema
192
+ - Response: [`AgentDeliveryReceipt`](#type-agentdeliveryreceipt); 409 { refused: "outstanding", outstanding?, allowed }
193
+ - Stream: no
194
+ - Decisions: [ADR-0013](decisions/0013-the-agent-reaches-its-machine-through-a-container-it-cannot-read.md), [ADR-0024](decisions/0024-an-agents-turn-ends-with-the-state-that-asked-for-it.md), [ADR-0029](decisions/0029-a-menu-is-fixed-for-a-conversation-and-a-turn-is-told-its-allowed-picks.md)
195
+
196
+ <a id="get-agents-instanceid-deliveries-deliveryid"></a>
197
+
198
+ ### `GET /agents/:instanceId/deliveries/:deliveryId`
199
+
200
+ - Summary: Long-poll the answer to an outstanding pick; 503 means ask again.
201
+ - Response: [`AgentDeliveryReceipt`](#type-agentdeliveryreceipt)
202
+ - Stream: no
203
+ - Decisions: [ADR-0013](decisions/0013-the-agent-reaches-its-machine-through-a-container-it-cannot-read.md), [ADR-0024](decisions/0024-an-agents-turn-ends-with-the-state-that-asked-for-it.md)
204
+
205
+ <a id="post-sandboxes-name-fetch"></a>
206
+
207
+ ### `POST /sandboxes/:name/fetch`
208
+
209
+ - Summary: Ask the node cache to fetch one Repo that this Sandbox mounts. A Sandbox token asks only for its own.
210
+ - Body: { identity }
211
+ - Response: [`FetchAnswer`](#type-fetchanswer): { fetched } | { stale, asOf }
212
+ - Stream: no
213
+ - Decisions: [ADR-0053](decisions/0053-a-fetch-inside-the-pod-asks-the-node-cache-and-the-cache-asks-the-remote.md)
214
+
215
+ <a id="band-instanceonly"></a>
216
+
217
+ ## Instance token only
218
+
219
+ The Instance token alone: run control, starting a run, and full run state. A Sandbox token is refused.
220
+
221
+ <a id="put-workflows-wrapper-charts-name"></a>
222
+
223
+ ### `PUT /workflows/:wrapper/charts/:name`
224
+
225
+ - Summary: Admit and keep a runtime Chart under a name. Its Workflow is `<wrapper>/<name>`.
226
+ - Body: the Chart text alone
227
+ - Response: 201 { name, origin, hash } when new, 200 when it replaced one; 422 { error, report } when refused
228
+ - Stream: no
229
+ - Decisions: [ADR-0070](decisions/0070-a-machine-lends-its-parts-to-a-chart.md)
230
+
231
+ <a id="delete-workflows-wrapper-charts-name"></a>
232
+
233
+ ### `DELETE /workflows/:wrapper/charts/:name`
234
+
235
+ - Summary: Remove a runtime Chart. A live run of it keeps its own text.
236
+ - Response: 204
237
+ - Stream: no
238
+ - Decisions: [ADR-0070](decisions/0070-a-machine-lends-its-parts-to-a-chart.md)
239
+
240
+ <a id="post-workflows-wrapper-charts-name-runs"></a>
241
+
242
+ ### `POST /workflows/:wrapper/charts/:name/runs`
243
+
244
+ - Summary: Start a run of a named Chart, as `POST /workflows/<wrapper>%2F<name>/runs` does.
245
+ - Body: the Chart wrapper's input, without the Chart
246
+ - Response: 201 { runId, instanceId }; 409 when the named Chart cannot run now
247
+ - Stream: no
248
+ - Decisions: [ADR-0070](decisions/0070-a-machine-lends-its-parts-to-a-chart.md)
249
+
250
+ <a id="post-workflows-name-runs"></a>
251
+
252
+ ### `POST /workflows/:name/runs`
253
+
254
+ - Summary: Start a run of a registered workflow. A `dispatch` from another Orchestrator sends the header `jr2-dispatched-by`, and a repeated start with its key answers the run that it started.
255
+ - Body: the workflow's input, checked against its declared input schema
256
+ - Response: 201 { runId, instanceId }; 200 { runId, instanceId, existing: true } for a repeated dispatch; 422 { error, report } when the door refuses a Chart in the input
257
+ - Stream: no
258
+ - Decisions: [ADR-0033](decisions/0033-a-machine-declares-the-input-that-starts-it.md), [ADR-0058](decisions/0058-a-harness-answers-the-orchestrator-alone.md), [ADR-0070](decisions/0070-a-machine-lends-its-parts-to-a-chart.md), [ADR-0071](decisions/0071-a-run-starts-a-run-through-a-dispatch-effect.md)
259
+
260
+ <a id="get-runs"></a>
261
+
262
+ ### `GET /runs`
263
+
264
+ - Summary: The live runs, with their full status.
265
+ - Response: [`RunStatus`](#type-runstatus)[]
266
+ - Stream: no
267
+ - Decisions: [ADR-0009](decisions/0009-cli-and-instance-interface.md), [ADR-0014](decisions/0014-observation-is-open-run-state-is-not.md)
268
+
269
+ <a id="get-repos"></a>
270
+
271
+ ### `GET /repos`
272
+
273
+ - Summary: The Repos as the cluster reports them.
274
+ - Response: { dataPlane, repos: [`RepoStatus`](#type-repostatus)[] }
275
+ - Stream: no
276
+ - Decisions: [ADR-0048](decisions/0048-the-orchestrator-boots-without-its-repos.md), [ADR-0051](decisions/0051-a-repo-is-a-slot-on-the-workspace-and-a-cache-on-the-node.md)
277
+
278
+ <a id="get-runs-resolve"></a>
279
+
280
+ ### `GET /runs/resolve`
281
+
282
+ - Summary: The run ids that start with a prefix (`?prefix=`, at least 4 characters).
283
+ - Response: { prefix, runIds: string[], truncated }
284
+ - Stream: no
285
+ - Decisions: [ADR-0009](decisions/0009-cli-and-instance-interface.md)
286
+
287
+ <a id="get-runs-runid"></a>
288
+
289
+ ### `GET /runs/:runId`
290
+
291
+ - Summary: One run's status, live or settled, with its open Gates.
292
+ - Response: [`RunStatus`](#type-runstatus) & { gates: [`GateView`](#type-gateview)[] }
293
+ - Stream: no
294
+ - Decisions: [ADR-0009](decisions/0009-cli-and-instance-interface.md), [ADR-0011](decisions/0011-workflow-defined-events.md)
295
+
296
+ <a id="post-runs-runid-gates-gate-events"></a>
297
+
298
+ ### `POST /runs/:runId/gates/:gate/events`
299
+
300
+ - Summary: Deliver an event to an open Gate of a run.
301
+ - Body: { type, ...payload }, checked against the Gate's schema for that event
302
+ - Response: { ok: true }; 409 { error, acceptsNow } when the run does not take it now
303
+ - Stream: no
304
+ - Decisions: [ADR-0011](decisions/0011-workflow-defined-events.md), [ADR-0013](decisions/0013-the-agent-reaches-its-machine-through-a-container-it-cannot-read.md)
305
+
306
+ <a id="get-runs-runid-events"></a>
307
+
308
+ ### `GET /runs/:runId/events`
309
+
310
+ - Summary: One run's full activity until it settles; a settled run's final status, once.
311
+ - Response: SSE: status, emit, retry, admission, pick, placing, placed, child-error, effect, gone
312
+ - Stream: yes: Server-Sent Events
313
+ - Decisions: [ADR-0022](decisions/0022-observation-is-a-level-triggered-feed.md), [ADR-0023](decisions/0023-the-harness-prints-the-conversation.md), [ADR-0064](decisions/0064-a-workspace-waits-for-capacity.md), [ADR-0067](decisions/0067-an-effect-is-an-actor-slot-and-runs-at-most-once-unless-marked-idempotent.md)
314
+
315
+ <a id="post-runs-runid-events"></a>
316
+
317
+ ### `POST /runs/:runId/events`
318
+
319
+ - Summary: Cancel a run: it ends, and its Workspaces go unless `keep` is true.
320
+ - Body: { type: "CANCEL", keep?: boolean }
321
+ - Response: { ok: true }
322
+ - Stream: no
323
+ - Decisions: [ADR-0002](decisions/0002-duplex-streaming-actor.md), [ADR-0025](decisions/0025-cancel-ends-a-run-stop-parks-it.md)
324
+
325
+ <a id="band-publishonly"></a>
326
+
327
+ ## Publish token only
328
+
329
+ The publish token alone, which `jr2 up` reads from the instance Secret. The Instance token is refused, because a publish puts code into the Orchestrator.
330
+
331
+ <a id="put-assembly"></a>
332
+
333
+ ### `PUT /assembly`
334
+
335
+ - Summary: Publish the next Assembly. `jr2 up` calls it, and nothing else. A refused Assembly leaves the current one current.
336
+ - Body: the Assembly as a tar stream, with the headers `jr2-kit-version` and `jr2-assembly-hash`
337
+ - Response: 200 with the Assembly, its Workflows, the held Assemblies and the ones collected; 400, 409 or 422 with the reason
338
+ - Stream: no
339
+ - Decisions: [ADR-0069](decisions/0069-the-orchestrator-is-a-kit-image-and-an-instance-publishes-its-assembly.md)
340
+
341
+ ## Types
342
+
343
+ <a id="type-workflowlisting"></a>
344
+
345
+ ### `WorkflowListing`
346
+
347
+ ```ts
348
+ type WorkflowListing = {
349
+ name: string;
350
+ origin: "machine" | ChartOrigin;
351
+ wrapper?: {
352
+ body: string;
353
+ oneShot: boolean;
354
+ charts: Array<{ name: string; origin: ChartOrigin; unrunnable?: string }>;
355
+ };
356
+ unrunnable?: string;
357
+ };
358
+ ```
359
+
360
+ One entry of `GET /workflows` ([ADR-0070](decisions/0070-a-machine-lends-its-parts-to-a-chart.md)): a Workflow and where it came from. A Chart wrapper's
361
+ entry carries its Open body, whether its door takes a Chart (`oneShot`), and its named Charts.
362
+
363
+ **Fields**
364
+
365
+ - `name`: `string`
366
+ - `origin`: `"machine" | ChartOrigin`
367
+ - `wrapper` (optional): `object`
368
+
369
+ - `body`: `string`
370
+ - `oneShot`: `boolean`
371
+ - `charts`: `Array<{ name: string; origin: ChartOrigin; unrunnable?: string; }>`
372
+ - `unrunnable` (optional): `string`
373
+
374
+ <a id="type-assemblyview"></a>
375
+
376
+ ### `AssemblyView`
377
+
378
+ ```ts
379
+ type AssemblyView = {
380
+ kitVersion: string;
381
+ current: { hash: string; kitVersion: string; workflows: string[] } | null;
382
+ held: HeldAssembly[];
383
+ };
384
+ ```
385
+
386
+ `GET /assembly`'s body.
387
+
388
+ **Fields**
389
+
390
+ - `kitVersion`: `string`
391
+ - `current`: `{ hash: string; kitVersion: string; workflows: string[]; } | null`
392
+ - `held`: `HeldAssembly[]`
393
+
394
+ <a id="type-machinedoc"></a>
395
+
396
+ ### `MachineDoc`
397
+
398
+ ```ts
399
+ type MachineDoc = MachineBodyDoc & {
400
+ workflow: string;
401
+ opaqueStates?: string[];
402
+ chartsNotDrawn?: Array<{ path: string; src: string; reason: string }>;
403
+ };
404
+ ```
405
+
406
+ The serialized structure of a workflow's Machine.
407
+
408
+ **Fields**: each field of [`MachineBodyDoc`](#type-machinebodydoc), and these:
409
+
410
+ - `workflow`: `string`
411
+ - `opaqueStates` (optional): `string[]`
412
+
413
+ States whose child list may be incomplete — see `opaqueStates`. Computed once here, on
414
+ the server, so the notice reaches whoever renders the doc without every consumer re-walking it
415
+ to discover the diagram is lying. Absent on the nested `MachineBodyDoc`s: it is a whole-doc
416
+ question, and the root's walk already covers them.
417
+ - `chartsNotDrawn` (optional): `Array<{ path: string; src: string; reason: string; }>`
418
+
419
+ A run's doc only (`runMachine`, [ADR-0070](decisions/0070-a-machine-lends-its-parts-to-a-chart.md)): each bound Chart the doc could not draw, so its Open
420
+ body shows the slot's own subgraph — the body's path in the run, its slot, and why (a stored
421
+ Chart the door no longer admits is drift, D-B). Absent when every bound Chart is drawn.
422
+
423
+ <a id="type-runobservation"></a>
424
+
425
+ ### `RunObservation`
426
+
427
+ ```ts
428
+ type RunObservation = {
429
+ runId: string;
430
+ workflow: string;
431
+ status: string;
432
+ value: unknown;
433
+ children: RunChild[];
434
+ bound?: true;
435
+ chartHashes?: string[];
436
+ dispatchedBy?: Omit<DispatchedBy, "effect">;
437
+ dispatched?: Array<{ slot: string; run: string }>;
438
+ };
439
+ ```
440
+
441
+ A run as an UNAUTHENTICATED observer may see it: which run, of what workflow, and where in the
442
+ Machine it is. That is the whole set — enough to light up a state in the Console, and nothing
443
+ more.
444
+
445
+ What is absent is the point. `context` is the workflow's working data (branch names, ticket
446
+ bodies, review verdicts, Harness endpoints) and `instanceId`/`fault` name live infrastructure and
447
+ leak error text; all of it is STATE, which [ADR-0013](decisions/0013-the-agent-reaches-its-machine-through-a-container-it-cannot-read.md) guards behind the Instance token. `value` is
448
+ a tree of state KEYS — it is structure, and structure is already public (`/workflows/:name/machine`
449
+ serves the whole Machine). So an observer learns nothing here it could not read from the Machine
450
+ doc, except which states are lit.
451
+
452
+ `children` extends that to the child machines (which is where a run mostly lives), and it does NOT
453
+ widen the line: a [`RunChild`](#type-runchild) is keys and ids by construction, with no context field at any
454
+ depth. The one thing it adds is the spawn ids, which are the workflow's own labels for its
455
+ parallel work (`"F-1"`) — the same class of thing as a state key.
456
+
457
+ **Fields**
458
+
459
+ - `runId`: `string`
460
+ - `workflow`: `string`
461
+ - `status`: `string`
462
+ - `value`: `unknown`
463
+ - `children`: `RunChild[]`
464
+ - `bound` (optional): `true`
465
+
466
+ The run binds a Chart ([ADR-0070](decisions/0070-a-machine-lends-its-parts-to-a-chart.md)): the Console draws `GET /workflows/:name/runs/:runId/machine`.
467
+ Structure, like `value`.
468
+ - `chartHashes` (optional): `string[]`
469
+
470
+ The hashes of the Charts it binds now (see `RunStatus.chartHashes`). Structure: a hash
471
+ of a Chart's text, which `runMachine` already serves on the open band.
472
+ - `dispatchedBy` (optional): `Omit<DispatchedBy, "effect">`
473
+
474
+ The run that dispatched this one, its slot, and the chain's depth ([ADR-0071](decisions/0071-a-run-starts-a-run-through-a-dispatch-effect.md)). Routing — two
475
+ ids, a slot name and a number — the class of thing `runId` and `value` are, so [ADR-0014](decisions/0014-observation-is-open-run-state-is-not.md)'s line
476
+ is unmoved. The idempotency key is not: it names the caller's ledger, which is the caller's.
477
+ - `dispatched` (optional): `Array<{ slot: string; run: string; }>`
478
+
479
+ The runs it dispatched, by slot ([ADR-0071](decisions/0071-a-run-starts-a-run-through-a-dispatch-effect.md)): the same routing as `dispatchedBy`, the other
480
+ direction.
481
+
482
+ <a id="type-runstatus"></a>
483
+
484
+ ### `RunStatus`
485
+
486
+ ```ts
487
+ type RunStatus = RunRecord & {
488
+ status: string;
489
+ value: unknown;
490
+ context: unknown;
491
+ children: RunChild[];
492
+ waiting: RunWaiting[];
493
+ held: RunHeld[];
494
+ fault?: string;
495
+ reason?: string;
496
+ assembly?: string;
497
+ bound?: true;
498
+ chartHashes?: string[];
499
+ output?: unknown;
500
+ dispatched?: Dispatched[];
501
+ };
502
+ ```
503
+
504
+ A run's current observable state. `fault` carries the error message when status is "error"
505
+ (e.g. a gate invoked with a name outside the workflow's manifest — [ADR-0011](decisions/0011-workflow-defined-events.md)). A run that ends
506
+ "failed" ([ADR-0073](decisions/0073-a-machine-fails-a-run-with-fail-and-an-uncaught-failure-ends-it-failed.md)) has no `fault`: its `output` is the Failure's `{ reason, detail? }`.
507
+
508
+ **Fields**: each field of [`RunRecord`](#type-runrecord), and these:
509
+
510
+ - `status`: `string`
511
+ - `value`: `unknown`
512
+ - `context`: `unknown`
513
+ - `children`: `RunChild[]`
514
+
515
+ The live child machines beneath the root — where most of a run actually is.
516
+ - `waiting`: `RunWaiting[]`
517
+
518
+ Every Workspace waiting for capacity, and why ([ADR-0064](decisions/0064-a-workspace-waits-for-capacity.md)). Behind the token: the reason is
519
+ the scheduler's or the quota's own words, which can name nodes and taints, so `observe`
520
+ never carries it — the open band sees only that a Workspace is in `placing`.
521
+ - `held`: `RunHeld[]`
522
+
523
+ Every pick of this run that is outstanding ([ADR-0024](decisions/0024-an-agents-turn-ends-with-the-state-that-asked-for-it.md)): the Agent, its pick, and since when —
524
+ the Console's "held since". There is no default time bound on a held Turn; this is how a
525
+ human sees one. Behind the token, like `context`: a pick names what the Agent did.
526
+ - `fault` (optional): `string`
527
+ - `reason` (optional): `string`
528
+
529
+ Why the HOST set this status, for the statuses the Machine did not choose — today `drifted`
530
+ ([ADR-0030](decisions/0030-a-snapshot-names-the-machine-it-was-written-under.md)). Distinct from `fault`, which is a running actor's own error; this is the store's
531
+ account of a run it declined to resume, and until it was surfaced here nothing on any HTTP
532
+ route could read it.
533
+ - `assembly` (optional): `string`
534
+
535
+ The hash of the Assembly the run started under ([ADR-0069](decisions/0069-the-orchestrator-is-a-kit-image-and-an-instance-publishes-its-assembly.md)). Absent for a run no Assembly
536
+ started.
537
+ - `bound` (optional): `true`
538
+
539
+ The run binds at least one Chart ([ADR-0070](decisions/0070-a-machine-lends-its-parts-to-a-chart.md)): its Machine is the bound one, `runMachine`.
540
+ - `chartHashes` (optional): `string[]`
541
+
542
+ The hashes of the Charts the run binds now, distinct and sorted ([ADR-0070](decisions/0070-a-machine-lends-its-parts-to-a-chart.md)). A run can bind a
543
+ second Chart in its life (a planner whose first Chart reaches a ceiling picks again), so these,
544
+ not the run id, say which bound Machine `runMachine` draws. Absent when it binds none.
545
+ - `output` (optional): `unknown`
546
+
547
+ The Machine's output, for a run that is no longer live ([ADR-0071](decisions/0071-a-run-starts-a-run-through-a-dispatch-effect.md)): what a `dispatch` with
548
+ `wait` settles with, and what `GET /runs/<id>` serves its foreign caller. Never for a live run,
549
+ whose Machine has none yet. For a `failed` run, the Failure's `{ reason, detail? }` ([ADR-0073](decisions/0073-a-machine-fails-a-run-with-fail-and-an-uncaught-failure-ends-it-failed.md)),
550
+ not a value of the Machine's output type. Behind the token, like `context`: it is the
551
+ workflow's data.
552
+ - `dispatched` (optional): `Dispatched[]`
553
+
554
+ The runs this run's `dispatch` Effects started, oldest first ([ADR-0071](decisions/0071-a-run-starts-a-run-through-a-dispatch-effect.md)): the chain's other
555
+ direction, read off the caller's own ledger rows. A foreign dispatch's run is a run of the
556
+ Orchestrator its target names. Absent when it started none.
557
+
558
+ <a id="type-repostatus"></a>
559
+
560
+ ### `RepoStatus`
561
+
562
+ ```ts
563
+ type RepoStatus = {
564
+ key: string;
565
+ url: string;
566
+ identity?: string;
567
+ bound: boolean;
568
+ lastAttached?: string;
569
+ nodes: RepoNodeState[];
570
+ };
571
+ ```
572
+
573
+ One `Repo` resource as the instance reports it (`GET /repos`).
574
+
575
+ **Fields**
576
+
577
+ - `key`: `string`
578
+
579
+ The cache key: the resource's name, the hostPath leaf, `/repos/<key>`.
580
+ - `url`: `string`
581
+
582
+ The Binding's own spelling — what the cache clones.
583
+ - `identity` (optional): `string`
584
+ - `bound`: `boolean`
585
+
586
+ A registered Machine binds it — never evicted by `jr2 gc`.
587
+ - `lastAttached` (optional): `string`
588
+
589
+ When a run last attached it — the eviction clock for a Repo nothing binds. Absent while only
590
+ the boot has stated it: a bound Repo no run has attached yet.
591
+ - `nodes`: `RepoNodeState[]`
592
+
593
+ <a id="type-gateview"></a>
594
+
595
+ ### `GateView`
596
+
597
+ ```ts
598
+ type GateView = {
599
+ gate: string;
600
+ path: string[];
601
+ accepts: Array<{ name: string; description?: string; input: unknown }>;
602
+ acceptsNow: string[];
603
+ meta?: Record<string, unknown>;
604
+ };
605
+ ```
606
+
607
+ One open gate as external callers discover it (`GET /runs/:id` — [ADR-0011](decisions/0011-workflow-defined-events.md)): the accepted
608
+ events with their input schemas as JSON Schema (what drives a form or a `jr2 send` prompt),
609
+ plus the workflow-supplied `meta` (what a UI renders and a webhook translator matches on).
610
+
611
+ **Fields**
612
+
613
+ - `gate`: `string`
614
+ - `path`: `string[]`
615
+
616
+ The invoking state's actor path below the run root — where the gate lives in the Machine
617
+ (what the Console's "parked here" pin resolves against its scope tree), stable whether the
618
+ id was authored ("F-12") or derived. Never parse `gate` for this.
619
+ - `accepts`: `Array<{ name: string; description?: string; input: unknown; }>`
620
+ - `acceptsNow`: `string[]`
621
+
622
+ The names of `accepts` the run would take from this Gate NOW, payload-blind ([ADR-0011](decisions/0011-workflow-defined-events.md),
623
+ [ADR-0029](decisions/0029-a-menu-is-fixed-for-a-conversation-and-a-turn-is-told-its-allowed-picks.md)): a send of another name is refused 409. `accepts` stays whole — it drives the forms.
624
+ - `meta` (optional): `Record<string, unknown>`
625
+
626
+ <a id="type-agentsurfaceview"></a>
627
+
628
+ ### `AgentSurfaceView`
629
+
630
+ ```ts
631
+ type AgentSurfaceView = {
632
+ instanceId: string;
633
+ runId: string;
634
+ sandbox?: string;
635
+ menu: SurfaceEvent[];
636
+ allowed: string[];
637
+ };
638
+ ```
639
+
640
+ One live agent surface, as the Harness reads it through its Custodian (`GET /agents/:iid/surface`
641
+ — [ADR-0013](decisions/0013-the-agent-reaches-its-machine-through-a-container-it-cannot-read.md), [ADR-0029](decisions/0029-a-menu-is-fixed-for-a-conversation-and-a-turn-is-told-its-allowed-picks.md)). Two answers, because they change at different rates:
642
+
643
+ - `menu` is the Agent's MENU — every pick any state invoking this Agent offers, in a fixed
644
+ order. The Harness presents it as the tools block, which is then byte-identical for every
645
+ Turn of the conversation and never breaks the provider's prompt cache.
646
+ - `allowed` is this Turn's ALLOWED PICKS — the invoking state's derived set, narrowed to what its
647
+ guards would accept now, in Menu order. The Harness states it in the Briefing's Turn part,
648
+ after the Frame's prompt ([ADR-0062](decisions/0062-jr2-briefs-the-agent-on-its-seat-never-on-its-task.md)). Enforced at delivery, not here.
649
+
650
+ `sandbox` is the Sandbox that may deliver here. It is not a secret from that pod (the pod IS the
651
+ sandbox), and serving it lets a caller fail loudly on a surface that is not its own.
652
+
653
+ **Fields**
654
+
655
+ - `instanceId`: `string`
656
+ - `runId`: `string`
657
+ - `sandbox` (optional): `string`
658
+ - `menu`: `SurfaceEvent[]`
659
+ - `allowed`: `string[]`
660
+
661
+ <a id="type-agentdeliveryreceipt"></a>
662
+
663
+ ### `AgentDeliveryReceipt`
664
+
665
+ ```ts
666
+ type AgentDeliveryReceipt = {
667
+ outstanding?: true;
668
+ since?: string;
669
+ answered?: true;
670
+ straightBack?: true;
671
+ answer?: PickAnswer;
672
+ stopped?: true;
673
+ delivered: true;
674
+ event: string;
675
+ moved: boolean;
676
+ turnComplete: boolean;
677
+ allowed: string[];
678
+ deliveryId: string;
679
+ };
680
+ ```
681
+
682
+ The answer to one Agent delivery (`POST /agents/:iid/events`) — a receipt that DESCRIBES ITSELF
683
+ ([ADR-0024](decisions/0024-an-agents-turn-ends-with-the-state-that-asked-for-it.md)). The Harness renders it as prose, because a bare `deliveryId` told the Agent nothing
684
+ about whether it was finished, and the model answered that silence by calling again.
685
+
686
+ `turnComplete` is the HINT, never the guarantee (the abort on invocation end is): it is read off
687
+ the registration table right after delivery, so it says whether the state that asked for this
688
+ turn has stopped waiting. It fails conservatively — anything that made the read unreliable reads
689
+ `false`, which is today's behavior, never a false claim.
690
+
691
+ `deliveryId` keeps the outcome ADDRESSABLE after the fact ([ADR-0013](decisions/0013-the-agent-reaches-its-machine-through-a-container-it-cannot-read.md)): a pick the workflow is still
692
+ running when the POST answers is OUTSTANDING (`outstanding: true`), and its answer is read at
693
+ `GET /agents/:iid/deliveries/:id` — the same shape, `answered: true`, once the workflow is back at
694
+ Rest in the Agent's state or has left it ([ADR-0024](decisions/0024-an-agents-turn-ends-with-the-state-that-asked-for-it.md)).
695
+
696
+ **Fields**
697
+
698
+ - `outstanding` (optional): `true`
699
+
700
+ The workflow is running the pick: the answer comes on the delivery's poll. `allowed` is empty:
701
+ no other pick is taken until it answers.
702
+ - `since` (optional): `string`
703
+
704
+ ISO time the pick was delivered — with `outstanding`.
705
+ - `answered` (optional): `true`
706
+
707
+ This receipt is a pick's answer, read at Rest (or once the Turn left the Agent's state): an outstanding
708
+ pick's, a reply inside the pick's own send, or a guard straight back with no reply.
709
+ - `straightBack` (optional): `true`
710
+
711
+ With `answered`: a guard straight back ([ADR-0024](decisions/0024-an-agents-turn-ends-with-the-state-that-asked-for-it.md)) — the pick entered a state below the Agent's
712
+ and came back inside its own send, nothing replying. The one answer that says "moved; nothing
713
+ ran"; an outstanding pick's answer never carries it.
714
+ - `answer` (optional): [`PickAnswer`](#type-pickanswer)
715
+
716
+ The last reply since the pick ([ADR-0024](decisions/0024-an-agents-turn-ends-with-the-state-that-asked-for-it.md)); absent with `answered`: no reply came.
717
+ - `stopped` (optional): `true`
718
+
719
+ With `answered` and `turnComplete`: something other than the pick's route left the Agent's
720
+ state while the pick's work ran, and that exit stopped the work before it finished. `answer`,
721
+ if any, is an earlier link's reply, kept ([ADR-0024](decisions/0024-an-agents-turn-ends-with-the-state-that-asked-for-it.md)).
722
+ - `delivered`: `true`
723
+ - `event`: `string`
724
+
725
+ The event delivered — the Agent reads its own pick back, by name.
726
+ - `moved`: `boolean`
727
+
728
+ A transition accepted it. False means the pick was well-formed, arrived, and moved nothing —
729
+ every transition for it was guarded false in the current state ([ADR-0029](decisions/0029-a-menu-is-fixed-for-a-conversation-and-a-turn-is-told-its-allowed-picks.md)). Distinct from
730
+ `turnComplete`: a pick can move the Machine WITHIN the invoking state, which is
731
+ `moved: true, turnComplete: false`. Before this existed the two were indistinguishable, so an
732
+ Agent whose pick a guard rejected was told the workflow was "still in the state that asked",
733
+ and its only move was to call again.
734
+ - `turnComplete`: `boolean`
735
+
736
+ The invoking state stopped waiting: this Agent's turn is over.
737
+ - `allowed`: `string[]`
738
+
739
+ The Allowed picks read AFTER the delivery ([ADR-0029](decisions/0029-a-menu-is-fixed-for-a-conversation-and-a-turn-is-told-its-allowed-picks.md)): what this Turn may pick now — narrowed by
740
+ a pick that moved the Machine within the invoking state, empty once the Turn is over. The
741
+ Harness renders it ("Allowed now: `finish`"); it does not pre-check against it.
742
+ - `deliveryId`: `string`
743
+
744
+ <a id="type-fetchanswer"></a>
745
+
746
+ ### `FetchAnswer`
747
+
748
+ ```ts
749
+ type FetchAnswer = { fetched: string } | { stale: string; asOf: string | null };
750
+ ```
751
+
752
+ What one ask settles as. `fetched` is the landing's timestamp; `stale` is git's own words (or
753
+ this port's, when the budget ran out) beside the time the cache's objects are as of — `null`
754
+ when nothing has ever fetched it, which the program prints as "an unknown time".
755
+
756
+ **Forms**: it is one of these objects.
757
+
758
+ - Form 1: `fetched`
759
+
760
+ - `fetched`: `string`
761
+ - Form 2: `stale`, `asOf`
762
+
763
+ - `stale`: `string`
764
+ - `asOf`: `string | null`
765
+
766
+ <a id="type-chartorigin"></a>
767
+
768
+ ### `ChartOrigin`
769
+
770
+ ```ts
771
+ type ChartOrigin = "file" | "runtime";
772
+ ```
773
+
774
+ Where a named Chart came from ([ADR-0070](decisions/0070-a-machine-lends-its-parts-to-a-chart.md)): the Assembly's own file, or a `PUT` at run time.
775
+
776
+ <a id="type-heldassembly"></a>
777
+
778
+ ### `HeldAssembly`
779
+
780
+ ```ts
781
+ type HeldAssembly = { hash: string; kitVersion: string; runs: string[] };
782
+ ```
783
+
784
+ An Assembly the process holds ([ADR-0069](decisions/0069-the-orchestrator-is-a-kit-image-and-an-instance-publishes-its-assembly.md)), as `GET /assembly` lists it: the current one, and
785
+ every one a live run holds, each with the runs that hold it.
786
+
787
+ **Fields**
788
+
789
+ - `hash`: `string`
790
+ - `kitVersion`: `string`
791
+ - `runs`: `string[]`
792
+
793
+ <a id="type-machinebodydoc"></a>
794
+
795
+ ### `MachineBodyDoc`
796
+
797
+ ```ts
798
+ type MachineBodyDoc = {
799
+ id: string;
800
+ root: MachineStateDoc;
801
+ transitions: MachineTransitionDoc[];
802
+ events: MachineEventDoc[];
803
+ seats: MachineSeat[];
804
+ warnings: string[];
805
+ };
806
+ ```
807
+
808
+ One Machine's structure, independent of what NAMES it (a `workflow` at the root, a `src` below).
809
+
810
+ **Fields**
811
+
812
+ - `id`: `string`
813
+
814
+ Machine id.
815
+ - `root`: [`MachineStateDoc`](#type-machinestatedoc)
816
+ - `transitions`: `MachineTransitionDoc[]`
817
+ - `events`: `MachineEventDoc[]`
818
+
819
+ The events THIS Machine declares, and only this one ([ADR-0049](decisions/0049-a-machine-carries-its-parts-and-composes-by-invoke.md)): a nested Machine's ride its
820
+ own `MachineBodyDoc`. Empty for a Machine not built by `jr2Setup`.
821
+ - `seats`: `MachineSeat[]`
822
+
823
+ Who may send what, per state ([ADR-0015](decisions/0015-authoring-surface-absorbs-the-mechanism.md)): one entry per party on each state that invokes one —
824
+ the audience rule's answer for this Machine, as `jr2 up` prints it. Empty for a Machine not
825
+ built by `jr2Setup`.
826
+ - `warnings`: `string[]`
827
+
828
+ What the build found legal and suspect ([ADR-0015](decisions/0015-authoring-surface-absorbs-the-mechanism.md)) — a mode nothing enters, a pick a Gate above
829
+ takes from the Agent below, one name written for two parties on one path.
830
+
831
+ <a id="type-runchild"></a>
832
+
833
+ ### `RunChild`
834
+
835
+ ```ts
836
+ type RunChild = { id: string; src: string; status: string; value: unknown; children: RunChild[] };
837
+ ```
838
+
839
+ One live child MACHINE of a run, and its own children below it. A workflow's root machine is
840
+ usually a coordinator — `coding` spawns a `featureWorkspace` per feature and the real work happens
841
+ in there — so the root's `value` alone says almost nothing about where a run IS. This is the rest.
842
+
843
+ Context-free BY CONSTRUCTION: there is no context field to forget to redact, which is what lets
844
+ `observe()` pass the whole tree through to unauthenticated observers untouched. `src` is the join
845
+ key ([`ChildMachineDoc`](#type-childmachinedoc)); `id` is the spawn id (`"F-1"`), which is how two live instances of
846
+ the same child machine are told apart.
847
+
848
+ **Fields**
849
+
850
+ - `id`: `string`
851
+ - `src`: `string`
852
+ - `status`: `string`
853
+ - `value`: `unknown`
854
+ - `children`: `RunChild[]`
855
+
856
+ <a id="type-dispatchedby"></a>
857
+
858
+ ### `DispatchedBy`
859
+
860
+ ```ts
861
+ type DispatchedBy = { run: string; slot: string; effect: string; depth: number; instance?: string };
862
+ ```
863
+
864
+ Which run dispatched a run ([ADR-0071](decisions/0071-a-run-starts-a-run-through-a-dispatch-effect.md)): the caller's run id, the slot of its `dispatch` Effect, and
865
+ that Effect's ledger row id, which is the idempotency key — a start that carries a key some run
866
+ already carries answers that run. `depth` is the dispatched run's depth in the chain, one below
867
+ its caller, stated by the caller and recorded as sent: one meaning on the wire, on the binding
868
+ and on the row. `instance` is set for a foreign caller, whose Orchestrator this one cannot
869
+ verify: opaque text, never resolved.
870
+
871
+ **Fields**
872
+
873
+ - `run`: `string`
874
+ - `slot`: `string`
875
+ - `effect`: `string`
876
+ - `depth`: `number`
877
+ - `instance` (optional): `string`
878
+
879
+ <a id="type-runrecord"></a>
880
+
881
+ ### `RunRecord`
882
+
883
+ ```ts
884
+ type RunRecord = { runId: string; workflow: string; instanceId: string; dispatchedBy?: DispatchedBy };
885
+ ```
886
+
887
+ The serializable identity of a run — what reconcile sees and what restore rebuilds from.
888
+ `dispatchedBy` is the run that started it through a `dispatch` Effect, and this run's depth in
889
+ that chain, as the caller sent it ([ADR-0071](decisions/0071-a-run-starts-a-run-through-a-dispatch-effect.md)); absent for a run a human or a client started.
890
+
891
+ **Fields**
892
+
893
+ - `runId`: `string`
894
+ - `workflow`: `string`
895
+ - `instanceId`: `string`
896
+ - `dispatchedBy` (optional): [`DispatchedBy`](#type-dispatchedby)
897
+
898
+ <a id="type-runwaiting"></a>
899
+
900
+ ### `RunWaiting`
901
+
902
+ ```ts
903
+ type RunWaiting = { child: string; on: "node" | "quota"; message: string; since: string };
904
+ ```
905
+
906
+ One Workspace of a run waiting for capacity ([ADR-0064](decisions/0064-a-workspace-waits-for-capacity.md)): its Sandbox has no node. `child` is the
907
+ Workspace's actor path below the run root — the [`RunChild`](#type-runchild) ids down to it, joined by `/`,
908
+ and `""` when the run's root IS the Workspace. `on` is what it waits for: a node from the
909
+ scheduler, or room under the cluster owner's quota; `message` is the scheduler's or the API
910
+ server's own words; `since` (ISO) is when the wait began, kept across a changed reason and a
911
+ restart.
912
+
913
+ **Fields**
914
+
915
+ - `child`: `string`
916
+ - `on`: `"node" | "quota"`
917
+ - `message`: `string`
918
+ - `since`: `string`
919
+
920
+ <a id="type-runheld"></a>
921
+
922
+ ### `RunHeld`
923
+
924
+ ```ts
925
+ type RunHeld = { agent: string; pick: string; since: string };
926
+ ```
927
+
928
+ One outstanding pick, as `RunStatus.held` reports it: the Agent slot, its pick, and the ISO time
929
+ it was delivered.
930
+
931
+ **Fields**
932
+
933
+ - `agent`: `string`
934
+ - `pick`: `string`
935
+ - `since`: `string`
936
+
937
+ <a id="type-dispatched"></a>
938
+
939
+ ### `Dispatched`
940
+
941
+ ```ts
942
+ type Dispatched = { slot: string; run: string; at: string };
943
+ ```
944
+
945
+ One run a `dispatch` Effect of this run started ([ADR-0071](decisions/0071-a-run-starts-a-run-through-a-dispatch-effect.md)): its slot, the run, and when the
946
+ ledger row was written.
947
+
948
+ **Fields**
949
+
950
+ - `slot`: `string`
951
+ - `run`: `string`
952
+ - `at`: `string`
953
+
954
+ <a id="type-reponodestate"></a>
955
+
956
+ ### `RepoNodeState`
957
+
958
+ ```ts
959
+ type RepoNodeState = {
960
+ node: string;
961
+ present: boolean;
962
+ synced: boolean;
963
+ attempted?: "Probe" | "Clone" | "Fetch";
964
+ lastAttempt?: string;
965
+ lastFetched?: string;
966
+ lastError?: string;
967
+ };
968
+ ```
969
+
970
+ One node's view of a Repo, as the cache agent reports it on the resource's status.
971
+
972
+ **Fields**
973
+
974
+ - `node`: `string`
975
+ - `present`: `boolean`
976
+
977
+ A clone exists on this node.
978
+ - `synced`: `boolean`
979
+
980
+ The last attempt — a probe, a clone, or a fetch — succeeded.
981
+ - `attempted` (optional): `"Probe" | "Clone" | "Fetch"`
982
+
983
+ Which of the three the last attempt was. A failed Probe is `jr2 status`'s signal for a Repo
984
+ no pod on the node mounts yet; only a failed Clone fails a Sandbox waiting on that node.
985
+ - `lastAttempt` (optional): `string`
986
+ - `lastFetched` (optional): `string`
987
+
988
+ The last successful clone or fetch.
989
+ - `lastError` (optional): `string`
990
+
991
+ git's own words; absent when synced.
992
+
993
+ <a id="type-surfaceevent"></a>
994
+
995
+ ### `SurfaceEvent`
996
+
997
+ ```ts
998
+ type SurfaceEvent = {
999
+ name: string;
1000
+ description?: string;
1001
+ input: unknown;
1002
+ semantics: EventSemantics;
1003
+ briefing?: string;
1004
+ };
1005
+ ```
1006
+
1007
+ One pick on the surface. `briefing` marks a pick whose parameter is a Chart: jr2's text on how a
1008
+ Chart runs (`CHART_BRIEFING`, [ADR-0070](decisions/0070-a-machine-lends-its-parts-to-a-chart.md)), which the Harness says in the Turn part when the pick is
1009
+ Allowed, so only the Turns that may write a Chart carry it.
1010
+
1011
+ **Fields**
1012
+
1013
+ - `name`: `string`
1014
+ - `description` (optional): `string`
1015
+ - `input`: `unknown`
1016
+ - `semantics`: [`EventSemantics`](authoring-surface/type-eventsemantics.md)
1017
+ - `briefing` (optional): `string`
1018
+
1019
+ <a id="type-pickanswer"></a>
1020
+
1021
+ ### `PickAnswer`
1022
+
1023
+ ```ts
1024
+ type PickAnswer =
1025
+ | { kind: "event"; event: string; sender?: { party: "agent" | "gate"; id: string }; payload: Record<string, unknown> }
1026
+ | { kind: "output"; actor: string; output: unknown }
1027
+ | { kind: "answer"; value: unknown };
1028
+ ```
1029
+
1030
+ What an outstanding pick's answer is ([ADR-0024](decisions/0024-an-agents-turn-ends-with-the-state-that-asked-for-it.md)): the LAST reply from below the Agent's state since
1031
+ the pick — a party's event (a Gate's answer, a nested Agent's pick) with its payload, or a child's
1032
+ output (a child Machine, an Effect stand-in) — named by who sent it. A child's error is no reply (a
1033
+ defect, [ADR-0024](decisions/0024-an-agents-turn-ends-with-the-state-that-asked-for-it.md)). Absent where nothing replied: the answer carries no reply, and says nothing of
1034
+ whether work ran. Plain data; the Harness writes the words. `answer`: the value the Machine's
1035
+ `answer` action set ([ADR-0067](decisions/0067-an-effect-is-an-actor-slot-and-runs-at-most-once-unless-marked-idempotent.md)), which replaces the default.
1036
+
1037
+ **Forms**: it is one of these objects.
1038
+
1039
+ - Form 1: `kind`, `event`, `sender`, `payload`
1040
+
1041
+ - `kind`: `"event"`
1042
+ - `event`: `string`
1043
+ - `sender` (optional): `object`
1044
+
1045
+ - `party`: `"agent" | "gate"`
1046
+ - `id`: `string`
1047
+ - `payload`: `Record<string, unknown>`
1048
+ - Form 2: `kind`, `actor`, `output`
1049
+
1050
+ - `kind`: `"output"`
1051
+ - `actor`: `string`
1052
+ - `output`: `unknown`
1053
+ - Form 3: `kind`, `value`
1054
+
1055
+ - `kind`: `"answer"`
1056
+ - `value`: `unknown`
1057
+
1058
+ <a id="type-machinestatedoc"></a>
1059
+
1060
+ ### `MachineStateDoc`
1061
+
1062
+ ```ts
1063
+ type MachineStateDoc = {
1064
+ id: string;
1065
+ key: string;
1066
+ type: "atomic" | "compound" | "parallel" | "final" | "history";
1067
+ initial?: string;
1068
+ invoke: Array<{ id: string; src: string; effect?: EffectDoc; fail?: true }>;
1069
+ tags: string[];
1070
+ description?: string;
1071
+ states: MachineStateDoc[];
1072
+ children: ChildMachineDoc[];
1073
+ opaqueActions?: boolean;
1074
+ };
1075
+ ```
1076
+
1077
+ One state of the Machine; `states` nests in document order.
1078
+
1079
+ **Fields**
1080
+
1081
+ - `id`: `string`
1082
+
1083
+ Unique state id (custom `id:` respected).
1084
+ - `key`: `string`
1085
+
1086
+ Relative key — the segment that appears in a run's `status.value`.
1087
+ - `type`: `"atomic" | "compound" | "parallel" | "final" | "history"`
1088
+ - `initial` (optional): `string`
1089
+
1090
+ Initial child state id (compound only).
1091
+ - `invoke`: `Array<{ id: string; src: string; effect?: EffectDoc; fail?: true; }>`
1092
+
1093
+ Each invoke's id and slot; an Effect's carries its plain-data parts ([ADR-0067](decisions/0067-an-effect-is-an-actor-slot-and-runs-at-most-once-unless-marked-idempotent.md)) — what it runs,
1094
+ where, and for how long, read without running anything. `fail`: the slot is a `fail()`, so this
1095
+ state can fail the run ([ADR-0073](decisions/0073-a-machine-fails-a-run-with-fail-and-an-uncaught-failure-ends-it-failed.md)).
1096
+ - `tags`: `string[]`
1097
+ - `description` (optional): `string`
1098
+ - `states`: `MachineStateDoc[]`
1099
+ - `children`: `ChildMachineDoc[]`
1100
+
1101
+ The child MACHINES this state runs — invoked ones (a subset of `invoke`, which stays the
1102
+ complete invocation list) plus spawned ones (which appear nowhere else). See
1103
+ [`ChildMachineDoc`](#type-childmachinedoc). A promise/callback actor has no state tree, so it is never here.
1104
+ - `opaqueActions` (optional): `boolean`
1105
+
1106
+ This state runs an `enqueueActions` closure, so THIS STATE'S `children` MAY BE INCOMPLETE.
1107
+
1108
+ Spawning is an action, and `spawnChild` is the only static trace it leaves (see
1109
+ `spawnedSrcs`). A spawn issued as `enqueue.spawnChild(...)` inside a closure resolves at
1110
+ runtime — it can be conditional, looped, or have a computed `src` — so no amount of static
1111
+ analysis recovers it, and the subgraph beneath it would simply be absent from the diagram while
1112
+ the machine ran correctly. That silence is the hazard, not the omission: it once erased the
1113
+ whole feature pipeline of a multi-stage Machine with no signal at all. So the doc carries the
1114
+ fact it cannot see, and callers say so out loud (`opaqueStates`, surfaced on the page).
1115
+
1116
+ <a id="type-machinetransitiondoc"></a>
1117
+
1118
+ ### `MachineTransitionDoc`
1119
+
1120
+ ```ts
1121
+ type MachineTransitionDoc = {
1122
+ source: string;
1123
+ targets: string[];
1124
+ event: string;
1125
+ label: string;
1126
+ guard?: string;
1127
+ description?: string;
1128
+ kind: "event" | "always" | "after" | "done" | "error";
1129
+ };
1130
+ ```
1131
+
1132
+ One transition of the Machine, id-addressed at both ends.
1133
+
1134
+ **Fields**
1135
+
1136
+ - `source`: `string`
1137
+
1138
+ Source state id.
1139
+ - `targets`: `string[]`
1140
+
1141
+ Target state ids; empty = targetless (self/internal) transition.
1142
+ - `event`: `string`
1143
+
1144
+ The raw event descriptor (`""` for always/eventless).
1145
+ - `label`: `string`
1146
+
1147
+ Display label, precomputed here so the renderer stays dumb.
1148
+ - `guard` (optional): `string`
1149
+
1150
+ Normalized guard name, if guarded.
1151
+ - `description` (optional): `string`
1152
+
1153
+ xstate's own transition `description`, as authored: what this writing does, where one name
1154
+ has writings that differ ([ADR-0015](decisions/0015-authoring-surface-absorbs-the-mechanism.md)'s "one def, one meaning").
1155
+ - `kind`: `"event" | "always" | "after" | "done" | "error"`
1156
+
1157
+ <a id="type-machineeventdoc"></a>
1158
+
1159
+ ### `MachineEventDoc`
1160
+
1161
+ ```ts
1162
+ type MachineEventDoc = {
1163
+ name: string;
1164
+ description?: string;
1165
+ audience?: EventAudience;
1166
+ input: unknown;
1167
+ };
1168
+ ```
1169
+
1170
+ One event a Machine declares — its Vocabulary entry ([ADR-0011](decisions/0011-workflow-defined-events.md)), as the doc carries it. Same
1171
+ shape a Gate's `accepts` serves, because it is the same thing seen statically: the name, what a
1172
+ caller sends (JSON Schema), and who may send it.
1173
+
1174
+ **Fields**
1175
+
1176
+ - `name`: `string`
1177
+ - `description` (optional): `string`
1178
+ - `audience` (optional): [`EventAudience`](authoring-surface/type-eventaudience.md)
1179
+
1180
+ Absent: each writing's state decides who may send it ([ADR-0015](decisions/0015-authoring-surface-absorbs-the-mechanism.md)) — see the body's `seats`.
1181
+ - `input`: `unknown`
1182
+
1183
+ The def's input schema as JSON Schema — what a form or a `jr2 send` prompt generates from.
1184
+
1185
+ <a id="type-machineseat"></a>
1186
+
1187
+ ### `MachineSeat`
1188
+
1189
+ ```ts
1190
+ type MachineSeat = { state: string; party: "agent" | "gate"; agent?: string; names: string[] };
1191
+ ```
1192
+
1193
+ One party's seat on one state: the state's id, the party, and the names it may send there —
1194
+ for an Agent the derived set its guards narrow; for a Gate its accepted set, unless the Gate's
1195
+ input names `accepts:` itself.
1196
+
1197
+ **Fields**
1198
+
1199
+ - `state`: `string`
1200
+ - `party`: `"agent" | "gate"`
1201
+ - `agent` (optional): `string`
1202
+ - `names`: `string[]`
1203
+
1204
+ <a id="type-eventsemantics"></a>
1205
+
1206
+ ### `EventSemantics`
1207
+
1208
+ ```ts
1209
+ type EventSemantics = "ack" | "poll";
1210
+ ```
1211
+
1212
+ How the party that sends an event gets its answer.
1213
+
1214
+ - `"ack"`, the default: jr2 delivers the event and answers the sender. When the event starts
1215
+ work inside the Agent's state, the answer comes when that work is done.
1216
+ - `"poll"`: reserved. `createMachine` refuses it: ``machine "<id>": event "<name>" is `poll`,
1217
+ which is reserved but NOT IMPLEMENTED (ADR-0013). Only `ack` events can be delivered today;
1218
+ nothing drains a steer inbox, and degrading it to `ack` would hand the Agent a lying tool
1219
+ contract.``
1220
+
1221
+ **See also**
1222
+
1223
+ - [The Menu](../concepts/the-menu.md)
1224
+ - [ADR-0006: The agent picks from a Machine-defined, schema-backed menu; it does not drive the workflow](decisions/0006-agent-control-surface.md)
1225
+
1226
+ <a id="type-effectdoc"></a>
1227
+
1228
+ ### `EffectDoc`
1229
+
1230
+ ```ts
1231
+ type EffectDoc =
1232
+ | { kind: "command"; argv: string[]; timeoutMs: number; slot?: string; secrets?: string[]; pin?: true }
1233
+ | {
1234
+ kind: "http";
1235
+ method: string;
1236
+ target: string;
1237
+ secrets: string[];
1238
+ timeoutMs: number;
1239
+ idempotent: boolean;
1240
+ file?: true;
1241
+ }
1242
+ | { kind: "push"; sign: boolean; squash: boolean; force: boolean; pin: boolean; timeoutMs: number; slot?: string }
1243
+ | { kind: "dispatch"; workflow: string; wait: boolean; target?: string; timeoutMs: number };
1244
+ ```
1245
+
1246
+ An Effect slot's parts, as the doc carries them ([ADR-0067](decisions/0067-an-effect-is-an-actor-slot-and-runs-at-most-once-unless-marked-idempotent.md)): a command's argv (an argv slot reads
1247
+ `<name>`), its timeout, and the Repo Slot whose Worktree is its cwd, when it names one.
1248
+
1249
+ **Forms**: it is one of these objects.
1250
+
1251
+ - Form 1: `kind`, `argv`, `timeoutMs`, `slot`, `secrets`, `pin`
1252
+
1253
+ - `kind`: `"command"`
1254
+ - `argv`: `string[]`
1255
+ - `timeoutMs`: `number`
1256
+ - `slot` (optional): `string`
1257
+ - `secrets` (optional): `string[]`
1258
+ - `pin` (optional): `true`
1259
+ - Form 2: `kind`, `method`, `target`, `secrets`, `timeoutMs`, `idempotent`, `file`
1260
+
1261
+ - `kind`: `"http"`
1262
+ - `method`: `string`
1263
+ - `target`: `string`
1264
+ - `secrets`: `string[]`
1265
+ - `timeoutMs`: `number`
1266
+ - `idempotent`: `boolean`
1267
+ - `file` (optional): `true`
1268
+ - Form 3: `kind`, `sign`, `squash`, `force`, `pin`, `timeoutMs`, `slot`
1269
+
1270
+ - `kind`: `"push"`
1271
+ - `sign`: `boolean`
1272
+ - `squash`: `boolean`
1273
+ - `force`: `boolean`
1274
+ - `pin`: `boolean`
1275
+ - `timeoutMs`: `number`
1276
+ - `slot` (optional): `string`
1277
+ - Form 4: `kind`, `workflow`, `wait`, `target`, `timeoutMs`
1278
+
1279
+ - `kind`: `"dispatch"`
1280
+ - `workflow`: `string`
1281
+ - `wait`: `boolean`
1282
+ - `target` (optional): `string`
1283
+ - `timeoutMs`: `number`
1284
+
1285
+ <a id="type-childmachinedoc"></a>
1286
+
1287
+ ### `ChildMachineDoc`
1288
+
1289
+ ```ts
1290
+ type ChildMachineDoc = {
1291
+ src: string;
1292
+ label: string;
1293
+ via: "invoke" | "spawn";
1294
+ machine?: MachineBodyDoc;
1295
+ recursive?: true;
1296
+ };
1297
+ ```
1298
+
1299
+ A child Machine reached from a state — the pipeline a workflow delegates to, which is most of
1300
+ what it DOES. Attached to the state that runs it, so the renderer nests it where it belongs.
1301
+
1302
+ `src` is the JOIN KEY: it is exactly the `src` a live child actor reports (`RunChild.src`), for
1303
+ both kinds — a named actor keeps its name (`"body"`, `"worker"`, `"featureWorkspace"`), an inline
1304
+ machine object gets xstate's generated key (`"xstate.invoke.0.wrapper.running"`) on both sides.
1305
+ That is what lets the page hang a run's live child state under the right subgraph without the two
1306
+ halves agreeing on anything but this string. Since [ADR-0049](decisions/0049-a-machine-carries-its-parts-and-composes-by-invoke.md) every kit wrapper names its child, so
1307
+ the generated key is an author's shape only.
1308
+
1309
+ **Fields**
1310
+
1311
+ - `src`: `string`
1312
+
1313
+ The join key — matches a live `RunChild.src` exactly.
1314
+ - `label`: `string`
1315
+
1316
+ Display name: the invoke id (`"body"`) or the spawned actor's name (`"featureWorkspace"`).
1317
+ - `via`: `"invoke" | "spawn"`
1318
+
1319
+ How the state reaches it: `invoke` binds it to the state's lifetime, `spawn` outlives it.
1320
+ - `machine` (optional): [`MachineBodyDoc`](#type-machinebodydoc)
1321
+
1322
+ The child's own structure. Absent iff `recursive`.
1323
+ - `recursive` (optional): `true`
1324
+
1325
+ The machine is already an ancestor of this point — the body is up there, not repeated here.
1326
+
1327
+ <a id="type-eventaudience"></a>
1328
+
1329
+ ### `EventAudience`
1330
+
1331
+ ```ts
1332
+ type EventAudience = "agent" | "external" | "any";
1333
+ ```
1334
+
1335
+ Who may send an event: `"agent"` (an Agent, as a pick from its Menu), `"external"` (the caller of
1336
+ a Gate), or `"any"` (both).
1337
+
1338
+ Leave it unset in most cases. Then the position of each `on` key decides: the event belongs to
1339
+ the party that its state, or the nearest state above it, invokes. An `on` key on a state that
1340
+ invokes no party, with no such state above it, belongs to both. Set an audience only to give an
1341
+ event to the other party too (`"any"`). Or set it to keep an event on the root from one party
1342
+ (`"agent"` or `"external"`).
1343
+
1344
+ **See also**
1345
+
1346
+ - [The Menu](../concepts/the-menu.md)
1347
+ - [Gates](../concepts/gates.md)
1348
+ - [ADR-0015: Workflows are authored through `jr2Setup`; vocabulary and agent menus derive from the machine](decisions/0015-authoring-surface-absorbs-the-mechanism.md)