@jr2/orchestrator 0.4.1 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (361) hide show
  1. package/README.md +20 -2
  2. package/console/components/app.ts +2 -0
  3. package/console/components/fleet.ts +14 -1
  4. package/console/components/machine-pane.ts +41 -2
  5. package/console/main.ts +13 -1
  6. package/console/store.ts +102 -6
  7. package/console/style.css +21 -0
  8. package/docs/agents-block.md +5 -0
  9. package/docs/concepts/agents-and-turns.md +478 -0
  10. package/docs/concepts/architecture.md +243 -0
  11. package/docs/concepts/charts.md +146 -0
  12. package/docs/concepts/composition.md +357 -0
  13. package/docs/concepts/converge.md +257 -0
  14. package/docs/concepts/durable-runs.md +189 -0
  15. package/docs/concepts/effects.md +658 -0
  16. package/docs/concepts/gates.md +208 -0
  17. package/docs/concepts/machines-and-workflows.md +298 -0
  18. package/docs/concepts/pools-and-sources.md +230 -0
  19. package/docs/concepts/secrets-and-trust.md +306 -0
  20. package/docs/concepts/the-menu.md +381 -0
  21. package/docs/concepts/workspaces.md +756 -0
  22. package/docs/get-started/a-model-decides.md +563 -0
  23. package/docs/get-started/an-agent-in-a-sandbox.md +383 -0
  24. package/docs/get-started/connect-a-model.md +248 -0
  25. package/docs/get-started/create-an-instance.md +194 -0
  26. package/docs/get-started/have-your-assistant-write-a-machine.md +993 -0
  27. package/docs/get-started/install.md +130 -0
  28. package/docs/guides/add-tools-to-the-sandbox.md +308 -0
  29. package/docs/guides/answer-a-gate.md +304 -0
  30. package/docs/guides/bind-open-parts.md +224 -0
  31. package/docs/guides/cancel-a-run.md +146 -0
  32. package/docs/guides/clean-up.md +206 -0
  33. package/docs/guides/cut-a-worktree.md +560 -0
  34. package/docs/guides/fix-a-failed-converge.md +361 -0
  35. package/docs/guides/give-the-cluster-git-credentials.md +222 -0
  36. package/docs/guides/iterate-on-a-machine-on-kind.md +190 -0
  37. package/docs/guides/let-an-agent-write-a-chart.md +230 -0
  38. package/docs/guides/look-inside-a-sandbox.md +177 -0
  39. package/docs/guides/mirror-the-kit-images.md +176 -0
  40. package/docs/guides/move-from-kind-to-a-shared-cluster.md +318 -0
  41. package/docs/guides/open-the-console.md +91 -0
  42. package/docs/guides/publish-a-machine-as-an-npm-package.md +350 -0
  43. package/docs/guides/push-and-sign-a-branch.md +532 -0
  44. package/docs/guides/run-a-chart-by-name.md +270 -0
  45. package/docs/guides/run-a-command-or-call-a-url.md +587 -0
  46. package/docs/guides/run-one-worker-per-item.md +322 -0
  47. package/docs/guides/set-an-agents-access-and-dials.md +420 -0
  48. package/docs/guides/size-a-workspace.md +217 -0
  49. package/docs/guides/start-a-run-from-a-run.md +237 -0
  50. package/docs/guides/start-a-run.md +207 -0
  51. package/docs/guides/upgrade-the-kit-version.md +240 -0
  52. package/docs/guides/use-a-hosted-provider.md +214 -0
  53. package/docs/guides/use-a-local-model.md +313 -0
  54. package/docs/guides/watch-a-run.md +349 -0
  55. package/docs/guides/write-a-workflow.md +318 -0
  56. package/docs/index.md +44 -0
  57. package/docs/llms.txt +237 -0
  58. package/docs/reference/authoring-surface/agent.md +151 -0
  59. package/docs/reference/authoring-surface/answer.md +156 -0
  60. package/docs/reference/authoring-surface/arg.md +82 -0
  61. package/docs/reference/authoring-surface/basic.md +62 -0
  62. package/docs/reference/authoring-surface/bearer.md +53 -0
  63. package/docs/reference/authoring-surface/branchname.md +15 -0
  64. package/docs/reference/authoring-surface/chartschema.md +23 -0
  65. package/docs/reference/authoring-surface/chartschemafor.md +48 -0
  66. package/docs/reference/authoring-surface/command.md +206 -0
  67. package/docs/reference/authoring-surface/customize.md +64 -0
  68. package/docs/reference/authoring-surface/defineconfig.md +41 -0
  69. package/docs/reference/authoring-surface/defineevent.md +114 -0
  70. package/docs/reference/authoring-surface/dispatch.md +126 -0
  71. package/docs/reference/authoring-surface/fail.md +96 -0
  72. package/docs/reference/authoring-surface/file.md +142 -0
  73. package/docs/reference/authoring-surface/frompick.md +277 -0
  74. package/docs/reference/authoring-surface/http.md +259 -0
  75. package/docs/reference/authoring-surface/isfailure.md +58 -0
  76. package/docs/reference/authoring-surface/isready.md +14 -0
  77. package/docs/reference/authoring-surface/jr2setup.md +237 -0
  78. package/docs/reference/authoring-surface/open.md +105 -0
  79. package/docs/reference/authoring-surface/openbody.md +86 -0
  80. package/docs/reference/authoring-surface/paramsof.md +143 -0
  81. package/docs/reference/authoring-surface/pool.md +186 -0
  82. package/docs/reference/authoring-surface/push.md +130 -0
  83. package/docs/reference/authoring-surface/readyof.md +21 -0
  84. package/docs/reference/authoring-surface/secret.md +139 -0
  85. package/docs/reference/authoring-surface/sentby.md +83 -0
  86. package/docs/reference/authoring-surface/source.md +51 -0
  87. package/docs/reference/authoring-surface/text.md +62 -0
  88. package/docs/reference/authoring-surface/type-agentdeclaration.md +27 -0
  89. package/docs/reference/authoring-surface/type-agentdefinition.md +80 -0
  90. package/docs/reference/authoring-surface/type-agentlogic.md +15 -0
  91. package/docs/reference/authoring-surface/type-agentslots.md +15 -0
  92. package/docs/reference/authoring-surface/type-answeraction.md +12 -0
  93. package/docs/reference/authoring-surface/type-anyframepath.md +14 -0
  94. package/docs/reference/authoring-surface/type-anyworktreepath.md +15 -0
  95. package/docs/reference/authoring-surface/type-arg.md +19 -0
  96. package/docs/reference/authoring-surface/type-argnames.md +12 -0
  97. package/docs/reference/authoring-surface/type-bindactors.md +14 -0
  98. package/docs/reference/authoring-surface/type-binding.md +61 -0
  99. package/docs/reference/authoring-surface/type-bindingof.md +12 -0
  100. package/docs/reference/authoring-surface/type-bodyacceptsdoor.md +15 -0
  101. package/docs/reference/authoring-surface/type-bodyacceptsslots.md +17 -0
  102. package/docs/reference/authoring-surface/type-ceilings.md +41 -0
  103. package/docs/reference/authoring-surface/type-chainlink.md +19 -0
  104. package/docs/reference/authoring-surface/type-chartaction.md +46 -0
  105. package/docs/reference/authoring-surface/type-chartagent.md +28 -0
  106. package/docs/reference/authoring-surface/type-chartevent.md +20 -0
  107. package/docs/reference/authoring-surface/type-chartguard.md +20 -0
  108. package/docs/reference/authoring-surface/type-chartinvoke.md +28 -0
  109. package/docs/reference/authoring-surface/type-chartjson.md +14 -0
  110. package/docs/reference/authoring-surface/type-chartstate.md +46 -0
  111. package/docs/reference/authoring-surface/type-charttext.md +40 -0
  112. package/docs/reference/authoring-surface/type-charttransition.md +22 -0
  113. package/docs/reference/authoring-surface/type-charttransitions.md +14 -0
  114. package/docs/reference/authoring-surface/type-chartvalue.md +15 -0
  115. package/docs/reference/authoring-surface/type-childat.md +12 -0
  116. package/docs/reference/authoring-surface/type-childslots.md +12 -0
  117. package/docs/reference/authoring-surface/type-commandenv.md +15 -0
  118. package/docs/reference/authoring-surface/type-commandinput.md +20 -0
  119. package/docs/reference/authoring-surface/type-commandoptions.md +56 -0
  120. package/docs/reference/authoring-surface/type-commandoutput.md +122 -0
  121. package/docs/reference/authoring-surface/type-customize.md +111 -0
  122. package/docs/reference/authoring-surface/type-dispatchdefinition.md +39 -0
  123. package/docs/reference/authoring-surface/type-dispatchinput.md +14 -0
  124. package/docs/reference/authoring-surface/type-dispatchopenparts.md +14 -0
  125. package/docs/reference/authoring-surface/type-dispatchoutput.md +72 -0
  126. package/docs/reference/authoring-surface/type-doorlessinput.md +19 -0
  127. package/docs/reference/authoring-surface/type-duration.md +15 -0
  128. package/docs/reference/authoring-surface/type-effectbinding.md +93 -0
  129. package/docs/reference/authoring-surface/type-effectlogic.md +12 -0
  130. package/docs/reference/authoring-surface/type-envopenparts.md +14 -0
  131. package/docs/reference/authoring-surface/type-eventaudience.md +27 -0
  132. package/docs/reference/authoring-surface/type-eventdef.md +45 -0
  133. package/docs/reference/authoring-surface/type-eventfrom.md +16 -0
  134. package/docs/reference/authoring-surface/type-eventsemantics.md +26 -0
  135. package/docs/reference/authoring-surface/type-execoutcome.md +34 -0
  136. package/docs/reference/authoring-surface/type-failslot.md +14 -0
  137. package/docs/reference/authoring-surface/type-failure.md +19 -0
  138. package/docs/reference/authoring-surface/type-failureinput.md +20 -0
  139. package/docs/reference/authoring-surface/type-filebody.md +37 -0
  140. package/docs/reference/authoring-surface/type-framepath.md +14 -0
  141. package/docs/reference/authoring-surface/type-frominput.md +14 -0
  142. package/docs/reference/authoring-surface/type-hostinjectedinput.md +56 -0
  143. package/docs/reference/authoring-surface/type-httpdefinition.md +104 -0
  144. package/docs/reference/authoring-surface/type-httpfileinput.md +20 -0
  145. package/docs/reference/authoring-surface/type-httpinput.md +12 -0
  146. package/docs/reference/authoring-surface/type-httpmethod.md +14 -0
  147. package/docs/reference/authoring-surface/type-httpopenparts.md +12 -0
  148. package/docs/reference/authoring-surface/type-httpoutput.md +95 -0
  149. package/docs/reference/authoring-surface/type-httprequestparts.md +33 -0
  150. package/docs/reference/authoring-surface/type-jr2config.md +126 -0
  151. package/docs/reference/authoring-surface/type-lateroutcome.md +21 -0
  152. package/docs/reference/authoring-surface/type-lends.md +38 -0
  153. package/docs/reference/authoring-surface/type-logicat.md +12 -0
  154. package/docs/reference/authoring-surface/type-markedif.md +12 -0
  155. package/docs/reference/authoring-surface/type-mergedactors.md +12 -0
  156. package/docs/reference/authoring-surface/type-namedsecret.md +25 -0
  157. package/docs/reference/authoring-surface/type-namestart.md +77 -0
  158. package/docs/reference/authoring-surface/type-noslotworkspaceoptions.md +27 -0
  159. package/docs/reference/authoring-surface/type-notworktreekeys.md +12 -0
  160. package/docs/reference/authoring-surface/type-openbodydeclaration.md +40 -0
  161. package/docs/reference/authoring-surface/type-openbodylogic.md +14 -0
  162. package/docs/reference/authoring-surface/type-openbodyoutput.md +42 -0
  163. package/docs/reference/authoring-surface/type-openbodyslot.md +18 -0
  164. package/docs/reference/authoring-surface/type-opencommandinput.md +22 -0
  165. package/docs/reference/authoring-surface/type-openeffect.md +12 -0
  166. package/docs/reference/authoring-surface/type-openeffectslots.md +12 -0
  167. package/docs/reference/authoring-surface/type-openof.md +12 -0
  168. package/docs/reference/authoring-surface/type-opensecret.md +23 -0
  169. package/docs/reference/authoring-surface/type-opensecretmark.md +12 -0
  170. package/docs/reference/authoring-surface/type-permissivenoslotworkspaceoptions.md +26 -0
  171. package/docs/reference/authoring-surface/type-permissiveworkspaceoptions.md +27 -0
  172. package/docs/reference/authoring-surface/type-poolmachine.md +28 -0
  173. package/docs/reference/authoring-surface/type-poolnextinput.md +22 -0
  174. package/docs/reference/authoring-surface/type-poolspec.md +60 -0
  175. package/docs/reference/authoring-surface/type-pushinput.md +34 -0
  176. package/docs/reference/authoring-surface/type-pushoptions.md +79 -0
  177. package/docs/reference/authoring-surface/type-pushoutput.md +149 -0
  178. package/docs/reference/authoring-surface/type-pushwireoutput.md +12 -0
  179. package/docs/reference/authoring-surface/type-quantity.md +14 -0
  180. package/docs/reference/authoring-surface/type-reached.md +12 -0
  181. package/docs/reference/authoring-surface/type-reposlot.md +70 -0
  182. package/docs/reference/authoring-surface/type-reposlotsof.md +16 -0
  183. package/docs/reference/authoring-surface/type-sandboxoptions.md +84 -0
  184. package/docs/reference/authoring-surface/type-secret.md +25 -0
  185. package/docs/reference/authoring-surface/type-sender.md +19 -0
  186. package/docs/reference/authoring-surface/type-sentbyguards.md +12 -0
  187. package/docs/reference/authoring-surface/type-size.md +85 -0
  188. package/docs/reference/authoring-surface/type-slothandles.md +24 -0
  189. package/docs/reference/authoring-surface/type-sourcenextresult.md +17 -0
  190. package/docs/reference/authoring-surface/type-sourcespec.md +44 -0
  191. package/docs/reference/authoring-surface/type-syncstate.md +12 -0
  192. package/docs/reference/authoring-surface/type-text.md +19 -0
  193. package/docs/reference/authoring-surface/type-textpart.md +24 -0
  194. package/docs/reference/authoring-surface/type-thinkinglevel.md +39 -0
  195. package/docs/reference/authoring-surface/type-toparameterizedobject.md +14 -0
  196. package/docs/reference/authoring-surface/type-toprovidedactor.md +14 -0
  197. package/docs/reference/authoring-surface/type-unknown.md +21 -0
  198. package/docs/reference/authoring-surface/type-usercontainer.md +77 -0
  199. package/docs/reference/authoring-surface/type-withoutemptyindex.md +20 -0
  200. package/docs/reference/authoring-surface/type-workflowevent.md +46 -0
  201. package/docs/reference/authoring-surface/type-workspaceaccess.md +16 -0
  202. package/docs/reference/authoring-surface/type-workspaced.md +115 -0
  203. package/docs/reference/authoring-surface/type-workspacehandles.md +22 -0
  204. package/docs/reference/authoring-surface/type-workspacemachine.md +29 -0
  205. package/docs/reference/authoring-surface/type-workspaceof.md +13 -0
  206. package/docs/reference/authoring-surface/type-workspaceoptions.md +27 -0
  207. package/docs/reference/authoring-surface/type-worktreefound.md +16 -0
  208. package/docs/reference/authoring-surface/type-worktreeinput.md +56 -0
  209. package/docs/reference/authoring-surface/type-worktreekey.md +14 -0
  210. package/docs/reference/authoring-surface/type-worktreeoptions.md +29 -0
  211. package/docs/reference/authoring-surface/type-worktreeoutput.md +45 -0
  212. package/docs/reference/authoring-surface/type-worktreepath.md +16 -0
  213. package/docs/reference/authoring-surface/type-worktreeready.md +37 -0
  214. package/docs/reference/authoring-surface/type-worktreerefused.md +21 -0
  215. package/docs/reference/authoring-surface/workspace.md +287 -0
  216. package/docs/reference/authoring-surface/worktree.md +71 -0
  217. package/docs/reference/authoring-surface.md +217 -0
  218. package/docs/reference/cli.md +433 -0
  219. package/docs/reference/config.md +765 -0
  220. package/docs/reference/decisions/0001-operator-owned-generic-sandbox.md +114 -0
  221. package/docs/reference/decisions/0002-duplex-streaming-actor.md +117 -0
  222. package/docs/reference/decisions/0004-worktree-provisioning-model.md +130 -0
  223. package/docs/reference/decisions/0005-sandbox-pod-composition.md +240 -0
  224. package/docs/reference/decisions/0006-agent-control-surface.md +50 -0
  225. package/docs/reference/decisions/0007-durable-machine-state.md +109 -0
  226. package/docs/reference/decisions/0008-orchestrator-as-deployed-app.md +60 -0
  227. package/docs/reference/decisions/0009-cli-and-instance-interface.md +275 -0
  228. package/docs/reference/decisions/0010-bdd-acceptance-tests.md +160 -0
  229. package/docs/reference/decisions/0011-workflow-defined-events.md +141 -0
  230. package/docs/reference/decisions/0012-workspace-wrapper-machine.md +103 -0
  231. package/docs/reference/decisions/0013-the-agent-reaches-its-machine-through-a-container-it-cannot-read.md +175 -0
  232. package/docs/reference/decisions/0014-observation-is-open-run-state-is-not.md +95 -0
  233. package/docs/reference/decisions/0015-authoring-surface-absorbs-the-mechanism.md +271 -0
  234. package/docs/reference/decisions/0016-agent-turn-mechanics-are-internal.md +126 -0
  235. package/docs/reference/decisions/0017-pool-over-a-source-port.md +71 -0
  236. package/docs/reference/decisions/0018-instance-agents-are-definitions-jr2-assembles-the-harness.md +111 -0
  237. package/docs/reference/decisions/0019-one-converging-command-against-the-current-context.md +287 -0
  238. package/docs/reference/decisions/0020-private-ca-trust-is-a-named-concept.md +60 -0
  239. package/docs/reference/decisions/0021-workspace-continuity-is-a-lease-that-answers-back.md +101 -0
  240. package/docs/reference/decisions/0022-observation-is-a-level-triggered-feed.md +103 -0
  241. package/docs/reference/decisions/0023-the-harness-prints-the-conversation.md +175 -0
  242. package/docs/reference/decisions/0024-an-agents-turn-ends-with-the-state-that-asked-for-it.md +436 -0
  243. package/docs/reference/decisions/0025-cancel-ends-a-run-stop-parks-it.md +65 -0
  244. package/docs/reference/decisions/0026-a-turn-that-is-over-is-never-prompted.md +62 -0
  245. package/docs/reference/decisions/0027-the-harness-is-jr2s-own-server-flue-retires-the-wire-stays.md +245 -0
  246. package/docs/reference/decisions/0028-what-an-agent-may-do-to-the-workspace-is-part-of-its-definition.md +90 -0
  247. package/docs/reference/decisions/0029-a-menu-is-fixed-for-a-conversation-and-a-turn-is-told-its-allowed-picks.md +154 -0
  248. package/docs/reference/decisions/0030-a-snapshot-names-the-machine-it-was-written-under.md +100 -0
  249. package/docs/reference/decisions/0031-menu-only-agents-run-on-the-instance-harness.md +193 -0
  250. package/docs/reference/decisions/0032-the-console-unlocks-with-the-instance-token.md +61 -0
  251. package/docs/reference/decisions/0033-a-machine-declares-the-input-that-starts-it.md +126 -0
  252. package/docs/reference/decisions/0034-the-console-renders-with-preact-and-the-server-erases-the-types.md +57 -0
  253. package/docs/reference/decisions/0035-a-runaway-turn-is-ended-rerolled-once-then-a-fault.md +92 -0
  254. package/docs/reference/decisions/0036-a-turn-compacts-its-own-context-mid-flight.md +138 -0
  255. package/docs/reference/decisions/0037-an-instance-builds-its-sandbox-images-jr2-injects-the-harness.md +196 -0
  256. package/docs/reference/decisions/0038-jr2-up-builds-every-image-it-deploys.md +170 -0
  257. package/docs/reference/decisions/0039-image-garbage-collects-by-reachability.md +115 -0
  258. package/docs/reference/decisions/0041-a-build-the-host-already-holds-is-not-spent-again.md +64 -0
  259. package/docs/reference/decisions/0042-ready-is-not-routable-an-admission-retries-its-connection.md +142 -0
  260. package/docs/reference/decisions/0043-the-kit-is-tested-as-installed-a-local-registry-stands-in-for-npm.md +170 -0
  261. package/docs/reference/decisions/0044-kit-images-live-at-a-canonical-home-a-self-host-mirrors-it.md +85 -0
  262. package/docs/reference/decisions/0045-the-platform-joins-the-image-address-and-the-cluster-chooses-it.md +82 -0
  263. package/docs/reference/decisions/0046-a-converge-failure-carries-its-diagnosis.md +34 -0
  264. package/docs/reference/decisions/0047-the-git-ssh-key-source-is-the-users-choice.md +47 -0
  265. package/docs/reference/decisions/0048-the-orchestrator-boots-without-its-repos.md +36 -0
  266. package/docs/reference/decisions/0049-a-machine-carries-its-parts-and-composes-by-invoke.md +126 -0
  267. package/docs/reference/decisions/0050-what-code-names-config-declares-what-the-cli-names-discovery-finds.md +73 -0
  268. package/docs/reference/decisions/0051-a-repo-is-a-slot-on-the-workspace-and-a-cache-on-the-node.md +238 -0
  269. package/docs/reference/decisions/0052-a-sandbox-lands-where-an-ordinary-pod-lands-and-the-cache-follows-it.md +86 -0
  270. package/docs/reference/decisions/0053-a-fetch-inside-the-pod-asks-the-node-cache-and-the-cache-asks-the-remote.md +123 -0
  271. package/docs/reference/decisions/0054-the-kit-ships-machines-and-a-shipped-machine-leaves-its-parts-open.md +126 -0
  272. package/docs/reference/decisions/0055-a-release-is-a-pushed-tag-and-the-publish-guard-is-the-credential.md +107 -0
  273. package/docs/reference/decisions/0056-a-global-jr2-hands-off-to-the-instances-own-and-an-instance-has-one-kit-version.md +62 -0
  274. package/docs/reference/decisions/0057-a-turn-is-its-frame-its-dials-and-whether-it-continues.md +152 -0
  275. package/docs/reference/decisions/0058-a-harness-answers-the-orchestrator-alone.md +108 -0
  276. package/docs/reference/decisions/0059-a-harness-holds-stand-ins-and-the-custodian-holds-the-keys.md +427 -0
  277. package/docs/reference/decisions/0060-a-workspace-states-its-size-and-jr2-reserves-all-of-it.md +111 -0
  278. package/docs/reference/decisions/0061-a-memory-kill-ends-the-agents-processes-not-the-harness.md +83 -0
  279. package/docs/reference/decisions/0062-jr2-briefs-the-agent-on-its-seat-never-on-its-task.md +239 -0
  280. package/docs/reference/decisions/0063-the-orchestrator-watches-the-cluster.md +82 -0
  281. package/docs/reference/decisions/0064-a-workspace-waits-for-capacity.md +79 -0
  282. package/docs/reference/decisions/0065-a-persist-survives-a-crash-and-history-is-a-week.md +65 -0
  283. package/docs/reference/decisions/0066-a-model-tier-runs-a-real-model-and-a-change-to-what-it-reads-runs-the-tier.md +552 -0
  284. package/docs/reference/decisions/0067-an-effect-is-an-actor-slot-and-runs-at-most-once-unless-marked-idempotent.md +458 -0
  285. package/docs/reference/decisions/0068-an-effector-holds-an-effects-secrets-and-signs-its-wire.md +475 -0
  286. package/docs/reference/decisions/0069-the-orchestrator-is-a-kit-image-and-an-instance-publishes-its-assembly.md +180 -0
  287. package/docs/reference/decisions/0070-a-machine-lends-its-parts-to-a-chart.md +334 -0
  288. package/docs/reference/decisions/0071-a-run-starts-a-run-through-a-dispatch-effect.md +183 -0
  289. package/docs/reference/decisions/0072-the-docs-ship-inside-the-kit-and-an-instances-agents-md-indexes-them.md +144 -0
  290. package/docs/reference/decisions/0073-a-machine-fails-a-run-with-fail-and-an-uncaught-failure-ends-it-failed.md +122 -0
  291. package/docs/reference/decisions/0074-an-unrouted-mechanism-event-is-refused-at-load-and-faults-the-run.md +76 -0
  292. package/docs/reference/decisions/0075-a-machine-cuts-a-worktree-and-the-workspace-only-clones.md +295 -0
  293. package/docs/reference/decisions/0076-an-agents-control-credential-lives-only-where-no-workspace-code-runs.md +320 -0
  294. package/docs/reference/decisions/0077-jr2-requires-landlock-on-every-sandbox-node.md +79 -0
  295. package/docs/reference/decisions.md +86 -0
  296. package/docs/reference/glossary.md +687 -0
  297. package/docs/reference/http-api.md +1386 -0
  298. package/docs/reference/machines.md +189 -0
  299. package/docs/reference/mechanism-events.md +72 -0
  300. package/docs/why.md +207 -0
  301. package/package.json +5 -3
  302. package/src/actor.ts +694 -106
  303. package/src/agent.ts +114 -38
  304. package/src/ambient.ts +3 -4
  305. package/src/assembly-checks.ts +189 -7
  306. package/src/cause.ts +234 -0
  307. package/src/chart.ts +345 -46
  308. package/src/charts.ts +43 -8
  309. package/src/config.ts +440 -178
  310. package/src/custodian.lua +17 -5
  311. package/src/custodian.ts +325 -99
  312. package/src/customize.ts +199 -49
  313. package/src/dispatch-effect.ts +945 -0
  314. package/src/door-compat.ts +217 -0
  315. package/src/durability.ts +11 -4
  316. package/src/effect-checks.ts +50 -3
  317. package/src/effect.ts +641 -128
  318. package/src/effector-wire.ts +165 -13
  319. package/src/fail.ts +222 -0
  320. package/src/harness-client.ts +587 -50
  321. package/src/harness-env.ts +33 -0
  322. package/src/held-secrets.ts +125 -16
  323. package/src/holds.ts +3 -0
  324. package/src/http-effect.ts +556 -58
  325. package/src/http.ts +480 -30
  326. package/src/index.ts +74 -82
  327. package/src/instance.ts +68 -8
  328. package/src/internal.ts +85 -0
  329. package/src/kube-client.ts +6 -3
  330. package/src/machine-doc.ts +24 -7
  331. package/src/mechanism-routes.ts +168 -0
  332. package/src/model-keys.generated.ts +53 -0
  333. package/src/model-keys.ts +42 -58
  334. package/src/names.ts +19 -6
  335. package/src/notices.ts +483 -41
  336. package/src/open-body.ts +242 -40
  337. package/src/open-effect.ts +81 -8
  338. package/src/open.ts +90 -6
  339. package/src/parts.ts +213 -30
  340. package/src/party.ts +101 -2
  341. package/src/pick.ts +497 -11
  342. package/src/pool.ts +282 -50
  343. package/src/registration.ts +133 -12
  344. package/src/repo-identity.ts +7 -3
  345. package/src/repos.ts +22 -3
  346. package/src/run-host.ts +665 -45
  347. package/src/run-output.ts +38 -0
  348. package/src/sandbox-effect.ts +457 -71
  349. package/src/sandbox-kube.ts +66 -17
  350. package/src/secret-placement.ts +59 -17
  351. package/src/server.ts +3 -0
  352. package/src/setup.ts +325 -62
  353. package/src/size.ts +121 -9
  354. package/src/snapshot-store.ts +54 -10
  355. package/src/stub-harness.ts +44 -16
  356. package/src/timers.ts +14 -1
  357. package/src/tokens.ts +107 -32
  358. package/src/vocabulary.ts +88 -14
  359. package/src/wire.ts +100 -26
  360. package/src/workspace.ts +771 -238
  361. package/src/worktree.ts +249 -0
@@ -0,0 +1,217 @@
1
+ // A dispatch's slot schema against its callee's door (ADR-0071): the comparison `jr2 up` and the
2
+ // publish door make before any run starts. A match is COMPATIBILITY, one direction: every field the
3
+ // door requires is one the slot's schema always sends, with a compatible type, values and bounds,
4
+ // and every field of the slot's schema is in the door, since a plain zod door strips the rest
5
+ // silently. Equality is not asked: a slot may narrow what the door takes, never widen it.
6
+ //
7
+ // It compares within the JSON Schema subset ADR-0070 names (`PAYLOAD_KEYWORDS`, chart.ts). A schema
8
+ // that uses anything outside it (`oneOf`, `$ref`, `pattern`, `format`) is "not compared", never
9
+ // guessed at: a guess that says "ok" hides the mismatch it was asked for, and one that says
10
+ // "mismatch" refuses a publish that would run.
11
+ //
12
+ // Pure, and over two JSON Schemas only: the slot's is `z.toJSONSchema(input, { io: "output" })`
13
+ // (what the driver sends, its defaults filled), the door's is what `GET /workflows/<name>` serves (run-host.ts `inputSchema`), so a foreign door
14
+ // at another Kit version is compared by the same rules as this Assembly's own.
15
+
16
+ import { doorSchemaFaults } from "./chart.ts";
17
+
18
+ /** The comparison's answer: compatible; the faults that make it not, each naming the field; or not
19
+ * compared, with why. */
20
+ export type DoorCompat = { ok: true } | { ok: false; faults: string[] } | { ok: "not-compared"; why: string };
21
+
22
+ type Schema = Record<string, unknown>;
23
+
24
+ /**
25
+ * Is a slot's input schema compatible with a door (ADR-0071)? `door` null is a door that declares
26
+ * no input (a run of it starts with anything): every slot is compatible with it.
27
+ */
28
+ export function doorCompat(slot: unknown, door: unknown): DoorCompat {
29
+ if (door === null) return { ok: true };
30
+ slot = withoutDefaults(slot);
31
+ door = withoutDefaults(door);
32
+ for (const [whose, schema] of [
33
+ ["the slot's input schema", slot],
34
+ ["the door", door],
35
+ ] as const) {
36
+ const fault = doorSchemaFaults(schema)[0];
37
+ if (fault) {
38
+ const at = fault.path.length ? `${fault.path.map(String).join(".")}: ` : "";
39
+ return { ok: "not-compared", why: `${whose} is outside the subset jr2 compares — ${at}${fault.message}` };
40
+ }
41
+ }
42
+ const faults: string[] = [];
43
+ compareValue(slot as Schema, door as Schema, "", faults);
44
+ return faults.length ? { ok: false, faults } : { ok: true };
45
+ }
46
+
47
+ /** Compare two object schemas at `at` (a field path, "" at the root), one direction. */
48
+ function compareObject(slot: Schema, door: Schema, at: string, faults: string[]): void {
49
+ const slotProps = propsOf(slot);
50
+ const doorProps = propsOf(door);
51
+ const required = Array.isArray(door.required) ? (door.required as unknown[]).map(String) : [];
52
+ const sent = new Set(Array.isArray(slot.required) ? (slot.required as unknown[]).map(String) : []);
53
+ for (const field of required) {
54
+ if (slotProps[field] === undefined) {
55
+ faults.push(`the door requires "${join(at, field)}", which the slot's input schema does not have`);
56
+ } else if (!sent.has(field)) {
57
+ // The slot's schema is what the driver sends after its parse (`io: "output"`), so a
58
+ // defaulted field is required there: optional means a body may leave it out.
59
+ faults.push(`the door requires "${join(at, field)}", which the slot's input schema leaves optional`);
60
+ }
61
+ }
62
+ // Every field both have is compared, the door's required ones among them.
63
+ const extra = door.additionalProperties;
64
+ for (const [field, sub] of Object.entries(slotProps)) {
65
+ const name = join(at, field);
66
+ const theirs = doorProps[field];
67
+ if (theirs !== undefined) {
68
+ compareValue(sub, theirs, name, faults);
69
+ continue;
70
+ }
71
+ // A door that takes any field (`additionalProperties: {}` or `true`) keeps the slot's extra one;
72
+ // a catchall door (`additionalProperties: <schema>`) keeps it when its value fits.
73
+ if (isOpen(extra)) continue;
74
+ if (isSchema(extra)) {
75
+ compareValue(sub, extra, name, faults);
76
+ continue;
77
+ }
78
+ faults.push(
79
+ extra === false
80
+ ? `the slot's field "${name}" is not in the door, which refuses it`
81
+ : `the slot's field "${name}" is not in the door, which strips it silently`,
82
+ );
83
+ }
84
+ }
85
+
86
+ /** Compare one field's schemas: the type, the values an `enum` or a `const` allows, the bounds,
87
+ * then `items` and nested `properties`, by the same rules. A door node that states none of these
88
+ * takes any value (`z.unknown()`, `z.any()`), and every slot is compatible with it. */
89
+ function compareValue(slot: Schema, door: Schema, at: string, faults: string[]): void {
90
+ const theirs = typesOf(door);
91
+ const ours = typesOf(slot);
92
+ if (theirs !== undefined) {
93
+ if (ours === undefined) {
94
+ faults.push(`${label(at)}: the door takes ${theirs.join(" or ")}, and the slot's input schema takes any value`);
95
+ return;
96
+ }
97
+ const outside = ours.filter((t) => !theirs.includes(t) && !(t === "integer" && theirs.includes("number")));
98
+ if (outside.length) {
99
+ faults.push(`${label(at)}: the slot sends ${ours.join(" or ")}, and the door takes ${theirs.join(" or ")}`);
100
+ return;
101
+ }
102
+ }
103
+ const allowed = valuesOf(door);
104
+ const sent = valuesOf(slot);
105
+ if (allowed !== undefined) {
106
+ const list = allowed.map((v) => JSON.stringify(v)).join(", ");
107
+ if (sent === undefined) {
108
+ faults.push(`${label(at)}: the door takes only ${list}, and the slot's input schema does not narrow to them`);
109
+ } else {
110
+ const extra = sent.filter((v) => !allowed.some((a) => same(a, v)));
111
+ if (extra.length) {
112
+ faults.push(
113
+ `${label(at)}: the slot may send ${extra.map((v) => JSON.stringify(v)).join(", ")}, which the door does ` +
114
+ `not take (it takes ${list})`,
115
+ );
116
+ }
117
+ }
118
+ }
119
+ compareBounds(slot, door, at, faults);
120
+ const may = (type: string): boolean => ours === undefined || ours.includes(type);
121
+ if (isSchema(door.items) && !isOpen(door.items) && may("array")) {
122
+ compareValue(isSchema(slot.items) ? slot.items : {}, door.items, `${at}[]`, faults);
123
+ }
124
+ const objectDoor =
125
+ isSchema(door.properties) || (theirs?.includes("object") ?? false) || door.additionalProperties !== undefined;
126
+ if (objectDoor && may("object")) compareObject(slot, door, at, faults);
127
+ }
128
+
129
+ /** The bounds, one direction: the slot's range lies inside the door's, so a bound the door sets
130
+ * and the slot does not is a fault, as is a slot bound wider than the door's. */
131
+ function compareBounds(slot: Schema, door: Schema, at: string, faults: string[]): void {
132
+ const pairs: Array<[string, string | undefined, "lower" | "upper"]> = [
133
+ ["minimum", "exclusiveMinimum", "lower"],
134
+ ["maximum", "exclusiveMaximum", "upper"],
135
+ ["minLength", undefined, "lower"],
136
+ ["maxLength", undefined, "upper"],
137
+ ["minItems", undefined, "lower"],
138
+ ["maxItems", undefined, "upper"],
139
+ ];
140
+ for (const [inclusive, exclusive, side] of pairs) {
141
+ const theirs = boundOf(door, inclusive, exclusive);
142
+ if (theirs === undefined) continue;
143
+ const ours = boundOf(slot, inclusive, exclusive);
144
+ const fits =
145
+ ours !== undefined &&
146
+ (side === "lower"
147
+ ? ours.value > theirs.value || (ours.value === theirs.value && (ours.exclusive || !theirs.exclusive))
148
+ : ours.value < theirs.value || (ours.value === theirs.value && (ours.exclusive || !theirs.exclusive)));
149
+ if (fits) continue;
150
+ faults.push(
151
+ `${label(at)}: the door takes ${theirs.keyword} ${theirs.value}, and the slot's input schema ` +
152
+ (ours === undefined ? "sets no such bound" : `allows ${ours.keyword} ${ours.value}`),
153
+ );
154
+ }
155
+ }
156
+
157
+ type Bound = { value: number; exclusive: boolean; keyword: string };
158
+
159
+ /** A schema's bound on one side: the tighter of its inclusive and exclusive keyword, if any. */
160
+ function boundOf(schema: Schema, inclusive: string, exclusive: string | undefined): Bound | undefined {
161
+ const inc = typeof schema[inclusive] === "number" ? (schema[inclusive] as number) : undefined;
162
+ const exc =
163
+ exclusive !== undefined && typeof schema[exclusive] === "number" ? (schema[exclusive] as number) : undefined;
164
+ if (inc === undefined && exc === undefined) return undefined;
165
+ if (exc === undefined) return { value: inc!, exclusive: false, keyword: inclusive };
166
+ if (inc === undefined) return { value: exc, exclusive: true, keyword: exclusive! };
167
+ const lowerSide = inclusive.startsWith("min");
168
+ const excTighter = lowerSide ? exc >= inc : exc <= inc;
169
+ return excTighter
170
+ ? { value: exc, exclusive: true, keyword: exclusive! }
171
+ : { value: inc, exclusive: false, keyword: inclusive };
172
+ }
173
+
174
+ function propsOf(schema: Schema): Record<string, Schema> {
175
+ const props = schema.properties;
176
+ if (!isSchema(props)) return {};
177
+ return Object.fromEntries(Object.entries(props).filter(([, v]) => isSchema(v))) as Record<string, Schema>;
178
+ }
179
+
180
+ /** A schema's types, as a list; undefined when it states none (any value). */
181
+ function typesOf(schema: Schema): string[] | undefined {
182
+ const t = schema.type;
183
+ if (typeof t === "string") return [t];
184
+ if (Array.isArray(t)) return t.map(String);
185
+ return undefined;
186
+ }
187
+
188
+ /** The values a schema allows by `enum` or `const`; undefined when it lists none. */
189
+ function valuesOf(schema: Schema): unknown[] | undefined {
190
+ if (Array.isArray(schema.enum)) return schema.enum as unknown[];
191
+ if (Object.hasOwn(schema, "const")) return [schema.const];
192
+ return undefined;
193
+ }
194
+
195
+ /**
196
+ * The schema without its `default`s, at every depth. A default is an annotation: it changes no
197
+ * value a schema takes (a defaulted field is already optional in `io: "input"`), so leaving it out
198
+ * guesses nothing, and a door with a defaulted field — common — is compared, not skipped.
199
+ */
200
+ function withoutDefaults(schema: unknown): unknown {
201
+ if (!isSchema(schema)) return schema;
202
+ const { default: _default, ...rest } = schema;
203
+ const out: Schema = { ...rest };
204
+ // Schema nodes only: a field NAMED "default" under `properties` stays.
205
+ if (isSchema(rest.properties)) {
206
+ out.properties = Object.fromEntries(Object.entries(rest.properties).map(([k, v]) => [k, withoutDefaults(v)]));
207
+ }
208
+ if (rest.items !== undefined) out.items = withoutDefaults(rest.items);
209
+ if (rest.additionalProperties !== undefined) out.additionalProperties = withoutDefaults(rest.additionalProperties);
210
+ return out;
211
+ }
212
+
213
+ const isSchema = (v: unknown): v is Schema => typeof v === "object" && v !== null && !Array.isArray(v);
214
+ const isOpen = (v: unknown): boolean => v === true || (isSchema(v) && Object.keys(v).length === 0);
215
+ const same = (a: unknown, b: unknown): boolean => JSON.stringify(a) === JSON.stringify(b);
216
+ const join = (at: string, field: string): string => (at ? `${at}.${field}` : field);
217
+ const label = (at: string): string => (at ? `"${at}"` : "the body");
package/src/durability.ts CHANGED
@@ -84,13 +84,13 @@ export function hydrateSnapshot(
84
84
  * twin of `AgentAdmission` — kept import-free so this codec module stays a pure leaf.
85
85
  * `instanceId` is the actor's live-conversation stamp (a runaway reroll advances it past the
86
86
  * ledger key — ADR-0035); it rides the rewrite verbatim so the restored actor re-addresses the
87
- * live conversation. */
88
- type Admission = { streamUrl: string; offset: string; submissionId: string; instanceId?: string };
87
+ * live conversation. `turnId` is the Turn that ledgered it (see `reattachAgentRuns`). */
88
+ type Admission = { streamUrl: string; offset: string; submissionId: string; instanceId?: string; turnId?: string };
89
89
 
90
90
  /** A persisted Agent child input: `instanceId` (the durable handle) beside `agentName` —
91
91
  * both strings by construction (machine children carry neither at top level; `endpoint` can no
92
92
  * longer identify it, being ambient-optional since ADR-0016). */
93
- function isAgentRunInput(input: unknown): input is { instanceId: string; agentName: string } {
93
+ function isAgentRunInput(input: unknown): input is { instanceId: string; agentName: string; turnId?: string } {
94
94
  return (
95
95
  !!input &&
96
96
  typeof input === "object" &&
@@ -107,6 +107,12 @@ function isAgentRunInput(input: unknown): input is { instanceId: string; agentNa
107
107
  * context leg). An instanceId with no recorded admission re-admits its prompt — a run that
108
108
  * crashed before its admission was ledgered is the same first-turn at-most-once edge as before
109
109
  * (ADR-0007), narrowed to the send→record window.
110
+ *
111
+ * The key is not the Turn: two Turns that continue one conversation share the iid, and nothing
112
+ * removes a Turn's entry when it ends. So an admission re-attaches only the Turn that ledgered it —
113
+ * its `turnId` equals the input's. A crash after the next Turn's state was saved, and before its
114
+ * admission was ledgered, finds the earlier Turn's admission under the key; that Turn is not this
115
+ * one, so the input keeps its prompt and the restore admits it.
110
116
  */
111
117
  export function reattachAgentRuns(snapshot: unknown, admissions: Record<string, Admission>): unknown {
112
118
  const walk = (node: unknown): unknown => {
@@ -114,7 +120,8 @@ export function reattachAgentRuns(snapshot: unknown, admissions: Record<string,
114
120
  const src = node as AnySnapshot & { input?: unknown };
115
121
  const out: typeof src = { ...src };
116
122
 
117
- const admission = isAgentRunInput(src.input) ? admissions[src.input.instanceId] : undefined;
123
+ const ledgered = isAgentRunInput(src.input) ? admissions[src.input.instanceId] : undefined;
124
+ const admission = isAgentRunInput(src.input) && ledgered?.turnId === src.input.turnId ? ledgered : undefined;
118
125
  if (isAgentRunInput(src.input) && admission !== undefined) {
119
126
  out.input = { ...src.input, prompt: undefined, attach: admission };
120
127
  }
@@ -27,6 +27,11 @@
27
27
  // Agent reads the Effect's output, not the answer. Everywhere else a settled child with no
28
28
  // `onDone` is Rest, and the one-line form is correct — silent on purpose.
29
29
  //
30
+ // - AN onDone WITH NO LAST ARM (ADR-0075, `refuseUnroutedOutcome`). Each Effect outcome is open,
31
+ // so an `onDone` that an output can miss holds the run in the state and shows no fault. A type
32
+ // cannot see the missing arm, so the walk refuses it. No `onDone` at all is Rest, as above: the
33
+ // author routes nothing, so no outcome can miss a route.
34
+ //
30
35
  // The probe reads, it never runs work: a mapper is called with a Proxy event whose reads are
31
36
  // recorded, and a context and self that survive any read. A guard and an assign are pure by
32
37
  // contract, and only they are probed; any other action may do work, and is never run.
@@ -34,12 +39,43 @@
34
39
  import type { AnyStateMachine, UnknownActorLogic } from "xstate";
35
40
  import type { EventDef } from "@jr2/agent-protocol";
36
41
  import { isAgent } from "./agent.ts";
37
- import { inputKeysOf, isEffect } from "./effect.ts";
42
+ import { inputKeysOf, inputShapeOf, isEffect } from "./effect.ts";
38
43
  import { mayTake, partiesAt } from "./party.ts";
39
44
  import { isAnswer, isPickMapper } from "./pick.ts";
40
45
 
41
46
  type Node = AnyStateMachine["root"];
42
47
 
48
+ /**
49
+ * Refuse a Machine with a state that invokes an Effect when the last arm of that `onDone` has a
50
+ * guard (ADR-0075). The slots are the Machine's own `actors`. Thrown at build by
51
+ * `jr2Setup.createMachine`, so also at a Chart's door, and at load by `partsOf`, so a Machine built
52
+ * with xstate's own `createMachine` is refused where `jr2 check`, `jr2 up` and the Orchestrator read
53
+ * it. Throws one line that names each state and the arm to write.
54
+ */
55
+ export function refuseUnroutedOutcome(machine: AnyStateMachine): void {
56
+ const actors = (machine.implementations.actors ?? {}) as Record<string, unknown>;
57
+ const unrouted: string[] = [];
58
+ const visit = (node: Node): void => {
59
+ for (const inv of node.invoke) {
60
+ if (typeof inv.src !== "string" || !isEffect(actors[inv.src])) continue;
61
+ const arms = node.transitions.get(`xstate.done.actor.${inv.id}`);
62
+ if (arms !== undefined && (arms.length === 0 || arms.at(-1)!.guard !== undefined)) {
63
+ unrouted.push(`"${node.id}" (Effect "${inv.src}")`);
64
+ }
65
+ }
66
+ for (const child of Object.values(node.states)) visit(child);
67
+ };
68
+ visit(machine.root);
69
+ if (!unrouted.length) return;
70
+ const many = unrouted.length > 1;
71
+ throw new Error(
72
+ `machine "${machine.id}": ${many ? "states" : "state"} ${unrouted.join(", ")} ${many ? "have" : "has"} an ` +
73
+ `onDone with no unguarded last arm — an Effect's outcomes are open, and an output that no arm matches holds ` +
74
+ `the run in that state with no fault: add a last arm with no guard, as onDone: [..., { target: "<the state ` +
75
+ `that handles the rest>" }] (ADR-0075)`,
76
+ );
77
+ }
78
+
43
79
  /** What the walk found: refusals, and warnings. */
44
80
  export type EffectFindings = { errors: string[]; warnings: string[] };
45
81
 
@@ -47,6 +83,7 @@ export function effectChecks(
47
83
  machine: AnyStateMachine,
48
84
  actors: Record<string, UnknownActorLogic>,
49
85
  defs: Map<string, EventDef>,
86
+ chart = false,
50
87
  ): EffectFindings {
51
88
  const errors: string[] = [];
52
89
  const warnings: string[] = [];
@@ -220,6 +257,15 @@ export function effectChecks(
220
257
  };
221
258
  });
222
259
  const effects = invokes.filter((inv) => inv.effect !== undefined);
260
+ // xstate's `input` is optional for an actor: a kit Effect that takes a key refuses an invoke
261
+ // with no input when `jr2Setup` or `customize()` builds the Machine.
262
+ for (const inv of effects) {
263
+ const shape = inputShapeOf(inv.effect!);
264
+ const needs = [...(shape?.required ?? []), ...(shape?.oneOf ?? [])];
265
+ if (inv.mapper === undefined && needs.length > 0) {
266
+ errors.push(`state "${n.id}": Effect "${inv.slot}" has no \`input\`, and it takes ${needs.join(", ")}`);
267
+ }
268
+ }
223
269
  if (!effects.length) continue;
224
270
  const at = `state "${n.id}" (Effect${effects.length > 1 ? "s" : ""} ${effects.map((e) => `"${e.slot}"`).join(", ")})`;
225
271
  for (const [event, { pick, ...reads }] of entering.get(n) ?? []) {
@@ -276,7 +322,8 @@ export function effectChecks(
276
322
  });
277
323
  } catch (err) {
278
324
  probed = false;
279
- warnings.push(`${own}: could not probe the input mapper (${messageOf(err)}); its params are unchecked`);
325
+ if (!chart)
326
+ warnings.push(`${own}: could not probe the input mapper (${messageOf(err)}); its params are unchecked`);
280
327
  }
281
328
  }
282
329
  }
@@ -289,7 +336,7 @@ export function effectChecks(
289
336
  const picked = effects.filter((e) => isPickMapper(e.mapper));
290
337
  if (probed && lost.length && probe.unrun.length) {
291
338
  // Any other action may do work, so the probe never runs one; it may read the param.
292
- warnings.push(unrunWarning(where, lost, probe.unrun));
339
+ if (!chart) warnings.push(unrunWarning(where, lost, probe.unrun));
293
340
  } else if (probed && lost.length && picked.length) {
294
341
  const inputs =
295
342
  picked.length === 1