@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
package/src/agent.ts CHANGED
@@ -22,57 +22,133 @@
22
22
 
23
23
  import { open } from "./open.ts";
24
24
 
25
- /** jr2's reasoning-effort scale (ADR-0027) — a strict subset of the runtime's, so every value
26
- * passes through unmapped; mirrored by `@jr2/harness`'s spec contract. */
25
+ // jr2's reasoning-effort scale (ADR-0027) — a strict subset of the runtime's, so every value
26
+ // passes through unmapped; mirrored by `@jr2/harness`'s spec contract.
27
+ /**
28
+ * How hard the model thinks before it answers: `"off"`, `"minimal"`, `"low"`, `"medium"`,
29
+ * `"high"` or `"xhigh"`. Set it on an Agent's definition (`thinkingLevel`), or for one Turn in the
30
+ * invoke's `input`.
31
+ *
32
+ * A model can lack a level. Claude Sonnet 5.5 has no `"off"`, and at `"off"` the Harness's request
33
+ * then sends effort `"high"`. The Harness does not refuse such a level: it runs the Turn, and the
34
+ * printed conversation names the level that the model ran at.
35
+ *
36
+ * @example
37
+ * ```ts
38
+ * import { agent, type ThinkingLevel } from "@jr2/orchestrator";
39
+ *
40
+ * const effort: ThinkingLevel = "high";
41
+ *
42
+ * export const reviewer = agent({
43
+ * model: "anthropic/claude-haiku-5-5",
44
+ * instructions: "You review diffs for correctness.",
45
+ * thinkingLevel: effort,
46
+ * });
47
+ * ```
48
+ *
49
+ * @see docs/guides/set-an-agents-access-and-dials.md
50
+ * @see docs/reference/decisions/0018-instance-agents-are-definitions-jr2-assembles-the-harness.md
51
+ */
27
52
  export type ThinkingLevel = "off" | "minimal" | "low" | "medium" | "high" | "xhigh";
28
53
 
29
- /** What an Agent may DO to the Workspace (ADR-0028) — and, through `"none"`, where its Turn runs
30
- * (ADR-0031): the value the Agent actor reads off its own slot's definition to place the Turn. */
54
+ // The value the Agent actor reads off its own slot's definition to place the Turn (ADR-0028,
55
+ // ADR-0031).
56
+ /** What an Agent may do to the Workspace: `"write"`, `"read"` or `"none"`. With `"none"`, its Turn
57
+ * runs on the Instance Harness, not in a Sandbox. The `workspace` field of {@link AgentDefinition}
58
+ * tells what each value gives. */
31
59
  export type WorkspaceAccess = "write" | "read" | "none";
32
60
 
33
- /** The plain-data Agent definition (ADR-0018): IDENTITY plus one default. A Turn's Frame — what
34
- * it is about and where it works — is not here and cannot be (ADR-0057): a Worktree path exists
35
- * only once a run has a branch, so no definition written before the run could name one.
61
+ // The plain-data Agent definition (ADR-0018): IDENTITY plus one default. A Turn's Frame — what it
62
+ // is about and where it works — is not here and cannot be (ADR-0057): a Worktree exists only
63
+ // once a run has cut it, so no definition written before the run could name one.
64
+ //
65
+ // Must stay JSON-serializable: the definition rides the Turn to the Harness (ADR-0049), so
66
+ // anything non-serializable would be silently lost — grow this contract deliberately. ADR-0028
67
+ // added a restriction vocabulary (`workspace`), not an extension one: custom tool implementations
68
+ // stay out of the contract.
69
+ /**
70
+ * An Agent's definition: which model it runs, its instructions, and what it may do to the
71
+ * Workspace. Give it to `agent()` to get the Agent's actor slot. It is plain data that can be
72
+ * written as JSON.
73
+ *
74
+ * It holds who the Agent is, not what one Turn does. The prompt of a Turn and the directory it
75
+ * works in are the Frame. The state that invokes the Agent sets the Frame in the invoke's
76
+ * `input`. That `input` can also set `model` and `thinkingLevel` for one Turn: the Dials. It
77
+ * cannot change `instructions` or `workspace`.
36
78
  *
37
- * Must stay JSON-serializable: the definition rides
38
- * the Turn to the Harness (ADR-0049), so anything non-serializable would be silently lost — grow
39
- * this contract deliberately. ADR-0028 added a restriction vocabulary (`workspace`), not an
40
- * extension one: custom tool implementations stay out of the contract. */
79
+ * @example
80
+ * ```ts
81
+ * import { agent, type AgentDefinition } from "@jr2/orchestrator";
82
+ *
83
+ * const definition: AgentDefinition = {
84
+ * model: "anthropic/claude-haiku-5-5",
85
+ * instructions: "You fix the failing test, and you change nothing else.",
86
+ * description: "Fixes one failing test",
87
+ * thinkingLevel: "medium",
88
+ * workspace: "write",
89
+ * };
90
+ *
91
+ * export const coder = agent(definition);
92
+ * ```
93
+ *
94
+ * @see docs/concepts/agents-and-turns.md
95
+ * @see docs/guides/set-an-agents-access-and-dials.md
96
+ * @see docs/reference/decisions/0018-instance-agents-are-definitions-jr2-assembles-the-harness.md
97
+ * @see docs/reference/decisions/0028-what-an-agent-may-do-to-the-workspace-is-part-of-its-definition.md
98
+ */
41
99
  export type AgentDefinition = {
42
- /** Model specifier, `<provider>/<modelId>`, e.g. `anthropic/claude-sonnet-4-6`. REQUIRED —
43
- * there is no instance-wide default (ADR-0018): `jr2.config.ts`'s `harness` section
44
- * declares which providers are REACHABLE, and the definition makes the choice. This is also the
45
- * only model `jr2 up` can preflight, since a workflow's is not statically recoverable. An
46
- * invocation may override it for one Turn (`AgentTurnInput.model`). */
100
+ // REQUIRED, with no instance-wide default (ADR-0018): `jr2.config.ts`'s `harness` section
101
+ // declares which providers are REACHABLE, and the definition makes the choice. This is also the
102
+ // only model `jr2 up` can preflight, since a workflow's is not statically recoverable. An
103
+ // invocation may override it for one Turn (`AgentTurnInput.model`).
104
+ /** The model, as `<provider>/<modelId>`: for example `anthropic/claude-haiku-5-5`. The
105
+ * provider must be one that `jr2.config.ts` can reach. Here it is always a string: an `open`
106
+ * model of `agent()` must be bound before a Turn starts. One Turn may set another model in the
107
+ * invoke's `input`. */
47
108
  model: string;
48
- /** The Agent's system prompt. */
109
+ /** The Agent's instructions: the text that tells the model who it is and how to work. The same
110
+ * on every Turn. */
49
111
  instructions: string;
50
- /** Optional static description — observability, never sent to the model. */
112
+ /** A short description, for people who read the Machine. The model never reads it. */
51
113
  description?: string;
52
- /** Reasoning effort. Omitted → the runtime's default. An invocation may override it for one
53
- * Turn (`AgentTurnInput.thinkingLevel`) — effort is a property of the task's difficulty, so the
54
- * same persona legitimately runs at different settings in different Machines. */
114
+ // Effort is a property of the task's difficulty, so the same persona legitimately runs at
115
+ // different settings in different Machines; an invocation may override it for one Turn
116
+ // (`AgentTurnInput.thinkingLevel`).
117
+ /** How hard the model thinks: one of {@link ThinkingLevel}. Absent: `"off"`. A model with no
118
+ * `"off"` runs at another level, and the printed conversation names it. One Turn may set another
119
+ * level in the invoke's `input`. */
55
120
  thinkingLevel?: ThinkingLevel;
56
- /** What this Agent may DO to the Workspace (ADR-0028) — the persona in one word, deliberately
57
- * not `tools` (that names the control-plane Menu, what it may SAY). `"read"` withholds the
58
- * write/edit Working tools; bash stays, so this states intent and stops the honest path — the
59
- * detached review worktree is the containment. `"none"` withholds the ENTIRE Working toolset:
60
- * the Menu-only Agent converses and picks from its Menu, nothing else (so its Turn frames no
61
- * directory — only Working tools consume one) — and places the Turn on the Instance Harness
62
- * (ADR-0031). Default `"write"`. */
121
+ // The persona in one word (ADR-0028), deliberately not `tools` (that names the control-plane
122
+ // Menu, what it may SAY). `"read"` states intent and stops the honest path: bash stays, and a
123
+ // detached Worktree is the containment. `"none"` frames no directory — only Working tools
124
+ // consume one — and places the Turn on the Instance Harness (ADR-0031).
125
+ /** What the Agent may do to the Workspace. Default: `"write"`.
126
+ * - `"write"`: all the Working tools (read, write, edit, bash, grep, glob).
127
+ * - `"read"`: no write or edit tool. The Agent keeps bash, so `"read"` does not stop a command
128
+ * that writes. To keep the Agent from changing the branch, frame its Turn in a detached
129
+ * Worktree: cut it with `{ path, detach: sha }`, then give that `path` as `cwd`.
130
+ * - `"none"`: no Working tools. The Agent only reads its prompt and picks from its Menu. Its Turn
131
+ * runs on the Instance Harness, not in a Sandbox, so it needs no `workspace()` around it. */
63
132
  workspace?: WorkspaceAccess;
64
133
  };
65
134
 
66
- /**
67
- * The Agent as an author DECLARES it (ADR-0054): the definition, except that `model` may be Open —
68
- * the one part a packaged Machine cannot honestly fill, since the package cannot pay for it. Every
69
- * other field is the wire's, because every other field a package CAN state.
70
- *
71
- * This is what `agent()` takes and what the slot's brand carries, so the walk and `customize()`
72
- * read the author's own answer, Open included. Nothing sends this: the wire takes an
73
- * {@link AgentDefinition}, and {@link requireBoundAgent} is the one door between the two.
74
- */
75
- export type AgentDeclaration = Omit<AgentDefinition, "model"> & { model: string | typeof open };
135
+ // The Agent as an author DECLARES it (ADR-0054): the definition, except that `model` may be Open —
136
+ // the one part a packaged Machine cannot honestly fill, since the package cannot pay for it. Every
137
+ // other field is the wire's, because every other field a package CAN state.
138
+ //
139
+ // This is what `agent()` takes and what the slot's brand carries, so the walk and `customize()`
140
+ // read the author's own answer, Open included. Nothing sends this: the wire takes an
141
+ // AgentDefinition, and `requireBoundAgent` is the one door between the two.
142
+ /** What `agent()` takes: an {@link AgentDefinition}, except that `model` can also be `open`. */
143
+ export type AgentDeclaration = Omit<AgentDefinition, "model"> & {
144
+ /** The model, as `<provider>/<modelId>`: for example `anthropic/claude-haiku-5-5`. Required:
145
+ * there is no default model. The provider must be one that `jr2.config.ts` can reach.
146
+ *
147
+ * Or `open`, in a Machine that you publish as a package. Then the Instance that registers the
148
+ * Machine binds the model with `customize()`. One Turn may set another model in the invoke's
149
+ * `input`. */
150
+ model: string | typeof open;
151
+ };
76
152
 
77
153
  /** The brand `agent(declaration)` stamps on its logic (ADR-0049): the declaration itself, readable
78
154
  * off the logic object. Everything that must recognize an Agent slot reads THIS — never a name
package/src/ambient.ts CHANGED
@@ -21,13 +21,12 @@ import type { AnyActorRef } from "xstate";
21
21
  export type AmbientHandles = {
22
22
  endpoint: string;
23
23
  sandbox: string;
24
- /** Every Repo Slot's branch-worktree path, by slot (ADR-0051). */
24
+ /** Every Repo Slot's folder, `/work/<slot>`, by slot (ADR-0051). */
25
25
  repos: Record<string, string>;
26
26
  /** Every Repo Slot's Binding url, by slot (ADR-0051): where a push goes. */
27
27
  bindings?: Record<string, string>;
28
- branch: string;
29
- /** Detached review-worktree paths, when the spec carried `reviewSha` (ADR-0028). */
30
- review?: Record<string, string>;
28
+ /** Each Repo Slot's Binding base, where the Binding names one: a cut with no `from` starts here. */
29
+ bases?: Record<string, string>;
31
30
  };
32
31
 
33
32
  const byRef = new WeakMap<AnyActorRef, AmbientHandles>();
@@ -6,16 +6,55 @@
6
6
 
7
7
  import { isAbsolute, relative, sep } from "node:path";
8
8
  import type { AnyStateMachine } from "xstate";
9
+ import { z } from "zod";
9
10
  import type { JR2Config } from "./config.ts";
10
11
  import { imageContextDigest, type ImageRefs } from "./images.ts";
11
12
  import { openPartsText } from "./open-effect.ts";
12
13
  import { customizeLine, partsOf, placedEffectsOf, workspacePodsOf } from "./parts.ts";
13
14
  import { refuseEffectSecrets, type PlacementWalk } from "./secret-placement.ts";
14
- import { chartFileRefusals, type ChartFile } from "./charts.ts";
15
+ import {
16
+ chartFileRefusals,
17
+ chartName,
18
+ chartWrapperOf,
19
+ splitChartName,
20
+ wrapperFault,
21
+ type ChartFile,
22
+ } from "./charts.ts";
23
+ import { doorCompat } from "./door-compat.ts";
24
+
25
+ // The comparison is the same one `jr2 up`'s foreign preflight makes, so it is exported beside the
26
+ // walk the CLI already imports (ADR-0071).
27
+ export { doorCompat, type DoorCompat } from "./door-compat.ts";
28
+ import { inputSchemaOf, isZodSchema } from "./vocabulary.ts";
15
29
 
16
30
  /** One registered Workflow, as `loadWorkflows` gives it. */
17
31
  export type LoadedWorkflow = { name: string; machine: AnyStateMachine };
18
32
 
33
+ /**
34
+ * Every registered Machine that has a zod `input` on its `createMachine` config and that `jr2Setup`
35
+ * did not make (ADR-0033). The `setup()` of xstate keeps that `input` in the config but does not read it,
36
+ * so the Machine has no door: a start with any input passes, and the Console start form is only a
37
+ * field for JSON. TypeScript accepts the config, so only this walk finds it. One line per Workflow,
38
+ * naming the fix.
39
+ * A Machine with no `input`, or with an `input` that is not zod, can still use `setup()`.
40
+ *
41
+ * The line text follows `refusing: ` in `jr2 up`'s output; the prefix is the caller's.
42
+ */
43
+ export function doorRefusals(workflows: readonly LoadedWorkflow[]): string[] {
44
+ const lines: string[] = [];
45
+ for (const w of workflows) {
46
+ const declared = (w.machine.config as { input?: unknown }).input;
47
+ if (!isZodSchema(declared) || inputSchemaOf(w.machine)) continue;
48
+ lines.push(
49
+ `workflow "${w.name}": machine "${w.machine.id}" has a zod \`input\` on createMachine, but jr2Setup did not ` +
50
+ "make this Machine, so no door reads that input: a run starts with any input, and the Console start form " +
51
+ "is only a field for JSON — make the Machine with jr2Setup in place of setup() or createMachine() (leave " +
52
+ "out `events` if it takes no workflow event) (ADR-0033)",
53
+ );
54
+ }
55
+ return lines;
56
+ }
57
+
19
58
  /**
20
59
  * Every part a registered Machine leaves Open (ADR-0051, ADR-0054): a Repo Slot with no url, an
21
60
  * Agent with no model, an Effect's url, argv or secret. One line per part, in walk order within
@@ -89,6 +128,139 @@ export function placementWalkOf(workflows: readonly LoadedWorkflow[]): Placement
89
128
  };
90
129
  }
91
130
 
131
+ /**
132
+ * What a `dispatch` names, checked against what the walk can see (ADR-0071). Each dispatch with no
133
+ * target — a same-Instance one; a foreign target is `jr2 up`'s preflight, a warning — must name a
134
+ * Workflow the Assembly has: a Machine (`workflows/<name>.ts`), or `<wrapper>/<name>`, a named Chart
135
+ * under a Chart wrapper the Assembly registers, from a Chart file or (when `runtime` is given) a
136
+ * runtime Chart. A miss is an error. Without `runtime` — on the host, which cannot see the
137
+ * Orchestrator's volume — a slashed name under a known wrapper with no Chart file is a warning.
138
+ * Then the slot's input schema, when it has one, is compared with the callee's door
139
+ * (`doorCompat`): a fault is an error, naming the field; a schema outside the compared subset is a
140
+ * warning, "not compared".
141
+ *
142
+ * A dispatch resolves at RUN time against the current Assembly (ADR-0069); this check is of the
143
+ * Assembly being published, so a later publish that drops the callee answers `refused` with the
144
+ * door's 404 then, and is not refused for it here.
145
+ */
146
+ export function dispatchRefusals(
147
+ workflows: readonly LoadedWorkflow[],
148
+ charts: readonly ChartFile[],
149
+ runtime?: readonly { name: string }[],
150
+ ): { errors: string[]; warnings: string[] } {
151
+ const errors: string[] = [];
152
+ const warnings: string[] = [];
153
+ const seen = new Set<string>();
154
+ for (const w of workflows) {
155
+ for (const effect of partsOf([w.machine]).effects) {
156
+ // A target, bound or Open, is another Orchestrator's: its door is not in this Assembly.
157
+ if (effect.kind !== "dispatch" || effect.target !== undefined || effect.open !== undefined) continue;
158
+ const name = effect.workflow;
159
+ const at = `workflow "${w.name}" dispatches "${name}"`;
160
+ const once = JSON.stringify([w.name, effect.name, name]);
161
+ if (seen.has(once)) continue;
162
+ seen.add(once);
163
+ const callee = calleeOf(workflows, charts, runtime, name);
164
+ if ("error" in callee) {
165
+ errors.push(`${at} ${callee.error} (ADR-0071)`);
166
+ continue;
167
+ }
168
+ // A slashed name with no Chart the host can see still has a known door: the wrapper's minus
169
+ // its Chart fields, the same for every Chart under it. So it is warned AND compared.
170
+ if (callee.warning) warnings.push(`${at}: ${callee.warning} (ADR-0071)`);
171
+ if (effect.input === undefined) continue;
172
+ if ("notDrawn" in callee.door) {
173
+ warnings.push(`${at}: its input schema and the door are not compared — ${callee.door.notDrawn} (ADR-0071)`);
174
+ continue;
175
+ }
176
+ const compared = doorCompat(effect.input, callee.door.schema);
177
+ if (compared.ok === "not-compared") {
178
+ warnings.push(`${at}: its input schema and the door are not compared — ${compared.why} (ADR-0071)`);
179
+ } else if (compared.ok === false) {
180
+ for (const fault of compared.faults) {
181
+ errors.push(
182
+ `${at} with input its door does not take: ${fault} — align the slot's \`input\` with the door ` +
183
+ "(derive it from the door's schema, `door.pick({ ... })`) (ADR-0071)",
184
+ );
185
+ }
186
+ }
187
+ }
188
+ }
189
+ return { errors, warnings };
190
+ }
191
+
192
+ /** The door a dispatch's name resolves to in these Workflows, or why it does not. */
193
+ function calleeOf(
194
+ workflows: readonly LoadedWorkflow[],
195
+ charts: readonly ChartFile[],
196
+ runtime: readonly { name: string }[] | undefined,
197
+ name: string,
198
+ ): { door: Door; warning?: string } | { error: string } {
199
+ const split = splitChartName(name);
200
+ if (!split) {
201
+ const found = workflows.find((w) => w.name === name);
202
+ if (!found) {
203
+ return {
204
+ error:
205
+ `which no Workflow in the Assembly has — add workflows/${name}.ts, or name one it registers` +
206
+ (workflows.length ? `: ${workflows.map((w) => `"${w.name}"`).join(", ")}` : ""),
207
+ };
208
+ }
209
+ return { door: doorOf(found.machine, []) };
210
+ }
211
+ const { wrapper, name: short } = split;
212
+ const fault = wrapperFault(workflows, wrapper);
213
+ if (fault) {
214
+ return {
215
+ error:
216
+ fault.status === 404
217
+ ? `which no Workflow in the Assembly has — no workflows/${wrapper}.ts registers the Chart wrapper "${wrapper}"`
218
+ : `which no Workflow in the Assembly can be: ${fault.error}`,
219
+ };
220
+ }
221
+ const machine = workflows.find((w) => w.name === wrapper)!.machine;
222
+ const door = doorOf(machine, chartWrapperOf(machine)?.chartFields ?? []);
223
+ const file = `workflows/${wrapper}/${short}.chart.json`;
224
+ if (charts.some((c) => chartName(c.wrapper, c.name) === name)) return { door };
225
+ if (runtime === undefined) {
226
+ return {
227
+ door,
228
+ warning:
229
+ `the Assembly has no Chart file ${file}, and a runtime Chart lives on the Orchestrator's volume alone, ` +
230
+ "which jr2 up cannot see — the publish door checks it, and a run of the dispatch is refused with the door's " +
231
+ "404 if it is not there",
232
+ };
233
+ }
234
+ if (runtime.some((c) => c.name === name)) return { door };
235
+ return {
236
+ error:
237
+ `which no Workflow in the Assembly has — add the Chart file ${file}; or, for a runtime Chart, PUT ` +
238
+ `/workflows/${wrapper}/charts/${short} before this publish (a PUT needs "${wrapper}" in the current ` +
239
+ `Assembly: when this publish adds it, publish "${wrapper}" first, then PUT the Chart, then publish the dispatch)`,
240
+ };
241
+ }
242
+
243
+ /** A door as the comparison reads it: its JSON Schema (null: it declares no input), or why zod
244
+ * could not draw one. */
245
+ type Door = { schema: Record<string, unknown> | null } | { notDrawn: string };
246
+
247
+ /** A Workflow's door as JSON Schema, exactly as `GET /workflows/<name>` serves it (run-host.ts
248
+ * `inputSchema`): null for a Machine that declares none; for a named Chart the wrapper's minus its
249
+ * Chart fields, which the Chart supplies (ADR-0070). A door zod cannot draw (`z.date()`,
250
+ * `z.custom()`) is not drawn as "any", which would guess "compatible": it is not compared. */
251
+ function doorOf(machine: AnyStateMachine, chartFields: readonly string[]): Door {
252
+ let schema = inputSchemaOf(machine);
253
+ if (!schema) return { schema: null };
254
+ if (chartFields.length) schema = schema.omit(Object.fromEntries(chartFields.map((f) => [f, true])) as never);
255
+ try {
256
+ return { schema: z.toJSONSchema(schema, { io: "input" }) as Record<string, unknown> };
257
+ } catch (err) {
258
+ return {
259
+ notDrawn: `the door has a part JSON Schema cannot state (${err instanceof Error ? err.message : String(err)})`,
260
+ };
261
+ }
262
+ }
263
+
92
264
  export type AssemblyRefusalInput = {
93
265
  /** The Assembly's `jr2.config.ts`, loaded; `undefined` when it ships none. */
94
266
  config: JR2Config | undefined;
@@ -99,6 +271,12 @@ export type AssemblyRefusalInput = {
99
271
  * admitted against its wrapper's Open body by the same door a run's Chart passes. Absent, none.
100
272
  */
101
273
  charts?: readonly ChartFile[];
274
+ /**
275
+ * The runtime Charts on the Orchestrator's volume (ADR-0070), by Workflow name
276
+ * (`<wrapper>/<name>`): what a dispatch of a named Chart may resolve to beside the Chart files
277
+ * (ADR-0071). The door can see them; absent, none.
278
+ */
279
+ runtimeCharts?: readonly { name: string }[];
102
280
  /**
103
281
  * The image map the Orchestrator reads per provision (ADR-0038), or a reader of it. Present
104
282
  * only when deployed: a host-booted process has no map, and no Sandbox to provision. When
@@ -116,16 +294,20 @@ export type AssemblyRefusalInput = {
116
294
  /**
117
295
  * The door's walk (ADR-0069): the refusals the Orchestrator can see in an Assembly it has already
118
296
  * imported. An import error, a missing `export const machine` and a Vocabulary error are the
119
- * caller's: they throw at import, before this runs. Here: every Open part, a secret the config does
120
- * not declare (or a literal one too short to scrub), a `file:` image context whose digest the
121
- * mounted image map does not hold, and a Chart file that does not admit under its wrapper
122
- * (ADR-0070), each line naming the file. The door runs this after `jr2 up` did its cluster work, so each
123
- * check is true when the Assembly lands.
297
+ * caller's: they throw at import, before this runs. Here: a zod `input` that no door reads, every
298
+ * Open part, a secret the config does not declare (or a literal one too short to scrub), a `file:`
299
+ * image context whose digest the mounted image map does not hold, and a Chart file that does not
300
+ * admit under its wrapper (ADR-0070), each line naming the file. The door runs this after `jr2 up`
301
+ * did its cluster work, so each check is true when the Assembly lands.
124
302
  */
125
303
  export async function assemblyRefusals(input: AssemblyRefusalInput): Promise<string[]> {
126
- const lines = openPartRefusals(input.workflows);
304
+ const lines = [...doorRefusals(input.workflows), ...openPartRefusals(input.workflows)];
127
305
  // A Chart file is the Instance's own (ADR-0070): one that fails refuses the publish.
128
306
  if (input.charts?.length) lines.push(...chartFileRefusals(input.charts, input.workflows));
307
+ // A same-Instance dispatch names a Workflow this Assembly has (ADR-0071). The door sees the
308
+ // runtime Charts, so a miss is an error here. Its warnings (a schema "not compared") have no
309
+ // channel in the publish's answer, and are dropped: `jr2 up` printed them before the publish.
310
+ lines.push(...dispatchRefusals(input.workflows, input.charts ?? [], input.runtimeCharts ?? []).errors);
129
311
  try {
130
312
  refuseEffectSecrets(input.config ?? {}, placementWalkOf(input.workflows));
131
313
  } catch (err) {