@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
@@ -43,7 +43,7 @@
43
43
  // containers:
44
44
  //
45
45
  // volume runtime the kit's Harness image, as an `image` volume → /opt/jr2
46
- // volume conversations an emptyDir → /conversations, the Harness container's alone
46
+ // volume conversations an emptyDir → /run/jr2/conversations, the Harness container's alone
47
47
  // (ADR-0031: a Harness restart inside the pod keeps its conversations)
48
48
  // initContainer preflight the USER'S image + that volume → ADR-0037's probe, the thing that
49
49
  // proves a registry ref, whose first appearance is this provision
@@ -83,11 +83,14 @@ import {
83
83
  custodianBootstrap,
84
84
  custodianComposition,
85
85
  custodianScript,
86
+ CREDENTIAL_KEYS,
87
+ heldStandInKey,
86
88
  CUSTODIAN_BOOTSTRAP_KEY,
87
89
  CUSTODIAN_SCRIPT_KEY,
88
90
  type CustodianComposition,
89
91
  } from "./custodian.ts";
90
- import { readHeldManifest, workspaceHeldPod, type HeldManifest } from "./held-secrets.ts";
92
+ import { heldStandIn, readHeldManifest, workspaceHeldPod, type HeldManifest } from "./held-secrets.ts";
93
+ import { markHarnessEnv } from "./harness-env.ts";
91
94
  import {
92
95
  effectorManifestKey,
93
96
  readSandboxEffectorManifest,
@@ -133,10 +136,14 @@ import {
133
136
  type SandboxObject,
134
137
  type SandboxWatch,
135
138
  } from "./sandbox-watch.ts";
136
- import { effectorKey, harnessToken, harnessTokenDigest, sandboxToken } from "./tokens.ts";
139
+ import { controlStandIn, controlToken, effectorKey, harnessToken, harnessTokenDigest, sandboxToken } from "./tokens.ts";
137
140
  import type { AttachError, AttachRequest, AttachResponse } from "./wire.ts";
138
141
  import type { Continuity, MemoryKill, PlacingWait, ProvisionedRepo, SandboxLoss, SandboxPort } from "./workspace.ts";
139
142
 
143
+ /** A Secret's `data`: each value base64'd. */
144
+ const base64Values = (values: Record<string, string>): Record<string, string> =>
145
+ Object.fromEntries(Object.entries(values).map(([k, v]) => [k, Buffer.from(v).toString("base64")]));
146
+
140
147
  /** Where jr2's runtime lands in every container that gets it (ADR-0037). `/opt/jr2` and not `/app`
141
148
  * because a stranger's base may already use `/app`, and one layout must serve both the stock
142
149
  * Harness image and an arbitrary Sandbox Image. It is a PUBLISHED surface: `bin/` beside `lib/`
@@ -156,11 +163,21 @@ const RUNTIME_VOLUME_MOUNT = { name: RUNTIME_VOLUME, mountPath: RUNTIME_MOUNT, s
156
163
  /** The primary container's command (ADR-0037). Absolute, so it never depends on the image's
157
164
  * `WORKDIR`, and identical to the stock Harness image's own `CMD` — one runtime, two placements.
158
165
  * `tini` is PID 1 (ADR-0061): the Agent's processes are the Harness's children, and a tree the
159
- * memory guard kills must leave no zombies behind. */
166
+ * memory guard kills must leave no zombies behind. The Harness holds the Stand-ins in its memory,
167
+ * and below Landlock ABI 6 a confined child can still signal it (ADR-0076): `effector nocore`
168
+ * starts it with no core file, so a dumping signal writes nothing a child reads, and
169
+ * `--disable-sigusr1` keeps SIGUSR1 from opening Node's inspector, which would run a child's code
170
+ * in the Harness. `--harness-env` gives the Harness process only the names jr2 composed, less each
171
+ * name that loads code from a path, and the domain the whole start env (`harness-env.ts`). */
160
172
  const HARNESS_COMMAND = [
161
173
  `${RUNTIME_MOUNT}/bin/tini`,
162
174
  "--",
175
+ `${RUNTIME_MOUNT}/bin/effector`,
176
+ "nocore",
177
+ "--harness-env",
178
+ "--",
163
179
  `${RUNTIME_MOUNT}/bin/node`,
180
+ "--disable-sigusr1",
164
181
  `${RUNTIME_MOUNT}/src/main.ts`,
165
182
  ];
166
183
 
@@ -834,8 +851,14 @@ export function kubeSandbox(opts: KubeSandboxOptions = {}): SandboxPort {
834
851
  // Never empty: the Custodian's address is unconditional. The seat's own vars (the fallback
835
852
  // `HOME`) come FIRST, so the instance's `harness.env` can still override them the way it
836
853
  // overrides anything the image set.
837
- env: [...seat.env, ...harnessEnv(req.name, custodian, cpuHintEnv())],
838
- ...(cfg().envFrom?.length ? { envFrom: cfg().envFrom } : {}),
854
+ // Marked (`harness-env.ts`, ADR-0076): the Harness's start tells jr2's names from the image's.
855
+ ...(() => {
856
+ const marked = markHarnessEnv(
857
+ [...seat.env, ...harnessEnv(req.name, custodian, cpuHintEnv())],
858
+ cfg().envFrom ?? [],
859
+ );
860
+ return { env: marked.env, ...(marked.envFrom.length ? { envFrom: marked.envFrom } : {}) };
861
+ })(),
839
862
  // What the AGENT gets: an address on its own loopback and a Stand-in for every credential,
840
863
  // and no credential anywhere. The Custodian beside it holds them (ADR-0013, ADR-0059).
841
864
  sidecars,
@@ -902,7 +925,7 @@ export function kubeSandbox(opts: KubeSandboxOptions = {}): SandboxPort {
902
925
  * `data`, not `stringData`: a server-side apply owns the fields it names, and `stringData` is
903
926
  * write-only — it never reads back as the field applied.
904
927
  */
905
- const applyTokenSecret = async (name: string, owner: KubeObject): Promise<void> => {
928
+ const applyTokenSecret = async (name: string, owner: KubeObject, manifest: HeldManifest): Promise<void> => {
906
929
  if (!opts.signingKey) throw new Error("kubeSandbox: a Custodian needs a signingKey to mint its Sandbox token");
907
930
  const uid = owner.metadata?.uid;
908
931
  if (!uid) throw new Error(`Sandbox "${name}": the CR's apply answered with no uid to own its token Secret`);
@@ -925,7 +948,19 @@ export function kubeSandbox(opts: KubeSandboxOptions = {}): SandboxPort {
925
948
  ],
926
949
  },
927
950
  type: "Opaque",
928
- data: { JR2_SANDBOX_TOKEN: Buffer.from(sandboxToken(opts.signingKey, name)).toString("base64") },
951
+ // The pod's credentials (ADR-0076, C1, C1b): its fetch token and its control token, which the
952
+ // Custodian alone mounts; its secret control Stand-in; and one secret Stand-in per held secret
953
+ // the pod's manifest names, which the Custodian (for its swap) and the Harness container (as
954
+ // files under `/run/jr2/`) mount. Every one a signed name, so a re-provision re-applies the
955
+ // same values. Never a ConfigMap, the CR, an env, an event or a log line.
956
+ data: base64Values({
957
+ [CREDENTIAL_KEYS.fetchToken]: sandboxToken(opts.signingKey, name),
958
+ [CREDENTIAL_KEYS.controlToken]: controlToken(opts.signingKey, name),
959
+ [CREDENTIAL_KEYS.controlStandIn]: controlStandIn(opts.signingKey, name),
960
+ ...Object.fromEntries(
961
+ manifest.secrets.map((s) => [heldStandInKey(s.name), heldStandIn(opts.signingKey!, name, s.name)]),
962
+ ),
963
+ }),
929
964
  });
930
965
  };
931
966
 
@@ -1030,7 +1065,7 @@ export function kubeSandbox(opts: KubeSandboxOptions = {}): SandboxPort {
1030
1065
  },
1031
1066
  data: {
1032
1067
  [CUSTODIAN_BOOTSTRAP_KEY]: JSON.stringify(custodianBootstrap(manifest, orchestrator)),
1033
- [CUSTODIAN_SCRIPT_KEY]: custodianScript(manifest),
1068
+ [CUSTODIAN_SCRIPT_KEY]: custodianScript(manifest, { fetch: true }),
1034
1069
  },
1035
1070
  });
1036
1071
  };
@@ -1257,8 +1292,9 @@ export function kubeSandbox(opts: KubeSandboxOptions = {}): SandboxPort {
1257
1292
  image: refs.custodian,
1258
1293
  pod,
1259
1294
  config: sandboxCustodianConfigMap(req.name),
1260
- token: { secret: secretName(req.name), key: "JR2_SANDBOX_TOKEN" },
1295
+ credentials: { secret: secretName(req.name) },
1261
1296
  sandbox: req.name,
1297
+ ...(req.secrets?.length ? { granted: req.secrets } : {}),
1262
1298
  caBundle: cfg().caBundle === true,
1263
1299
  resources: split.custodian,
1264
1300
  });
@@ -1287,7 +1323,7 @@ export function kubeSandbox(opts: KubeSandboxOptions = {}): SandboxPort {
1287
1323
  sandboxes();
1288
1324
  const applied = await kube().apply(SANDBOXES, ns, cr).catch(noOperator(req.name, "Sandbox"));
1289
1325
  // After the CR: its uid owns both, so they go when it goes.
1290
- await applyTokenSecret(req.name, applied);
1326
+ await applyTokenSecret(req.name, applied, manifest);
1291
1327
  await applyCustodianConfig(req.name, applied, manifest);
1292
1328
  if (effectorManifest) {
1293
1329
  await applyEffectorKey(req.name, applied);
@@ -1394,19 +1430,19 @@ export function kubeSandbox(opts: KubeSandboxOptions = {}): SandboxPort {
1394
1430
  const endpoint = sandbox?.status?.endpoint;
1395
1431
  if (!endpoint) throw new Error(`Sandbox "${req.name}" has no endpoint to attach through — is it gone?`);
1396
1432
  if (req.repos.length === 0) {
1397
- throw new Error("the attach names no Repo Slot — nothing to attach (a workspace() declares at least one)");
1433
+ throw new Error(
1434
+ "the attach names no Repo Slot — nothing to attach (a Workspace with no Repo Slot skips the attach, ADR-0051)",
1435
+ );
1398
1436
  }
1399
1437
  const body: AttachRequest = {
1400
1438
  slots: req.repos.map((r) => {
1401
1439
  const { identity, key } = repoIdentity(r.url);
1402
1440
  return { slot: r.slot, url: r.url, identity, key, ...(r.ref !== undefined ? { ref: r.ref } : {}) };
1403
1441
  }),
1404
- branch: req.spec.branch,
1405
- ...(req.spec.reviewSha ? { reviewSha: req.spec.reviewSha } : {}),
1406
1442
  };
1407
- const { repos, review } = await postAttach(req.name, endpoint, body);
1443
+ const { repos, bases } = await postAttach(req.name, endpoint, body);
1408
1444
  const stale = staleSlots(req.repos, staleByName.get(req.name));
1409
- return { repos, ...(review ? { review } : {}), ...(stale ? { stale } : {}) };
1445
+ return { repos, bases, ...(stale ? { stale } : {}) };
1410
1446
  },
1411
1447
 
1412
1448
  leaseIntervalMs,
@@ -1456,7 +1492,20 @@ export function kubeSandbox(opts: KubeSandboxOptions = {}): SandboxPort {
1456
1492
  async destroy(name) {
1457
1493
  staleByName.delete(name);
1458
1494
  // The token Secret is the CR's child from birth, so deleting the CR reaps it (ADR-0001).
1459
- await kube().delete(SANDBOXES, ns, name);
1495
+ await kube().delete(SANDBOXES, ns, name, { foreground: true });
1496
+ // A retry of the same invoke id takes the same name, and the pod takes it too: a new Sandbox
1497
+ // must not find the old pod on its way out, and read `Lost` (ADR-0075). So the wait is
1498
+ // for the pod as well: foreground keeps the CR until the pod is gone. Bounded: a stuck finalizer
1499
+ // is the operator's to report, and the run does not wait on it for ever.
1500
+ for (let i = 0; i < 120; i++) {
1501
+ if (
1502
+ (await kube()
1503
+ .get<SandboxObject>(SANDBOXES, ns, name)
1504
+ .catch(() => undefined)) === undefined
1505
+ )
1506
+ return;
1507
+ await new Promise((resolve) => setTimeout(resolve, 500));
1508
+ }
1460
1509
  },
1461
1510
  };
1462
1511
  }
@@ -6,7 +6,8 @@
6
6
  // - the Instance Harness: the model keys of the `"none"` Agents it hosts, and nothing else (they
7
7
  // cannot execute code, ADR-0031, so nothing else is theirs to use);
8
8
  // - an Effector: what its Effects name with `secret("name")` — the Instance Effector what its
9
- // `http` Effects name; a Workspace's Sandbox Effector what its file-body `http`s and
9
+ // `http` Effects name and the token of each `dispatch` with a target (ADR-0071; a dispatch with
10
+ // no target runs in the Orchestrator's own process and names nothing); a Workspace's Sandbox Effector what its file-body `http`s and
10
11
  // credentialed `command`s name. The push credential its `push`es spend is not placed here: the provision
11
12
  // names the entry the slot's url matches on the Sandbox, by reference (git-push.ts, ADR-0051).
12
13
  //
@@ -27,6 +28,7 @@ import {
27
28
  type HeldLookups,
28
29
  } from "./held-secrets.ts";
29
30
  import type { JR2Config } from "./config.ts";
31
+ import { needsASlot } from "./effect.ts";
30
32
  import { declaredPushKinds, pushRefusal } from "./git-push.ts";
31
33
  import { INSTANCE_HARNESS_HELD_POD } from "./names.ts";
32
34
  import { routeText, type CarriedEffect, type WorkspacePod } from "./parts.ts";
@@ -140,7 +142,36 @@ export function refuseEffectSecrets(config: JR2Config, walk: PlacementWalk): voi
140
142
  // An empty value is refused later with the list's own rule (`sourceOf`): it is an unset variable.
141
143
  if (namedBy.has(e.name) && e.value) shortRefusal(e, e.value.length);
142
144
  }
143
- for (const ws of walk.workspaces) pushesOf(config, ws);
145
+ for (const ws of walk.workspaces) {
146
+ refuseWithNoSlot(ws);
147
+ pushesOf(config, ws);
148
+ }
149
+ }
150
+
151
+ /**
152
+ * A Workspace with no Repo Slot (ADR-0051) has no branch and no commit, so the two Sandbox Effector kinds that
153
+ * run on a commit of a slot's branch have none: a `push`, and a `command` with an Effect secret
154
+ * (ADR-0067). A `worktree()` has no clone to cut from (ADR-0075). Refused here, before anything is
155
+ * built, as the invoke would refuse them mid-run. A file-body `http` reads `/work` and stays.
156
+ */
157
+ function refuseWithNoSlot(ws: PlacedWorkspace): void {
158
+ if (!ws.pod.noSlot) return;
159
+ for (const effect of ws.pod.effects) {
160
+ // Every `command` placed in a Sandbox Effector names a secret: the others run beside the Agent.
161
+ const why = needsASlot(effect.kind);
162
+ if (why === undefined) continue;
163
+ throw new Error(
164
+ `workflow "${ws.workflow}": ${effect.kind} "${effect.name}" runs in ${workspaceLabel(ws)}, which has no Repo ` +
165
+ `Slot: ${why} (ADR-0051)`,
166
+ );
167
+ }
168
+ const [cut] = ws.pod.cuts ?? [];
169
+ if (cut !== undefined) {
170
+ throw new Error(
171
+ `workflow "${ws.workflow}": worktree "${cut}" runs in ${workspaceLabel(ws)}, which has no Repo Slot: ` +
172
+ `${needsASlot("worktree")} (ADR-0075)`,
173
+ );
174
+ }
144
175
  }
145
176
 
146
177
  /**
@@ -153,7 +184,7 @@ export function secretPlacementsOf(
153
184
  walk: PlacementWalk,
154
185
  lookups: Pick<HeldLookups, "secretKeys" | "valueLength"> = {},
155
186
  ): SecretPlacements {
156
- const { entries, namedBy, http } = namesOf(config, walk);
187
+ const { entries, namedBy, instancePlaced } = namesOf(config, walk);
157
188
  const { pods, redundant } = heldPodsOf(config, walk, new Set(entries.map((e) => e.name)));
158
189
  const claimed = new Set(pods.flatMap((p) => p.names));
159
190
 
@@ -207,12 +238,12 @@ export function secretPlacementsOf(
207
238
  report.push(`${label}: secrets lists ${name}, which its Agents' provider claims already — redundant`);
208
239
  }
209
240
 
210
- const instanceSecrets = new Set(http.flatMap((p) => p.effect.secrets));
241
+ const instanceSecrets = new Set(instancePlaced.flatMap((p) => p.effect.secrets));
211
242
  const instance =
212
- http.length === 0
243
+ instancePlaced.length === 0
213
244
  ? undefined
214
245
  : effectorPlan(
215
- http,
246
+ instancePlaced,
216
247
  secrets.filter((s) => instanceSecrets.has(s.name)),
217
248
  values,
218
249
  );
@@ -267,6 +298,7 @@ function sandboxPlanOf(
267
298
  x.scheme === t.scheme && x.host === t.host && x.port === t.port && x.secrets.join() === t.secrets.join();
268
299
  if (!targets.some(same)) targets.push(t);
269
300
  }
301
+ refuseWithNoSlot(ws);
270
302
  const pushes = pushesOf(config, ws);
271
303
  const commands = ws.pod.effects.some((e) => e.kind === "command" && (e.secrets?.length ?? 0) > 0);
272
304
  return {
@@ -322,10 +354,12 @@ function pushesOf(config: JR2Config, ws: PlacedWorkspace): SandboxPush[] {
322
354
  return out;
323
355
  }
324
356
 
325
- function effectorPlan(http: HttpPlaced[], secrets: EffectSecret[], values: Record<string, string>): EffectorPlan {
357
+ function effectorPlan(placed: InstancePlaced[], secrets: EffectSecret[], values: Record<string, string>): EffectorPlan {
326
358
  const targets: EffectorTargetConfig[] = [];
327
- for (const { effect } of http) {
328
- // An Open url has no target, so it allows nothing: `jr2 up` refuses it before this (ADR-0054).
359
+ for (const { effect } of placed) {
360
+ // An Open url or an Open dispatch target has no target, so it allows nothing: `jr2 up` refuses
361
+ // it before this (ADR-0054). A dispatch's target is its origin, its one secret the token
362
+ // (ADR-0071).
329
363
  if (effect.target === undefined) continue;
330
364
  const t = { ...effect.target, secrets: [...effect.secrets].sort() };
331
365
  const same = (x: EffectorTargetConfig) =>
@@ -337,12 +371,17 @@ function effectorPlan(http: HttpPlaced[], secrets: EffectSecret[], values: Recor
337
371
  secrets,
338
372
  values,
339
373
  targets,
340
- longestTimeoutMs: Math.max(...http.map((p) => p.effect.timeoutMs)),
341
- effects: http.map((p) => `${p.workflow}/${p.effect.name}`),
374
+ // The grace a rollout gives a replica covers the http Effects alone (ADR-0071): a dispatch is
375
+ // idempotent by construction, so a `wait` a rollout cuts is sent again under its key and its
376
+ // poll resumes, and a wait of hours never stretches the Effector's grace.
377
+ longestTimeoutMs: Math.max(0, ...placed.flatMap((p) => (p.effect.kind === "http" ? [p.effect.timeoutMs] : []))),
378
+ effects: placed.map((p) => `${p.workflow}/${p.effect.name}`),
342
379
  };
343
380
  }
344
381
 
345
- type HttpPlaced = { workflow: string; effect: Extract<CarriedEffect, { method: string }> };
382
+ /** An Effect the Instance Effector runs: an http one with no Worktree file, or a dispatch with a
383
+ * target (ADR-0068, ADR-0071). */
384
+ type InstancePlaced = { workflow: string; effect: Extract<CarriedEffect, { kind: "http" | "dispatch" }> };
346
385
 
347
386
  /** A Workspace as a human reads it: its workflow and the placement route to it, an inline hop as
348
387
  * `invoked inline in state <id>`. */
@@ -423,11 +462,14 @@ function namesOf(config: JR2Config, walk: PlacementWalk) {
423
462
  }
424
463
  byName.set(e.name, e);
425
464
  }
426
- // Every Effect that names a secret names it, whatever its kind: an `http` one in the Instance
427
- // Effector, a file-body `http` and a credentialed `command` in their Workspace's Sandbox Effector.
465
+ // Every Effect that names a secret names it, whatever its kind: an `http` one and a `dispatch`'s
466
+ // token in the Instance Effector, a file-body `http` and a credentialed `command` in their
467
+ // Workspace's Sandbox Effector. A dispatch with no target is placed "orchestrator" and names none
468
+ // (ADR-0071).
428
469
  const namedBy = new Map<string, Array<{ label: string; where: string }>>();
429
- const http = walk.effects.filter(
430
- (p): p is HttpPlaced => p.effect.kind === "http" && p.effect.placement === "instance",
470
+ const instancePlaced = walk.effects.filter(
471
+ (p): p is InstancePlaced =>
472
+ (p.effect.kind === "http" || p.effect.kind === "dispatch") && p.effect.placement === "instance",
431
473
  );
432
474
  // Keyed by the Effect's placement route and slot name, as workspacePodsOf keys a pod's Effects:
433
475
  // two slots of one name in one workflow — one in a workspace(), one outside it — are two Effects,
@@ -463,7 +505,7 @@ function namesOf(config: JR2Config, walk: PlacementWalk) {
463
505
  namedBy.set(name, [...(namedBy.get(name) ?? []), { label, where }]);
464
506
  }
465
507
  }
466
- return { entries, namedBy, http };
508
+ return { entries, namedBy, instancePlaced };
467
509
  }
468
510
 
469
511
  /** An Effect secret shorter than 8 characters is refused, and the refusal says why. */
package/src/server.ts CHANGED
@@ -295,6 +295,9 @@ export async function serverMain(opts: ServerMainOptions): Promise<RunningInstan
295
295
  instanceHarness: namespace
296
296
  ? `http://${INSTANCE_HARNESS_SERVICE}.${namespace}.svc:${INSTANCE_HARNESS_PORT}`
297
297
  : undefined,
298
+ // What a foreign dispatch names this Orchestrator by at the callee's door (ADR-0071): its
299
+ // namespace, which is stable and not secret — never a run's Instance ID.
300
+ ...(namespace ? { orchestratorName: namespace } : {}),
298
301
  // Where an http Effect runs (ADR-0068): the Instance Effector's headless Service. `jr2 up`
299
302
  // converges it whenever a registered Machine carries an http Effect.
300
303
  ...(namespace ? { instanceEffector: `${INSTANCE_EFFECTOR}.${namespace}.svc:${EFFECTOR_PORT}` } : {}),