@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
@@ -50,6 +50,7 @@ import type {
50
50
  EffectLogic,
51
51
  EffectMarker,
52
52
  EffectRow,
53
+ EffectParts,
53
54
  EffectSnapshot,
54
55
  HttpParts,
55
56
  OpenHttpParts,
@@ -106,9 +107,9 @@ declare const openSecretMark: unique symbol;
106
107
  */
107
108
  export type OpenSecretMark = { readonly [openSecretMark]: true };
108
109
 
109
- /** A named secret, never `secret(open)`: where a definition's Open part is a whole that holds a
110
- * secret — a dispatch's target (ADR-0071) — the secret is bound with it, to a name, so the mark
111
- * `secret(open)` carries may not be present. One type for the definition and the binding. */
110
+ /** A secret bound to a name, never `secret(open)`. Where a definition's Open part is a whole that
111
+ * holds a secret — a dispatch's target (ADR-0071) — the secret is bound with it, to a name, so the
112
+ * mark `secret(open)` carries may not be present. One type for the definition and the binding. */
112
113
  export type NamedSecret = Secret & { readonly [K in keyof OpenSecretMark]?: never };
113
114
 
114
115
  /** `secret(open)`: a secret a packaged Machine names in its auth, a header or a command's env, and
@@ -1067,8 +1068,58 @@ export function httpWith<S extends z.ZodType | undefined = undefined>(
1067
1068
  const unbound = openHttpOf(def, (bound) => httpWith(portFactory, bound));
1068
1069
  if (unbound) return unbound as EffectLogic<HttpInput<S>, HttpOutput>;
1069
1070
  const parts = httpParts(def);
1070
- type I = HttpInput<S>;
1071
- type O = HttpOutput;
1071
+ return instanceEffectLogic<HttpInput<S>, HttpOutput>(
1072
+ parts,
1073
+ {
1074
+ kind: "http",
1075
+ idempotent: parts.idempotent,
1076
+ label: `${parts.method} ${hostText(parts)}`,
1077
+ request: (input, slot) => {
1078
+ if (def.input !== undefined) {
1079
+ const parsed = def.input.safeParse(input);
1080
+ if (!parsed.success) {
1081
+ throw new Error(
1082
+ `http "${slot}": its input does not match the definition's input schema — ` +
1083
+ parsed.error.issues.map((i) => `${i.path.join(".") || "(root)"}: ${i.message}`).join("; "),
1084
+ );
1085
+ }
1086
+ input = parsed.data;
1087
+ }
1088
+ const runParts = def.request ? (def.request as (i: unknown) => HttpRequestParts)(input) : {};
1089
+ return startRequestOf(parts, runParts ?? {});
1090
+ },
1091
+ },
1092
+ portFactory,
1093
+ );
1094
+ }
1095
+
1096
+ /**
1097
+ * What the Instance Effector's driver needs of one kind that runs there and has no stop: `http`
1098
+ * and `mcp` (ADR-0068, ADR-0079). The driver is the same for both: the write-ahead intent row, the
1099
+ * restore rule, a forged answer, and D1.
1100
+ */
1101
+ export type InstanceKind = {
1102
+ readonly kind: "http" | "mcp";
1103
+ /** The author's mark: a restore that finds no replica that holds it sends it again. */
1104
+ readonly idempotent: boolean;
1105
+ /** What the `started` marker says: `POST https://host`, `mcp slack-acme/post_message`. */
1106
+ readonly label: string;
1107
+ /** The run's start, from the invoke's input. It throws on a defect of the Machine, and then
1108
+ * nothing is sent. */
1109
+ readonly request: (input: unknown, slot: string) => StartRequest;
1110
+ };
1111
+
1112
+ /**
1113
+ * The slot logic of an Effect that the Instance Effector runs, over an injected port factory: the
1114
+ * seam `httpWith` and `mcpWith` share.
1115
+ *
1116
+ * @internal
1117
+ */
1118
+ export function instanceEffectLogic<I, O>(
1119
+ parts: EffectParts,
1120
+ spec: InstanceKind,
1121
+ portFactory: EffectorPortFactory,
1122
+ ): EffectLogic<I, O> {
1072
1123
  const logic: ActorLogic<EffectSnapshot<O, I>, EventObject, I> = {
1073
1124
  getInitialSnapshot: (_scope, input) => ({
1074
1125
  status: "active",
@@ -1086,7 +1137,7 @@ export function httpWith<S extends z.ZodType | undefined = undefined>(
1086
1137
  return { ...snapshot, status: "error", error: (event as Fault).error, input: undefined };
1087
1138
  }
1088
1139
  if (event.type === "xstate.stop") {
1089
- stopped(self, system, snapshot.effectId);
1140
+ stopped(self, system, snapshot.effectId, spec.kind);
1090
1141
  return { ...snapshot, status: "stopped", input: undefined };
1091
1142
  }
1092
1143
  return snapshot;
@@ -1095,7 +1146,7 @@ export function httpWith<S extends z.ZodType | undefined = undefined>(
1095
1146
  if (snapshot.status !== "active") return;
1096
1147
  const run: Running = { controller: new AbortController() };
1097
1148
  running.set(self, run);
1098
- void drive(self, system, snapshot, parts, def, portFactory, run).catch((error: unknown) => {
1149
+ void drive(self, system, snapshot, spec, portFactory, run).catch((error: unknown) => {
1099
1150
  if (run.controller.signal.aborted) return;
1100
1151
  if (self.getSnapshot().status === "active") self.send({ type: "jr2.effect.error", error } as Fault);
1101
1152
  });
@@ -1111,8 +1162,7 @@ async function drive<I, O>(
1111
1162
  self: AnyActorRef,
1112
1163
  system: AnyActorSystem,
1113
1164
  snapshot: EffectSnapshot<O, I>,
1114
- parts: HttpParts,
1115
- def: HttpDefinition<z.ZodType | undefined>,
1165
+ spec: InstanceKind,
1116
1166
  portFactory: EffectorPortFactory,
1117
1167
  run: Running,
1118
1168
  ): Promise<void> {
@@ -1123,11 +1173,11 @@ async function drive<I, O>(
1123
1173
  const now = (): string => new Date().toISOString();
1124
1174
  const mark = (marker: Omit<EffectMarker, "kind" | "slot" | "effect">): void =>
1125
1175
  binding?.marker?.({ kind: "effect", slot, effect: id, ...marker });
1126
- const settle = (output: HttpOutput): void => {
1176
+ const settle = (output: NonNullable<EffectMarker["output"]>): void => {
1127
1177
  if (signal.aborted || self.getSnapshot().status !== "active") return;
1128
1178
  // The settled row first, saved at the write: a restart before the transition is saved delivers
1129
1179
  // this output, and sends nothing.
1130
- binding?.recordEffect?.(id, { state: "settled", kind: "http", slot, output, at: now() });
1180
+ binding?.recordEffect?.(id, { state: "settled", kind: spec.kind, slot, output, at: now() });
1131
1181
  mark({ stage: "settled", output });
1132
1182
  self.send({ type: "jr2.effect.settle", output } satisfies Settle);
1133
1183
  };
@@ -1149,8 +1199,8 @@ async function drive<I, O>(
1149
1199
  const target = binding?.effector?.("instance");
1150
1200
  if (!target) {
1151
1201
  throw new Error(
1152
- `http "${slot}" runs in the Instance Effector, and this Orchestrator knows none — \`jr2 up\` converges it ` +
1153
- "when a registered Machine carries an http Effect (ADR-0068)",
1202
+ `${spec.kind} "${slot}" runs in the Instance Effector, and this Orchestrator knows none — \`jr2 up\` ` +
1203
+ `converges it when a registered Machine carries an ${spec.kind} Effect (ADR-0068)`,
1154
1204
  );
1155
1205
  }
1156
1206
  const port = portFactory(target);
@@ -1180,7 +1230,7 @@ async function drive<I, O>(
1180
1230
  await follow(found);
1181
1231
  return;
1182
1232
  }
1183
- if (!parts.idempotent) {
1233
+ if (!spec.idempotent) {
1184
1234
  settle(
1185
1235
  unknown(
1186
1236
  "it was in flight when the Orchestrator restarted, and no Effector replica holds it; not sent again " +
@@ -1189,7 +1239,7 @@ async function drive<I, O>(
1189
1239
  );
1190
1240
  return;
1191
1241
  }
1192
- mark({ stage: "started", text: `${parts.method} ${hostText(parts)} (sent again: it is idempotent)` });
1242
+ mark({ stage: "started", text: `${spec.label} (sent again: it is idempotent)` });
1193
1243
  await send(requestFor());
1194
1244
  return;
1195
1245
  }
@@ -1207,29 +1257,17 @@ async function drive<I, O>(
1207
1257
  // request leaves.
1208
1258
  binding?.recordEffect?.(id, {
1209
1259
  state: "intent",
1210
- kind: "http",
1260
+ kind: spec.kind,
1211
1261
  slot,
1212
1262
  placement: "instance",
1213
- idempotent: parts.idempotent,
1263
+ idempotent: spec.idempotent,
1214
1264
  at: now(),
1215
1265
  });
1216
- mark({ stage: "started", text: `${parts.method} ${hostText(parts)}` });
1266
+ mark({ stage: "started", text: spec.label });
1217
1267
  await send(req);
1218
1268
 
1219
1269
  function requestFor(): StartRequest {
1220
- let input: unknown = snapshot.input;
1221
- if (def.input !== undefined) {
1222
- const parsed = def.input.safeParse(input);
1223
- if (!parsed.success) {
1224
- throw new Error(
1225
- `http "${slot}": its input does not match the definition's input schema — ` +
1226
- parsed.error.issues.map((i) => `${i.path.join(".") || "(root)"}: ${i.message}`).join("; "),
1227
- );
1228
- }
1229
- input = parsed.data;
1230
- }
1231
- const runParts = def.request ? (def.request as (i: unknown) => HttpRequestParts)(input) : {};
1232
- return startRequestOf(parts, runParts ?? {});
1270
+ return spec.request(snapshot.input, slot);
1233
1271
  }
1234
1272
 
1235
1273
  /** Send the start, and follow it. A start that never reached a replica is sent again; one whose
@@ -1256,7 +1294,7 @@ async function drive<I, O>(
1256
1294
  await follow(found);
1257
1295
  return;
1258
1296
  }
1259
- if (!parts.idempotent) {
1297
+ if (!spec.idempotent) {
1260
1298
  settle(unknown("its start may have reached the Effector, and no replica holds it now; not sent again"));
1261
1299
  return;
1262
1300
  }
@@ -1277,7 +1315,7 @@ async function drive<I, O>(
1277
1315
  let replica: Replica = first.replica;
1278
1316
  for (;;) {
1279
1317
  if (state.state === "settled" && state.output) {
1280
- settle(state.output as HttpOutput);
1318
+ settle(state.output as NonNullable<EffectMarker["output"]>);
1281
1319
  return;
1282
1320
  }
1283
1321
  if (state.state === "unknown") {
@@ -1285,7 +1323,7 @@ async function drive<I, O>(
1285
1323
  if (!asked || signal.aborted) return;
1286
1324
  const { found } = asked;
1287
1325
  if (!found) {
1288
- if (parts.idempotent) {
1326
+ if (spec.idempotent) {
1289
1327
  await send(requestFor());
1290
1328
  return;
1291
1329
  }
@@ -1316,15 +1354,15 @@ async function drive<I, O>(
1316
1354
  * unknown": an http Effect has no stop route, so the Effector finishes the call and drops an
1317
1355
  * outcome nobody reads. The Machine never hears it.
1318
1356
  */
1319
- function stopped(self: AnyActorRef, system: AnyActorSystem, effectId: string): void {
1357
+ function stopped(self: AnyActorRef, system: AnyActorSystem, effectId: string, kind: "http" | "mcp"): void {
1320
1358
  const run = running.get(self);
1321
1359
  running.delete(self);
1322
1360
  run?.controller.abort();
1323
1361
  const binding = boundRun(system);
1324
1362
  if (binding?.hostStopping) return;
1325
1363
  const row = binding?.effectRow?.(effectId);
1326
- if (row?.state !== "intent" || row.kind !== "http") return;
1327
- const aborted: EffectRow = { state: "aborted", kind: "http", slot: row.slot, at: new Date().toISOString() };
1364
+ if (row?.state !== "intent" || row.kind !== kind) return;
1365
+ const aborted: EffectRow = { state: "aborted", kind, slot: row.slot, at: new Date().toISOString() };
1328
1366
  binding?.recordEffect?.(effectId, aborted, "with-transition");
1329
1367
  binding?.marker?.({
1330
1368
  kind: "effect",
@@ -1337,7 +1375,7 @@ function stopped(self: AnyActorRef, system: AnyActorSystem, effectId: string): v
1337
1375
 
1338
1376
  /** A start over the bytes the Effector reads is output `refused` (ADR-0068): the Effector could not
1339
1377
  * verify it, and a body built from context or a pick's param can reach the bound. */
1340
- function tooLarge(req: StartRequest): HttpOutput | undefined {
1378
+ function tooLarge(req: StartRequest): { outcome: "refused"; reason: string } | undefined {
1341
1379
  const bytes = Buffer.byteLength(JSON.stringify(req), "utf8");
1342
1380
  if (bytes <= MAX_START_BYTES) return undefined;
1343
1381
  return {