@jr2/orchestrator 0.5.1 → 0.7.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 (350) hide show
  1. package/console/components/app.ts +55 -15
  2. package/console/components/bottom-drawer.ts +259 -0
  3. package/console/components/drawer.ts +14 -6
  4. package/console/components/fleet.ts +36 -13
  5. package/console/components/machine-pane.ts +61 -5
  6. package/console/components/nav.ts +54 -8
  7. package/console/conversation.ts +161 -0
  8. package/console/login.ts +123 -0
  9. package/console/main.ts +600 -60
  10. package/console/store.ts +611 -64
  11. package/console/style.css +231 -0
  12. package/docs/agents-block.md +2 -2
  13. package/docs/concepts/agents-and-turns.md +142 -29
  14. package/docs/concepts/architecture.md +60 -34
  15. package/docs/concepts/callers-and-hooks.md +205 -0
  16. package/docs/concepts/charts.md +13 -8
  17. package/docs/concepts/composition.md +10 -1
  18. package/docs/concepts/converge.md +7 -2
  19. package/docs/concepts/durable-runs.md +43 -16
  20. package/docs/concepts/effects.md +133 -50
  21. package/docs/concepts/gates.md +95 -25
  22. package/docs/concepts/machines-and-workflows.md +14 -4
  23. package/docs/concepts/pools-and-sources.md +193 -17
  24. package/docs/concepts/secrets-and-trust.md +186 -62
  25. package/docs/concepts/the-menu.md +14 -0
  26. package/docs/concepts/workspaces.md +135 -56
  27. package/docs/get-started/a-model-decides.md +14 -13
  28. package/docs/get-started/an-agent-in-a-sandbox.md +46 -35
  29. package/docs/get-started/connect-a-model.md +1 -1
  30. package/docs/get-started/create-an-instance.md +17 -14
  31. package/docs/get-started/have-your-assistant-write-a-machine.md +111 -40
  32. package/docs/get-started/install.md +4 -0
  33. package/docs/guides/add-tools-to-the-sandbox.md +72 -15
  34. package/docs/guides/answer-a-gate-from-a-forge.md +304 -0
  35. package/docs/guides/answer-a-gate.md +74 -37
  36. package/docs/guides/bind-open-parts.md +29 -12
  37. package/docs/guides/call-an-mcp-tool-from-a-machine.md +572 -0
  38. package/docs/guides/cancel-a-run.md +26 -16
  39. package/docs/guides/cut-a-worktree.md +560 -0
  40. package/docs/guides/fix-a-failed-converge.md +19 -7
  41. package/docs/guides/give-a-caller-a-scope.md +203 -0
  42. package/docs/guides/give-an-agent-mcp-tools.md +422 -0
  43. package/docs/guides/iterate-on-a-machine-on-kind.md +10 -9
  44. package/docs/guides/let-an-agent-write-a-chart.md +14 -7
  45. package/docs/guides/look-inside-a-sandbox.md +115 -42
  46. package/docs/guides/move-from-kind-to-a-shared-cluster.md +16 -0
  47. package/docs/guides/open-the-console.md +63 -14
  48. package/docs/guides/push-and-sign-a-branch.md +67 -21
  49. package/docs/guides/read-a-conversation.md +225 -0
  50. package/docs/guides/run-a-chart-by-name.md +17 -16
  51. package/docs/guides/run-a-command-or-call-a-url.md +84 -41
  52. package/docs/guides/run-one-worker-per-item.md +34 -27
  53. package/docs/guides/set-an-agents-access-and-dials.md +69 -22
  54. package/docs/guides/size-a-workspace.md +19 -6
  55. package/docs/guides/start-a-run-for-each-alert.md +290 -0
  56. package/docs/guides/start-a-run-from-a-run.md +18 -16
  57. package/docs/guides/start-a-run.md +24 -18
  58. package/docs/guides/steer-an-agent.md +332 -0
  59. package/docs/guides/use-a-hosted-provider.md +7 -1
  60. package/docs/guides/watch-a-run.md +146 -117
  61. package/docs/guides/write-a-hook-kind.md +238 -0
  62. package/docs/guides/write-a-tool-as-an-mcp-server.md +351 -0
  63. package/docs/guides/write-a-workflow.md +18 -8
  64. package/docs/llms.txt +110 -23
  65. package/docs/reference/authoring-surface/agent.md +35 -12
  66. package/docs/reference/authoring-surface/answer.md +20 -4
  67. package/docs/reference/authoring-surface/arg.md +28 -6
  68. package/docs/reference/authoring-surface/basic.md +1 -1
  69. package/docs/reference/authoring-surface/bearer.md +1 -1
  70. package/docs/reference/authoring-surface/branchname.md +15 -0
  71. package/docs/reference/authoring-surface/carry.md +23 -0
  72. package/docs/reference/authoring-surface/chartschema.md +1 -1
  73. package/docs/reference/authoring-surface/chartschemafor.md +1 -1
  74. package/docs/reference/authoring-surface/command.md +37 -22
  75. package/docs/reference/authoring-surface/customize.md +4 -1
  76. package/docs/reference/authoring-surface/defineconfig.md +1 -1
  77. package/docs/reference/authoring-surface/defineevent.md +1 -1
  78. package/docs/reference/authoring-surface/dispatch.md +5 -4
  79. package/docs/reference/authoring-surface/fail.md +18 -5
  80. package/docs/reference/authoring-surface/file.md +37 -17
  81. package/docs/reference/authoring-surface/frompick.md +1 -1
  82. package/docs/reference/authoring-surface/gate.md +118 -0
  83. package/docs/reference/authoring-surface/group-agents.md +15 -0
  84. package/docs/reference/authoring-surface/group-charts.md +16 -0
  85. package/docs/reference/authoring-surface/group-composition.md +25 -0
  86. package/docs/reference/authoring-surface/group-config.md +17 -0
  87. package/docs/reference/authoring-surface/group-effects.md +48 -0
  88. package/docs/reference/authoring-surface/group-failure.md +13 -0
  89. package/docs/reference/authoring-surface/group-gates.md +16 -0
  90. package/docs/reference/authoring-surface/group-machine-and-events.md +15 -0
  91. package/docs/reference/authoring-surface/group-steering.md +12 -0
  92. package/docs/reference/authoring-surface/group-types-these-signatures-name.md +137 -0
  93. package/docs/reference/authoring-surface/group-workspaces-and-repos.md +15 -0
  94. package/docs/reference/authoring-surface/http.md +109 -9
  95. package/docs/reference/authoring-surface/isfailure.md +1 -1
  96. package/docs/reference/authoring-surface/isready.md +14 -0
  97. package/docs/reference/authoring-surface/jr2setup.md +14 -4
  98. package/docs/reference/authoring-surface/mcp.md +107 -0
  99. package/docs/reference/authoring-surface/open.md +41 -8
  100. package/docs/reference/authoring-surface/openbody.md +1 -1
  101. package/docs/reference/authoring-surface/paramsof.md +23 -5
  102. package/docs/reference/authoring-surface/pool.md +79 -11
  103. package/docs/reference/authoring-surface/push.md +31 -13
  104. package/docs/reference/authoring-surface/readyof.md +21 -0
  105. package/docs/reference/authoring-surface/reread.md +19 -0
  106. package/docs/reference/authoring-surface/secret.md +26 -5
  107. package/docs/reference/authoring-surface/sentby.md +1 -1
  108. package/docs/reference/authoring-surface/skip.md +22 -0
  109. package/docs/reference/authoring-surface/source.md +59 -4
  110. package/docs/reference/authoring-surface/steer.md +93 -0
  111. package/docs/reference/authoring-surface/text.md +1 -1
  112. package/docs/reference/authoring-surface/type-agentdefinition.md +16 -3
  113. package/docs/reference/authoring-surface/type-agentmcpserver.md +54 -0
  114. package/docs/reference/authoring-surface/type-agentslots.md +4 -1
  115. package/docs/reference/authoring-surface/type-anyframepath.md +14 -0
  116. package/docs/reference/authoring-surface/type-anyworktreepath.md +15 -0
  117. package/docs/reference/authoring-surface/type-bindactors.md +14 -0
  118. package/docs/reference/authoring-surface/type-binding.md +6 -7
  119. package/docs/reference/authoring-surface/type-caller.md +40 -0
  120. package/docs/reference/authoring-surface/type-callerrecord.md +32 -0
  121. package/docs/reference/authoring-surface/type-carry.md +19 -0
  122. package/docs/reference/authoring-surface/type-chainlink.md +3 -3
  123. package/docs/reference/authoring-surface/type-commandinput.md +4 -3
  124. package/docs/reference/authoring-surface/type-commandoptions.md +0 -22
  125. package/docs/reference/authoring-surface/type-commandoutput.md +23 -5
  126. package/docs/reference/authoring-surface/type-customize.md +20 -3
  127. package/docs/reference/authoring-surface/type-delivered.md +17 -0
  128. package/docs/reference/authoring-surface/type-deliveredevent.md +18 -0
  129. package/docs/reference/authoring-surface/type-dispatchdefinition.md +4 -3
  130. package/docs/reference/authoring-surface/type-dispatchoutput.md +9 -2
  131. package/docs/reference/authoring-surface/type-doorlessinput.md +19 -0
  132. package/docs/reference/authoring-surface/type-effectbinding.md +12 -2
  133. package/docs/reference/authoring-surface/type-filebody.md +4 -8
  134. package/docs/reference/authoring-surface/type-framepath.md +14 -0
  135. package/docs/reference/authoring-surface/type-gatebinding.md +15 -0
  136. package/docs/reference/authoring-surface/type-gatehooks.md +12 -0
  137. package/docs/reference/authoring-surface/type-gatelook.md +37 -0
  138. package/docs/reference/authoring-surface/type-gateoutcome.md +32 -0
  139. package/docs/reference/authoring-surface/type-gatereply.md +19 -0
  140. package/docs/reference/authoring-surface/type-gateslot.md +21 -0
  141. package/docs/reference/authoring-surface/type-gateslotinput.md +13 -0
  142. package/docs/reference/authoring-surface/type-gateslotparts.md +18 -0
  143. package/docs/reference/authoring-surface/type-gateslots.md +12 -0
  144. package/docs/reference/authoring-surface/type-gatetypesat.md +13 -0
  145. package/docs/reference/authoring-surface/type-hostinjectedinput.md +3 -5
  146. package/docs/reference/authoring-surface/type-httpdefinition.md +6 -3
  147. package/docs/reference/authoring-surface/type-httpfileinput.md +20 -0
  148. package/docs/reference/authoring-surface/type-httpoutput.md +8 -2
  149. package/docs/reference/authoring-surface/type-jr2config.md +37 -2
  150. package/docs/reference/authoring-surface/type-lateroutcome.md +21 -0
  151. package/docs/reference/authoring-surface/type-lends.md +5 -1
  152. package/docs/reference/authoring-surface/type-lookoutput.md +14 -0
  153. package/docs/reference/authoring-surface/type-mcpcalloutput.md +78 -0
  154. package/docs/reference/authoring-surface/type-mcpnotreturned.md +42 -0
  155. package/docs/reference/authoring-surface/type-mcpoptions.md +47 -0
  156. package/docs/reference/authoring-surface/type-mcpoutput.md +50 -0
  157. package/docs/reference/authoring-surface/type-mcpreadoutput.md +53 -0
  158. package/docs/reference/authoring-surface/type-mcpremoteserver.md +50 -0
  159. package/docs/reference/authoring-surface/type-mcpserver.md +41 -0
  160. package/docs/reference/authoring-surface/type-mcpstdioserver.md +42 -0
  161. package/docs/reference/authoring-surface/type-namedsecret.md +4 -4
  162. package/docs/reference/authoring-surface/type-namestart.md +77 -0
  163. package/docs/reference/authoring-surface/type-noslotworkspaceoptions.md +1 -6
  164. package/docs/reference/authoring-surface/type-notworktreekeys.md +12 -0
  165. package/docs/reference/authoring-surface/type-openbodydeclaration.md +1 -1
  166. package/docs/reference/authoring-surface/type-openbodyoutput.md +1 -1
  167. package/docs/reference/authoring-surface/type-opencommandinput.md +7 -2
  168. package/docs/reference/authoring-surface/type-permissivenoslotworkspaceoptions.md +1 -6
  169. package/docs/reference/authoring-surface/type-permissiveworkspaceoptions.md +5 -10
  170. package/docs/reference/authoring-surface/type-poolnextinput.md +22 -0
  171. package/docs/reference/authoring-surface/type-poolspec.md +11 -6
  172. package/docs/reference/authoring-surface/type-pushinput.md +22 -3
  173. package/docs/reference/authoring-surface/type-pushoutput.md +33 -8
  174. package/docs/reference/authoring-surface/type-pushsourcespec.md +38 -0
  175. package/docs/reference/authoring-surface/type-readsourcespec.md +47 -0
  176. package/docs/reference/authoring-surface/type-reposlot.md +6 -6
  177. package/docs/reference/authoring-surface/type-reread.md +18 -0
  178. package/docs/reference/authoring-surface/type-runsconfig.md +41 -0
  179. package/docs/reference/authoring-surface/type-sandboxoptions.md +11 -4
  180. package/docs/reference/authoring-surface/type-sender.md +26 -1
  181. package/docs/reference/authoring-surface/type-sendercallerfield.md +14 -0
  182. package/docs/reference/authoring-surface/type-size.md +1 -1
  183. package/docs/reference/authoring-surface/type-skip.md +19 -0
  184. package/docs/reference/authoring-surface/type-slothandles.md +5 -13
  185. package/docs/reference/authoring-surface/type-sourcehooks.md +23 -0
  186. package/docs/reference/authoring-surface/type-sourcein.md +25 -0
  187. package/docs/reference/authoring-surface/type-sourcereply.md +18 -0
  188. package/docs/reference/authoring-surface/type-sourcespec.md +26 -17
  189. package/docs/reference/authoring-surface/type-sourceverdict.md +49 -0
  190. package/docs/reference/authoring-surface/type-standingpoolmachine.md +12 -0
  191. package/docs/reference/authoring-surface/type-standingpoolspec.md +51 -0
  192. package/docs/reference/authoring-surface/type-steerargs.md +20 -0
  193. package/docs/reference/authoring-surface/type-thinkinglevel.md +1 -1
  194. package/docs/reference/authoring-surface/type-usercontainer.md +1 -1
  195. package/docs/reference/authoring-surface/type-workspaced.md +30 -9
  196. package/docs/reference/authoring-surface/type-workspacehandles.md +5 -6
  197. package/docs/reference/authoring-surface/type-workspaceoptions.md +1 -13
  198. package/docs/reference/authoring-surface/type-worktreefound.md +16 -0
  199. package/docs/reference/authoring-surface/type-worktreeinput.md +56 -0
  200. package/docs/reference/authoring-surface/type-worktreekey.md +14 -0
  201. package/docs/reference/authoring-surface/type-worktreeoptions.md +29 -0
  202. package/docs/reference/authoring-surface/type-worktreeoutput.md +45 -0
  203. package/docs/reference/authoring-surface/type-worktreepath.md +16 -0
  204. package/docs/reference/authoring-surface/type-worktreeready.md +37 -0
  205. package/docs/reference/authoring-surface/type-worktreerefused.md +21 -0
  206. package/docs/reference/authoring-surface/workspace.md +66 -38
  207. package/docs/reference/authoring-surface/worktree.md +71 -0
  208. package/docs/reference/authoring-surface.md +88 -147
  209. package/docs/reference/cli.md +413 -74
  210. package/docs/reference/config.md +248 -6
  211. package/docs/reference/decisions/0001-operator-owned-generic-sandbox.md +10 -9
  212. package/docs/reference/decisions/0002-duplex-streaming-actor.md +81 -14
  213. package/docs/reference/decisions/0004-worktree-provisioning-model.md +27 -21
  214. package/docs/reference/decisions/0005-sandbox-pod-composition.md +39 -25
  215. package/docs/reference/decisions/0006-agent-control-surface.md +6 -3
  216. package/docs/reference/decisions/0007-durable-machine-state.md +1 -1
  217. package/docs/reference/decisions/0009-cli-and-instance-interface.md +150 -49
  218. package/docs/reference/decisions/0010-bdd-acceptance-tests.md +5 -3
  219. package/docs/reference/decisions/0011-workflow-defined-events.md +256 -12
  220. package/docs/reference/decisions/0012-workspace-wrapper-machine.md +39 -32
  221. package/docs/reference/decisions/0013-the-agent-reaches-its-machine-through-a-container-it-cannot-read.md +54 -30
  222. package/docs/reference/decisions/0014-observation-is-open-run-state-is-not.md +53 -27
  223. package/docs/reference/decisions/0015-authoring-surface-absorbs-the-mechanism.md +26 -16
  224. package/docs/reference/decisions/0016-agent-turn-mechanics-are-internal.md +9 -7
  225. package/docs/reference/decisions/0017-pool-over-a-source-port.md +226 -10
  226. package/docs/reference/decisions/0018-instance-agents-are-definitions-jr2-assembles-the-harness.md +15 -7
  227. package/docs/reference/decisions/0019-one-converging-command-against-the-current-context.md +53 -27
  228. package/docs/reference/decisions/0021-workspace-continuity-is-a-lease-that-answers-back.md +16 -2
  229. package/docs/reference/decisions/0022-observation-is-a-level-triggered-feed.md +4 -4
  230. package/docs/reference/decisions/0023-the-harness-prints-the-conversation.md +124 -43
  231. package/docs/reference/decisions/0024-an-agents-turn-ends-with-the-state-that-asked-for-it.md +36 -38
  232. package/docs/reference/decisions/0025-cancel-ends-a-run-stop-parks-it.md +10 -5
  233. package/docs/reference/decisions/0027-the-harness-is-jr2s-own-server-flue-retires-the-wire-stays.md +16 -7
  234. package/docs/reference/decisions/0028-what-an-agent-may-do-to-the-workspace-is-part-of-its-definition.md +36 -19
  235. package/docs/reference/decisions/0029-a-menu-is-fixed-for-a-conversation-and-a-turn-is-told-its-allowed-picks.md +18 -10
  236. package/docs/reference/decisions/0030-a-snapshot-names-the-machine-it-was-written-under.md +3 -2
  237. package/docs/reference/decisions/0031-menu-only-agents-run-on-the-instance-harness.md +23 -15
  238. package/docs/reference/decisions/0032-the-console-unlocks-with-a-callers-credential.md +101 -0
  239. package/docs/reference/decisions/0033-a-machine-declares-the-input-that-starts-it.md +22 -22
  240. package/docs/reference/decisions/0034-the-console-renders-with-preact-and-the-server-erases-the-types.md +6 -6
  241. package/docs/reference/decisions/0037-an-instance-builds-its-sandbox-images-jr2-injects-the-harness.md +13 -12
  242. package/docs/reference/decisions/0049-a-machine-carries-its-parts-and-composes-by-invoke.md +23 -23
  243. package/docs/reference/decisions/0050-what-code-names-config-declares-what-the-cli-names-discovery-finds.md +6 -1
  244. package/docs/reference/decisions/0051-a-repo-is-a-slot-on-the-workspace-and-a-cache-on-the-node.md +57 -46
  245. package/docs/reference/decisions/0052-a-sandbox-lands-where-an-ordinary-pod-lands-and-the-cache-follows-it.md +5 -0
  246. package/docs/reference/decisions/0053-a-fetch-inside-the-pod-asks-the-node-cache-and-the-cache-asks-the-remote.md +20 -8
  247. package/docs/reference/decisions/0054-the-kit-ships-machines-and-a-shipped-machine-leaves-its-parts-open.md +55 -40
  248. package/docs/reference/decisions/0055-a-release-is-a-pushed-tag-and-the-publish-guard-is-the-credential.md +14 -13
  249. package/docs/reference/decisions/0057-a-turn-is-its-frame-its-dials-and-whether-it-continues.md +31 -24
  250. package/docs/reference/decisions/0058-a-harness-answers-the-orchestrator-alone.md +18 -10
  251. package/docs/reference/decisions/0059-a-harness-holds-stand-ins-and-the-custodian-holds-the-keys.md +137 -86
  252. package/docs/reference/decisions/0062-jr2-briefs-the-agent-on-its-seat-never-on-its-task.md +165 -91
  253. package/docs/reference/decisions/0063-the-orchestrator-watches-the-cluster.md +7 -7
  254. package/docs/reference/decisions/0064-a-workspace-waits-for-capacity.md +2 -2
  255. package/docs/reference/decisions/0065-a-persist-survives-a-crash-and-history-is-kept-for-a-set-time.md +109 -0
  256. package/docs/reference/decisions/0066-a-model-tier-runs-a-real-model-and-a-change-to-what-it-reads-runs-the-tier.md +53 -23
  257. package/docs/reference/decisions/0067-an-effect-is-an-actor-slot-and-runs-at-most-once-unless-marked-idempotent.md +221 -153
  258. package/docs/reference/decisions/0068-an-effector-holds-an-effects-secrets-and-signs-its-wire.md +161 -96
  259. package/docs/reference/decisions/0069-the-orchestrator-is-a-kit-image-and-an-instance-publishes-its-assembly.md +32 -9
  260. package/docs/reference/decisions/0070-a-machine-lends-its-parts-to-a-chart.md +48 -33
  261. package/docs/reference/decisions/0071-a-run-starts-a-run-through-a-dispatch-effect.md +56 -30
  262. package/docs/reference/decisions/0072-the-docs-ship-inside-the-kit-and-an-instances-agents-md-indexes-them.md +35 -25
  263. package/docs/reference/decisions/0073-a-machine-fails-a-run-with-fail-and-an-uncaught-failure-ends-it-failed.md +1 -1
  264. package/docs/reference/decisions/0075-a-machine-cuts-a-worktree-and-the-workspace-only-clones.md +296 -0
  265. package/docs/reference/decisions/0076-an-agents-control-credential-lives-only-where-no-workspace-code-runs.md +347 -0
  266. package/docs/reference/decisions/0077-jr2-requires-landlock-on-every-sandbox-node.md +79 -0
  267. package/docs/reference/decisions/0078-a-caller-comes-from-one-authenticator-seam-and-acts-within-its-scopes.md +285 -0
  268. package/docs/reference/decisions/0079-an-agent-holds-mcp-tools-a-machine-calls-them-as-an-effect-and-the-machine-is-the-approval.md +198 -0
  269. package/docs/reference/decisions.md +9 -4
  270. package/docs/reference/glossary.md +138 -45
  271. package/docs/reference/hooks.md +1077 -0
  272. package/docs/reference/http-api.md +988 -123
  273. package/docs/reference/machines.md +0 -1
  274. package/docs/why.md +7 -5
  275. package/package.json +10 -3
  276. package/src/actor.ts +194 -42
  277. package/src/agent.ts +56 -6
  278. package/src/ambient.ts +3 -5
  279. package/src/assembly-checks.ts +530 -4
  280. package/src/callers.ts +245 -0
  281. package/src/chart.ts +238 -26
  282. package/src/charts.ts +9 -2
  283. package/src/config.ts +566 -7
  284. package/src/conversations.ts +453 -0
  285. package/src/custodian.lua +17 -5
  286. package/src/custodian.ts +257 -77
  287. package/src/customize.ts +154 -7
  288. package/src/dispatch-effect.ts +142 -26
  289. package/src/durability.ts +2 -0
  290. package/src/duration.ts +20 -0
  291. package/src/effect-checks.ts +52 -4
  292. package/src/effect.ts +401 -132
  293. package/src/effector-wire.ts +278 -30
  294. package/src/fail.ts +17 -4
  295. package/src/gate-brand.ts +16 -0
  296. package/src/gate.ts +634 -48
  297. package/src/harness-client.ts +84 -35
  298. package/src/harness-env.ts +33 -0
  299. package/src/held-secrets.ts +197 -39
  300. package/src/holds.ts +5 -2
  301. package/src/hook-kinds/discord.ts +92 -0
  302. package/src/hook-kinds/door.ts +107 -0
  303. package/src/hook-kinds/github.ts +89 -0
  304. package/src/hook-kinds/gitlab.ts +72 -0
  305. package/src/hook-kinds/hook.ts +7 -0
  306. package/src/hook-kinds/index.ts +465 -0
  307. package/src/hook-kinds/slack.ts +151 -0
  308. package/src/hook-kinds/webhook.ts +113 -0
  309. package/src/hooks.ts +506 -0
  310. package/src/http-effect.ts +164 -70
  311. package/src/http.ts +933 -99
  312. package/src/index.ts +30 -5
  313. package/src/instance.ts +196 -26
  314. package/src/internal.ts +23 -3
  315. package/src/kube-client.ts +6 -3
  316. package/src/machine-doc.ts +29 -5
  317. package/src/mcp-effect.ts +424 -0
  318. package/src/model-keys.ts +24 -0
  319. package/src/mount-digest.ts +41 -7
  320. package/src/names.ts +82 -7
  321. package/src/notices.ts +576 -59
  322. package/src/open-body.ts +110 -30
  323. package/src/open-effect.ts +17 -4
  324. package/src/open.ts +40 -7
  325. package/src/parts.ts +125 -35
  326. package/src/party.ts +35 -1
  327. package/src/pick.ts +43 -9
  328. package/src/pool.ts +1172 -172
  329. package/src/registration.ts +249 -17
  330. package/src/repo-identity.ts +7 -3
  331. package/src/repos.ts +20 -2
  332. package/src/run-host.ts +1614 -190
  333. package/src/run-list.ts +191 -0
  334. package/src/sandbox-effect.ts +217 -66
  335. package/src/sandbox-kube.ts +116 -21
  336. package/src/secret-placement.ts +248 -35
  337. package/src/server.ts +53 -4
  338. package/src/setup.ts +158 -38
  339. package/src/snapshot-store.ts +565 -48
  340. package/src/steer.ts +111 -0
  341. package/src/stub-harness.ts +6 -2
  342. package/src/tokens.ts +362 -46
  343. package/src/vocabulary.ts +23 -4
  344. package/src/wire.ts +27 -10
  345. package/src/workspace.ts +314 -259
  346. package/src/worktree.ts +249 -0
  347. package/docs/reference/authoring-surface/type-noslotspec.md +0 -26
  348. package/docs/reference/authoring-surface/type-workspacespec.md +0 -37
  349. package/docs/reference/decisions/0032-the-console-unlocks-with-the-instance-token.md +0 -61
  350. package/docs/reference/decisions/0065-a-persist-survives-a-crash-and-history-is-a-week.md +0 -65
@@ -49,21 +49,21 @@ jr2 up — instance "my-instance" → context kind-jr2 / namespace my-instance
49
49
  typecheck: tsc --noEmit (the instance's own compiler)
50
50
  agents: (none) (carried by 1 workflow machine(s))
51
51
  assembly: staging
52
- assembly: 0adf5bff234d (kit v<version>; 1 workflow(s): ping)
52
+ assembly: 0756fbb530cb (kit v<version>; 1 workflow(s): ping)
53
53
  …
54
54
  sandbox images: skipped (no registered Machine composes a Sandbox)
55
55
  …
56
56
  orchestrator: applying (image ghcr.io/snapwich/jr2-orchestrator:<version>)
57
57
  orchestrator: waiting for rollout
58
58
  orchestrator: verified — 1 pod(s) running ghcr.io/snapwich/jr2-orchestrator:<version>
59
- instance effector: none (no Effect is placed there)
60
- assembly: publishing 0adf5bff234d (current is ba71fa27f37f)
61
- assembly: 0adf5bff234d is current — workflows: ping
62
- swept nothing — every labeled image is named by a live root
59
+ instance effector: none (no Effect is placed there, and no Hook needs it)
60
+ assembly: publishing 0756fbb530cb (current is 50e6f81e3bfb)
61
+ assembly: 0756fbb530cb is current — workflows: ping
62
+ …
63
63
  converged — `jr2 run <workflow>` when ready
64
64
  ```
65
65
 
66
- `0adf5bff234d` is the hash of the new [Assembly](../reference/glossary.md#assembly), and `ba71fa27f37f` is the hash of
66
+ `0756fbb530cb` is the hash of the new [Assembly](../reference/glossary.md#assembly), and `50e6f81e3bfb` is the hash of
67
67
  the Assembly that was current. Your hashes can be different. `<version>` is the
68
68
  [Kit version](../reference/glossary.md#kit-version). The hash changed, because the Workflow changed. Thus `jr2 up`
69
69
  published the new Assembly to the [Orchestrator](../reference/glossary.md#orchestrator). The image of the Orchestrator
@@ -84,9 +84,9 @@ jr2 run ping --input '{"message":"hi"}'
84
84
 
85
85
  ```text
86
86
  → context kind-jr2 / namespace my-instance
87
- run 7df09f94-d26d-44c3-ba1e-0279f16ccacb (ping) — attached
87
+ run 8b6c68a2-2ab6-498b-9cc5-bb722d71140f (ping) — attached
88
88
  → done "done"
89
- {"runId":"7df09f94-d26d-44c3-ba1e-0279f16ccacb","workflow":"ping","instanceId":"b2ec6504-553e-495a-a8be-62715c6d8595","status":"done","value":"done","context":{"message":"hi","reply":"pong, again: hi"},"children":[],"waiting":[],"held":[],"assembly":"0adf5bff234d"}
89
+ {"runId":"8b6c68a2-2ab6-498b-9cc5-bb722d71140f","workflow":"ping","instanceId":"919c7165-d20e-472b-b889-1ba4209a488b","startedAt":"2026-11-06T19:17:06.158Z","status":"done","value":"done","context":{"message":"hi","reply":"pong, again: hi"},"children":[],"waiting":[],"held":[],"assembly":"0756fbb530cb","startedBy":{"kind":"caller","via":"token","name":"instance","onBehalfOf":"kubernetes-admin"}}
90
90
  ```
91
91
 
92
92
  Your run id and your instance id are different. The `reply` comes from the new Machine, and `assembly` is the hash of
@@ -112,8 +112,9 @@ A second `jr2 up` with no change builds nothing and publishes nothing:
112
112
 
113
113
  ```text
114
114
  …
115
- assembly: 0adf5bff234d (current — publish skipped)
115
+ assembly: 0756fbb530cb (current — publish skipped)
116
116
  swept nothing — every labeled image is named by a live root
117
+ …
117
118
  converged — `jr2 run <workflow>` when ready
118
119
  ```
119
120
 
@@ -158,15 +158,18 @@ jr2 run plan --input '{"task":"Write the release notes for the greet CLI, and as
158
158
  Open the run in the [Console](../reference/glossary.md#console). After the planner picks `run_chart`, the Console draws
159
159
  the Chart inside `running`. The Chart of each run is different, because the planner writes it.
160
160
 
161
- When the door refuses a Chart, the answer to the pick holds the report. The log of the
162
- [Instance Harness](../reference/glossary.md#instance-harness) shows each answer. Replace `<namespace>` with the
163
- namespace of your Instance, and `<run id>` with the full run id. The log holds the lines of each run of a Menu-only
164
- Agent, and the first `grep` keeps the lines of your run:
161
+ When the door refuses a Chart, the answer to the pick holds the report. The conversation of the planner shows each
162
+ answer. [`jr2 logs`](../reference/cli.md#logs) prints it. Replace `<run id>` with the run id, or its first 4 characters
163
+ or more:
165
164
 
166
165
  ```sh
167
- kubectl -n <namespace> logs statefulset/jr2-instance-harness -c harness | grep -F '[<run id>/' | grep -F '[run_chart answer]'
166
+ jr2 logs <run id> planner | grep -F '[run_chart answer]'
168
167
  ```
169
168
 
169
+ [Read a conversation](read-a-conversation.md) tells more. The log of the Instance Harness has the same lines, for each
170
+ run of a Menu-only Agent:
171
+ `kubectl -n <namespace> logs statefulset/jr2-instance-harness -c harness | grep -F '[<run id>/'`, with the full run id.
172
+
170
173
  For example, in one run with the model of each tab, the first Chart of the planner gave a prompt to the Gate. The door
171
174
  refused it:
172
175
 
@@ -185,7 +188,7 @@ it. Then the Chart ends, and the run ends with the status `done`.
185
188
 
186
189
  - [`openBody()`](../reference/authoring-surface/openbody.md) refuses a declaration that is not correct, with one line
187
190
  for each problem. The refusal starts with `openBody: `, then each problem, separated by `; `. For example:
188
- - `lends.<kind>: an Open body lends agents, effects, machines, guards, actions, delays, gate and fail only`
191
+ - `lends.<kind>: an Open body lends agents, effects, machines, gates, guards, actions, delays, gate and fail only`
189
192
  - `allows.workspace: "<value>" is not a Workspace access (write, read, none)`
190
193
  - `ceilings.<ceiling>: missing; an Open body states every ceiling`
191
194
  - `ceilings.<ceiling>: <value> is not a positive integer`
@@ -200,11 +203,15 @@ it. Then the Chart ends, and the run ends with the status `done`.
200
203
  - The door refuses a Chart, and gives one line for each problem. Each line starts with the path in the Chart. For
201
204
  example:
202
205
  - `<path>: "<name>" is not a lent actor or an Agent of this Chart; lent: <names>; kit: <gate, fail or none>; minted: <names>`
203
- - `<path>: "<name>" is not a lent guard; lent guards: <names> (and jr2.sentBy with params { id }, and jr2.failure)`
206
+ - `<path>: "<name>" is not a lent guard; lent guards: <names> (and jr2.sentBy with params { id }, jr2.failure and jr2.ready)`
204
207
  - `<path>.type: "<name>" is not a generic or a lent action; generic: set, append, increment, clear; lent: <names>`
205
208
  - ``<path>: <reference> is supplied by nothing: it is not in the initial `context`, and no `set`, `append` or `increment` writes it``,
206
209
  then what a write supplies
207
210
  - `<path>: "<reference>" is not a reference: it starts at context, event or input (a reference is a path, never an expression)`
211
+ - ``<path>: the lent cut "<slot>" does not state `expect`, so a Chart cannot use it; <fix>``
212
+ - ``<path>: the lent cut "<slot>" states `expect: "existing"` beside the lent force push "<slot>", and together they can force-push any existing branch; <fix>``
213
+ - ``<path>.cwd: "<cwd>" is a Repo Slot's folder, not a Worktree; `cwd` is a Worktree that a cut made, "/work/<slot>/<name>", or "/work/<slot>/default" to read, or "/work"``
214
+ - ``<path>: <agent> works under a Workspace with Repo Slots, and a Turn there says where: `cwd` is a Worktree, or "/work"``
208
215
  - The door then compiles the Chart as the Open body does. A line of this last check starts with `(chart):`, and names a
209
216
  state by its [xstate](https://xstate.js.org) id (for example `body.writing`), not by its path in the Chart.
210
217
  - A refusal is output, not an error: the Open body ends with `{ outcome: "refused", report }`. A Chart wrapper that
@@ -11,61 +11,89 @@ Open a shell in the [Sandbox](../reference/glossary.md#sandbox) of a run, and re
11
11
  A [Workspace](../reference/glossary.md#workspace) of the run makes the Sandbox, and deletes it when the body of the
12
12
  Workspace gets to its final state or fails. The [Rules](#rules) give the cases in which the Sandbox stays. The Sandbox
13
13
  is a pod. Its `harness` container runs the [Harness](../reference/glossary.md#harness), and the Agent's
14
- [Working tools](../reference/glossary.md#working-tools) run in it. When you use `kubectl exec`, you get a shell in the
15
- same container. An Agent that has only the [Menu](../reference/glossary.md#menu) has no Sandbox. To read its
16
- conversation, see [Watch a run](watch-a-run.md).
14
+ [Working tools](../reference/glossary.md#working-tools) run in it. `jr2 workspace shell` gives you a shell in the same
15
+ container, as the Agent's tools run. An Agent that has only the [Menu](../reference/glossary.md#menu) has no Sandbox. To
16
+ read what an Agent said and did, see [Read a conversation](read-a-conversation.md).
17
17
 
18
- In the commands on this page, replace these values:
18
+ In the commands on this page, replace `<run id>` with the run id, or its first 4 characters or more.
19
+ [`jr2 run`](../reference/cli.md#run) prints it in the line `run <run id> (<workflow>) — attached`.
20
+ [`jr2 runs`](../reference/cli.md#runs) prints the `runId` of each live run.
19
21
 
20
- - `<namespace>`: the namespace of your [Instance](../reference/glossary.md#instance). It is the
21
- [`name`](../reference/config.md#name) in `jr2.config.ts`. When `jr2.config.ts` sets no `name`, it is the name of the
22
- Instance folder.
23
- - `<run id>`: the full run id. [`jr2 run`](../reference/cli.md#run) prints it in the line
24
- `run <run id> (<workflow>) — attached`. [`jr2 runs`](../reference/cli.md#runs) prints the `runId` of each live run. A
25
- prefix does not work here, because `kubectl` does not know the run ids.
26
-
27
- Give each `jr2` command in the Instance folder.
22
+ Give each `jr2` command in the [Instance](../reference/glossary.md#instance) folder. The `jr2 workspace` commands read
23
+ the Sandbox resources from the cluster with your kubectl credentials. They do not use the
24
+ [Orchestrator](../reference/glossary.md#orchestrator), so they also work when the Orchestrator is down.
28
25
 
29
26
  ## Find the Sandbox
30
27
 
31
- The label `jr2.dev/run` on each Sandbox holds the full id of its run:
28
+ Run [`jr2 workspace ls`](../reference/cli.md#workspace-ls) with the run id. Without a run id, it lists each Workspace of
29
+ the Instance:
32
30
 
33
31
  ```sh
34
- kubectl -n <namespace> get sandboxes -l jr2.dev/run=<run id>
32
+ jr2 workspace ls <run id>
35
33
  ```
36
34
 
37
35
  ```text
38
- NAME PHASE ENDPOINT AGE
39
- ws-a1322024-x-2-h8pgwk Ready http://ws-a1322024-x-2-h8pgwk.my-instance.svc:8080 16s
36
+ → context <context> / namespace <namespace>
37
+ WORKSPACE SANDBOX WORKFLOW PHASE AGE RUN
38
+ 7a0e8b50/x:0 ws-7a0e8b50-x-0-1eolpdi task Ready 32s held
40
39
  ```
41
40
 
42
- - `NAME` is the name of the Sandbox, here `ws-a1322024-x-2-h8pgwk`. Your name is different. It starts with `ws-`, then
43
- the first 8 characters of the run id. The pod has the same name. In the commands below, write it in place of
44
- `<sandbox>`.
41
+ - `WORKSPACE` is the handle of the Workspace: the first 8 characters of the run id, then the path of the Workspace in
42
+ the run. In the commands below, write it in place of `<workspace>`. You can also give the name of the Sandbox, or the
43
+ first characters of the run id, then `/` and the path.
44
+ - `SANDBOX` is the name of the Sandbox, here `ws-7a0e8b50-x-0-1eolpdi`. Your name is different. The pod has the same
45
+ name.
45
46
  - A run that has two Workspaces at the same time has two rows.
46
- - `PHASE` is `Pending` until the pod is ready and its node has a fresh cache of each Repo. Then it is `Ready`. It is
47
- `Lost` when the pod is gone, and a `Lost` Sandbox does not get a new pod. A delete removes the Sandbox at once, so you
48
- seldom see the phase `Terminating`.
49
- - When the run has no Sandbox now, `kubectl` prints `No resources found in <namespace> namespace.`
47
+ - `PHASE` is `Pending` until the pod is ready and its node has a fresh cache of each
48
+ [Repo](../reference/glossary.md#repo). Then it is `Ready`. It is `Lost` when the pod is gone, and a `Lost` Sandbox
49
+ does not get a new pod. A delete removes the Sandbox at once, so you seldom see the phase `Terminating`.
50
+ - `RUN` tells if a run holds the Sandbox. `held`: a run holds it, or an Orchestrator that stopped held it. `released`:
51
+ its run does not hold it now. `idle`: nothing renewed its [Lease](../reference/glossary.md#lease) for its idle time.
52
+ `unknown`: the Sandbox has no mark.
53
+ - When the run has no Sandbox now, the table has only its header.
54
+ - `--json` prints the list as one JSON object.
55
+ - [`jr2 status <run id>`](../reference/cli.md#status) prints each [Worktree](../reference/glossary.md#worktree) that the
56
+ run cut, with its path and its branch, in `worktrees` and in one `worktree:` line for each cut. Give this command on
57
+ your computer, not in the Sandbox.
50
58
  - When a [Workflow](../reference/glossary.md#workflow) puts `branch` and `worktree` in the `meta` of a
51
59
  [Gate](../reference/glossary.md#gate), as the `review` Gate of [`task`](../reference/machines.md#task) does,
52
- [`jr2 status <run id>`](../reference/cli.md#status) prints them in `gates`. Give this command on your computer, not in
53
- the Sandbox. Then you can copy the Worktree from the status.
60
+ `jr2 status <run id>` prints them in `gates` too.
54
61
 
55
62
  ## Open a shell
56
63
 
64
+ Run [`jr2 workspace shell`](../reference/cli.md#workspace-shell) with the handle:
65
+
57
66
  ```sh
58
- kubectl -n <namespace> exec -it <sandbox> -c harness -- bash
67
+ jr2 workspace shell <workspace>
59
68
  ```
60
69
 
61
- The default [Sandbox Image](../reference/glossary.md#sandbox-image) that [`jr2 init`](../reference/cli.md#init) writes
62
- starts from `node:24-slim`, which has `bash`. If your Sandbox Image has no `bash`, use `sh`.
70
+ `jr2 completion bash|zsh|fish` completes the handles; see [`jr2 completion`](../reference/cli.md#completion).
71
+
72
+ The shell runs as the Agent's tools run. The Harness starts it in the same Landlock domain as the Agents, in `/work`.
73
+ Thus it has the same files, the same limits and the same [Stand-ins](../reference/glossary.md#stand-in) as an Agent's
74
+ `bash`, and it cannot read the credential with which the Harness speaks for the Agents. It can see and stop a process
75
+ that an Agent started, such as a dev server. The shell is `bash`, or `sh` when the image has no `bash`. The default
76
+ [Sandbox Image](../reference/glossary.md#sandbox-image) that [`jr2 init`](../reference/cli.md#init) writes starts from
77
+ `node:24-slim`, which has `bash`.
78
+
79
+ To run one command and not a shell, give it after `--`:
80
+
81
+ ```sh
82
+ jr2 workspace shell <workspace> -- git -C /work status
83
+ ```
84
+
85
+ A command after `--` has no terminal. Ctrl-C stops `jr2`, and the command gets the end of its input but no signal. Thus
86
+ a command that does not stop at the end of its input, such as a dev server, can continue to run.
87
+
88
+ When the Workspace has a [User Container](../reference/glossary.md#user-container), add `--user` to open a shell in it.
89
+ [Add tools to the Sandbox](add-tools-to-the-sandbox.md#run-a-service-beside-the-agent) tells how to reach a service in
90
+ it.
63
91
 
64
92
  ## Find the Worktree
65
93
 
66
94
  Each [Repo Slot](../reference/glossary.md#repo-slot) of the Workspace has a folder in `/work`. In it, `default` is a
67
- clone of the [Repo](../reference/glossary.md#repo), and the [Worktree](../reference/glossary.md#worktree) of the branch
68
- is beside it. To show the folders of the Repo Slots, use this command:
95
+ clone of the Repo, and each [Worktree](../reference/glossary.md#worktree) that the Machine cut is beside it. To show the
96
+ folders of the Repo Slots, use this command:
69
97
 
70
98
  ```sh
71
99
  ls /work
@@ -80,20 +108,20 @@ git -C /work/<Repo Slot>/default worktree list
80
108
  For the slot `target` of a run of `task`, the output is:
81
109
 
82
110
  ```text
83
- /work/target/default 1e40403 [main]
84
- /work/target/jr2-task-0cbdb607-48dc-4eab-9469-f8e41f2b0025 1e40403 [jr2/task-0cbdb607-48dc-4eab-9469-f8e41f2b0025]
111
+ /work/target/default 9f67321f (detached HEAD)
112
+ /work/target/task 9f67321f [jr2/task-48ebf9ad-1e5d-4997-a330-d91ec762f83c]
85
113
  ```
86
114
 
87
- The first line is the clone, on the default branch of the Repo. The second line is the Worktree of the branch. Your
88
- commits and your instance id are different.
115
+ The first line is the clone, on the base of the Repo Slot. Here the base is a tag, so the clone is detached. On a
116
+ branch, the line shows the branch. The second line is the Worktree that `task` cut. Your commits and your instance id
117
+ are different.
89
118
 
90
- - In the commands below, `<branch>` is the name of the branch, and `<worktree>` is the folder of its Worktree. The
91
- folder is the name of the branch, with each `/` changed to `-`. For example, the branch `jr2/task-<instance id>` has
92
- the Worktree `/work/target/jr2-task-<instance id>`.
93
- - A Workspace that has a commit to review has one more Worktree, `/work/<Repo Slot>/<worktree>-review`. It holds that
94
- commit, with no branch.
95
- - The attach makes the folders and the Worktrees after the Sandbox is `Ready`. Until then, `/work` has no folder for the
96
- Repo Slot.
119
+ - In the commands below, `<branch>` is the name of the branch, and `<worktree>` is the name of the folder of its
120
+ Worktree. Your Machine chooses each one. The name of the folder does not come from the branch. `task` names the folder
121
+ `task`.
122
+ - A detached Worktree, such as the Worktree of a reviewer, shows `(detached HEAD)` in place of a branch.
123
+ - The attach makes the folders and the clones after the Sandbox is `Ready`. Until then, `/work` has no folder for the
124
+ Repo Slot. The Machine cuts each Worktree in a state of its body. See [Cut a Worktree](cut-a-worktree.md).
97
125
 
98
126
  ## Read the branch
99
127
 
@@ -124,7 +152,7 @@ git show --stat HEAD
124
152
  You can also give one command, with no shell:
125
153
 
126
154
  ```sh
127
- kubectl -n <namespace> exec <sandbox> -c harness -- git -C /work/<Repo Slot>/<worktree> log --oneline
155
+ jr2 workspace shell <workspace> -- git -C /work/<Repo Slot>/<worktree> log --oneline
128
156
  ```
129
157
 
130
158
  ## Push the branch
@@ -148,6 +176,23 @@ A [Machine](../reference/glossary.md#machine) can also push the branch with an
148
176
  > The Agent works in the same files as your shell, so it sees each change that you make there. When the Sandbox goes, a
149
177
  > commit that you did not push goes with it.
150
178
 
179
+ ## Remove a Sandbox that no run holds
180
+
181
+ A Sandbox that a cancel with `--keep` or a fault left stays until the operator deletes it. To delete it before then, run
182
+ [`jr2 workspace rm`](../reference/cli.md#workspace-rm):
183
+
184
+ ```sh
185
+ jr2 workspace rm <workspace>
186
+ ```
187
+
188
+ ```text
189
+ → context <context> / namespace <namespace>
190
+ removed Workspace 7a0e8b50/x:0 (ws-7a0e8b50-x-0-1eolpdi)
191
+ ```
192
+
193
+ `jr2 workspace rm` removes only a Sandbox that `jr2 workspace ls` shows as `released` or `idle`. To remove the Sandbox
194
+ of a live run, cancel the run. See [Cancel a run](cancel-a-run.md).
195
+
151
196
  ## Rules
152
197
 
153
198
  - The Workspace deletes its Sandbox when its body gets to its final state. When the body of each Workspace of the run
@@ -164,11 +209,39 @@ A [Machine](../reference/glossary.md#machine) can also push the branch with an
164
209
  its Workspace. The operator deletes the Sandbox 30 minutes after the last renewal.
165
210
  - A Workspace in [Placing](../reference/glossary.md#placing) deletes its Sandbox at once, also after a fault and after a
166
211
  CANCEL with `--keep`. Its Sandbox has no node yet, so it has nothing to look inside.
212
+ - The `jr2 workspace` commands need your kubectl credentials to list the Sandbox resources. Without them, the command
213
+ says: `cannot list the Sandboxes in namespace <namespace>: <message>`
214
+ - With no kube context, the `jr2 workspace` commands say:
215
+ ``no kube context — `kind create cluster` (or point kubectl at one), then `jr2 up` ``
216
+ - A handle that names no Workspace is an error. The command exits with `1`:
217
+ ``no Workspace "<handle>" — `jr2 workspace ls` lists them``
218
+ - A handle that names more than one Workspace is an error. The command lists each Workspace that it names, and exits
219
+ with `1`: `"<handle>" names <n> Workspaces — give more of the run id:`
220
+ - `jr2 workspace rm` refuses the Sandbox of a live run, and exits with `1`. There is no option to force it:
221
+ ``Workspace <handle> (<sandbox>) is not removed: run <run id> holds it — cancel the run first (`jr2 send <run id> --event CANCEL`)``
222
+ - `jr2 workspace rm` refuses a Sandbox with no hold mark (`RUN` is `unknown`), and exits with `1`:
223
+ ``Workspace <handle> (<sandbox>) is not removed: it has no hold mark, so it may be held by run <run id> — cancel the run first (`jr2 send <run id> --event CANCEL`)``
224
+ - `jr2 workspace rm` refuses a Sandbox that a run started to hold again after `jr2 workspace rm` read it:
225
+ ``Workspace <handle> (<sandbox>) is not removed: it changed after it was read, so a run may hold it again — run `jr2 workspace ls` and try again``
226
+ - `jr2 workspace shell --user` refuses a Workspace with no User Container, and exits with `1`:
227
+ ``Workspace <handle> has no User Container: its workspace() names no `user` image``
228
+ - A refusal of the Harness starts with `jr2 workspace shell: `.
229
+ - `jr2 workspace shell` needs `bash` or `sh` on the `PATH` of the Sandbox Image. When it has neither, the command says:
230
+ `jr2 workspace shell: the Sandbox Image has no bash and no sh on its PATH`
231
+ - `jr2 workspace shell --user` with no command needs `sh` in the image of the User Container. When it has none, the
232
+ command says: `the User Container's image has no sh: give it a shell, or name a command after --`
233
+ - `jr2 workspace shell --user -- <command>` says this when the User Container cannot run the command (exit `126` or
234
+ `127`): `the User Container could not run <command> (exit <code>)`
167
235
 
168
236
  ## Read next
169
237
 
170
238
  - [Workspaces](../concepts/workspaces.md)
239
+ - [Cut a Worktree](cut-a-worktree.md)
171
240
  - [ADR-0004](../reference/decisions/0004-worktree-provisioning-model.md): the clone and the Worktree.
172
241
  - [ADR-0005](../reference/decisions/0005-sandbox-pod-composition.md): the containers of a Sandbox.
173
242
  - [ADR-0012](../reference/decisions/0012-workspace-wrapper-machine.md): when a Workspace deletes its Sandbox.
243
+ - [ADR-0021](../reference/decisions/0021-workspace-continuity-is-a-lease-that-answers-back.md): the Lease, and when a
244
+ run holds its Sandbox.
245
+ - [ADR-0076](../reference/decisions/0076-an-agents-control-credential-lives-only-where-no-workspace-code-runs.md): why
246
+ your shell runs in the domain of the Agents.
174
247
  - [Watch a run](watch-a-run.md)
@@ -54,6 +54,22 @@ below explains one field. Set only the fields that your cluster needs.
54
54
  API server and in the kubelets.
55
55
  - A container runtime that mounts image volumes, such as containerd 2.1 or later, or CRI-O 1.31 or later. `jr2 up` does
56
56
  not check the runtime. With an older runtime, the first Sandbox fails, and its pod events give the cause.
57
+ - Landlock ABI 3 or later in the kernel of each [Sandbox node](../reference/glossary.md#sandbox-node): Linux 6.2 or
58
+ later, with `landlock` in its list of security modules. A distribution kernel can have it at an older version: the
59
+ check, not the version, decides. The Harness confines each program of an Agent with it. The Repo cache agent on each
60
+ Sandbox node checks it, and `jr2 up` refuses to converge while a Sandbox node has no Landlock. It names each such
61
+ node. To keep a node out, use `sandbox.nodeSelector` or a taint (see
62
+ [Choose the Sandbox nodes](#choose-the-sandbox-nodes)). A node that joins later and has no Landlock gets no working
63
+ Sandbox: its Harness does not start.
64
+ - A CNI that enforces NetworkPolicy, and no node credential that a pod can get. `jr2 up` applies a NetworkPolicy that
65
+ stops each Harness pod at the cloud metadata addresses: `169.254.169.254`, `fd00:ec2::254`, `169.254.170.2`,
66
+ `169.254.170.23` and `100.100.100.200`. There, the metadata service of a node can give the node's cloud credential to
67
+ a pod. `jr2 up` does not check these. Do these checks:
68
+ - Find the metadata address of your cloud provider. If it is not in the list, block it with a NetworkPolicy of your
69
+ own.
70
+ - Make sure that the CNI enforces NetworkPolicy. Without it, the policy stops nothing.
71
+ - Give pods no node credential. On GKE, use Workload Identity. On AWS, use IMDSv2 with a hop limit of 1. Then a pod
72
+ gets no node credential from the metadata service, also where the policy does not apply.
57
73
  - Your kubectl user can apply objects outside the namespace of the Instance. `jr2 up` applies the operator in the
58
74
  `jr2-system` namespace, with its CustomResourceDefinitions, ClusterRoles and ClusterRoleBindings. It also applies two
59
75
  PriorityClasses, unless you name your own.
@@ -1,12 +1,13 @@
1
1
  ---
2
2
  title: Open the Console
3
- description: Forward the port of the Orchestrator, open the Console, and unlock it with the Instance token.
3
+ description: Forward the port of the Orchestrator, open the Console, and unlock it with a token or a login.
4
4
  ---
5
5
 
6
6
  # Open the Console
7
7
 
8
- Open the [Console](../reference/glossary.md#console) in a browser, and paste the Instance token to start runs and answer
9
- [Gates](../reference/glossary.md#gate).
8
+ Open the [Console](../reference/glossary.md#console) in a browser. Paste a token, or log in, to start runs and answer
9
+ [Gates](../reference/glossary.md#gate). The Console shows only what the [Caller](../reference/glossary.md#caller) of the
10
+ token may do.
10
11
 
11
12
  The [Orchestrator](../reference/glossary.md#orchestrator) serves the Console on port 4000, in the cluster. To reach it
12
13
  from your computer, forward the port with `kubectl`. In the commands on this page, replace `<namespace>` with the
@@ -39,6 +40,8 @@ Without the token, the Console shows the runs, and you cannot change them:
39
40
  Click the caret of a Workflow to list its runs.
40
41
  - The center shows the [Machine](../reference/glossary.md#machine) of the Workflow that you select. When you select a
41
42
  run, the Console shows the states that the run is in.
43
+ - A run on an [Assembly](../reference/glossary.md#assembly) that is not the current one shows the mark
44
+ `older Assembly · <hash>`. The center then shows the Machine of that run, not the current Machine.
42
45
  - The Activity tab of the right drawer lists the type of each [Emit](../reference/glossary.md#emit) of the runs of the
43
46
  Workflow, the newest first.
44
47
 
@@ -62,29 +65,75 @@ The command prints the token, with no line break after it.
62
65
 
63
66
  ## Paste the token
64
67
 
65
- Paste the token into the box `instance token` in the nav of the Console. Push Enter. The badge after the box shows `…`
66
- while the Console checks the token, then `live`. With a live token, the Console shows more:
68
+ Paste the token into the box `Caller token` in the nav of the Console. Push Enter. The badge after the box shows `…`
69
+ while the Console checks the token, then `live`. The nav then shows who the Console acts as, such as
70
+ `as token/instance`. Put the pointer on the name to see its scopes.
67
71
 
68
- - A `start` button for each Workflow in the Fleet rail. It opens a form for the run input of the Workflow. A Workflow
69
- that declares no run input gets a box for JSON.
70
- - The Attention tab of the right drawer. It shows a card for each open Gate of the selected Workflow, with a form to
71
- send each event that the Gate takes. Select `all workflows` to see the Gates of each Workflow.
72
+ The Console asks the Orchestrator what the token may do ([`GET /whoami`](../reference/http-api.md#get-whoami)). Then it
73
+ shows each control that a scope of the token opens:
72
74
 
73
- The Console keeps the token in the browser tab. A reload keeps it. When you close the tab, the token is gone.
75
+ | Scope | What the Console shows |
76
+ | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
77
+ | `start` | A `start` button for the Workflow in the Fleet rail. It opens a form for the run input of the Workflow. |
78
+ | `answer` | The Attention tab of the right drawer, with a card for each open Gate and a form for each event it takes. |
79
+ | `read` | The full state of the selected run: why it waits, why it failed, and who started it. The ended runs of the Workflow in the Fleet rail. The conversations of the run in the bottom drawer. |
80
+ | `cancel` | A `cancel run` button on the selected run, while the run is live. |
81
+ | `steer` | A box in the bottom drawer, beside the [Agent](../reference/glossary.md#agent) slot, to send a [Steering message](../reference/glossary.md#steering-message) while the run is live. |
82
+
83
+ The Instance token has each scope for each Workflow, so it shows each control. A named Caller token shows the controls
84
+ of its scopes, for its Workflows ([Give a Caller a scope](give-a-caller-a-scope.md)). A Workflow that declares no run
85
+ input gets a box for JSON in its start form. In the Attention tab, select `all workflows` to see the Gates of each
86
+ Workflow.
87
+
88
+ The Console keeps the token in the browser tab. A reload keeps it. When you close the tab, the token is gone. Click
89
+ `sign out` to forget it before then.
90
+
91
+ ## Read a conversation
92
+
93
+ With `read`, the Fleet rail lists the ended runs of the selected Workflow under its live runs, each with its status. A
94
+ `drifted` run shows its reason. Click an ended run to see its Machine, the state where it ended, and its conversations,
95
+ for as long as jr2 keeps the run ([`runs.retain`](../reference/config.md#runs)).
96
+
97
+ The bottom drawer shows the [Conversations](../reference/glossary.md#conversation) of the selected run. Closed, it is a
98
+ bar with one tab for each Agent slot of the run. A dot shows a slot whose [Turn](../reference/glossary.md#turn) is open.
99
+ Click a tab to open the drawer on that slot. The drawer shows what the model wrote, each tool call with the answer of
100
+ its pick, the refusals, the Steering messages and the notices. While the Turn is open, the drawer adds each new entry.
101
+ Drag the top edge of the drawer to change its height. The browser keeps the height for you.
102
+
103
+ ## Log in
104
+
105
+ When the Instance declares an issuer with [`login: true`](../reference/config.md#callers), the nav shows a `log in`
106
+ button. Click it. The browser goes to the login page of the issuer, and then comes back to the Console. The Console then
107
+ acts as you, with the scopes that your groups give. The nav shows the name that jr2 shows for you, such as your email.
108
+
109
+ To make the login work, register a client at the issuer:
110
+
111
+ - A public client, with no secret. Its client id is the `audience` of the issuer entry.
112
+ - The redirect URI is the root of the Console, such as `http://localhost:4000/`.
113
+ - The issuer must let the origin of the Console call its discovery document and its token endpoint (CORS).
114
+
115
+ The login needs the Console on `https`, or on `localhost`, because the browser makes its code challenge only there.
74
116
 
75
117
  ## Rules
76
118
 
77
119
  - A token that the Orchestrator does not accept reads `invalid`. The Console then shows no `start` button and no
78
120
  Attention tab.
79
- - When the Orchestrator refuses the token later, with the status 401, the Console goes back to view only.
80
- - Only the Instance token unlocks the Console. A [Sandbox](../reference/glossary.md#sandbox) token reads `invalid`.
121
+ - When the Orchestrator refuses the token later, with the status 401, the Console goes back to view only. An expired
122
+ login and a rotated token do this.
123
+ - A login whose groups give no scope reads `live` and shows no control. The nav shows who you are, so that you can see
124
+ why.
125
+ - A [Sandbox](../reference/glossary.md#sandbox) token is not a Caller. It reads `invalid`.
126
+ - The Console hides a control that the scopes do not open, so that you do not get a 403. The Orchestrator still checks
127
+ each request.
81
128
  - The port forward stops when you stop its command, or when the Orchestrator pod restarts. Then run the command again.
82
129
 
83
130
  ## Read next
84
131
 
85
132
  - [Architecture](../concepts/architecture.md)
86
- - [ADR-0032](../reference/decisions/0032-the-console-unlocks-with-the-instance-token.md): why the token unlocks the
87
- Console.
133
+ - [ADR-0032](../reference/decisions/0032-the-console-unlocks-with-a-callers-credential.md): why a Caller's credential
134
+ unlocks the Console, and how the login works.
135
+ - [ADR-0078](../reference/decisions/0078-a-caller-comes-from-one-authenticator-seam-and-acts-within-its-scopes.md): the
136
+ Callers and their scopes.
88
137
  - [ADR-0014](../reference/decisions/0014-observation-is-open-run-state-is-not.md): what the Console shows with no token.
89
138
  - [`GET /`](../reference/http-api.md#get) and the [open band](../reference/http-api.md#band-open)
90
139
  - [Answer a Gate](answer-a-gate.md)