@jr2/orchestrator 0.6.0 → 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 (301) 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 +86 -9
  14. package/docs/concepts/architecture.md +41 -28
  15. package/docs/concepts/callers-and-hooks.md +205 -0
  16. package/docs/concepts/charts.md +7 -5
  17. package/docs/concepts/composition.md +10 -1
  18. package/docs/concepts/converge.md +4 -2
  19. package/docs/concepts/durable-runs.md +43 -16
  20. package/docs/concepts/effects.md +50 -22
  21. package/docs/concepts/gates.md +95 -25
  22. package/docs/concepts/machines-and-workflows.md +5 -4
  23. package/docs/concepts/pools-and-sources.md +187 -11
  24. package/docs/concepts/secrets-and-trust.md +73 -33
  25. package/docs/concepts/the-menu.md +11 -0
  26. package/docs/concepts/workspaces.md +6 -5
  27. package/docs/get-started/a-model-decides.md +14 -13
  28. package/docs/get-started/an-agent-in-a-sandbox.md +43 -34
  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/guides/add-tools-to-the-sandbox.md +55 -11
  32. package/docs/guides/answer-a-gate-from-a-forge.md +304 -0
  33. package/docs/guides/answer-a-gate.md +74 -37
  34. package/docs/guides/bind-open-parts.md +24 -8
  35. package/docs/guides/call-an-mcp-tool-from-a-machine.md +572 -0
  36. package/docs/guides/cancel-a-run.md +26 -16
  37. package/docs/guides/fix-a-failed-converge.md +18 -6
  38. package/docs/guides/give-a-caller-a-scope.md +203 -0
  39. package/docs/guides/give-an-agent-mcp-tools.md +422 -0
  40. package/docs/guides/iterate-on-a-machine-on-kind.md +10 -9
  41. package/docs/guides/let-an-agent-write-a-chart.md +9 -6
  42. package/docs/guides/look-inside-a-sandbox.md +101 -31
  43. package/docs/guides/open-the-console.md +63 -14
  44. package/docs/guides/read-a-conversation.md +225 -0
  45. package/docs/guides/run-a-chart-by-name.md +17 -16
  46. package/docs/guides/run-one-worker-per-item.md +15 -9
  47. package/docs/guides/set-an-agents-access-and-dials.md +2 -0
  48. package/docs/guides/start-a-run-for-each-alert.md +290 -0
  49. package/docs/guides/start-a-run-from-a-run.md +18 -16
  50. package/docs/guides/start-a-run.md +24 -18
  51. package/docs/guides/steer-an-agent.md +332 -0
  52. package/docs/guides/use-a-hosted-provider.md +1 -1
  53. package/docs/guides/watch-a-run.md +127 -121
  54. package/docs/guides/write-a-hook-kind.md +238 -0
  55. package/docs/guides/write-a-tool-as-an-mcp-server.md +351 -0
  56. package/docs/guides/write-a-workflow.md +17 -7
  57. package/docs/llms.txt +81 -15
  58. package/docs/reference/authoring-surface/agent.md +1 -1
  59. package/docs/reference/authoring-surface/answer.md +1 -1
  60. package/docs/reference/authoring-surface/arg.md +1 -1
  61. package/docs/reference/authoring-surface/basic.md +1 -1
  62. package/docs/reference/authoring-surface/bearer.md +1 -1
  63. package/docs/reference/authoring-surface/branchname.md +1 -1
  64. package/docs/reference/authoring-surface/carry.md +23 -0
  65. package/docs/reference/authoring-surface/chartschema.md +1 -1
  66. package/docs/reference/authoring-surface/chartschemafor.md +1 -1
  67. package/docs/reference/authoring-surface/command.md +1 -1
  68. package/docs/reference/authoring-surface/customize.md +4 -1
  69. package/docs/reference/authoring-surface/defineconfig.md +1 -1
  70. package/docs/reference/authoring-surface/defineevent.md +1 -1
  71. package/docs/reference/authoring-surface/dispatch.md +5 -4
  72. package/docs/reference/authoring-surface/fail.md +1 -1
  73. package/docs/reference/authoring-surface/file.md +1 -1
  74. package/docs/reference/authoring-surface/frompick.md +1 -1
  75. package/docs/reference/authoring-surface/gate.md +118 -0
  76. package/docs/reference/authoring-surface/group-agents.md +15 -0
  77. package/docs/reference/authoring-surface/group-charts.md +16 -0
  78. package/docs/reference/authoring-surface/group-composition.md +25 -0
  79. package/docs/reference/authoring-surface/group-config.md +17 -0
  80. package/docs/reference/authoring-surface/group-effects.md +48 -0
  81. package/docs/reference/authoring-surface/group-failure.md +13 -0
  82. package/docs/reference/authoring-surface/group-gates.md +16 -0
  83. package/docs/reference/authoring-surface/group-machine-and-events.md +15 -0
  84. package/docs/reference/authoring-surface/group-steering.md +12 -0
  85. package/docs/reference/authoring-surface/group-types-these-signatures-name.md +137 -0
  86. package/docs/reference/authoring-surface/group-workspaces-and-repos.md +15 -0
  87. package/docs/reference/authoring-surface/http.md +1 -1
  88. package/docs/reference/authoring-surface/isfailure.md +1 -1
  89. package/docs/reference/authoring-surface/isready.md +1 -1
  90. package/docs/reference/authoring-surface/jr2setup.md +13 -3
  91. package/docs/reference/authoring-surface/mcp.md +107 -0
  92. package/docs/reference/authoring-surface/open.md +5 -3
  93. package/docs/reference/authoring-surface/openbody.md +1 -1
  94. package/docs/reference/authoring-surface/paramsof.md +1 -1
  95. package/docs/reference/authoring-surface/pool.md +77 -9
  96. package/docs/reference/authoring-surface/push.md +1 -1
  97. package/docs/reference/authoring-surface/readyof.md +1 -1
  98. package/docs/reference/authoring-surface/reread.md +19 -0
  99. package/docs/reference/authoring-surface/secret.md +1 -1
  100. package/docs/reference/authoring-surface/sentby.md +1 -1
  101. package/docs/reference/authoring-surface/skip.md +22 -0
  102. package/docs/reference/authoring-surface/source.md +56 -1
  103. package/docs/reference/authoring-surface/steer.md +93 -0
  104. package/docs/reference/authoring-surface/text.md +1 -1
  105. package/docs/reference/authoring-surface/type-agentdefinition.md +14 -1
  106. package/docs/reference/authoring-surface/type-agentmcpserver.md +54 -0
  107. package/docs/reference/authoring-surface/type-anyframepath.md +1 -1
  108. package/docs/reference/authoring-surface/type-anyworktreepath.md +1 -1
  109. package/docs/reference/authoring-surface/type-binding.md +1 -1
  110. package/docs/reference/authoring-surface/type-caller.md +40 -0
  111. package/docs/reference/authoring-surface/type-callerrecord.md +32 -0
  112. package/docs/reference/authoring-surface/type-carry.md +19 -0
  113. package/docs/reference/authoring-surface/type-chainlink.md +3 -3
  114. package/docs/reference/authoring-surface/type-commandoutput.md +1 -1
  115. package/docs/reference/authoring-surface/type-customize.md +16 -1
  116. package/docs/reference/authoring-surface/type-delivered.md +17 -0
  117. package/docs/reference/authoring-surface/type-deliveredevent.md +18 -0
  118. package/docs/reference/authoring-surface/type-dispatchdefinition.md +4 -3
  119. package/docs/reference/authoring-surface/type-dispatchoutput.md +1 -1
  120. package/docs/reference/authoring-surface/type-effectbinding.md +12 -2
  121. package/docs/reference/authoring-surface/type-framepath.md +1 -1
  122. package/docs/reference/authoring-surface/type-gatebinding.md +15 -0
  123. package/docs/reference/authoring-surface/type-gatehooks.md +12 -0
  124. package/docs/reference/authoring-surface/type-gatelook.md +37 -0
  125. package/docs/reference/authoring-surface/type-gateoutcome.md +32 -0
  126. package/docs/reference/authoring-surface/type-gatereply.md +19 -0
  127. package/docs/reference/authoring-surface/type-gateslot.md +21 -0
  128. package/docs/reference/authoring-surface/type-gateslotinput.md +13 -0
  129. package/docs/reference/authoring-surface/type-gateslotparts.md +18 -0
  130. package/docs/reference/authoring-surface/type-gateslots.md +12 -0
  131. package/docs/reference/authoring-surface/type-gatetypesat.md +13 -0
  132. package/docs/reference/authoring-surface/type-hostinjectedinput.md +1 -1
  133. package/docs/reference/authoring-surface/type-httpoutput.md +1 -1
  134. package/docs/reference/authoring-surface/type-jr2config.md +37 -2
  135. package/docs/reference/authoring-surface/type-lateroutcome.md +1 -1
  136. package/docs/reference/authoring-surface/type-lends.md +5 -1
  137. package/docs/reference/authoring-surface/type-lookoutput.md +14 -0
  138. package/docs/reference/authoring-surface/type-mcpcalloutput.md +78 -0
  139. package/docs/reference/authoring-surface/type-mcpnotreturned.md +42 -0
  140. package/docs/reference/authoring-surface/type-mcpoptions.md +47 -0
  141. package/docs/reference/authoring-surface/type-mcpoutput.md +50 -0
  142. package/docs/reference/authoring-surface/type-mcpreadoutput.md +53 -0
  143. package/docs/reference/authoring-surface/type-mcpremoteserver.md +50 -0
  144. package/docs/reference/authoring-surface/type-mcpserver.md +41 -0
  145. package/docs/reference/authoring-surface/type-mcpstdioserver.md +42 -0
  146. package/docs/reference/authoring-surface/type-namedsecret.md +4 -4
  147. package/docs/reference/authoring-surface/type-openbodydeclaration.md +1 -1
  148. package/docs/reference/authoring-surface/type-openbodyoutput.md +1 -1
  149. package/docs/reference/authoring-surface/type-poolnextinput.md +1 -1
  150. package/docs/reference/authoring-surface/type-poolspec.md +11 -6
  151. package/docs/reference/authoring-surface/type-pushoutput.md +1 -1
  152. package/docs/reference/authoring-surface/type-pushsourcespec.md +38 -0
  153. package/docs/reference/authoring-surface/type-readsourcespec.md +47 -0
  154. package/docs/reference/authoring-surface/type-reposlot.md +1 -1
  155. package/docs/reference/authoring-surface/type-reread.md +18 -0
  156. package/docs/reference/authoring-surface/type-runsconfig.md +41 -0
  157. package/docs/reference/authoring-surface/type-sender.md +26 -1
  158. package/docs/reference/authoring-surface/type-sendercallerfield.md +14 -0
  159. package/docs/reference/authoring-surface/type-size.md +1 -1
  160. package/docs/reference/authoring-surface/type-skip.md +19 -0
  161. package/docs/reference/authoring-surface/type-sourcehooks.md +23 -0
  162. package/docs/reference/authoring-surface/type-sourcein.md +25 -0
  163. package/docs/reference/authoring-surface/type-sourcereply.md +18 -0
  164. package/docs/reference/authoring-surface/type-sourcespec.md +16 -7
  165. package/docs/reference/authoring-surface/type-sourceverdict.md +49 -0
  166. package/docs/reference/authoring-surface/type-standingpoolmachine.md +12 -0
  167. package/docs/reference/authoring-surface/type-standingpoolspec.md +51 -0
  168. package/docs/reference/authoring-surface/type-steerargs.md +20 -0
  169. package/docs/reference/authoring-surface/type-thinkinglevel.md +1 -1
  170. package/docs/reference/authoring-surface/type-usercontainer.md +1 -1
  171. package/docs/reference/authoring-surface/type-workspaced.md +1 -1
  172. package/docs/reference/authoring-surface/type-worktreefound.md +3 -3
  173. package/docs/reference/authoring-surface/type-worktreeinput.md +1 -1
  174. package/docs/reference/authoring-surface/type-worktreeoptions.md +1 -1
  175. package/docs/reference/authoring-surface/type-worktreeoutput.md +1 -1
  176. package/docs/reference/authoring-surface/type-worktreepath.md +1 -1
  177. package/docs/reference/authoring-surface/type-worktreeready.md +1 -1
  178. package/docs/reference/authoring-surface/type-worktreerefused.md +4 -4
  179. package/docs/reference/authoring-surface/workspace.md +1 -1
  180. package/docs/reference/authoring-surface/worktree.md +1 -1
  181. package/docs/reference/authoring-surface.md +88 -167
  182. package/docs/reference/cli.md +413 -74
  183. package/docs/reference/config.md +235 -2
  184. package/docs/reference/decisions/0002-duplex-streaming-actor.md +71 -11
  185. package/docs/reference/decisions/0005-sandbox-pod-composition.md +14 -10
  186. package/docs/reference/decisions/0006-agent-control-surface.md +4 -4
  187. package/docs/reference/decisions/0007-durable-machine-state.md +1 -1
  188. package/docs/reference/decisions/0009-cli-and-instance-interface.md +150 -49
  189. package/docs/reference/decisions/0010-bdd-acceptance-tests.md +5 -3
  190. package/docs/reference/decisions/0011-workflow-defined-events.md +256 -12
  191. package/docs/reference/decisions/0012-workspace-wrapper-machine.md +9 -2
  192. package/docs/reference/decisions/0013-the-agent-reaches-its-machine-through-a-container-it-cannot-read.md +20 -14
  193. package/docs/reference/decisions/0014-observation-is-open-run-state-is-not.md +53 -27
  194. package/docs/reference/decisions/0015-authoring-surface-absorbs-the-mechanism.md +18 -14
  195. package/docs/reference/decisions/0017-pool-over-a-source-port.md +226 -12
  196. package/docs/reference/decisions/0018-instance-agents-are-definitions-jr2-assembles-the-harness.md +15 -7
  197. package/docs/reference/decisions/0019-one-converging-command-against-the-current-context.md +32 -18
  198. package/docs/reference/decisions/0021-workspace-continuity-is-a-lease-that-answers-back.md +14 -1
  199. package/docs/reference/decisions/0022-observation-is-a-level-triggered-feed.md +4 -4
  200. package/docs/reference/decisions/0023-the-harness-prints-the-conversation.md +116 -34
  201. package/docs/reference/decisions/0024-an-agents-turn-ends-with-the-state-that-asked-for-it.md +38 -37
  202. package/docs/reference/decisions/0025-cancel-ends-a-run-stop-parks-it.md +10 -5
  203. package/docs/reference/decisions/0027-the-harness-is-jr2s-own-server-flue-retires-the-wire-stays.md +7 -6
  204. package/docs/reference/decisions/0028-what-an-agent-may-do-to-the-workspace-is-part-of-its-definition.md +23 -7
  205. package/docs/reference/decisions/0029-a-menu-is-fixed-for-a-conversation-and-a-turn-is-told-its-allowed-picks.md +18 -10
  206. package/docs/reference/decisions/0030-a-snapshot-names-the-machine-it-was-written-under.md +3 -2
  207. package/docs/reference/decisions/0031-menu-only-agents-run-on-the-instance-harness.md +23 -18
  208. package/docs/reference/decisions/0032-the-console-unlocks-with-a-callers-credential.md +101 -0
  209. package/docs/reference/decisions/0033-a-machine-declares-the-input-that-starts-it.md +4 -3
  210. package/docs/reference/decisions/0034-the-console-renders-with-preact-and-the-server-erases-the-types.md +6 -6
  211. package/docs/reference/decisions/0037-an-instance-builds-its-sandbox-images-jr2-injects-the-harness.md +5 -4
  212. package/docs/reference/decisions/0049-a-machine-carries-its-parts-and-composes-by-invoke.md +19 -19
  213. package/docs/reference/decisions/0050-what-code-names-config-declares-what-the-cli-names-discovery-finds.md +6 -1
  214. package/docs/reference/decisions/0054-the-kit-ships-machines-and-a-shipped-machine-leaves-its-parts-open.md +55 -40
  215. package/docs/reference/decisions/0055-a-release-is-a-pushed-tag-and-the-publish-guard-is-the-credential.md +14 -13
  216. package/docs/reference/decisions/0057-a-turn-is-its-frame-its-dials-and-whether-it-continues.md +7 -0
  217. package/docs/reference/decisions/0058-a-harness-answers-the-orchestrator-alone.md +13 -7
  218. package/docs/reference/decisions/0059-a-harness-holds-stand-ins-and-the-custodian-holds-the-keys.md +38 -30
  219. package/docs/reference/decisions/0062-jr2-briefs-the-agent-on-its-seat-never-on-its-task.md +64 -17
  220. package/docs/reference/decisions/0063-the-orchestrator-watches-the-cluster.md +2 -1
  221. package/docs/reference/decisions/0064-a-workspace-waits-for-capacity.md +2 -2
  222. package/docs/reference/decisions/0065-a-persist-survives-a-crash-and-history-is-kept-for-a-set-time.md +109 -0
  223. package/docs/reference/decisions/0066-a-model-tier-runs-a-real-model-and-a-change-to-what-it-reads-runs-the-tier.md +51 -23
  224. package/docs/reference/decisions/0067-an-effect-is-an-actor-slot-and-runs-at-most-once-unless-marked-idempotent.md +94 -54
  225. package/docs/reference/decisions/0068-an-effector-holds-an-effects-secrets-and-signs-its-wire.md +101 -47
  226. package/docs/reference/decisions/0069-the-orchestrator-is-a-kit-image-and-an-instance-publishes-its-assembly.md +32 -9
  227. package/docs/reference/decisions/0070-a-machine-lends-its-parts-to-a-chart.md +17 -13
  228. package/docs/reference/decisions/0071-a-run-starts-a-run-through-a-dispatch-effect.md +56 -30
  229. package/docs/reference/decisions/0072-the-docs-ship-inside-the-kit-and-an-instances-agents-md-indexes-them.md +35 -25
  230. package/docs/reference/decisions/0075-a-machine-cuts-a-worktree-and-the-workspace-only-clones.md +4 -3
  231. package/docs/reference/decisions/0076-an-agents-control-credential-lives-only-where-no-workspace-code-runs.md +37 -10
  232. package/docs/reference/decisions/0078-a-caller-comes-from-one-authenticator-seam-and-acts-within-its-scopes.md +285 -0
  233. 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
  234. package/docs/reference/decisions.md +6 -4
  235. package/docs/reference/glossary.md +96 -42
  236. package/docs/reference/hooks.md +1077 -0
  237. package/docs/reference/http-api.md +976 -149
  238. package/docs/why.md +2 -1
  239. package/package.json +10 -3
  240. package/src/actor.ts +36 -10
  241. package/src/agent.ts +50 -0
  242. package/src/assembly-checks.ts +530 -4
  243. package/src/callers.ts +245 -0
  244. package/src/chart.ts +52 -7
  245. package/src/config.ts +550 -1
  246. package/src/conversations.ts +453 -0
  247. package/src/custodian.ts +8 -2
  248. package/src/customize.ts +143 -4
  249. package/src/dispatch-effect.ts +142 -26
  250. package/src/durability.ts +2 -0
  251. package/src/duration.ts +20 -0
  252. package/src/effect-checks.ts +2 -1
  253. package/src/effect.ts +60 -7
  254. package/src/effector-wire.ts +272 -27
  255. package/src/gate-brand.ts +16 -0
  256. package/src/gate.ts +634 -48
  257. package/src/harness-client.ts +10 -4
  258. package/src/held-secrets.ts +72 -23
  259. package/src/holds.ts +2 -2
  260. package/src/hook-kinds/discord.ts +92 -0
  261. package/src/hook-kinds/door.ts +107 -0
  262. package/src/hook-kinds/github.ts +89 -0
  263. package/src/hook-kinds/gitlab.ts +72 -0
  264. package/src/hook-kinds/hook.ts +7 -0
  265. package/src/hook-kinds/index.ts +465 -0
  266. package/src/hook-kinds/slack.ts +151 -0
  267. package/src/hook-kinds/webhook.ts +113 -0
  268. package/src/hooks.ts +506 -0
  269. package/src/http-effect.ts +76 -38
  270. package/src/http.ts +889 -94
  271. package/src/index.ts +16 -5
  272. package/src/instance.ts +196 -26
  273. package/src/internal.ts +22 -3
  274. package/src/machine-doc.ts +26 -1
  275. package/src/mcp-effect.ts +424 -0
  276. package/src/mount-digest.ts +41 -7
  277. package/src/names.ts +64 -2
  278. package/src/notices.ts +138 -10
  279. package/src/open-body.ts +25 -11
  280. package/src/open-effect.ts +17 -4
  281. package/src/open.ts +4 -2
  282. package/src/parts.ts +87 -9
  283. package/src/party.ts +2 -1
  284. package/src/pick.ts +2 -2
  285. package/src/pool.ts +1142 -163
  286. package/src/registration.ts +203 -13
  287. package/src/run-host.ts +1509 -171
  288. package/src/run-list.ts +191 -0
  289. package/src/sandbox-kube.ts +53 -5
  290. package/src/secret-placement.ts +239 -33
  291. package/src/server.ts +53 -4
  292. package/src/setup.ts +72 -32
  293. package/src/snapshot-store.ts +565 -48
  294. package/src/steer.ts +111 -0
  295. package/src/stub-harness.ts +6 -2
  296. package/src/tokens.ts +263 -22
  297. package/src/wire.ts +17 -0
  298. package/src/workspace.ts +50 -6
  299. package/src/worktree.ts +3 -3
  300. package/docs/reference/decisions/0032-the-console-unlocks-with-the-instance-token.md +0 -61
  301. package/docs/reference/decisions/0065-a-persist-survives-a-crash-and-history-is-a-week.md +0 -65
@@ -15,7 +15,7 @@ Sandbox Image: a Machine names those itself.
15
15
  Every field is optional, and an Instance can run with no `jr2.config.ts`. Write the file as
16
16
  `export default defineConfig({ … })`. When the config loads, a file with no default export is
17
17
  refused: `` <file> has no default export (use `export default defineConfig({…})`) ``. The load also
18
- checks the shape of `git.credentials`, `secrets`, `harness.catalog` and `priorityClasses`. It
18
+ checks the shape of `git.credentials`, `secrets`, `harness.catalog`, `priorityClasses` and `mcp`. It
19
19
  checks that `sandbox` is an object, and checks its `resources`. Each refusal names the field.
20
20
  `jr2 up` checks the rest.
21
21
 
@@ -42,7 +42,7 @@ export default defineConfig({ name: "my-instance", harness });
42
42
  - [Secrets and trust](../concepts/secrets-and-trust.md)
43
43
  - [ADR-0050: What code names, config declares; what the CLI names, discovery finds](decisions/0050-what-code-names-config-declares-what-the-cli-names-discovery-finds.md)
44
44
 
45
- Fields: [`name`](#name), [`secrets`](#secrets), [`git`](#git), [`harness`](#harness), [`sandbox`](#sandbox), [`priorityClasses`](#priorityclasses), [`registry`](#registry), [`kitRegistry`](#kitregistry), [`platforms`](#platforms), [`operator`](#operator).
45
+ Fields: [`name`](#name), [`secrets`](#secrets), [`git`](#git), [`harness`](#harness), [`sandbox`](#sandbox), [`priorityClasses`](#priorityclasses), [`callers`](#callers), [`cors`](#cors), [`hooks`](#hooks), [`mcp`](#mcp), [`runs`](#runs), [`registry`](#registry), [`kitRegistry`](#kitregistry), [`platforms`](#platforms), [`operator`](#operator).
46
46
 
47
47
  <a id="name"></a>
48
48
 
@@ -701,6 +701,239 @@ An existing PriorityClass for the Orchestrator, the operator and the Repo cache
701
701
 
702
702
  An existing PriorityClass for the Sandboxes and the Instance Harness.
703
703
 
704
+ <a id="callers"></a>
705
+
706
+ ## `callers`
707
+
708
+ - Type: `CallersConfig`
709
+ - Required: no
710
+ - Default: none; only the Instance token acts
711
+
712
+ The Callers that act on the Instance with a credential of their own, and what each may do.
713
+ See `CallersConfig`.
714
+
715
+ <a id="callers-tokens"></a>
716
+
717
+ ### `callers.tokens`
718
+
719
+ - Type: `Readonly<Record<string, CallerToken>>`
720
+ - Required: no
721
+
722
+ The named Caller tokens, by name. A name is lowercase letters, digits and `-`, at most 40
723
+ characters, from a letter to a letter or digit. The config load refuses `instance`, the
724
+ Instance token's name. A name that the config no longer declares stops working at the next
725
+ `jr2 up`.
726
+
727
+ <a id="callers-tokens-name-may"></a>
728
+
729
+ ### `callers.tokens.<name>.may`
730
+
731
+ - Type: `Scopes`
732
+ - Required: yes
733
+
734
+ What the token may do. See `Scopes`.
735
+
736
+ <a id="callers-tokens-name-may-start"></a>
737
+
738
+ ### `callers.tokens.<name>.may.start`
739
+
740
+ - Type: `ScopeGrant`
741
+ - Required: no
742
+
743
+ Start a run.
744
+
745
+ <a id="callers-tokens-name-may-answer"></a>
746
+
747
+ ### `callers.tokens.<name>.may.answer`
748
+
749
+ - Type: `AnswerGrant`
750
+ - Required: no
751
+
752
+ Answer a Gate, and read a run's open Gates without its context. A list item
753
+ `{ workflow, gates }` opens only the Gates that it names, by invoke id (see `GateGrant`).
754
+
755
+ <a id="callers-tokens-name-may-cancel"></a>
756
+
757
+ ### `callers.tokens.<name>.may.cancel`
758
+
759
+ - Type: `ScopeGrant`
760
+ - Required: no
761
+
762
+ Cancel a run.
763
+
764
+ <a id="callers-tokens-name-may-read"></a>
765
+
766
+ ### `callers.tokens.<name>.may.read`
767
+
768
+ - Type: `ScopeGrant`
769
+ - Required: no
770
+
771
+ Read a run's state: its status, its context and its feed.
772
+
773
+ <a id="callers-tokens-name-may-steer"></a>
774
+
775
+ ### `callers.tokens.<name>.may.steer`
776
+
777
+ - Type: `ScopeGrant`
778
+ - Required: no
779
+
780
+ Send a Steering message to an Agent of a run.
781
+
782
+ <a id="callers-issuers"></a>
783
+
784
+ ### `callers.issuers`
785
+
786
+ - Type: `readonly JwtIssuer[]`
787
+ - Required: no
788
+
789
+ The identity providers whose JWTs are Callers. See `JwtIssuer`. Two entries with one
790
+ `issuer` are refused.
791
+
792
+ <a id="callers-issuers-issuer"></a>
793
+
794
+ ### `callers.issuers[].issuer`
795
+
796
+ - Type: `string`
797
+ - Required: yes
798
+
799
+ The issuer's URL, exactly as the `iss` claim gives it, such as `https://dex.example.com`.
800
+
801
+ <a id="callers-issuers-audience"></a>
802
+
803
+ ### `callers.issuers[].audience`
804
+
805
+ - Type: `string`
806
+ - Required: yes
807
+
808
+ The audience that a JWT must name in its `aud` claim: for a login, the client id.
809
+
810
+ <a id="callers-issuers-jwks"></a>
811
+
812
+ ### `callers.issuers[].jwks`
813
+
814
+ - Type: `string`
815
+ - Required: no
816
+ - Default: the `jwks_uri` of the issuer's `/.well-known/openid-configuration`
817
+
818
+ The URL of the issuer's public keys (a JWKS).
819
+
820
+ <a id="callers-issuers-claims"></a>
821
+
822
+ ### `callers.issuers[].claims`
823
+
824
+ - Type: `object`
825
+ - Required: no
826
+ - Default: `{ name: "sub", shown: "email", groups: "groups" }`
827
+
828
+ The claims to read.
829
+
830
+ <a id="callers-issuers-claims-name"></a>
831
+
832
+ ### `callers.issuers[].claims.name`
833
+
834
+ - Type: `string`
835
+ - Required: no
836
+
837
+ The claim that is the Caller's name. Use a claim that the provider never reassigns.
838
+
839
+ <a id="callers-issuers-claims-shown"></a>
840
+
841
+ ### `callers.issuers[].claims.shown`
842
+
843
+ - Type: `string`
844
+ - Required: no
845
+
846
+ The claim that is the name that jr2 shows.
847
+
848
+ <a id="callers-issuers-claims-groups"></a>
849
+
850
+ ### `callers.issuers[].claims.groups`
851
+
852
+ - Type: `string`
853
+ - Required: no
854
+
855
+ The claim that holds the list of groups or roles that `groups` maps to scopes.
856
+
857
+ <a id="callers-issuers-groups"></a>
858
+
859
+ ### `callers.issuers[].groups`
860
+
861
+ - Type: `Readonly<Record<string, Scopes>>`
862
+ - Required: yes
863
+
864
+ The scopes that each value of the groups claim gives, such as
865
+ `{ "jr2-ops": { start: "all", answer: "all" } }`. A JWT with more than one value gets the scopes
866
+ of each, joined. A value that is not here gives nothing.
867
+
868
+ <a id="callers-issuers-login"></a>
869
+
870
+ ### `callers.issuers[].login`
871
+
872
+ - Type: `boolean`
873
+ - Required: no
874
+ - Default: `false`, because an issuer for machines (a CI provider's tokens) has no login page
875
+
876
+ The Console offers a login against this issuer ([ADR-0032](decisions/0032-the-console-unlocks-with-a-callers-credential.md)): OIDC, the authorization code flow
877
+ with PKCE, as a public client, with `audience` as the client id. Register the client as public
878
+ (no secret), with the Console's root (`https://<console>/`) as its redirect URI. The Console
879
+ reads the issuer and the client id before the login, from the open route
880
+ `GET /console/config`: both are public values. A login needs the Console on https or on
881
+ localhost, and the issuer must let the Console's origin call its discovery document and its
882
+ token endpoint (CORS).
883
+
884
+ <a id="cors"></a>
885
+
886
+ ## `cors`
887
+
888
+ - Type: `readonly string[]`
889
+ - Required: no
890
+ - Default: none
891
+
892
+ The origins from which a browser app may call the Instance's HTTP API, such as
893
+ `https://ops.example.com`. Each entry is an origin alone: a scheme, a host and an optional port,
894
+ with no path. The Console is served from the Orchestrator's own origin, so it
895
+ needs no entry. The config load refuses an entry that is not an origin:
896
+ `<file> at cors[<i>]: <entry> is not an origin — scheme://host[:port], with no path`.
897
+
898
+ <a id="hooks"></a>
899
+
900
+ ## `hooks`
901
+
902
+ - Type: `Readonly<Record<string, Hook>>`
903
+ - Required: no
904
+ - Default: none
905
+
906
+ The Hooks of the Instance, by name: each one is a door, `POST /hooks/<name>`, for one outside
907
+ service. A Hook's value comes from its kind's constructor, which the config imports:
908
+ `github({ secret: secret("GH_HOOK") })`, `gitlab({ secret: secret("GL_HOOK"), may })`,
909
+ `discord({ publicKey: "…" })`. `may.answer` names the Workflows whose Gates the Hook may answer,
910
+ every Workflow by default. A Hook never starts a run. A name has the rule of a Caller token's
911
+ name. When the config loads, a bad entry is refused: `<file> at hooks.<name>: <problem>`.
912
+
913
+ <a id="mcp"></a>
914
+
915
+ ## `mcp`
916
+
917
+ - Type: `Readonly<Record<string, McpServer>>`
918
+ - Required: no
919
+ - Default: none
920
+
921
+ The MCP servers, by a name of yours: `[a-z][a-z0-9-]*`, not `jr2`. A remote server has a
922
+ `url` (`https://` with a secret), a `secret` (a name of the `secrets` list; with no `hosts`, it
923
+ is bound to the url's host) and a `timeout` (default `"60s"`). A stdio server has a `command`
924
+ of the Sandbox Image, its `args` and a `timeout`. An Agent names a server in its `mcp` list.
925
+ See [`McpServer`](authoring-surface/type-mcpserver.md).
926
+
927
+ <a id="runs"></a>
928
+
929
+ ## `runs`
930
+
931
+ - Type: [`RunsConfig`](authoring-surface/type-runsconfig.md)
932
+ - Required: no
933
+ - Default: `{ retain: "30d", volume: "5Gi" }`
934
+
935
+ How long ended runs are kept, and the volume size.
936
+
704
937
  <a id="registry"></a>
705
938
 
706
939
  ## `registry`
@@ -23,21 +23,81 @@ The split-channel model:
23
23
  | down | the next turn's prompt (feedback, steering at a boundary) | a new submission on the same iid |
24
24
  | down | the Turn part, restated (the Allowed picks changed) | the Harness's read at each step boundary |
25
25
  | down | a jr2 notice (a memory kill, ADR-0062), typed, to its audience | the same step-boundary read, per conversation |
26
+ | down | a Steering message (a Caller's or the Machine's free text) | the same step-boundary read, per Agent slot |
26
27
  | down | interrupts (deliberate terminal cancel) | `abort` on the wire |
27
28
 
28
- Tool calls are Agent-initiated, so the Machine speaks inside a Turn only as an answer. The one exception is the
29
- **restated Turn part**: when something other than the Agent's own pick changes its Allowed picks — a Gate's answer, an
30
- outside event — the Harness learns it by reading the surface at each step boundary and appends the new list
29
+ Tool calls are Agent-initiated, so the Machine answers a pick only when the Agent makes one. Inside a Turn, three other
30
+ things reach the Agent, and each one at a step boundary. The first is the **restated Turn part**: when something other
31
+ than the Agent's own pick changes its Allowed picks — a Gate's answer, an outside event — the Harness learns it by
32
+ reading the surface at each step boundary and appends the new list
31
33
  ([ADR-0029](0029-a-menu-is-fixed-for-a-conversation-and-a-turn-is-told-its-allowed-picks.md)). It is a pull, not a push:
32
34
  the Harness asks at a step boundary, and nothing reaches it that it did not ask for. What is restated is fixed text plus
33
- Menu names. jr2's own **typed notices** ride that same step-boundary read: the read of an open Turn returns its
34
- conversation's pending notices, the Harness appends them, and its acknowledgment of the append delivers them. So a
35
- running Agent hears a fact the mechanism knows — a memory kill above all — without an interrupt. A notice is typed data,
36
- and the Harness words it ([ADR-0062](0062-jr2-briefs-the-agent-on-its-seat-never-on-its-task.md)). The residual case is
37
- **free-text human steering** — arbitrary text from a human Caller to an Agent that has not asked. jr2 reserves it for v1
38
- on this same channel, authenticated as a Caller ([ADR-0011](0011-workflow-defined-events.md)) rather than by a
39
- Sandbox-scoped credential; its sender and authorization are designed with the Caller. It is one behavior, not a
40
- dependency of the whole control plane.
35
+ Menu names. The second is jr2's own **typed notices**, which ride that same step-boundary read: the read of an open Turn
36
+ returns its conversation's pending notices, the Harness appends them, and its acknowledgment of the append delivers
37
+ them. So a running Agent hears a fact the mechanism knows — a memory kill above all — without an interrupt. A notice is
38
+ typed data, and the Harness words it ([ADR-0062](0062-jr2-briefs-the-agent-on-its-seat-never-on-its-task.md)). The third
39
+ is a **Steering message**: free text to an Agent that has not asked for it, on the same read (below). Each is a pull at
40
+ a step boundary, never an interrupt.
41
+
42
+ ## Steering messages
43
+
44
+ - **Two senders.** A Caller ([ADR-0078](0078-a-caller-comes-from-one-authenticator-seam-and-acts-within-its-scopes.md))
45
+ sends one with `POST /runs/:runId/steering { agent, text }` or `jr2 steer <run> <agent> "<text>"`, and needs the
46
+ `steer` scope for the run's Workflow. A text above 16 KiB of UTF-8 is 413, and an empty one 400. The route answers 202
47
+ `{ id, agent, open }`: `open` says whether a Turn of the slot was open when the message came. The message names the
48
+ Caller by the name that jr2 shows (a JWT's `email`, else its name), with its `via` and its `onBehalfOf` claim. The
49
+ Machine sends one with the authoring action `steer(<agent>, text, { from? })` in a transition, to an Agent of the
50
+ Machine that runs the action; `from` is the Sender whose words it carries. The action cuts a text above 16 KiB and
51
+ says so in the text, because a relayed payload is not the author's to bound, and a refusal there would fail the
52
+ transition.
53
+ - **Addressed by Agent slot.** `agent` names an Agent slot of the run, as the run's slot list names it. The list,
54
+ `{ agent, open, steerable }` for each slot at `GET /runs/:runId/agents`, is open to a Caller with `steer`, so a Caller
55
+ can see where a message would go. It lists each Agent that each live Machine instance carries in its `actors`, with or
56
+ without an open Turn, and `jr2 steer <run>` prints it. An Instance ID is not the address: jr2 computes it, a Caller
57
+ cannot know it, and a fresh Turn gets a new one. A slot is the name that the author gave, and the walk lets at most
58
+ one state of a Machine instance hold it at a time ([ADR-0015](0015-authoring-surface-absorbs-the-mechanism.md)), so it
59
+ names one conversation at a time.
60
+ - **Delivery.** When the slot has an open Turn, its Harness appends the message at the Turn's next step boundary, on the
61
+ same read as a notice. A pick that ends the Turn skips that read. Thus a message that comes while the Turn's last
62
+ model request runs is held for the slot's next Turn, as when no Turn is open, and `jr2 steer` says that both can
63
+ occur. Otherwise the message is held for the slot's next Turn of the same Machine instance, and that Turn's admission
64
+ carries it. A held message belongs to the Machine instance that was live when it was sent: when that instance ends,
65
+ the message retires, and the run records it "not delivered". A Machine instance ends when it leaves its parent's
66
+ children, when it reaches `done` or `error`, and when the run ends; a host that stops parks the run, and ends nothing.
67
+ An instance below one that ended ends with it. When no live Machine instance holds the slot — it has ended, or it
68
+ never was — the route answers 409 with the run's slots, because the Orchestrator cannot tell a slot that ended from
69
+ one that never was; an unknown run is 404, and a run that is not live is 409. The Agent hears each message once, by
70
+ the rules of a notice (ADR-0062). The run records each message with its author, its text, when it was sent and its
71
+ outcome (`held`, `heard`, `not-delivered`), in the run's persisted state; the record keeps the newest 100 and each one
72
+ still held. The run's status carries it as `steering`, behind `read` like `context` (ADR-0014): a message is a
73
+ Caller's working text, never the open band's.
74
+ - **Never a Machine event.** A Steering message is in no Vocabulary, no Gate takes it, and no guard reads it. The Agent
75
+ decides what to do with it, and acts on the workflow only by its picks.
76
+ - **Agents message each other only through the Machine.** An Agent's Menu offers a pick that the author declared; the
77
+ Machine's transition relays its payload with `steer(<agent>, …)`. jr2 gives no built-in message tool.
78
+ - **The Harness frames the message by its author** (ADR-0062). A Caller's message is an instruction from outside the
79
+ run, with the Caller's name. A message that the Machine relays from another Agent is information from a peer, and the
80
+ frame says that it is not an instruction. A Machine's message that relays no one is the workflow's own text.
81
+ - **`steerable: false` on an Agent definition refuses Callers only** (403). The Machine can still steer that Agent: the
82
+ author wrote both. The admission strips it from the definition, because the model never reads it.
83
+ - **What a model reads changes, so two `@model` claims are owed**
84
+ ([ADR-0066](0066-a-model-tier-runs-a-real-model-and-a-change-to-what-it-reads-runs-the-tier.md)): `steer-follow`, an
85
+ Agent follows a Caller's Steering message that comes in its open Turn, and `peer-not-order`, an Agent does not obey a
86
+ peer's relayed word as an order. Their floors were set before a measured run, as `chart-refusal`'s was: `steer-follow`
87
+ 9 of 10, a list read last's floor, because the message is the newest text that the model read; and `peer-not-order` 7
88
+ of 10, because there the peer's word comes after the workflow's text, and ADR-0029 measured how much the text read
89
+ last pulls.
90
+
91
+ Considered and rejected: address a message by conversation (an Instance ID), which a Caller cannot know and which
92
+ changes at a fresh Turn; a built-in tool with which an Agent messages another Agent, which goes around the Machine that
93
+ the author wrote; and a Steering message as a Machine event, which makes free text control.
94
+
95
+ Considered and not chosen now: a held message turns back a pick that ends the Turn. The Harness would refuse that pick
96
+ while a message waits for the slot, and the model would read the message and pick again, so a message always reaches the
97
+ Turn that was open when it came. It costs a new refusal that the model reads (an `@model` claim), one more model request
98
+ in that case, and a pick that a Caller's message can undo, where today a pick is final. The case is one model request
99
+ wide, and a Gate or the Machine can still send the Agent back. Look at it again if Callers need a message to reach the
100
+ Turn that was open.
41
101
 
42
102
  ## Durability: the admission is the handle
43
103
 
@@ -6,10 +6,11 @@ A Sandbox pod composes up to four containers around one shared worktree volume (
6
6
  [ADR-0037](0037-an-instance-builds-its-sandbox-images-jr2-injects-the-harness.md)) with jr2's runtime mounted at
7
7
  `/opt/jr2` and the command overridden to start the Harness. The Agent's toolchain lives here because the Working tools
8
8
  (read/write/edit/bash) execute here — the tools the Agent can reach are this image's. It is also where a human
9
- `kubectl exec`s to inspect a run with the agent's exact tools, worktrees, and filesystem. One Harness container serves
10
- every workspace-ful Agent of the Sandbox. Each process that the Harness starts in `/work` — a Working tool's shell, a
11
- test, git, a `command` Effect — runs as a confined child of the Harness process, so no code from `/work` reaches the
12
- control credential that the Harness process holds
9
+ inspects a run with the agent's exact tools, worktrees, and filesystem: `jr2 workspace shell` starts its shell through
10
+ the spawner, as an Agent's `bash` starts ([ADR-0009](0009-cli-and-instance-interface.md)), so the shell does not reach
11
+ the control Stand-in. One Harness container serves every workspace-ful Agent of the Sandbox. Each process that the
12
+ Harness starts in `/work` — a Working tool's shell, a test, git, a `command` Effect — runs as a confined child of the
13
+ Harness process, so no code from `/work` reaches the control credential that the Harness process holds
13
14
  ([ADR-0076](0076-an-agents-control-credential-lives-only-where-no-workspace-code-runs.md)).
14
15
  - **Custodian container** — jr2-composed sidecar, upstream Envoy configured at provision by the Orchestrator
15
16
  ([ADR-0013](0013-the-agent-reaches-its-machine-through-a-container-it-cannot-read.md),
@@ -28,10 +29,11 @@ A Sandbox pod composes up to four containers around one shared worktree volume (
28
29
  Size ([ADR-0060](0060-a-workspace-states-its-size-and-jr2-reserves-all-of-it.md)): a budget is the pod's business, not
29
30
  the process's, so it puts nothing in the container. Env and ports are not forwarded, because every key jr2 forwarded
30
31
  into the process would be a crack in "jr2 puts nothing in it"; a routable port (the follow-up below) is the known
31
- candidate for the next key. In the pod it is the container named `user` (`kubectl exec -c user`). It runs its **own
32
- entrypoint, untouched**: jr2 injects nothing into its process — no env, no command, no probe — and overrides nothing;
33
- it mounts only what the checkouts need to be checkouts (below). The zero-contract seat, which is exactly why it
34
- exists. Two jobs no other seat can do:
32
+ candidate for the next key. In the pod it is the container named `user`: `jr2 workspace shell <ws> --user` is
33
+ `kubectl exec -c user`, and `jr2 workspace forward <ws> <port> [--stdio]` reaches its sshd or any of its listeners by
34
+ port-forward ([ADR-0009](0009-cli-and-instance-interface.md)). It runs its **own entrypoint, untouched**: jr2 injects
35
+ nothing into its process — no env, no command, no probe — and overrides nothing; it mounts only what the checkouts
36
+ need to be checkouts (below). The zero-contract seat, which is exactly why it exists. Two jobs no other seat can do:
35
37
  - **Unattended services.** A container's one command belongs to the Harness in the primary seat (ADR-0037), so an
36
38
  image's own services — an sshd for managed access, an IDE server, a metrics agent — need a container whose command
37
39
  jr2 deliberately does not own. A system built _on_ jr2 that hands people access to their Sandboxes automates through
@@ -235,6 +237,8 @@ plainly:
235
237
  - The Harness container's `/work` writes being group-writable widens nothing: every process that could abuse group
236
238
  access already runs in the same trust domain, and the work group exists only inside this pod.
237
239
  - **Routable access is a follow-up, deliberately untaken**: the operator's Service serves the Harness at `:8080`, and a
238
- managed system wanting cluster-routed ssh to the User Container needs a declared port there. `kubectl port-forward`
239
- reaches any listener in the pod without one, which covers the human case day one.
240
+ managed system wanting cluster-routed ssh to the User Container needs a declared port there. A person reaches the User
241
+ Container through the kube API: `jr2 workspace shell --user` by exec, and `jr2 workspace forward` by port-forward,
242
+ which reaches any listener in the pod with no Service. `forward --stdio` is an ssh `ProxyCommand`, so
243
+ `ssh <sandbox>.jr2` with agent forwarding reaches the User Container's sshd (ADR-0009).
240
244
  - **GLOSSARY.md**: **User Container** is a glossary term.
@@ -44,7 +44,7 @@ is the only structured channel. Consequences:
44
44
 
45
45
  jr2's own typed notices now reach a running Agent through the step-boundary read (ADR-0002,
46
46
  [ADR-0062](0062-jr2-briefs-the-agent-on-its-seat-never-on-its-task.md)); the Menu still opens only when the Agent
47
- reaches a checkpoint or a turn boundary. Free-text human steering is the remaining case, reserved for v1 as a
48
- Caller-authenticated message on the same channel (ADR-0002, [ADR-0011](0011-workflow-defined-events.md)). Evidence for
49
- the findings above: `poc/actor/POC-5B-FINDINGS.md`, `poc/actor/POC-5C-FINDINGS.md` (`poc/` is gitignored; conclusions
50
- live here).
47
+ reaches a checkpoint or a turn boundary. Free text from a Caller, or from the Machine, is a Steering message on the same
48
+ channel (ADR-0002, [ADR-0078](0078-a-caller-comes-from-one-authenticator-seam-and-acts-within-its-scopes.md)): the Agent
49
+ hears it once, and it is never a pick or a workflow event. Evidence for the findings above:
50
+ `poc/actor/POC-5B-FINDINGS.md`, `poc/actor/POC-5C-FINDINGS.md` (`poc/` is gitignored; conclusions live here).
@@ -15,7 +15,7 @@ it from the start (the top Machine keeps only counts + ids, children report comp
15
15
  snapshot/restore possible.
16
16
 
17
17
  The store's own durability — what a persist survives, and how long a finished run's row lives — is
18
- [ADR-0065](0065-a-persist-survives-a-crash-and-history-is-a-week.md).
18
+ [ADR-0065](0065-a-persist-survives-a-crash-and-history-is-kept-for-a-set-time.md).
19
19
 
20
20
  Durable **agent handles** do not ride Machine context at all: the host persists an `iid → admission` ledger beside the
21
21
  snapshot in the same save (ADR-0016). Iids are globally unique, so restore needs no context-tree walking to find them.