@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
@@ -1,20 +1,22 @@
1
1
  ---
2
2
  title: Push and sign a branch
3
- description: Push the branch of a Workspace, and sign its commits with a key that the Agent never reads.
3
+ description: Push the branch of a Worktree, and sign its commits with a key that the Agent never reads.
4
4
  ---
5
5
 
6
6
  # Push and sign a branch
7
7
 
8
- Push the branch of a [Workspace](../reference/glossary.md#workspace) with a `push`
8
+ Push the branch of a [Worktree](../reference/glossary.md#worktree) with a `push`
9
9
  [Effect](../reference/glossary.md#effect), signed with a key that the [Agent](../reference/glossary.md#agent) never
10
10
  reads.
11
11
 
12
12
  [`push(options)`](../reference/authoring-surface/push.md) pushes the branch to the [Repo](../reference/glossary.md#repo)
13
- that the [Binding](../reference/glossary.md#binding) of its [Repo Slot](../reference/glossary.md#repo-slot) names. With
14
- `sign: true`, it pushes signed copies of the Agent's commits. In this [Workflow](../reference/glossary.md#workflow), a
15
- coder fixes the tests and commits. A person reads the branch at the [Gate](../reference/glossary.md#gate) of the state
16
- `review`, then sends `approve`. Then the [Machine](../reference/glossary.md#machine) pushes the branch, signed. Save the
17
- file as `workflows/publish.ts` in your [Instance](../reference/glossary.md#instance):
13
+ that the [Binding](../reference/glossary.md#binding) of its [Repo Slot](../reference/glossary.md#repo-slot) names. Its
14
+ input names the Worktree, `{ worktree }`, and has no branch. jr2 reads the branch from the cut of that path, so an Agent
15
+ that moves `HEAD` does not change what jr2 pushes. With `sign: true`, it pushes signed copies of the Agent's commits. In
16
+ this [Workflow](../reference/glossary.md#workflow), a coder fixes the tests and commits. A person reads the branch at
17
+ the [Gate](../reference/glossary.md#gate) of the state `review`, then sends `approve`. Then the
18
+ [Machine](../reference/glossary.md#machine) pushes the branch, signed. Save the file as `workflows/publish.ts` in your
19
+ [Instance](../reference/glossary.md#instance):
18
20
 
19
21
  **Anthropic**
20
22
 
@@ -25,9 +27,11 @@ import {
25
27
  agent,
26
28
  defineEvent,
27
29
  fail,
30
+ isReady,
28
31
  jr2Setup,
29
32
  push,
30
33
  workspace,
34
+ worktree,
31
35
  type PushOutput,
32
36
  type Workspaced,
33
37
  } from "@jr2/orchestrator";
@@ -45,6 +49,9 @@ const runInput = z.object({ prompt: z.string(), branch: z.string() });
45
49
  type BodyInput = Workspaced<z.infer<typeof runInput>, "app">;
46
50
  type Context = BodyInput & { pushed?: PushOutput };
47
51
 
52
+ // The Worktree of the coder. The push names it, and jr2 reads its branch from the cut.
53
+ const fixTree = (context: BodyInput) => `${context.workspace.repos.app}/fix` as const;
54
+
48
55
  const body = jr2Setup({
49
56
  types: {} as { input: BodyInput; context: Context },
50
57
  events: [finished, approve, stop],
@@ -53,6 +60,7 @@ const body = jr2Setup({
53
60
  model: "anthropic/claude-haiku-5-5",
54
61
  instructions: "You fix failing tests. You change no test. You commit the fix.",
55
62
  }),
63
+ cut: worktree(),
56
64
  // Push signed copies of the Agent's commits, with the key of the git.credentials entry.
57
65
  publish: push({ sign: true }),
58
66
  fail: fail(),
@@ -61,23 +69,32 @@ const body = jr2Setup({
61
69
  id: "publish",
62
70
  context: ({ input }) => input,
63
71
  on: { "workspace.lost": ".lost", "agent.fault": ".failed" },
64
- initial: "coding",
72
+ initial: "cutting",
65
73
  states: {
74
+ // The Workspace only clones. The Machine cuts the Worktree that the Agent works in.
75
+ cutting: {
76
+ invoke: {
77
+ src: "cut",
78
+ input: ({ context }) => ({ path: fixTree(context), branch: context.branch }),
79
+ onDone: [{ guard: ({ event }) => isReady(event.output), target: "coding" }, { target: "notCut" }],
80
+ },
81
+ },
66
82
  coding: {
67
83
  invoke: {
68
84
  src: "coder",
69
- input: ({ context }) => ({ prompt: context.prompt, cwd: context.workspace.repos.app }),
85
+ input: ({ context }) => ({ prompt: context.prompt, cwd: fixTree(context) }),
70
86
  },
71
87
  on: { finished: "review" },
72
88
  },
73
89
  // A person reads the branch, then answers.
74
90
  review: {
75
- invoke: { src: "gate", input: ({ context }) => ({ meta: { branch: context.workspace.branch } }) },
91
+ invoke: { src: "gate", input: ({ context }) => ({ meta: { branch: context.branch } }) },
76
92
  on: { approve: "publishing", stop: "done" },
77
93
  },
78
94
  publishing: {
79
95
  invoke: {
80
96
  src: "publish",
97
+ input: ({ context }) => ({ worktree: fixTree(context) }),
81
98
  onDone: [
82
99
  { guard: ({ event }) => event.output.outcome === "pushed", target: "done" },
83
100
  // rejected, diverged or unknown: the run waits, so that the Sandbox and its commits stay.
@@ -90,6 +107,7 @@ const body = jr2Setup({
90
107
  on: { approve: "publishing", stop: "done" },
91
108
  },
92
109
  done: { type: "final" },
110
+ notCut: { invoke: { src: "fail", input: { reason: "the Worktree was not cut" } } },
93
111
  failed: { invoke: { src: "fail", input: { reason: "the Agent's Turn could not go on" } } },
94
112
  lost: { invoke: { src: "fail", input: { reason: "the Sandbox is gone" } } },
95
113
  },
@@ -98,7 +116,6 @@ const body = jr2Setup({
98
116
  export const machine = workspace(body, {
99
117
  input: runInput,
100
118
  repos: { app: "https://github.com/<you>/app.git" },
101
- spec: ({ input }) => ({ branch: input.branch }),
102
119
  });
103
120
  ```
104
121
 
@@ -111,9 +128,11 @@ import {
111
128
  agent,
112
129
  defineEvent,
113
130
  fail,
131
+ isReady,
114
132
  jr2Setup,
115
133
  push,
116
134
  workspace,
135
+ worktree,
117
136
  type PushOutput,
118
137
  type Workspaced,
119
138
  } from "@jr2/orchestrator";
@@ -131,6 +150,9 @@ const runInput = z.object({ prompt: z.string(), branch: z.string() });
131
150
  type BodyInput = Workspaced<z.infer<typeof runInput>, "app">;
132
151
  type Context = BodyInput & { pushed?: PushOutput };
133
152
 
153
+ // The Worktree of the coder. The push names it, and jr2 reads its branch from the cut.
154
+ const fixTree = (context: BodyInput) => `${context.workspace.repos.app}/fix` as const;
155
+
134
156
  const body = jr2Setup({
135
157
  types: {} as { input: BodyInput; context: Context },
136
158
  events: [finished, approve, stop],
@@ -139,6 +161,7 @@ const body = jr2Setup({
139
161
  model: "local/qwen3.6-35b-a3b",
140
162
  instructions: "You fix failing tests. You change no test. You commit the fix.",
141
163
  }),
164
+ cut: worktree(),
142
165
  // Push signed copies of the Agent's commits, with the key of the git.credentials entry.
143
166
  publish: push({ sign: true }),
144
167
  fail: fail(),
@@ -147,23 +170,32 @@ const body = jr2Setup({
147
170
  id: "publish",
148
171
  context: ({ input }) => input,
149
172
  on: { "workspace.lost": ".lost", "agent.fault": ".failed" },
150
- initial: "coding",
173
+ initial: "cutting",
151
174
  states: {
175
+ // The Workspace only clones. The Machine cuts the Worktree that the Agent works in.
176
+ cutting: {
177
+ invoke: {
178
+ src: "cut",
179
+ input: ({ context }) => ({ path: fixTree(context), branch: context.branch }),
180
+ onDone: [{ guard: ({ event }) => isReady(event.output), target: "coding" }, { target: "notCut" }],
181
+ },
182
+ },
152
183
  coding: {
153
184
  invoke: {
154
185
  src: "coder",
155
- input: ({ context }) => ({ prompt: context.prompt, cwd: context.workspace.repos.app }),
186
+ input: ({ context }) => ({ prompt: context.prompt, cwd: fixTree(context) }),
156
187
  },
157
188
  on: { finished: "review" },
158
189
  },
159
190
  // A person reads the branch, then answers.
160
191
  review: {
161
- invoke: { src: "gate", input: ({ context }) => ({ meta: { branch: context.workspace.branch } }) },
192
+ invoke: { src: "gate", input: ({ context }) => ({ meta: { branch: context.branch } }) },
162
193
  on: { approve: "publishing", stop: "done" },
163
194
  },
164
195
  publishing: {
165
196
  invoke: {
166
197
  src: "publish",
198
+ input: ({ context }) => ({ worktree: fixTree(context) }),
167
199
  onDone: [
168
200
  { guard: ({ event }) => event.output.outcome === "pushed", target: "done" },
169
201
  // rejected, diverged or unknown: the run waits, so that the Sandbox and its commits stay.
@@ -176,6 +208,7 @@ const body = jr2Setup({
176
208
  on: { approve: "publishing", stop: "done" },
177
209
  },
178
210
  done: { type: "final" },
211
+ notCut: { invoke: { src: "fail", input: { reason: "the Worktree was not cut" } } },
179
212
  failed: { invoke: { src: "fail", input: { reason: "the Agent's Turn could not go on" } } },
180
213
  lost: { invoke: { src: "fail", input: { reason: "the Sandbox is gone" } } },
181
214
  },
@@ -184,7 +217,6 @@ const body = jr2Setup({
184
217
  export const machine = workspace(body, {
185
218
  input: runInput,
186
219
  repos: { app: "https://github.com/<you>/app.git" },
187
- spec: ({ input }) => ({ branch: input.branch }),
188
220
  });
189
221
  ```
190
222
 
@@ -313,6 +345,7 @@ jr2 up
313
345
  ```text
314
346
  …
315
347
  effects: workflow "publish" — what it runs outside itself (ADR-0067)
348
+ cut: worktree — 600s, in the Harness
316
349
  publish: push (sign) — 300s, in the Sandbox Effector
317
350
  …
318
351
  Workspace of workflow "publish": Sandbox Effector (image the Sandbox Image) holds no Effect secret; pushes Repo Slot "app" with git.credentials "github.com/<you>/"
@@ -372,7 +405,8 @@ Each outcome is output for `onDone`. Route on `outcome`
372
405
  ([`PushOutput`](../reference/authoring-surface/type-pushoutput.md)):
373
406
 
374
407
  - `pushed`: the remote has the commit. `published` is the commit on the remote, and `source` is the Agent's commit.
375
- - `rejected`: git, the remote or the Sandbox Effector refused the push. `stage` tells where, and `reason` tells why.
408
+ - `rejected`: git, the remote or the Sandbox Effector refused the push. `stage` tells where, and `reason` tells why. A
409
+ `worktree` that jr2 cannot use is `rejected` at the `stage` `start`, and jr2 pushes nothing. See [Rules](#rules).
376
410
  - `diverged`: in a signed push, the commit on the remote is not in the history of the Agent's branch, and jr2 cannot
377
411
  pair it with an Agent commit. jr2 pushed nothing. An unsigned push to a remote branch that moved is `rejected`.
378
412
  - `unknown`: jr2 cannot tell what the push did.
@@ -394,12 +428,14 @@ jr2 send <run id> --gate body.notPushed --event approve
394
428
 
395
429
  ## Other options
396
430
 
397
- - `pin: true`: push the commit that the input of the Effect names, `{ sha: "<full commit id>" }`. Use it for a commit
398
- that a Gate approved. Without `pin`, jr2 pushes the tip of the branch when the Effect starts.
399
- - `squash: true`: push one commit that holds all of the changes. The input gives its message, `{ message: "<text>" }`.
400
- Without `sign`, the [`committer`](../reference/config.md#git-credentials-committer) of the entry commits it.
431
+ - `pin: true`: push the commit that the input of the Effect names, `{ worktree, sha: "<full commit id>" }`. Use it for a
432
+ commit that a Gate approved. Without `pin`, jr2 pushes the tip of the branch when the Effect starts.
433
+ - `squash: true`: push one commit that holds all of the changes. The input gives its message,
434
+ `{ worktree, message: "<text>" }`. Without `sign`, the [`committer`](../reference/config.md#git-credentials-committer)
435
+ of the entry commits it.
401
436
  - `force: true`: replace what the remote branch holds.
402
- - `slot`: the Repo Slot to push. Write it only when the Workspace has more than one Repo Slot.
437
+ - `slot`: the Repo Slot to push. Write it only when the Workspace has more than one Repo Slot. It is static, because
438
+ `jr2 up` places the credential for each slot.
403
439
  - `timeout`: how long jr2 waits for the push. The default is `"5m"`. After it, the outcome is `unknown`.
404
440
 
405
441
  ## Rules
@@ -461,6 +497,15 @@ When a `push` starts, it refuses:
461
497
  `push({ pin: true }): its input's sha is not a full commit id (got <sha>)`
462
498
  - with `squash: true`, an input with no message: `push({ squash: true }): its input carries no message`
463
499
 
500
+ A push settles `rejected`, with `stage` `start`, for each of these. Its `reason` ends `; nothing was pushed`:
501
+
502
+ - a `worktree` that is not a Worktree path, or a slot that the Workspace does not have:
503
+ `"<path>" is not a Worktree path: /work/<slot>/<name>, with one segment in <name>`, or
504
+ `"<path>" names Repo Slot "<slot>", which its Workspace does not carry (<slots>)`
505
+ - a `worktree` that no cut made in this Sandbox: `no cut made <path> in this Sandbox: cut it with worktree()`
506
+ - a Worktree of a different Repo Slot: `<path> is a Worktree of Repo Slot "<slot>", not of "<slot>"`
507
+ - a detached Worktree: `<path> is detached: a push publishes the branch of a Worktree, and it holds none`
508
+
464
509
  `push()` refuses a timeout that is not a positive duration:
465
510
  `timeout "<timeout>" is not a positive duration (like "30s", "5m")`
466
511
 
@@ -474,6 +519,7 @@ the push Secret of the entry, `jr2-git-push-<hash>`, as `jr2 up` shows it. It is
474
519
  - [Secrets and trust](../concepts/secrets-and-trust.md): who holds the push credential and the signing key.
475
520
  - [Give the cluster git credentials](give-the-cluster-git-credentials.md): the entries of `git.credentials`.
476
521
  - [Add tools to the Sandbox](add-tools-to-the-sandbox.md): the Sandbox Image.
522
+ - [Cut a Worktree](cut-a-worktree.md): the Worktree that a `push` publishes.
477
523
  - Reference: [`push`](../reference/authoring-surface/push.md),
478
524
  [`PushOptions`](../reference/authoring-surface/type-pushoptions.md),
479
525
  [`PushOutput`](../reference/authoring-surface/type-pushoutput.md) and
@@ -0,0 +1,225 @@
1
+ ---
2
+ title: Read a conversation
3
+ description: Read what an Agent said and did in a run, live or after the run ended, with jr2 logs or the Console.
4
+ ---
5
+
6
+ # Read a conversation
7
+
8
+ Read the [Conversation](../reference/glossary.md#conversation) of each [Agent](../reference/glossary.md#agent) of a run,
9
+ while the run continues or after it ended.
10
+
11
+ The [Harness](../reference/glossary.md#harness) of each Agent sends the entries of its conversation to the
12
+ [Orchestrator](../reference/glossary.md#orchestrator) during the [Turn](../reference/glossary.md#turn). The Orchestrator
13
+ keeps them for as long as it keeps the run. Thus you can read a conversation after its
14
+ [Sandbox](../reference/glossary.md#sandbox) is gone. A [Menu](../reference/glossary.md#menu)-only Agent sends its
15
+ conversation in the same way.
16
+
17
+ The examples on this page use a run of the `task` [Workflow](../reference/glossary.md#workflow) of
18
+ [An Agent in a Sandbox](../get-started/an-agent-in-a-sandbox.md), with the prompt
19
+ ``In docs/intro/repo, run `node bin/greet.js`. Then finish, with what it printed.``. In the commands, replace `<run id>`
20
+ with the run id, or its first 4 characters or more. `jr2 run` prints the run id in the line
21
+ `run <run id> (<workflow>) — attached`.
22
+
23
+ Give each `jr2` command in the [Instance](../reference/glossary.md#instance) folder.
24
+
25
+ ## Print the conversations of a run
26
+
27
+ Run [`jr2 logs`](../reference/cli.md#logs) with the run id. It prints the conversation of each Agent of the run, in the
28
+ order of the time of each entry:
29
+
30
+ ```sh
31
+ jr2 logs <run id>
32
+ ```
33
+
34
+ ```text
35
+ → context <context> / namespace <namespace>
36
+ [coder] [7a0e8b50-7b3e-4d83-837c-d07857d81868/body/coder] [prompt] In docs/intro/repo, run `node bin/greet.js`. Then finish, with what it printed.
37
+ [coder] [7a0e8b50-7b3e-4d83-837c-d07857d81868/body/coder]
38
+ [coder] [7a0e8b50-7b3e-4d83-837c-d07857d81868/body/coder] Work in /work/target/task, on branch jr2/task-48ebf9ad-1e5d-4997-a330-d91ec762f83c — your tools are rooted there, so a relative path lands inside it. Commit what you do there, then call finish.
39
+ [coder] [7a0e8b50-7b3e-4d83-837c-d07857d81868/body/coder]
40
+ [coder] [7a0e8b50-7b3e-4d83-837c-d07857d81868/body/coder] <jr2-turn>
41
+ [coder] [7a0e8b50-7b3e-4d83-837c-d07857d81868/body/coder] Working directory: /work/target/task
42
+ [coder] [7a0e8b50-7b3e-4d83-837c-d07857d81868/body/coder] Allowed now: `mcp__jr2__finish`.
43
+ [coder] [7a0e8b50-7b3e-4d83-837c-d07857d81868/body/coder] </jr2-turn>
44
+ [coder] [7a0e8b50-7b3e-4d83-837c-d07857d81868/body/coder] [thinking] The user wants me to:
45
+ [coder] [7a0e8b50-7b3e-4d83-837c-d07857d81868/body/coder] 1. Run `node bin/greet.js` in the directory `docs/intro/repo`
46
+ [coder] [7a0e8b50-7b3e-4d83-837c-d07857d81868/body/coder] 2. Finish with what it printed
47
+ [coder] [7a0e8b50-7b3e-4d83-837c-d07857d81868/body/coder]
48
+ [coder] [7a0e8b50-7b3e-4d83-837c-d07857d81868/body/coder] Let me first check if this file exists and what it contains, then run it.
49
+ [coder] [7a0e8b50-7b3e-4d83-837c-d07857d81868/body/coder]
50
+ [coder] [7a0e8b50-7b3e-4d83-837c-d07857d81868/body/coder] [text]
51
+ [coder] [7a0e8b50-7b3e-4d83-837c-d07857d81868/body/coder]
52
+ [coder] [7a0e8b50-7b3e-4d83-837c-d07857d81868/body/coder]
53
+ [coder] [7a0e8b50-7b3e-4d83-837c-d07857d81868/body/coder] [bash] node docs/intro/repo/bin/greet.js
54
+ [coder] [7a0e8b50-7b3e-4d83-837c-d07857d81868/body/coder] [thinking] The command printed "hello, world". Now I need to finish with that.
55
+ [coder] [7a0e8b50-7b3e-4d83-837c-d07857d81868/body/coder]
56
+ [coder] [7a0e8b50-7b3e-4d83-837c-d07857d81868/body/coder] [text]
57
+ [coder] [7a0e8b50-7b3e-4d83-837c-d07857d81868/body/coder]
58
+ [coder] [7a0e8b50-7b3e-4d83-837c-d07857d81868/body/coder]
59
+ [coder] [7a0e8b50-7b3e-4d83-837c-d07857d81868/body/coder] [finish] {"summary":"Ran `node bin/greet.js` in docs/intro/repo. It printed: hello, world"}
60
+ [coder] [7a0e8b50-7b3e-4d83-837c-d07857d81868/body/coder] [finish answer] Delivered "finish" to the workflow (delivery a86c2340-377a-4c4d-a138-2872c38c1219). The workflow consumed it and moved on: your turn is over.
61
+ ```
62
+
63
+ The thinking, the calls and the text are the words of the model, so your conversation is different. Your ids are
64
+ different too.
65
+
66
+ `jr2 logs` prints the conversation lines of the pod log of the Harness. It does not print the lines of the story of the
67
+ run: `[run] …`, and `[<agent>] [admitted] …` and `[<agent>] [pick] …`, which have no Instance ID.
68
+ [Watch a run](watch-a-run.md#read-the-pod-log) tells how to read the pod log.
69
+
70
+ ## Print the conversation of one Agent
71
+
72
+ Give an Agent slot, or the name of an Agent, after the run id. An Agent slot is the path of the
73
+ [Machine](../reference/glossary.md#machine) of the Agent, then its name, such as `body/coder`.
74
+ [`jr2 steer`](../reference/cli.md#steer) `<run id>` lists the Agent slots of a live run. A name, such as `coder`, prints
75
+ each conversation of the Agents of that name:
76
+
77
+ ```sh
78
+ jr2 logs <run id> coder
79
+ ```
80
+
81
+ When the run keeps no conversation of that Agent, `jr2 logs` lists the Agents that it keeps. Without `-f`, it then exits
82
+ with `1`. With `-f`, it waits for the conversation of that Agent.
83
+
84
+ ## Follow a conversation
85
+
86
+ Add `-f` to print each new entry when the Orchestrator keeps it:
87
+
88
+ ```sh
89
+ jr2 logs <run id> -f
90
+ ```
91
+
92
+ `jr2 logs -f` first prints what the Orchestrator keeps. Then it follows each conversation that has an open Turn, and it
93
+ finds each new conversation of the run. It stops when the run ended and no Turn is open. The Harness sends its entries
94
+ when the model's answer ends, at the end of the Turn, and about one time each second. Thus a line comes a short time
95
+ after the model wrote it.
96
+
97
+ ## Read the lines
98
+
99
+ Each line starts with the name of the Agent in brackets, then the [Instance ID](../reference/glossary.md#instance-id) of
100
+ the conversation in brackets. The Instance ID starts with the run id. The first line of each entry then has a label in
101
+ brackets. The next lines of the same entry have no label:
102
+
103
+ | Line | What it shows |
104
+ | --------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
105
+ | `[<agent>] [<iid>] [prompt] <text>` | A message that the model reads: the prompt of the Turn, or a message that jr2 adds to the Turn, such as a [Steering message](../reference/glossary.md#steering-message) or a notice. |
106
+ | `[<agent>] [<iid>] [thinking] <text>` | The thinking of the model. |
107
+ | `[<agent>] [<iid>] [text] <text>` | The text of the model. |
108
+ | `[<agent>] [<iid>] [<call>] <input>` | A call of a [Working tool](../reference/glossary.md#working-tools), or a pick from the Menu. `<input>` is a path for read, write and edit, the command for `bash`, or else JSON. |
109
+ | `[<agent>] [<iid>] [<server>/<tool>] <input>` | A call of an [MCP tool](../reference/glossary.md#mcp-tools): the server's name in `jr2.config.ts`, then the tool. `<input>` is JSON. A pick never prints with a `/`. |
110
+ | `[<agent>] [<iid>] [<pick> answer] <text>` | The answer that the model got for a pick from its Menu. |
111
+ | `[<agent>] [<iid>] [<pick> error] <text>` | An answer to a pick that the model reads as an error, such as a refusal. |
112
+ | `[<agent>] [<iid>] [compacted] <text>` | The Harness made the context of the conversation smaller: `context <before> → ~<after> tokens (window <window>)`. |
113
+ | `[<agent>] [<iid>] [thinking level] <text>` | The model has no thinking level of the name that the Turn asked for, and the line names the level that the model ran at. The Harness prints it one time for each Turn. |
114
+ | `[<agent>] [<iid>] [cut] <text>` | The Orchestrator keeps no more entries of this conversation. See [Rules](#rules). |
115
+
116
+ The conversation does not hold the result of a Working tool or of an MCP tool. For example, it does not hold the text of
117
+ a file that the Agent read, or the output of a command that the Agent ran. The Harness cuts an input that is longer than
118
+ 2000 characters at its end, and marks the cut with `…`. It cuts a long answer to a pick in its middle, and marks the cut
119
+ with `… [<n> characters cut] …`. The model reads the full text.
120
+
121
+ ## Read a conversation in the Console
122
+
123
+ With a [Caller](../reference/glossary.md#caller) token that has the `read` scope for the Workflow, the
124
+ [Console](../reference/glossary.md#console) shows the conversations of the run that you select:
125
+
126
+ - The bottom drawer has one tab for each Agent slot of the run. A dot on a tab shows a slot whose Turn is open.
127
+ - Click a tab. The drawer opens on the conversation of that slot. While the Turn is open, the drawer adds each new
128
+ entry.
129
+ - The drawer folds each pick with its answer. A Working tool's call shows no result. It shows the Steering messages, the
130
+ notices and each [Compaction](../reference/glossary.md#compaction).
131
+ - The Fleet rail lists the ended runs of the Workflow under its live runs. Click an ended run to read its conversations.
132
+
133
+ [Open the Console](open-the-console.md#read-a-conversation) tells more.
134
+
135
+ ## Keep conversations for a different time
136
+
137
+ The Orchestrator keeps an ended run, with its conversations, for 30 days. To change the time, set
138
+ [`runs.retain`](../reference/config.md#runs) in `jr2.config.ts`. The conversations are on the state volume of the
139
+ Orchestrator. A new volume claim is `5Gi` by default. To make it larger, set `runs.volume`:
140
+
141
+ ```ts
142
+ import { defineConfig } from "@jr2/orchestrator";
143
+
144
+ export default defineConfig({
145
+ runs: {
146
+ // Keep each ended run, its conversations and the hook log for 90 days.
147
+ retain: "90d",
148
+ // The size of the Orchestrator's state volume. A larger size needs a StorageClass that allows expansion.
149
+ volume: "20Gi",
150
+ },
151
+ });
152
+ ```
153
+
154
+ Then run [`jr2 up`](../reference/cli.md#up). The Orchestrator uses the new `retain` at its next sweep, one time each
155
+ hour. When `runs.volume` is larger than the volume claim, `jr2 up` makes the claim larger, but only when its
156
+ StorageClass allows expansion. The `standard` class of kind does not. Thus on kind, with the claim of `5Gi` that the
157
+ first `jr2 up` made, `jr2 up` refuses, and applies nothing:
158
+
159
+ ```text
160
+ …
161
+ refusing: runs.volume is 20Gi, larger than the state volume claim jr2-state (5Gi), and its StorageClass "standard" does not allow expansion (allowVolumeExpansion is not true). Keep runs.volume at 5Gi, or use a StorageClass that allows expansion (ADR-0065). Nothing was applied.
162
+ ```
163
+
164
+ On kind, set `runs.volume` before the first `jr2 up` of the Instance. A new claim takes that size, and `jr2 up` prints
165
+ no line about it. A live run and its conversations stay, whatever their age.
166
+
167
+ ## Rules
168
+
169
+ - The Orchestrator keeps at most 8 MiB of one conversation. It keeps the start of the conversation. In place of the
170
+ entry that goes above the limit, it keeps one entry `[cut]`, and it keeps no entry after it:
171
+ `the Orchestrator keeps no more of this conversation: it is at its cap of 8 MiB (ADR-0023)`
172
+ - When the state volume is more than 80% full, the Orchestrator deletes the conversations of the runs that ended, the
173
+ oldest run first, until the volume is less than 80% full. It does not delete the row of the run. It never deletes a
174
+ conversation of a live run for space. `jr2 logs` prints `<agent slot> [<iid>]: no space` in place of a conversation
175
+ that it deleted, and `jr2 status` and `jr2 runs` give the run `swept: "conversation swept: no space"`.
176
+ - When the volume is more than 95% full and no ended run has a conversation to delete, the Orchestrator keeps no more
177
+ entries of each open conversation:
178
+ `the Orchestrator keeps no more of this conversation: its state volume is full (ADR-0065)`
179
+ - `jr2 logs` with an Agent that the run keeps no conversation of prints a line on stderr. Without `-f`, it then exits
180
+ with `1`; with `-f`, it waits: `run <run id> keeps no conversation of "<agent>" — its Agents: <slots>`
181
+ - When the run keeps no conversation at all, the line ends differently:
182
+ `run <run id> keeps no conversation of "<agent>" — it keeps no conversation yet`
183
+ - The routes of the conversations refuse a Caller without the `read` scope for the Workflow of the run, with the status
184
+ code `403`: `the Caller <via>/<name> needs the "read" scope for Workflow "<workflow>" (ADR-0078)`. A Caller with the
185
+ `read` scope for no Workflow gets this refusal first:
186
+ `the Caller <via>/<name> has no "read" scope for any Workflow (ADR-0078)`
187
+ - `GET /runs/:runId/conversations/:instanceId` refuses an Instance ID that the run does not keep, with the status code
188
+ `404`: `run "<run id>" keeps no conversation "<iid>"`
189
+ - `runs.retain` is a number and `m`, `h`, `d` or `w`. The config load refuses another value:
190
+ `<file> at runs.retain: "<value>" is not a duration — a number and m, h, d or w, such as "30d" (ADR-0065)`
191
+ - The config load refuses a `runs.retain` that is shorter than one hour:
192
+ `<file> at runs.retain: "<value>" is shorter than 1h — jr2 keeps an ended run for at least 1h (ADR-0065)`
193
+ - The config load refuses a `runs.volume` with no unit:
194
+ `<file> at runs.volume: "<value>" is not a storage quantity — a number and a unit, such as "5Gi" or "500Mi" (ADR-0065)`
195
+ - `jr2 up` grows the claim when `runs.volume` is larger and the StorageClass allows expansion:
196
+ `state volume: growing the claim jr2-state from <claim size> to <size>`
197
+ - `jr2 up` keeps the size of a claim that exists when `runs.volume` is not set, and the claim is not `5Gi`:
198
+ `state volume: keeping the claim jr2-state at <claim size> — runs.volume is not set, and the default 5Gi is for a new claim`
199
+ - `jr2 up` refuses, and applies nothing, when it cannot read the claim:
200
+ `refusing: cannot read the state volume claim jr2-state in namespace "<namespace>" (<error>). Nothing was applied.`
201
+ - `jr2 up` refuses, and applies nothing, when `runs.volume` is larger and it cannot read the StorageClass:
202
+ `refusing: runs.volume is <size>, larger than the state volume claim jr2-state (<claim size>), and jr2 cannot read StorageClass "<class>" to see if it allows expansion (<error>). Nothing was applied.`
203
+ - `jr2 up` refuses a `runs.volume` that is smaller than the claim, and applies nothing:
204
+ `refusing: runs.volume is <size>, smaller than the state volume claim jr2-state (<claim size>) — Kubernetes never makes a claim smaller. Set runs.volume to <claim size> or more (ADR-0065). Nothing was applied.`
205
+ - `jr2 up` refuses a larger `runs.volume` on a StorageClass that does not allow expansion, and applies nothing:
206
+ `refusing: runs.volume is <size>, larger than the state volume claim jr2-state (<claim size>), and its StorageClass "<class>" does not allow expansion (allowVolumeExpansion is not true). Keep runs.volume at <claim size>, or use a StorageClass that allows expansion (ADR-0065). Nothing was applied.`
207
+
208
+ > **Caution**
209
+ >
210
+ > A Caller with `read` can read each conversation of the Workflow, and the answers that jr2 gives to the picks. An answer
211
+ > can hold the output of a [`command`](../reference/authoring-surface/command.md)
212
+ > [Effect](../reference/glossary.md#effect). Give `read` only to the Callers that can see that output.
213
+ > [Secrets and trust](../concepts/secrets-and-trust.md) tells what a conversation can hold.
214
+
215
+ ## Read next
216
+
217
+ - [Agents and Turns](../concepts/agents-and-turns.md)
218
+ - [Durable runs](../concepts/durable-runs.md): how long jr2 keeps a run.
219
+ - [ADR-0023](../reference/decisions/0023-the-harness-prints-the-conversation.md): the Harness prints the conversation,
220
+ and the Orchestrator keeps it.
221
+ - [ADR-0065](../reference/decisions/0065-a-persist-survives-a-crash-and-history-is-kept-for-a-set-time.md):
222
+ `runs.retain`, `runs.volume` and the space guard.
223
+ - Reference: [`jr2 logs`](../reference/cli.md#logs), [`runs`](../reference/config.md#runs),
224
+ [`GET /runs/:runId/conversations`](../reference/http-api.md#get-runs-runid-conversations)
225
+ - [Watch a run](watch-a-run.md)
@@ -141,26 +141,24 @@ Put the Chart file in a folder that has the name of its wrapper: `workflows/<wra
141
141
  lower-case letters, digits and `-`. Then run [`jr2 up`](../reference/cli.md#up). It checks each Chart file at the door
142
142
  before it changes the cluster, and publishes it in the [Assembly](../reference/glossary.md#assembly).
143
143
 
144
- [`jr2 runs`](../reference/cli.md#runs) lists the Chart under its wrapper, on stderr:
144
+ [`jr2 workflows`](../reference/cli.md#workflows) lists the Chart under its wrapper:
145
145
 
146
146
  ```sh
147
- jr2 runs
147
+ jr2 workflows
148
148
  ```
149
149
 
150
150
  ```text
151
151
  …
152
152
  → context kind-jr2 / namespace my-instance
153
- workflows:
154
- notes (machine, Chart wrapper: body "body", one-shot)
155
- notes/summary (chart file)
156
- ping (machine)
157
- []
153
+ notes (machine, Chart wrapper: body "body", one-shot)
154
+ notes/summary (chart file)
155
+ ping (machine)
158
156
  ```
159
157
 
160
158
  The first line, `…`, is the line `→ .env:`, with the keys that the CLI took from `.env`.
161
159
 
162
- `one-shot` means that the wrapper also takes a Chart in its run input. `jr2 runs --workflows` prints the same list as
163
- JSON on stdout.
160
+ `one-shot` means that the wrapper also takes a Chart in its run input. `jr2 workflows --json` prints the same list as
161
+ JSON.
164
162
 
165
163
  ## Run the Chart
166
164
 
@@ -173,7 +171,7 @@ jr2 run notes/summary --input '{"topic":"the greet CLI"}'
173
171
  ```text
174
172
  …
175
173
  → context kind-jr2 / namespace my-instance
176
- run 08a1a07b-b5d8-4e8b-aec5-811eab9289ec (notes/summary) — attached
174
+ run ff5db853-9afc-4563-9db4-e5c2a49b15a2 (notes/summary) — attached
177
175
  → active "running"
178
176
  → active "running"
179
177
  → done "done"
@@ -203,12 +201,12 @@ curl -X PUT -H "Authorization: Bearer $TOKEN" -H "content-type: application/json
203
201
  ```
204
202
 
205
203
  ```text
206
- {"name":"notes/brief","origin":"runtime","hash":"4685124c248a"}
204
+ {"name":"notes/brief","origin":"runtime","hash":"4f2fb0e7474c"}
207
205
  ```
208
206
 
209
207
  `hash` is the hash of the Chart text. The status code is `201` for a new name, and `200` when the Chart replaced a
210
- runtime Chart with the same name. `jr2 runs` then lists `notes/brief (chart)`, and `jr2 run notes/brief` starts it. A
211
- run of the old text keeps its own text.
208
+ runtime Chart with the same name. `jr2 workflows` then lists `notes/brief (chart)`, and `jr2 run notes/brief` starts it.
209
+ A run of the old text keeps its own text.
212
210
 
213
211
  To remove the Chart:
214
212
 
@@ -217,7 +215,7 @@ curl -X DELETE -H "Authorization: Bearer $TOKEN" http://localhost:4000/workflows
217
215
  ```
218
216
 
219
217
  The Orchestrator keeps a runtime Chart on its volume, so it stays after a restart. When a publish removes a part that it
220
- uses, it stays, and `jr2 runs` marks it `unrunnable` with the reason.
218
+ uses, it stays, and `jr2 workflows` marks it `unrunnable` with the reason.
221
219
 
222
220
  ## Run a Chart one time
223
221
 
@@ -254,7 +252,9 @@ write.
254
252
  - The `PUT` refuses a Chart that the door refuses, with the status `422`: `{"error":"refused","report":[<problems>]}`
255
253
  - The `DELETE` refuses a Chart file, with the status `409`:
256
254
  ``a Chart file is the Instance's own: remove workflows/<wrapper>/<name>.chart.json and `jr2 up` (ADR-0070)``
257
- - `PUT` and `DELETE` need the Instance token. Without it, the status is `401`.
255
+ - `PUT` and `DELETE` need the Instance token. No scope opens them. Without a token, the status is `401`. With the token
256
+ of a named Caller or a JWT, the status is `403`:
257
+ `this route needs the Instance token: no scope opens it, so the Caller <via>/<name> cannot`
258
258
  - An unrunnable named Chart does not start. The status is `409`: `named Chart "<wrapper>/<name>" cannot run: <reason>`
259
259
  - `jr2 run` prints the report of a Chart that the door refuses in the run input, and exits with `1`:
260
260
  `error: the door refused the Chart for "<workflow>"`, then one line for each problem.
@@ -264,7 +264,8 @@ write.
264
264
  - [Charts](../concepts/charts.md)
265
265
  - [Start a run](start-a-run.md)
266
266
  - [Let an Agent write a Chart](let-an-agent-write-a-chart.md)
267
- - Reference: [`chartSchema`](../reference/authoring-surface/chartschema.md), [`jr2 runs`](../reference/cli.md#runs),
267
+ - Reference: [`chartSchema`](../reference/authoring-surface/chartschema.md),
268
+ [`jr2 workflows`](../reference/cli.md#workflows),
268
269
  [`PUT /workflows/:wrapper/charts/:name`](../reference/http-api.md#put-workflows-wrapper-charts-name),
269
270
  [`GET /workflows/:wrapper/chart-schema`](../reference/http-api.md#get-workflows-wrapper-chart-schema)
270
271
  - [ADR-0070](../reference/decisions/0070-a-machine-lends-its-parts-to-a-chart.md): a Machine lends its parts to a Chart.