@jr2/orchestrator 0.5.1 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (350) hide show
  1. package/console/components/app.ts +55 -15
  2. package/console/components/bottom-drawer.ts +259 -0
  3. package/console/components/drawer.ts +14 -6
  4. package/console/components/fleet.ts +36 -13
  5. package/console/components/machine-pane.ts +61 -5
  6. package/console/components/nav.ts +54 -8
  7. package/console/conversation.ts +161 -0
  8. package/console/login.ts +123 -0
  9. package/console/main.ts +600 -60
  10. package/console/store.ts +611 -64
  11. package/console/style.css +231 -0
  12. package/docs/agents-block.md +2 -2
  13. package/docs/concepts/agents-and-turns.md +142 -29
  14. package/docs/concepts/architecture.md +60 -34
  15. package/docs/concepts/callers-and-hooks.md +205 -0
  16. package/docs/concepts/charts.md +13 -8
  17. package/docs/concepts/composition.md +10 -1
  18. package/docs/concepts/converge.md +7 -2
  19. package/docs/concepts/durable-runs.md +43 -16
  20. package/docs/concepts/effects.md +133 -50
  21. package/docs/concepts/gates.md +95 -25
  22. package/docs/concepts/machines-and-workflows.md +14 -4
  23. package/docs/concepts/pools-and-sources.md +193 -17
  24. package/docs/concepts/secrets-and-trust.md +186 -62
  25. package/docs/concepts/the-menu.md +14 -0
  26. package/docs/concepts/workspaces.md +135 -56
  27. package/docs/get-started/a-model-decides.md +14 -13
  28. package/docs/get-started/an-agent-in-a-sandbox.md +46 -35
  29. package/docs/get-started/connect-a-model.md +1 -1
  30. package/docs/get-started/create-an-instance.md +17 -14
  31. package/docs/get-started/have-your-assistant-write-a-machine.md +111 -40
  32. package/docs/get-started/install.md +4 -0
  33. package/docs/guides/add-tools-to-the-sandbox.md +72 -15
  34. package/docs/guides/answer-a-gate-from-a-forge.md +304 -0
  35. package/docs/guides/answer-a-gate.md +74 -37
  36. package/docs/guides/bind-open-parts.md +29 -12
  37. package/docs/guides/call-an-mcp-tool-from-a-machine.md +572 -0
  38. package/docs/guides/cancel-a-run.md +26 -16
  39. package/docs/guides/cut-a-worktree.md +560 -0
  40. package/docs/guides/fix-a-failed-converge.md +19 -7
  41. package/docs/guides/give-a-caller-a-scope.md +203 -0
  42. package/docs/guides/give-an-agent-mcp-tools.md +422 -0
  43. package/docs/guides/iterate-on-a-machine-on-kind.md +10 -9
  44. package/docs/guides/let-an-agent-write-a-chart.md +14 -7
  45. package/docs/guides/look-inside-a-sandbox.md +115 -42
  46. package/docs/guides/move-from-kind-to-a-shared-cluster.md +16 -0
  47. package/docs/guides/open-the-console.md +63 -14
  48. package/docs/guides/push-and-sign-a-branch.md +67 -21
  49. package/docs/guides/read-a-conversation.md +225 -0
  50. package/docs/guides/run-a-chart-by-name.md +17 -16
  51. package/docs/guides/run-a-command-or-call-a-url.md +84 -41
  52. package/docs/guides/run-one-worker-per-item.md +34 -27
  53. package/docs/guides/set-an-agents-access-and-dials.md +69 -22
  54. package/docs/guides/size-a-workspace.md +19 -6
  55. package/docs/guides/start-a-run-for-each-alert.md +290 -0
  56. package/docs/guides/start-a-run-from-a-run.md +18 -16
  57. package/docs/guides/start-a-run.md +24 -18
  58. package/docs/guides/steer-an-agent.md +332 -0
  59. package/docs/guides/use-a-hosted-provider.md +7 -1
  60. package/docs/guides/watch-a-run.md +146 -117
  61. package/docs/guides/write-a-hook-kind.md +238 -0
  62. package/docs/guides/write-a-tool-as-an-mcp-server.md +351 -0
  63. package/docs/guides/write-a-workflow.md +18 -8
  64. package/docs/llms.txt +110 -23
  65. package/docs/reference/authoring-surface/agent.md +35 -12
  66. package/docs/reference/authoring-surface/answer.md +20 -4
  67. package/docs/reference/authoring-surface/arg.md +28 -6
  68. package/docs/reference/authoring-surface/basic.md +1 -1
  69. package/docs/reference/authoring-surface/bearer.md +1 -1
  70. package/docs/reference/authoring-surface/branchname.md +15 -0
  71. package/docs/reference/authoring-surface/carry.md +23 -0
  72. package/docs/reference/authoring-surface/chartschema.md +1 -1
  73. package/docs/reference/authoring-surface/chartschemafor.md +1 -1
  74. package/docs/reference/authoring-surface/command.md +37 -22
  75. package/docs/reference/authoring-surface/customize.md +4 -1
  76. package/docs/reference/authoring-surface/defineconfig.md +1 -1
  77. package/docs/reference/authoring-surface/defineevent.md +1 -1
  78. package/docs/reference/authoring-surface/dispatch.md +5 -4
  79. package/docs/reference/authoring-surface/fail.md +18 -5
  80. package/docs/reference/authoring-surface/file.md +37 -17
  81. package/docs/reference/authoring-surface/frompick.md +1 -1
  82. package/docs/reference/authoring-surface/gate.md +118 -0
  83. package/docs/reference/authoring-surface/group-agents.md +15 -0
  84. package/docs/reference/authoring-surface/group-charts.md +16 -0
  85. package/docs/reference/authoring-surface/group-composition.md +25 -0
  86. package/docs/reference/authoring-surface/group-config.md +17 -0
  87. package/docs/reference/authoring-surface/group-effects.md +48 -0
  88. package/docs/reference/authoring-surface/group-failure.md +13 -0
  89. package/docs/reference/authoring-surface/group-gates.md +16 -0
  90. package/docs/reference/authoring-surface/group-machine-and-events.md +15 -0
  91. package/docs/reference/authoring-surface/group-steering.md +12 -0
  92. package/docs/reference/authoring-surface/group-types-these-signatures-name.md +137 -0
  93. package/docs/reference/authoring-surface/group-workspaces-and-repos.md +15 -0
  94. package/docs/reference/authoring-surface/http.md +109 -9
  95. package/docs/reference/authoring-surface/isfailure.md +1 -1
  96. package/docs/reference/authoring-surface/isready.md +14 -0
  97. package/docs/reference/authoring-surface/jr2setup.md +14 -4
  98. package/docs/reference/authoring-surface/mcp.md +107 -0
  99. package/docs/reference/authoring-surface/open.md +41 -8
  100. package/docs/reference/authoring-surface/openbody.md +1 -1
  101. package/docs/reference/authoring-surface/paramsof.md +23 -5
  102. package/docs/reference/authoring-surface/pool.md +79 -11
  103. package/docs/reference/authoring-surface/push.md +31 -13
  104. package/docs/reference/authoring-surface/readyof.md +21 -0
  105. package/docs/reference/authoring-surface/reread.md +19 -0
  106. package/docs/reference/authoring-surface/secret.md +26 -5
  107. package/docs/reference/authoring-surface/sentby.md +1 -1
  108. package/docs/reference/authoring-surface/skip.md +22 -0
  109. package/docs/reference/authoring-surface/source.md +59 -4
  110. package/docs/reference/authoring-surface/steer.md +93 -0
  111. package/docs/reference/authoring-surface/text.md +1 -1
  112. package/docs/reference/authoring-surface/type-agentdefinition.md +16 -3
  113. package/docs/reference/authoring-surface/type-agentmcpserver.md +54 -0
  114. package/docs/reference/authoring-surface/type-agentslots.md +4 -1
  115. package/docs/reference/authoring-surface/type-anyframepath.md +14 -0
  116. package/docs/reference/authoring-surface/type-anyworktreepath.md +15 -0
  117. package/docs/reference/authoring-surface/type-bindactors.md +14 -0
  118. package/docs/reference/authoring-surface/type-binding.md +6 -7
  119. package/docs/reference/authoring-surface/type-caller.md +40 -0
  120. package/docs/reference/authoring-surface/type-callerrecord.md +32 -0
  121. package/docs/reference/authoring-surface/type-carry.md +19 -0
  122. package/docs/reference/authoring-surface/type-chainlink.md +3 -3
  123. package/docs/reference/authoring-surface/type-commandinput.md +4 -3
  124. package/docs/reference/authoring-surface/type-commandoptions.md +0 -22
  125. package/docs/reference/authoring-surface/type-commandoutput.md +23 -5
  126. package/docs/reference/authoring-surface/type-customize.md +20 -3
  127. package/docs/reference/authoring-surface/type-delivered.md +17 -0
  128. package/docs/reference/authoring-surface/type-deliveredevent.md +18 -0
  129. package/docs/reference/authoring-surface/type-dispatchdefinition.md +4 -3
  130. package/docs/reference/authoring-surface/type-dispatchoutput.md +9 -2
  131. package/docs/reference/authoring-surface/type-doorlessinput.md +19 -0
  132. package/docs/reference/authoring-surface/type-effectbinding.md +12 -2
  133. package/docs/reference/authoring-surface/type-filebody.md +4 -8
  134. package/docs/reference/authoring-surface/type-framepath.md +14 -0
  135. package/docs/reference/authoring-surface/type-gatebinding.md +15 -0
  136. package/docs/reference/authoring-surface/type-gatehooks.md +12 -0
  137. package/docs/reference/authoring-surface/type-gatelook.md +37 -0
  138. package/docs/reference/authoring-surface/type-gateoutcome.md +32 -0
  139. package/docs/reference/authoring-surface/type-gatereply.md +19 -0
  140. package/docs/reference/authoring-surface/type-gateslot.md +21 -0
  141. package/docs/reference/authoring-surface/type-gateslotinput.md +13 -0
  142. package/docs/reference/authoring-surface/type-gateslotparts.md +18 -0
  143. package/docs/reference/authoring-surface/type-gateslots.md +12 -0
  144. package/docs/reference/authoring-surface/type-gatetypesat.md +13 -0
  145. package/docs/reference/authoring-surface/type-hostinjectedinput.md +3 -5
  146. package/docs/reference/authoring-surface/type-httpdefinition.md +6 -3
  147. package/docs/reference/authoring-surface/type-httpfileinput.md +20 -0
  148. package/docs/reference/authoring-surface/type-httpoutput.md +8 -2
  149. package/docs/reference/authoring-surface/type-jr2config.md +37 -2
  150. package/docs/reference/authoring-surface/type-lateroutcome.md +21 -0
  151. package/docs/reference/authoring-surface/type-lends.md +5 -1
  152. package/docs/reference/authoring-surface/type-lookoutput.md +14 -0
  153. package/docs/reference/authoring-surface/type-mcpcalloutput.md +78 -0
  154. package/docs/reference/authoring-surface/type-mcpnotreturned.md +42 -0
  155. package/docs/reference/authoring-surface/type-mcpoptions.md +47 -0
  156. package/docs/reference/authoring-surface/type-mcpoutput.md +50 -0
  157. package/docs/reference/authoring-surface/type-mcpreadoutput.md +53 -0
  158. package/docs/reference/authoring-surface/type-mcpremoteserver.md +50 -0
  159. package/docs/reference/authoring-surface/type-mcpserver.md +41 -0
  160. package/docs/reference/authoring-surface/type-mcpstdioserver.md +42 -0
  161. package/docs/reference/authoring-surface/type-namedsecret.md +4 -4
  162. package/docs/reference/authoring-surface/type-namestart.md +77 -0
  163. package/docs/reference/authoring-surface/type-noslotworkspaceoptions.md +1 -6
  164. package/docs/reference/authoring-surface/type-notworktreekeys.md +12 -0
  165. package/docs/reference/authoring-surface/type-openbodydeclaration.md +1 -1
  166. package/docs/reference/authoring-surface/type-openbodyoutput.md +1 -1
  167. package/docs/reference/authoring-surface/type-opencommandinput.md +7 -2
  168. package/docs/reference/authoring-surface/type-permissivenoslotworkspaceoptions.md +1 -6
  169. package/docs/reference/authoring-surface/type-permissiveworkspaceoptions.md +5 -10
  170. package/docs/reference/authoring-surface/type-poolnextinput.md +22 -0
  171. package/docs/reference/authoring-surface/type-poolspec.md +11 -6
  172. package/docs/reference/authoring-surface/type-pushinput.md +22 -3
  173. package/docs/reference/authoring-surface/type-pushoutput.md +33 -8
  174. package/docs/reference/authoring-surface/type-pushsourcespec.md +38 -0
  175. package/docs/reference/authoring-surface/type-readsourcespec.md +47 -0
  176. package/docs/reference/authoring-surface/type-reposlot.md +6 -6
  177. package/docs/reference/authoring-surface/type-reread.md +18 -0
  178. package/docs/reference/authoring-surface/type-runsconfig.md +41 -0
  179. package/docs/reference/authoring-surface/type-sandboxoptions.md +11 -4
  180. package/docs/reference/authoring-surface/type-sender.md +26 -1
  181. package/docs/reference/authoring-surface/type-sendercallerfield.md +14 -0
  182. package/docs/reference/authoring-surface/type-size.md +1 -1
  183. package/docs/reference/authoring-surface/type-skip.md +19 -0
  184. package/docs/reference/authoring-surface/type-slothandles.md +5 -13
  185. package/docs/reference/authoring-surface/type-sourcehooks.md +23 -0
  186. package/docs/reference/authoring-surface/type-sourcein.md +25 -0
  187. package/docs/reference/authoring-surface/type-sourcereply.md +18 -0
  188. package/docs/reference/authoring-surface/type-sourcespec.md +26 -17
  189. package/docs/reference/authoring-surface/type-sourceverdict.md +49 -0
  190. package/docs/reference/authoring-surface/type-standingpoolmachine.md +12 -0
  191. package/docs/reference/authoring-surface/type-standingpoolspec.md +51 -0
  192. package/docs/reference/authoring-surface/type-steerargs.md +20 -0
  193. package/docs/reference/authoring-surface/type-thinkinglevel.md +1 -1
  194. package/docs/reference/authoring-surface/type-usercontainer.md +1 -1
  195. package/docs/reference/authoring-surface/type-workspaced.md +30 -9
  196. package/docs/reference/authoring-surface/type-workspacehandles.md +5 -6
  197. package/docs/reference/authoring-surface/type-workspaceoptions.md +1 -13
  198. package/docs/reference/authoring-surface/type-worktreefound.md +16 -0
  199. package/docs/reference/authoring-surface/type-worktreeinput.md +56 -0
  200. package/docs/reference/authoring-surface/type-worktreekey.md +14 -0
  201. package/docs/reference/authoring-surface/type-worktreeoptions.md +29 -0
  202. package/docs/reference/authoring-surface/type-worktreeoutput.md +45 -0
  203. package/docs/reference/authoring-surface/type-worktreepath.md +16 -0
  204. package/docs/reference/authoring-surface/type-worktreeready.md +37 -0
  205. package/docs/reference/authoring-surface/type-worktreerefused.md +21 -0
  206. package/docs/reference/authoring-surface/workspace.md +66 -38
  207. package/docs/reference/authoring-surface/worktree.md +71 -0
  208. package/docs/reference/authoring-surface.md +88 -147
  209. package/docs/reference/cli.md +413 -74
  210. package/docs/reference/config.md +248 -6
  211. package/docs/reference/decisions/0001-operator-owned-generic-sandbox.md +10 -9
  212. package/docs/reference/decisions/0002-duplex-streaming-actor.md +81 -14
  213. package/docs/reference/decisions/0004-worktree-provisioning-model.md +27 -21
  214. package/docs/reference/decisions/0005-sandbox-pod-composition.md +39 -25
  215. package/docs/reference/decisions/0006-agent-control-surface.md +6 -3
  216. package/docs/reference/decisions/0007-durable-machine-state.md +1 -1
  217. package/docs/reference/decisions/0009-cli-and-instance-interface.md +150 -49
  218. package/docs/reference/decisions/0010-bdd-acceptance-tests.md +5 -3
  219. package/docs/reference/decisions/0011-workflow-defined-events.md +256 -12
  220. package/docs/reference/decisions/0012-workspace-wrapper-machine.md +39 -32
  221. package/docs/reference/decisions/0013-the-agent-reaches-its-machine-through-a-container-it-cannot-read.md +54 -30
  222. package/docs/reference/decisions/0014-observation-is-open-run-state-is-not.md +53 -27
  223. package/docs/reference/decisions/0015-authoring-surface-absorbs-the-mechanism.md +26 -16
  224. package/docs/reference/decisions/0016-agent-turn-mechanics-are-internal.md +9 -7
  225. package/docs/reference/decisions/0017-pool-over-a-source-port.md +226 -10
  226. package/docs/reference/decisions/0018-instance-agents-are-definitions-jr2-assembles-the-harness.md +15 -7
  227. package/docs/reference/decisions/0019-one-converging-command-against-the-current-context.md +53 -27
  228. package/docs/reference/decisions/0021-workspace-continuity-is-a-lease-that-answers-back.md +16 -2
  229. package/docs/reference/decisions/0022-observation-is-a-level-triggered-feed.md +4 -4
  230. package/docs/reference/decisions/0023-the-harness-prints-the-conversation.md +124 -43
  231. package/docs/reference/decisions/0024-an-agents-turn-ends-with-the-state-that-asked-for-it.md +36 -38
  232. package/docs/reference/decisions/0025-cancel-ends-a-run-stop-parks-it.md +10 -5
  233. package/docs/reference/decisions/0027-the-harness-is-jr2s-own-server-flue-retires-the-wire-stays.md +16 -7
  234. package/docs/reference/decisions/0028-what-an-agent-may-do-to-the-workspace-is-part-of-its-definition.md +36 -19
  235. package/docs/reference/decisions/0029-a-menu-is-fixed-for-a-conversation-and-a-turn-is-told-its-allowed-picks.md +18 -10
  236. package/docs/reference/decisions/0030-a-snapshot-names-the-machine-it-was-written-under.md +3 -2
  237. package/docs/reference/decisions/0031-menu-only-agents-run-on-the-instance-harness.md +23 -15
  238. package/docs/reference/decisions/0032-the-console-unlocks-with-a-callers-credential.md +101 -0
  239. package/docs/reference/decisions/0033-a-machine-declares-the-input-that-starts-it.md +22 -22
  240. package/docs/reference/decisions/0034-the-console-renders-with-preact-and-the-server-erases-the-types.md +6 -6
  241. package/docs/reference/decisions/0037-an-instance-builds-its-sandbox-images-jr2-injects-the-harness.md +13 -12
  242. package/docs/reference/decisions/0049-a-machine-carries-its-parts-and-composes-by-invoke.md +23 -23
  243. package/docs/reference/decisions/0050-what-code-names-config-declares-what-the-cli-names-discovery-finds.md +6 -1
  244. package/docs/reference/decisions/0051-a-repo-is-a-slot-on-the-workspace-and-a-cache-on-the-node.md +57 -46
  245. package/docs/reference/decisions/0052-a-sandbox-lands-where-an-ordinary-pod-lands-and-the-cache-follows-it.md +5 -0
  246. package/docs/reference/decisions/0053-a-fetch-inside-the-pod-asks-the-node-cache-and-the-cache-asks-the-remote.md +20 -8
  247. package/docs/reference/decisions/0054-the-kit-ships-machines-and-a-shipped-machine-leaves-its-parts-open.md +55 -40
  248. package/docs/reference/decisions/0055-a-release-is-a-pushed-tag-and-the-publish-guard-is-the-credential.md +14 -13
  249. package/docs/reference/decisions/0057-a-turn-is-its-frame-its-dials-and-whether-it-continues.md +31 -24
  250. package/docs/reference/decisions/0058-a-harness-answers-the-orchestrator-alone.md +18 -10
  251. package/docs/reference/decisions/0059-a-harness-holds-stand-ins-and-the-custodian-holds-the-keys.md +137 -86
  252. package/docs/reference/decisions/0062-jr2-briefs-the-agent-on-its-seat-never-on-its-task.md +165 -91
  253. package/docs/reference/decisions/0063-the-orchestrator-watches-the-cluster.md +7 -7
  254. package/docs/reference/decisions/0064-a-workspace-waits-for-capacity.md +2 -2
  255. package/docs/reference/decisions/0065-a-persist-survives-a-crash-and-history-is-kept-for-a-set-time.md +109 -0
  256. package/docs/reference/decisions/0066-a-model-tier-runs-a-real-model-and-a-change-to-what-it-reads-runs-the-tier.md +53 -23
  257. package/docs/reference/decisions/0067-an-effect-is-an-actor-slot-and-runs-at-most-once-unless-marked-idempotent.md +221 -153
  258. package/docs/reference/decisions/0068-an-effector-holds-an-effects-secrets-and-signs-its-wire.md +161 -96
  259. package/docs/reference/decisions/0069-the-orchestrator-is-a-kit-image-and-an-instance-publishes-its-assembly.md +32 -9
  260. package/docs/reference/decisions/0070-a-machine-lends-its-parts-to-a-chart.md +48 -33
  261. package/docs/reference/decisions/0071-a-run-starts-a-run-through-a-dispatch-effect.md +56 -30
  262. package/docs/reference/decisions/0072-the-docs-ship-inside-the-kit-and-an-instances-agents-md-indexes-them.md +35 -25
  263. package/docs/reference/decisions/0073-a-machine-fails-a-run-with-fail-and-an-uncaught-failure-ends-it-failed.md +1 -1
  264. package/docs/reference/decisions/0075-a-machine-cuts-a-worktree-and-the-workspace-only-clones.md +296 -0
  265. package/docs/reference/decisions/0076-an-agents-control-credential-lives-only-where-no-workspace-code-runs.md +347 -0
  266. package/docs/reference/decisions/0077-jr2-requires-landlock-on-every-sandbox-node.md +79 -0
  267. package/docs/reference/decisions/0078-a-caller-comes-from-one-authenticator-seam-and-acts-within-its-scopes.md +285 -0
  268. package/docs/reference/decisions/0079-an-agent-holds-mcp-tools-a-machine-calls-them-as-an-effect-and-the-machine-is-the-approval.md +198 -0
  269. package/docs/reference/decisions.md +9 -4
  270. package/docs/reference/glossary.md +138 -45
  271. package/docs/reference/hooks.md +1077 -0
  272. package/docs/reference/http-api.md +988 -123
  273. package/docs/reference/machines.md +0 -1
  274. package/docs/why.md +7 -5
  275. package/package.json +10 -3
  276. package/src/actor.ts +194 -42
  277. package/src/agent.ts +56 -6
  278. package/src/ambient.ts +3 -5
  279. package/src/assembly-checks.ts +530 -4
  280. package/src/callers.ts +245 -0
  281. package/src/chart.ts +238 -26
  282. package/src/charts.ts +9 -2
  283. package/src/config.ts +566 -7
  284. package/src/conversations.ts +453 -0
  285. package/src/custodian.lua +17 -5
  286. package/src/custodian.ts +257 -77
  287. package/src/customize.ts +154 -7
  288. package/src/dispatch-effect.ts +142 -26
  289. package/src/durability.ts +2 -0
  290. package/src/duration.ts +20 -0
  291. package/src/effect-checks.ts +52 -4
  292. package/src/effect.ts +401 -132
  293. package/src/effector-wire.ts +278 -30
  294. package/src/fail.ts +17 -4
  295. package/src/gate-brand.ts +16 -0
  296. package/src/gate.ts +634 -48
  297. package/src/harness-client.ts +84 -35
  298. package/src/harness-env.ts +33 -0
  299. package/src/held-secrets.ts +197 -39
  300. package/src/holds.ts +5 -2
  301. package/src/hook-kinds/discord.ts +92 -0
  302. package/src/hook-kinds/door.ts +107 -0
  303. package/src/hook-kinds/github.ts +89 -0
  304. package/src/hook-kinds/gitlab.ts +72 -0
  305. package/src/hook-kinds/hook.ts +7 -0
  306. package/src/hook-kinds/index.ts +465 -0
  307. package/src/hook-kinds/slack.ts +151 -0
  308. package/src/hook-kinds/webhook.ts +113 -0
  309. package/src/hooks.ts +506 -0
  310. package/src/http-effect.ts +164 -70
  311. package/src/http.ts +933 -99
  312. package/src/index.ts +30 -5
  313. package/src/instance.ts +196 -26
  314. package/src/internal.ts +23 -3
  315. package/src/kube-client.ts +6 -3
  316. package/src/machine-doc.ts +29 -5
  317. package/src/mcp-effect.ts +424 -0
  318. package/src/model-keys.ts +24 -0
  319. package/src/mount-digest.ts +41 -7
  320. package/src/names.ts +82 -7
  321. package/src/notices.ts +576 -59
  322. package/src/open-body.ts +110 -30
  323. package/src/open-effect.ts +17 -4
  324. package/src/open.ts +40 -7
  325. package/src/parts.ts +125 -35
  326. package/src/party.ts +35 -1
  327. package/src/pick.ts +43 -9
  328. package/src/pool.ts +1172 -172
  329. package/src/registration.ts +249 -17
  330. package/src/repo-identity.ts +7 -3
  331. package/src/repos.ts +20 -2
  332. package/src/run-host.ts +1614 -190
  333. package/src/run-list.ts +191 -0
  334. package/src/sandbox-effect.ts +217 -66
  335. package/src/sandbox-kube.ts +116 -21
  336. package/src/secret-placement.ts +248 -35
  337. package/src/server.ts +53 -4
  338. package/src/setup.ts +158 -38
  339. package/src/snapshot-store.ts +565 -48
  340. package/src/steer.ts +111 -0
  341. package/src/stub-harness.ts +6 -2
  342. package/src/tokens.ts +362 -46
  343. package/src/vocabulary.ts +23 -4
  344. package/src/wire.ts +27 -10
  345. package/src/workspace.ts +314 -259
  346. package/src/worktree.ts +249 -0
  347. package/docs/reference/authoring-surface/type-noslotspec.md +0 -26
  348. package/docs/reference/authoring-surface/type-workspacespec.md +0 -37
  349. package/docs/reference/decisions/0032-the-console-unlocks-with-the-instance-token.md +0 -61
  350. package/docs/reference/decisions/0065-a-persist-survives-a-crash-and-history-is-a-week.md +0 -65
@@ -49,19 +49,26 @@ their own maintainers, and the escapes shipped in systems that used them were in
49
49
  answer into the run), so the Open body lends it whole, `lends.gate: true`, and a body that does not has no `gate` in
50
50
  its grammar and refuses one at the door; a lent Gate's ids sit below the body's own actor path, so a Chart cannot take
51
51
  the name of its wrapper's Gate. (Measured: with `gate` offered beside one lent Agent, three of five missed second
52
- Charts reached for it as a worker.) And it mints its own Agents, because an Agent is five plain fields
52
+ Charts reached for it as a worker.) And it mints its own Agents, because an Agent is plain fields
53
53
  ([ADR-0049](0049-a-machine-carries-its-parts-and-composes-by-invoke.md)) and the Harness runs whatever definition
54
- rides the Turn. A minted Agent's model must be one the Open body allows and the Assembly placed a key for;
55
- `workspace: "none"` needs the Instance Harness the Assembly converged. Both are door refusals, never a 401 mid-run. It
56
- borrows, by slot name only, every Effect (the url, argv and secret were bound once by the author and the Chart fills
57
- only its input slots), every Repo and image, every secret, every child Machine, and every guard, action or delay
58
- beyond the generic set. Lending is attenuated by construction; an author who lends
59
- `command(["sh", "-c", arg("script")])` has lent a shell, and that is theirs to choose. A lent name may not be dotted,
60
- `gate`, `fail`, a generic action's name or an integer, because those are the kit's; the Gate itself is lent as
61
- `gate: true`, and the Part that fails the run as `fail: true`
54
+ rides the Turn. A minted Agent names no MCP server: the Chart grammar refuses `mcp`, because an MCP server with its
55
+ secret is reach, and MCP tools reach a Chart only through a lent Agent
56
+ ([ADR-0079](0079-an-agent-holds-mcp-tools-a-machine-calls-them-as-an-effect-and-the-machine-is-the-approval.md)). A
57
+ minted Agent's model must be one the Open body allows and the Assembly placed a key for; `workspace: "none"` needs the
58
+ Instance Harness the Assembly converged. Both are door refusals, never a 401 mid-run. It borrows, by slot name only,
59
+ every Effect (the url, argv, MCP server and tool, and secret were bound once by the author and the Chart fills only
60
+ its input slots), every Repo and image, every secret, every child Machine, and every guard, action or delay beyond the
61
+ generic set. Lending is attenuated by construction; an author who lends `command(["sh", "-c", arg("script")])` has
62
+ lent a shell, and that is theirs to choose. A lent name may not be dotted, `gate`, `fail`, a generic action's name or
63
+ an integer, because those are the kit's; the Gate itself is lent as `gate: true`, and a Gate slot that hears a Hook
64
+ ([ADR-0011](0011-workflow-defined-events.md)) is lent by its slot name in `lends.gates`, as an Effect is in
65
+ `lends.effects`; the door refuses a lent Gate slot whose `delivers` names an event that is not in the Chart's
66
+ Vocabulary. The Part that fails the run is lent as `fail: true`
62
67
  ([ADR-0073](0073-a-machine-fails-a-run-with-fail-and-an-uncaught-failure-ends-it-failed.md)), because the Machine
63
- decides which ends a Chart can choose. The guard `jr2.failure`, which tells a Failure from a defect on an `onError`,
64
- is in every Chart, as `jr2.sentBy` is: it is a predicate and gives no capability.
68
+ decides which ends a Chart can choose. The guards `jr2.failure`, which tells a Failure from a defect on an `onError`,
69
+ and `jr2.ready`, which says that a cut settled `ready`
70
+ ([ADR-0075](0075-a-machine-cuts-a-worktree-and-the-workspace-only-clones.md)), are in every Chart, as `jr2.sentBy` is:
71
+ each is a predicate and gives no capability.
65
72
  - **Constants for authority, references for data.** `invoke.src`, guard and action `type`s, delay names and event names
66
73
  are constants, checked against the lent set and the Chart's own declarations at admission. Data flows through
67
74
  references: a placeholder `{{context.ticket.title}}`, or `{ "$ref": "event.summary" }`, in an invoke's `input`, an
@@ -130,11 +137,14 @@ their own maintainers, and the escapes shipped in systems that used them were in
130
137
  briefing names the lent Agents, and a body that allows no model has NO `agents` in its grammar and a briefing that
131
138
  says so: a planner reads a field it cannot fill as one to fill (measured: eight of ten first Charts minted under a
132
139
  `never` model, and read "must not have additional properties" for it), and a Chart that brings `agents` anyway reads
133
- at the door why there is none. And the Agent's surface MARKS a pick whose parameter is a Chart with that grammar's
134
- briefing (`SurfaceEvent.briefing`, by schema identity), so the Harness says the text in the Turn part, right before
135
- "Allowed now", on every Turn where that pick is Allowed, and on a restatement that opens it
136
- ([ADR-0062](0062-jr2-briefs-the-agent-on-its-seat-never-on-its-task.md)). Nowhere else: the standing Briefing stays
137
- Chart-agnostic, the tools block stays the same bytes on every Turn
140
+ at the door why there is none. The briefing of a body that lends an Effect says how a Chart works under Repo Slots:
141
+ work happens in a Worktree; a lent cut takes a `path` of `/work/<slot>/<name>` and a `branch`, and `<name>` is not the
142
+ branch; its `onDone` has an edge with the guard `jr2.ready` and an edge with no guard, for a refused cut; and that one
143
+ literal path is the `cwd` of each Turn and the `worktree` of each Effect there. And the Agent's surface MARKS a pick
144
+ whose parameter is a Chart with that grammar's briefing (`SurfaceEvent.briefing`, by schema identity), so the Harness
145
+ says the text in the Turn part, right before "Allowed now", on every Turn where that pick is Allowed, and on a
146
+ restatement that opens it ([ADR-0062](0062-jr2-briefs-the-agent-on-its-seat-never-on-its-task.md)). Nowhere else: the
147
+ standing Briefing stays Chart-agnostic, the tools block stays the same bytes on every Turn
138
148
  ([ADR-0029](0029-a-menu-is-fixed-for-a-conversation-and-a-turn-is-told-its-allowed-picks.md)), and a seat whose Menu
139
149
  holds no Chart pick reads not a word of it. The cost is the author's to scope: a seat whose Menu holds a Chart pick
140
150
  carries the grammar as cached tool parameters on every Turn, so an author who wants a planner that only sometimes
@@ -167,10 +177,9 @@ their own maintainers, and the escapes shipped in systems that used them were in
167
177
  token, not the publish token, because a Chart is data and cannot reach the process, which is the whole point of this
168
178
  decision; it lives on the Orchestrator's volume at `.jr2/charts/<wrapper>/<name>.chart.json` beside the Assemblies,
169
179
  written durably, and survives restarts. A live run holds its Chart through the text in its own snapshot, so a `DELETE`
170
- while a run is live answers at once and the run goes on. It lists in `jr2 runs` and the Console with its origin shown:
171
- `jr2 runs` keeps its result, the live runs, and prints the listing beside it as activity, with `--workflows` to make
172
- the listing the result ([ADR-0009](0009-cli-and-instance-interface.md)); there is no verb for `PUT` or `DELETE`, an
173
- MCP or `curl` is the client. `GET /workflows` lists each wrapper with its Charts inside its entry, not beside it, and
180
+ while a run is live answers at once and the run goes on. It lists in `jr2 workflows` and the Console with its origin
181
+ shown ([ADR-0009](0009-cli-and-instance-interface.md)); there is no verb for `PUT` or `DELETE`, an MCP or `curl` is
182
+ the client. `GET /workflows` lists each wrapper with its Charts inside its entry, not beside it, and
174
183
  `GET /workflows/<wrapper>` carries each Open body's declaration. So a Workflow is one of three things: a Machine from
175
184
  the Assembly, a Chart file from the Assembly, or a runtime Chart, and the last two are children of the first. **There
176
185
  is no collision rule between a Machine and a Chart**: a Machine's name is a filename stem and holds no slash, a
@@ -206,13 +215,14 @@ their own maintainers, and the escapes shipped in systems that used them were in
206
215
  above. The minted Agents: every model against the allowed list and the placed keys, every Workspace access against the
207
216
  allowed set. The structure: no `always` cycle without a guard, through parallel regions and history too; no `onDone`
208
217
  on an Agent invoke, because a Turn never settles by itself, it ends on a pick in `on`; no Agent state that nothing can
209
- end; no parallel state at or below an Agent's. An Agent state of a Chart needs no `agent.fault` route. A state of a
210
- Machine needs one ([ADR-0074](0074-an-unrouted-mechanism-event-is-refused-at-load-and-faults-the-run.md)). An
211
- `agent.fault` that no transition of the Chart takes goes, unchanged, to the Machine that invoked the Open body, and
212
- that Machine's `agent.fault` route takes it, as it takes the fault of an Agent of its own. So a Machine that invokes
213
- an Open body that can run an Agent needs the route too, on that state or above it. A route in the Chart stays legal,
214
- and it can read `{{event.reason}}`. The wrapper is the right place: a Chart under a body that lends no `fail` has no
215
- correct end for a fault, because a final state means `done`
218
+ end; no parallel state at or below an Agent's; no Agent in two states that can be active together. An Agent state of a
219
+ Chart needs no `agent.fault` route. A state of a Machine needs one
220
+ ([ADR-0074](0074-an-unrouted-mechanism-event-is-refused-at-load-and-faults-the-run.md)). An `agent.fault` that no
221
+ transition of the Chart takes goes, unchanged, to the Machine that invoked the Open body, and that Machine's
222
+ `agent.fault` route takes it, as it takes the fault of an Agent of its own. So a Machine that invokes an Open body
223
+ that can run an Agent needs the route too, on that state or above it. A route in the Chart stays legal, and it can
224
+ read `{{event.reason}}`. The wrapper is the right place: a Chart under a body that lends no `fail` has no correct end
225
+ for a fault, because a final state means `done`
216
226
  ([ADR-0073](0073-a-machine-fails-a-run-with-fail-and-an-uncaught-failure-ends-it-failed.md)) and a state that waits
217
227
  holds the run until the wall clock. So the briefing does not teach the route, and the grammar's fragment does not show
218
228
  it. And two checks that stand in for the types a Chart does not have. **Dataflow**: every reference a Chart makes,
@@ -224,12 +234,17 @@ their own maintainers, and the escapes shipped in systems that used them were in
224
234
  is refused. The fields a Chart declares are its types. **Lent input shapes**: an Effect carries an `input` schema and
225
235
  an Agent's Turn input is a fixed key set (`prompt`, `cwd`, `continue`, `model`, `thinkingLevel`, no placement), so the
226
236
  literal parts of a Chart's `input` objects are validated at the door and the resolved object again at invoke time,
227
- where a failure is that invoke's error and never a mid-Turn surprise. Last, the door compiles the Chart as the body
228
- would: `jr2Setup`'s own refusals (less its `agent.fault` refusal), and the load warnings a hand-written Machine gets
229
- (an unentered mode), are refusal lines for a Chart, because a planner reads a report and nobody reads a warning. A
230
- refusal is the body's OUTPUT, `{ outcome: "refused", report }`, routed by the wrapper's `onDone` with a guard on
231
- `outcome`, so a wrapper whose `onDone` returns to the planning state hands it to the planner as the output link in its
232
- Chain ([ADR-0067](0067-an-effect-is-an-actor-slot-and-runs-at-most-once-unless-marked-idempotent.md)): "Chart refused:
237
+ where a failure is that invoke's error and never a mid-Turn surprise. Then the rules of a Worktree (ADR-0075). Under
238
+ Repo Slots, a Turn's `cwd` and an Effect's `worktree` are required, and the door refuses a `cwd` that is a slot's
239
+ folder. A cut lent to a Chart must state `expect`, which is static, so a Chart cannot change it. The door refuses
240
+ `expect: "existing"` beside a lent force push, because together they let a Chart force-push any existing branch that
241
+ `default/` does not hold. A Chart's payload has no `pattern`, so a bad branch name reaches the cut, and the cut
242
+ refuses it. Last, the door compiles the Chart as the body would: `jr2Setup`'s own refusals (less its `agent.fault`
243
+ refusal), and the load warnings a hand-written Machine gets (an unentered mode), are refusal lines for a Chart,
244
+ because a planner reads a report and nobody reads a warning. A refusal is the body's OUTPUT,
245
+ `{ outcome: "refused", report }`, routed by the wrapper's `onDone` with a guard on `outcome`, so a wrapper whose
246
+ `onDone` returns to the planning state hands it to the planner as the output link in its Chain
247
+ ([ADR-0067](0067-an-effect-is-an-actor-slot-and-runs-at-most-once-unless-marked-idempotent.md)): "Chart refused:
233
248
  `src: "linter"` is not a lent actor; lent: coder, reviewer, push", and the planner answers with a corrected Chart. It
234
249
  is not the body's error, because a child's error is a defect that never reaches the model (ADR-0067, which stands); at
235
250
  the HTTP door it is 422 with the same report. No new mechanism: an Agent reads its children's outputs through the
@@ -48,9 +48,13 @@ composition and does not replace it. The two uses stay two mechanisms.
48
48
  the url and the token together, one Open part, with `customize(m, { effects: { task: { target: { url, token } } } })`
49
49
  ([ADR-0054](0054-the-kit-ships-machines-and-a-shipped-machine-leaves-its-parts-open.md)); `secret(open)` inside a
50
50
  target is refused, since the whole target is the part. Another Instance may run another Kit version, so the HTTP door
51
- is the only contract there. The token is the Instance token, which unlocks all control
52
- ([ADR-0032](0032-the-console-unlocks-with-the-instance-token.md)); a start-only token is a token kind of its own and
53
- is deferred.
51
+ is the only contract there. The token is any Caller's credential of the other Instance with `start` for the callee
52
+ Workflow ([ADR-0078](0078-a-caller-comes-from-one-authenticator-seam-and-acts-within-its-scopes.md)): a named Caller
53
+ token made for this, or that Instance's Instance token. A `wait` also polls `GET /runs/<id>`, so its token needs
54
+ `read` for that Workflow too. The start carries the first Caller of the calling run's `startedBy` chain as
55
+ `onBehalfOf`, in the header `jr2-on-behalf-of`, which the other Instance records and does not check: that Caller's own
56
+ `onBehalfOf`, else the name that jr2 shows, else `<via>/<name>`. A chain that jr2 started, or a text that is not
57
+ printable ASCII of at most 256 characters, sends no claim.
54
58
  - **Two settlements, `started` by default, and every outcome is output.** `{ outcome: "started", run }` settles when the
55
59
  Orchestrator accepts the run; the watcher goes round again. `wait: true` settles
56
60
  `{ outcome: "settled", run, status, output }` when that run ends, `status` in the store's own words (`done`, `failed`,
@@ -69,12 +73,12 @@ composition and does not replace it. The two uses stay two mechanisms.
69
73
  a DELETE of the Effect ends that poll and never touches the run. No callback from the callee: a callback needs the
70
74
  callee to hold its caller's address and a token for it, which inverts the trust. A door refusal is OUTPUT,
71
75
  `{ outcome: "refused", status, report }`, with the door's status — 400 for bad input, 404 for a name the current
72
- Assembly lacks, 409 for an unrunnable named Chart or a key another Workflow's run holds, 422 for a Chart the door
73
- refuses, 413 for a start over the bytes an Effector reads, 0 when the Effector refused it before anything was sent —
74
- as a Chart refusal is ([ADR-0070](0070-a-machine-lends-its-parts-to-a-chart.md)): the body may have come from a model,
75
- and the report must be able to reach it through the Chain. A target no replica could reach is
76
- `{ outcome: "unreachable" }`, output, as an `http` Effect's is (ADR-0067): nothing was started. The invoke's error is
77
- kept for defects: no run host or Effector, input that fails the slot's schema, a refused or malformed wire.
76
+ Assembly lacks, 409 for an unrunnable named Chart, 422 for a Chart the door refuses, 413 for a start over the bytes an
77
+ Effector reads, 0 when the Effector refused it before anything was sent — as a Chart refusal is
78
+ ([ADR-0070](0070-a-machine-lends-its-parts-to-a-chart.md)): the body may have come from a model, and the report must
79
+ be able to reach it through the Chain. A target no replica could reach is `{ outcome: "unreachable" }`, output, as an
80
+ `http` Effect's is (ADR-0067): nothing was started. The invoke's error is kept for defects: no run host or Effector,
81
+ input that fails the slot's schema (when no run has the key, below), a refused or malformed wire.
78
82
  - **The two runs are independent.** Cancelling the caller never cancels the callee; the caller's end never ends it;
79
83
  leaving the state stops a wait and never the run; the callee's Workspaces are its own. Temporal's parent-close policy
80
84
  (`TERMINATE` by default, `REQUEST_CANCEL`, `ABANDON`) exists because a child there is both a run and a child, and its
@@ -89,7 +93,8 @@ composition and does not replace it. The two uses stay two mechanisms.
89
93
  `dispatched [{ slot, run, at }]`, the chain's other direction. `jr2 runs` carries `dispatchedBy` after the id,
90
94
  `jr2 status` prints `dispatched by:` and `dispatched:` lines, and the Console shows both. The word is **dispatched
91
95
  by**. The callee reads nothing of its caller from its input: a Machine that wants to tell its callee something passes
92
- it as input like any caller.
96
+ it as input like any caller. A local dispatch records its caller's run as the callee's `startedBy`,
97
+ `{ kind: "run", run, slot }`, and `jr2 status` walks that chain to the first Caller (ADR-0078).
93
98
  - **A chain of dispatches is unbounded.** A run may dispatch a Workflow that dispatches another, or itself: a run that
94
99
  dispatches its own successor and ends is Temporal's continue-as-new, the honest way to keep a watcher's snapshot
95
100
  small, and a depth ceiling would refuse it. A runaway chain is a resource problem the cluster owner's quota and
@@ -100,24 +105,45 @@ composition and does not replace it. The two uses stay two mechanisms.
100
105
  key, out of band — the `jr2-dispatched-by` header, the `dispatchedBy` record as JSON, never a body field the callee's
101
106
  door would have to reserve — and `POST /workflows/<name>/runs` asks the key before anything else, so a re-sent start
102
107
  answers its run even when the name would be refused now: 201 with the run for a new one, 200 with
103
- `{ runId, instanceId, existing: true }` for a repeat, 409 when a run of ANOTHER Workflow holds the key (the caller
104
- asked for one Workflow and would wait on a run of another), 400 when the header does not parse, and 500, never 404,
105
- for any other throw, since a foreign caller reads a 404 as "nothing was started" (ADR-0033 as amended). The key lives
106
- in the callee's blob, and the store copies it into a `dispatch_effect` column of its own at every save and indexes
107
- that, not an expression index over `json_extract`: SQLite's JSON parser refuses a blob nested about a thousand deep,
108
- and such an index would fail that row's save and every later open of the volume. A run restore marks `lost` keeps its
109
- row and its blob, so its key keeps answering; the weekly sweep
110
- ([ADR-0065](0065-a-persist-survives-a-crash-and-history-is-a-week.md)) removes the key with the row, and a re-send
111
- after it starts a new run: known, and not guarded. In-process the ledger is consulted directly, through the same start
112
- under the same key, with the starts in flight held so two arrivals of one key before the first save are one run. So a
113
- dispatch is idempotent whatever its author writes: its intent row says `idempotent: true`, a restore that cannot tell
114
- whether its start arrived sends it again under its key with what is left of the bound, the Instance Effector sends a
115
- start whose answer was lost again under its key with backoff until the bound, and the Effector's rollout grace is
116
- never stretched by a dispatch's wait. Once the answer names the run, the intent row carries it, the Effector's
117
- `running` state carries it on the wire, and a restore with it starts nothing: it settles `started` at once, or resumes
118
- the wait. Without it a watcher double-starts a run after a restart, which a human notices as two pull requests. What
119
- it does not guard: a door at a Kit version before this decision ignores the header, so a re-send to it starts a second
120
- run, and neither the Effector nor the preflight can tell. A capability check is named and deferred.
108
+ `{ runId, instanceId, existing: true }` for a repeat, 200 with `{ existing: false }` for a key-only ask (below) with
109
+ no run under the key, 400 when a header does not parse, and 500, never 404, for any other throw, since a foreign
110
+ caller reads a 404 as "nothing was started" (ADR-0033 as amended). **The key is scoped to the callee Workflow**: the
111
+ store finds a key with the Workflow's name, so the same key in two Workflows is two runs, and a key never answers with
112
+ a run of another Workflow. A key answers `existing` while its run's row lives, in any status: live, and for
113
+ `runs.retain` after it ends ([ADR-0065](0065-a-persist-survives-a-crash-and-history-is-kept-for-a-set-time.md)). A
114
+ retry after a failure is then a person's act, not a re-sent start's. The Effect checks the key before it checks its
115
+ input against the slot's schema, in-process and on the foreign path, as the door does: a start sent again across a
116
+ change of the callee's door answers `existing`, not an error. In-process it asks the run host for the key before it
117
+ reads the input, within the slot's bound. On the foreign path, a body that the slot's schema refuses is never sent:
118
+ the start is a **key-only ask**, the header `jr2-key-only: true` beside `jr2-dispatched-by` and no body, out of band
119
+ as the key is. The door keeps its order: the scope check (ADR-0078), then the key. With a run under the key it answers
120
+ `existing`, as for any start; with none it starts nothing and answers 200 with `{ existing: false }`, which a foreign
121
+ caller cannot read as a refused name (404) or a defect (5xx). The Instance Effector settles that answer as `absent`,
122
+ an outcome of the wire alone, and the Effect makes it the slot's schema refusal, the invoke's error. So input that
123
+ fails the slot's schema starts nothing on either path, and a run that its key already started is answered on both. A
124
+ body that the slot's schema takes goes as before, in one request. This is the same for a first send and for a send
125
+ again (a restore, a retry): a Pool's hand-over is a first send of a new run's Effect under a key that may already name
126
+ a run of a callee whose door changed. A `wait` sent again under a key that answers `existing` follows that run, and
127
+ settles when it ends. **A Pool's worker sends its `itemId` as the key** ([ADR-0017](0017-pool-over-a-source-port.md)),
128
+ so a Pool's hand-over re-attaches to each live run. An author's own key (`dispatch({ key })`) is not offered now; to
129
+ add it later breaks nothing. The key lives in the callee's blob (a Pool's `dispatchedBy.key`, else
130
+ `dispatchedBy.effect`), and the store copies it and the Workflow into columns of their own (`dispatch_effect`,
131
+ `dispatch_workflow`) at every save and indexes the pair, not an expression index over `json_extract`: SQLite's JSON
132
+ parser refuses a blob nested about a thousand deep, and such an index would fail that row's save and every later open
133
+ of the volume. A run restore marks `lost` keeps its row and its blob, so its key keeps answering; the sweep of rows
134
+ older than `runs.retain` ([ADR-0065](0065-a-persist-survives-a-crash-and-history-is-kept-for-a-set-time.md)) removes
135
+ the key with the row, and a re-send after it starts a new run: known, and not guarded. In-process the ledger is
136
+ consulted directly, through the same start under the same key, with the starts in flight held so two arrivals of one
137
+ key before the first save are one run. So a dispatch is idempotent whatever its author writes: its intent row says
138
+ `idempotent: true`, a restore that cannot tell whether its start arrived sends it again under its key with what is
139
+ left of the bound, the Instance Effector sends a start whose answer was lost again under its key with backoff until
140
+ the bound, and the Effector's rollout grace is never stretched by a dispatch's wait. Once the answer names the run,
141
+ the intent row carries it, the Effector's `running` state carries it on the wire, and a restore with it starts
142
+ nothing: it settles `started` at once, or resumes the wait. Without it a watcher double-starts a run after a restart,
143
+ which a human notices as two pull requests. What it does not guard: a door at a Kit version before this decision
144
+ ignores the header, so a re-send to it starts a second run, and a door that knows the key but not the key-only ask
145
+ reads one as a start with no body; neither the Effector nor the preflight can tell. A capability check is named and
146
+ deferred.
121
147
  - **`jr2 up` checks what it can see, and the severity follows who owns both sides.** For a same-Instance name the walk
122
148
  resolves it in the Assembly and REFUSES a miss, naming the fix: on the host, among the Machines and the Chart files,
123
149
  and a slashed name whose wrapper exists but whose Chart the host cannot see is a warning there, since a runtime Chart
@@ -172,7 +198,7 @@ composition and does not replace it. The two uses stay two mechanisms.
172
198
  - ADR-0049's "no sub-run" is restated, not reversed: a nested Machine is reached by `import`, never by name; a run that
173
199
  starts a run is a `dispatch`, by name, and the two are different uses. ADR-0067 gains the kind and a fourth Placement,
174
200
  `orchestrator`. ADR-0068's Instance Effector gains the `dispatch` kind, its stop route stops a dispatch's wait too,
175
- and its `running` state carries the run. ADR-0033's door gains an idempotency key.
201
+ and its `running` state carries the run. ADR-0033's door gains an idempotency key and the key-only ask.
176
202
  - The GLOSSARY's **Effect** gains "or starts a run", and `_Avoid_: sub-run, child run, nested run, spawned run` for the
177
203
  relation, which is **dispatched by**; its **Effector** and **Instance Effector** entries name the in-process exception
178
204
  and the new kind.
@@ -180,4 +206,4 @@ composition and does not replace it. The two uses stay two mechanisms.
180
206
  routing of both, without the key.
181
207
  - An Open body may lend a `dispatch` slot as it lends any Effect (`lends.effects`), so a Chart can start a run of a
182
208
  Workflow its wrapper chose; the Chart fills the body only.
183
- - Deferred, named: a start-only token; a depth ceiling; a capability check for a door that ignores the key.
209
+ - Deferred, named: a depth ceiling; a capability check for a door that ignores the key; an author's own key.
@@ -15,22 +15,27 @@ Next.js ships the same design: its docs as Markdown inside the `next` package, a
15
15
  - **The bundle.** `@jr2/orchestrator` ships `docs/`: every page of the sitemap, the generated Reference, the Glossary
16
16
  and the Decisions, as plain Markdown. No site-generator syntax reaches it. It is the main channel for an Assistant.
17
17
  Each page is at its slug, such as `concepts/gates.md`, and each ADR is at `reference/decisions/<file>`. An Assistant
18
- reads a page with its file tool, which cuts off a long file. So the Authoring surface is two parts:
19
- `reference/authoring-surface.md`, a contents page that gives each name its kind and the first sentence of its TSDoc,
20
- and `reference/authoring-surface/<anchor>.md`, one page for each export and for each type that a signature names.
21
- One page of all the names is about 200 KB, and the contents page is less than 25 KB. No line of the contents page or
22
- of an entry page is longer than 1,000 characters, so the type plumbing is a list, not a paragraph. When the contents
23
- page passes 25 KB, first make the long first sentences shorter; if it still passes, give each group of the contents
24
- page a page of its own, and make the contents page a list of the groups. The first sentence ends at a stop, not at a
25
- colon, because the words before a colon often tell nothing alone ("An invoke."). A link to an entry goes to its
26
- page. Each of the other generated Reference pages (CLI, config, machines, mechanism events, HTTP API) stays one
27
- page. Each is less than 30 KB, the size that one read of a file tool shows, with one exception: the HTTP API page is
28
- about 50 KB. It is one page because its routes come first and are less than 30 KB, so one read shows every route;
29
- the types of the bodies come after the routes, and an Assistant reads one of them with an offset or by its heading.
30
- When the routes pass 30 KB, give the types a page of their own. The alternative, a split of the HTTP API page now,
31
- is rejected because a route and the types it names are then on two pages, and one read shows all routes already. The
32
- Glossary and the Decisions are not generated, and this rule does not hold them: an ADR can be about 50 KB, and an
33
- Assistant reads the one ADR that a page links to.
18
+ reads a page with its file tool, which cuts off a long file. So the Authoring surface is three parts.
19
+ `reference/authoring-surface.md` is a contents page that gives each group of the root's `src/index.ts`, and the
20
+ group of the types that the signatures name, its description and its names.
21
+ `reference/authoring-surface/group-<title>.md` is one page for each group, which gives each name of the group its
22
+ kind and the first sentence of its TSDoc. `reference/authoring-surface/<anchor>.md` is one page for each export and
23
+ for each type that a signature names. The `group-` prefix keeps a group page apart from an entry page, and
24
+ `docs:build` fails when two pages have one path. One page of all the names is about 200 KB. The contents page and
25
+ each group page are less than 25 KB, and each entry page is less than 15 KB. On the contents page, a type that a
26
+ signature names is code with no link, because there are more than a hundred of them; its group page links each one.
27
+ No line of a contents, group or entry page is longer than 1,000 characters, so the contents page breaks a list of
28
+ names into lines, and the type plumbing is a list, not a paragraph. When a group page passes 25 KB, first make the
29
+ long first sentences shorter; if it still passes, divide that group into two groups. The first sentence ends at a
30
+ stop, not at a colon, because the words before a colon often tell nothing alone ("An invoke."). A link to an entry
31
+ goes to its page. Each of the other generated Reference pages (CLI, config, machines, Hook kinds, mechanism events,
32
+ HTTP API) stays one page. Each is less than 30 KB, the size that one read of a file tool shows, with one exception:
33
+ the HTTP API page is about 50 KB. It is one page because its routes come first and are less than 30 KB, so one read
34
+ shows every route; the types of the bodies come after the routes, and an Assistant reads one of them with an offset
35
+ or by its heading. When the routes pass 30 KB, give the types a page of their own. The alternative, a split of the
36
+ HTTP API page now, is rejected because a route and the types it names are then on two pages, and one read shows all
37
+ routes already. The Glossary and the Decisions are not generated, and this rule does not hold them: an ADR can be
38
+ about 50 KB, and an Assistant reads the one ADR that a page links to.
34
39
  - **The `AGENTS.md` block.** A compressed index of the bundle, and an instruction in five parts. jr2 is newer than
35
40
  your training data, so read the bundled docs before you write a Machine or config. Start with the guide "Write a
36
41
  workflow" and the contents page of the Authoring surface. Read one page with each call of the file tool. Run
@@ -63,21 +68,26 @@ Next.js ships the same design: its docs as Markdown inside the `next` package, a
63
68
  exists for it. A broken marker pair is reported, and `up` does not change the file.
64
69
  - **The Reference is generated from the code wherever the code holds the facts.**
65
70
 
66
- | Page | Source |
67
- | ------------------------------------------------------- | ------------------------------------------------------ |
68
- | Authoring surface: a contents page, and a page per name | TSDoc on the exports, exactly the root's list |
69
- | `@jr2/machines` | TSDoc on the exports |
70
- | `jr2.config.ts` | TSDoc on the `JR2Config` fields |
71
- | CLI | a structured command table, which also prints `--help` |
72
- | HTTP API | the route table in `http.ts`, made data |
73
- | Mechanism events | the code that defines them |
74
- | Glossary, Decisions | `GLOSSARY.md` and `docs/adr/`, rendered as they are |
71
+ | Page | Source |
72
+ | ------------------------------------------------------------------------- | -------------------------------------------------------------- |
73
+ | Authoring surface: a contents page, a page per group, and a page per name | TSDoc on the exports, exactly the root's list |
74
+ | `@jr2/machines` | TSDoc on the exports |
75
+ | `@jr2/orchestrator/hooks` | TSDoc on the exports of each module but `door`, one group each |
76
+ | `jr2.config.ts` | TSDoc on the `JR2Config` fields |
77
+ | CLI | a structured command table, which also prints `--help` |
78
+ | HTTP API | the route table in `http.ts`, made data |
79
+ | Mechanism events | the code that defines them |
80
+ | Glossary, Decisions | `GLOSSARY.md` and `docs/adr/`, rendered as they are |
75
81
 
76
82
  The TSDoc on an Authoring surface export is written for the author: what it does, what it refuses, what to read next,
77
83
  and one example. Maintainer reasoning goes in `//` comments in the body. The packages ship their `.ts` source, so an
78
84
  Assistant that follows an import into `node_modules` reads the same text the site shows. The Authoring surface is
79
85
  exactly what `@jr2/orchestrator` exports from its root: what the kit's packages share is internal even where it can be
80
86
  imported, and `@jr2/machines` is not part of it, because it ships Machines, not names to author with.
87
+ `@jr2/orchestrator/hooks` is not part of it either, because a Hook kind is a module of its own interface, which a kind
88
+ from another package imports too
89
+ ([ADR-0078](0078-a-caller-comes-from-one-authenticator-seam-and-acts-within-its-scopes.md)). Its page leaves out
90
+ `hook-kinds/door.ts`, which only the Orchestrator reads.
81
91
 
82
92
  - **`docs:build` assembles the bundle at pack time.** Its inputs are the hand-written pages in `docs/site/`, the
83
93
  generated Reference, `GLOSSARY.md`, and `docs/adr/`. It runs in `@jr2/orchestrator`'s `prepack` and before the site
@@ -39,7 +39,7 @@ comment "the run faults rather than lie about a decision", and that run ended `d
39
39
  the run holds then, and nor does a Workspace that was stopped in `placing`
40
40
  ([ADR-0064](0064-a-workspace-waits-for-capacity.md)): a parent that invokes the same Machine again gives the new
41
41
  Workspace the same invoke id, and so the same Sandbox name. That new Workspace takes over the Sandbox and its
42
- Worktree, as a restore does, with the work of the failed attempt still in it. To keep the work for a person to read,
42
+ Worktrees, as a restore does, with the work of the failed attempt still in it. To keep the work for a person to read,
43
43
  the Machine waits at a Gate before it fails.
44
44
  - **`jr2 run` exits 0 only for `done`.** It exits 1 for every other end: `failed`, `error`, `cancelled`, `lost`,
45
45
  `drifted`, and a run that was parked before it settled. Exit code 2 stays the CLI's code for a usage error. The status