@jr2/orchestrator 0.4.1 → 0.5.1

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 (327) hide show
  1. package/README.md +20 -2
  2. package/console/components/app.ts +2 -0
  3. package/console/components/fleet.ts +14 -1
  4. package/console/components/machine-pane.ts +41 -2
  5. package/console/main.ts +13 -1
  6. package/console/store.ts +102 -6
  7. package/console/style.css +21 -0
  8. package/docs/agents-block.md +5 -0
  9. package/docs/concepts/agents-and-turns.md +442 -0
  10. package/docs/concepts/architecture.md +230 -0
  11. package/docs/concepts/charts.md +143 -0
  12. package/docs/concepts/composition.md +357 -0
  13. package/docs/concepts/converge.md +254 -0
  14. package/docs/concepts/durable-runs.md +189 -0
  15. package/docs/concepts/effects.md +603 -0
  16. package/docs/concepts/gates.md +208 -0
  17. package/docs/concepts/machines-and-workflows.md +289 -0
  18. package/docs/concepts/pools-and-sources.md +230 -0
  19. package/docs/concepts/secrets-and-trust.md +222 -0
  20. package/docs/concepts/the-menu.md +378 -0
  21. package/docs/concepts/workspaces.md +678 -0
  22. package/docs/get-started/a-model-decides.md +563 -0
  23. package/docs/get-started/an-agent-in-a-sandbox.md +381 -0
  24. package/docs/get-started/connect-a-model.md +248 -0
  25. package/docs/get-started/create-an-instance.md +194 -0
  26. package/docs/get-started/have-your-assistant-write-a-machine.md +922 -0
  27. package/docs/get-started/install.md +126 -0
  28. package/docs/guides/add-tools-to-the-sandbox.md +295 -0
  29. package/docs/guides/answer-a-gate.md +304 -0
  30. package/docs/guides/bind-open-parts.md +223 -0
  31. package/docs/guides/cancel-a-run.md +146 -0
  32. package/docs/guides/clean-up.md +206 -0
  33. package/docs/guides/fix-a-failed-converge.md +361 -0
  34. package/docs/guides/give-the-cluster-git-credentials.md +222 -0
  35. package/docs/guides/iterate-on-a-machine-on-kind.md +190 -0
  36. package/docs/guides/let-an-agent-write-a-chart.md +226 -0
  37. package/docs/guides/look-inside-a-sandbox.md +174 -0
  38. package/docs/guides/mirror-the-kit-images.md +176 -0
  39. package/docs/guides/move-from-kind-to-a-shared-cluster.md +302 -0
  40. package/docs/guides/open-the-console.md +91 -0
  41. package/docs/guides/publish-a-machine-as-an-npm-package.md +350 -0
  42. package/docs/guides/push-and-sign-a-branch.md +486 -0
  43. package/docs/guides/run-a-chart-by-name.md +270 -0
  44. package/docs/guides/run-a-command-or-call-a-url.md +544 -0
  45. package/docs/guides/run-one-worker-per-item.md +321 -0
  46. package/docs/guides/set-an-agents-access-and-dials.md +375 -0
  47. package/docs/guides/size-a-workspace.md +204 -0
  48. package/docs/guides/start-a-run-from-a-run.md +237 -0
  49. package/docs/guides/start-a-run.md +207 -0
  50. package/docs/guides/upgrade-the-kit-version.md +240 -0
  51. package/docs/guides/use-a-hosted-provider.md +208 -0
  52. package/docs/guides/use-a-local-model.md +313 -0
  53. package/docs/guides/watch-a-run.md +326 -0
  54. package/docs/guides/write-a-workflow.md +318 -0
  55. package/docs/index.md +44 -0
  56. package/docs/llms.txt +216 -0
  57. package/docs/reference/authoring-surface/agent.md +128 -0
  58. package/docs/reference/authoring-surface/answer.md +140 -0
  59. package/docs/reference/authoring-surface/arg.md +60 -0
  60. package/docs/reference/authoring-surface/basic.md +62 -0
  61. package/docs/reference/authoring-surface/bearer.md +53 -0
  62. package/docs/reference/authoring-surface/chartschema.md +23 -0
  63. package/docs/reference/authoring-surface/chartschemafor.md +48 -0
  64. package/docs/reference/authoring-surface/command.md +191 -0
  65. package/docs/reference/authoring-surface/customize.md +64 -0
  66. package/docs/reference/authoring-surface/defineconfig.md +41 -0
  67. package/docs/reference/authoring-surface/defineevent.md +114 -0
  68. package/docs/reference/authoring-surface/dispatch.md +126 -0
  69. package/docs/reference/authoring-surface/fail.md +83 -0
  70. package/docs/reference/authoring-surface/file.md +122 -0
  71. package/docs/reference/authoring-surface/frompick.md +277 -0
  72. package/docs/reference/authoring-surface/http.md +159 -0
  73. package/docs/reference/authoring-surface/isfailure.md +58 -0
  74. package/docs/reference/authoring-surface/jr2setup.md +237 -0
  75. package/docs/reference/authoring-surface/open.md +74 -0
  76. package/docs/reference/authoring-surface/openbody.md +86 -0
  77. package/docs/reference/authoring-surface/paramsof.md +125 -0
  78. package/docs/reference/authoring-surface/pool.md +186 -0
  79. package/docs/reference/authoring-surface/push.md +112 -0
  80. package/docs/reference/authoring-surface/secret.md +118 -0
  81. package/docs/reference/authoring-surface/sentby.md +83 -0
  82. package/docs/reference/authoring-surface/source.md +51 -0
  83. package/docs/reference/authoring-surface/text.md +62 -0
  84. package/docs/reference/authoring-surface/type-agentdeclaration.md +27 -0
  85. package/docs/reference/authoring-surface/type-agentdefinition.md +80 -0
  86. package/docs/reference/authoring-surface/type-agentlogic.md +15 -0
  87. package/docs/reference/authoring-surface/type-agentslots.md +12 -0
  88. package/docs/reference/authoring-surface/type-answeraction.md +12 -0
  89. package/docs/reference/authoring-surface/type-arg.md +19 -0
  90. package/docs/reference/authoring-surface/type-argnames.md +12 -0
  91. package/docs/reference/authoring-surface/type-binding.md +62 -0
  92. package/docs/reference/authoring-surface/type-bindingof.md +12 -0
  93. package/docs/reference/authoring-surface/type-bodyacceptsdoor.md +15 -0
  94. package/docs/reference/authoring-surface/type-bodyacceptsslots.md +17 -0
  95. package/docs/reference/authoring-surface/type-ceilings.md +41 -0
  96. package/docs/reference/authoring-surface/type-chainlink.md +19 -0
  97. package/docs/reference/authoring-surface/type-chartaction.md +46 -0
  98. package/docs/reference/authoring-surface/type-chartagent.md +28 -0
  99. package/docs/reference/authoring-surface/type-chartevent.md +20 -0
  100. package/docs/reference/authoring-surface/type-chartguard.md +20 -0
  101. package/docs/reference/authoring-surface/type-chartinvoke.md +28 -0
  102. package/docs/reference/authoring-surface/type-chartjson.md +14 -0
  103. package/docs/reference/authoring-surface/type-chartstate.md +46 -0
  104. package/docs/reference/authoring-surface/type-charttext.md +40 -0
  105. package/docs/reference/authoring-surface/type-charttransition.md +22 -0
  106. package/docs/reference/authoring-surface/type-charttransitions.md +14 -0
  107. package/docs/reference/authoring-surface/type-chartvalue.md +15 -0
  108. package/docs/reference/authoring-surface/type-childat.md +12 -0
  109. package/docs/reference/authoring-surface/type-childslots.md +12 -0
  110. package/docs/reference/authoring-surface/type-commandenv.md +15 -0
  111. package/docs/reference/authoring-surface/type-commandinput.md +19 -0
  112. package/docs/reference/authoring-surface/type-commandoptions.md +78 -0
  113. package/docs/reference/authoring-surface/type-commandoutput.md +104 -0
  114. package/docs/reference/authoring-surface/type-customize.md +109 -0
  115. package/docs/reference/authoring-surface/type-dispatchdefinition.md +39 -0
  116. package/docs/reference/authoring-surface/type-dispatchinput.md +14 -0
  117. package/docs/reference/authoring-surface/type-dispatchopenparts.md +14 -0
  118. package/docs/reference/authoring-surface/type-dispatchoutput.md +65 -0
  119. package/docs/reference/authoring-surface/type-duration.md +15 -0
  120. package/docs/reference/authoring-surface/type-effectbinding.md +93 -0
  121. package/docs/reference/authoring-surface/type-effectlogic.md +12 -0
  122. package/docs/reference/authoring-surface/type-envopenparts.md +14 -0
  123. package/docs/reference/authoring-surface/type-eventaudience.md +27 -0
  124. package/docs/reference/authoring-surface/type-eventdef.md +45 -0
  125. package/docs/reference/authoring-surface/type-eventfrom.md +16 -0
  126. package/docs/reference/authoring-surface/type-eventsemantics.md +26 -0
  127. package/docs/reference/authoring-surface/type-execoutcome.md +34 -0
  128. package/docs/reference/authoring-surface/type-failslot.md +14 -0
  129. package/docs/reference/authoring-surface/type-failure.md +19 -0
  130. package/docs/reference/authoring-surface/type-failureinput.md +20 -0
  131. package/docs/reference/authoring-surface/type-filebody.md +41 -0
  132. package/docs/reference/authoring-surface/type-frominput.md +14 -0
  133. package/docs/reference/authoring-surface/type-hostinjectedinput.md +58 -0
  134. package/docs/reference/authoring-surface/type-httpdefinition.md +101 -0
  135. package/docs/reference/authoring-surface/type-httpinput.md +12 -0
  136. package/docs/reference/authoring-surface/type-httpmethod.md +14 -0
  137. package/docs/reference/authoring-surface/type-httpopenparts.md +12 -0
  138. package/docs/reference/authoring-surface/type-httpoutput.md +89 -0
  139. package/docs/reference/authoring-surface/type-httprequestparts.md +33 -0
  140. package/docs/reference/authoring-surface/type-jr2config.md +126 -0
  141. package/docs/reference/authoring-surface/type-lends.md +38 -0
  142. package/docs/reference/authoring-surface/type-logicat.md +12 -0
  143. package/docs/reference/authoring-surface/type-markedif.md +12 -0
  144. package/docs/reference/authoring-surface/type-mergedactors.md +12 -0
  145. package/docs/reference/authoring-surface/type-namedsecret.md +25 -0
  146. package/docs/reference/authoring-surface/type-noslotspec.md +26 -0
  147. package/docs/reference/authoring-surface/type-noslotworkspaceoptions.md +32 -0
  148. package/docs/reference/authoring-surface/type-openbodydeclaration.md +40 -0
  149. package/docs/reference/authoring-surface/type-openbodylogic.md +14 -0
  150. package/docs/reference/authoring-surface/type-openbodyoutput.md +42 -0
  151. package/docs/reference/authoring-surface/type-openbodyslot.md +18 -0
  152. package/docs/reference/authoring-surface/type-opencommandinput.md +17 -0
  153. package/docs/reference/authoring-surface/type-openeffect.md +12 -0
  154. package/docs/reference/authoring-surface/type-openeffectslots.md +12 -0
  155. package/docs/reference/authoring-surface/type-openof.md +12 -0
  156. package/docs/reference/authoring-surface/type-opensecret.md +23 -0
  157. package/docs/reference/authoring-surface/type-opensecretmark.md +12 -0
  158. package/docs/reference/authoring-surface/type-permissivenoslotworkspaceoptions.md +31 -0
  159. package/docs/reference/authoring-surface/type-permissiveworkspaceoptions.md +32 -0
  160. package/docs/reference/authoring-surface/type-poolmachine.md +28 -0
  161. package/docs/reference/authoring-surface/type-poolspec.md +60 -0
  162. package/docs/reference/authoring-surface/type-pushinput.md +15 -0
  163. package/docs/reference/authoring-surface/type-pushoptions.md +79 -0
  164. package/docs/reference/authoring-surface/type-pushoutput.md +124 -0
  165. package/docs/reference/authoring-surface/type-pushwireoutput.md +12 -0
  166. package/docs/reference/authoring-surface/type-quantity.md +14 -0
  167. package/docs/reference/authoring-surface/type-reached.md +12 -0
  168. package/docs/reference/authoring-surface/type-reposlot.md +70 -0
  169. package/docs/reference/authoring-surface/type-reposlotsof.md +16 -0
  170. package/docs/reference/authoring-surface/type-sandboxoptions.md +77 -0
  171. package/docs/reference/authoring-surface/type-secret.md +25 -0
  172. package/docs/reference/authoring-surface/type-sender.md +19 -0
  173. package/docs/reference/authoring-surface/type-sentbyguards.md +12 -0
  174. package/docs/reference/authoring-surface/type-size.md +85 -0
  175. package/docs/reference/authoring-surface/type-slothandles.md +32 -0
  176. package/docs/reference/authoring-surface/type-sourcenextresult.md +17 -0
  177. package/docs/reference/authoring-surface/type-sourcespec.md +44 -0
  178. package/docs/reference/authoring-surface/type-syncstate.md +12 -0
  179. package/docs/reference/authoring-surface/type-text.md +19 -0
  180. package/docs/reference/authoring-surface/type-textpart.md +24 -0
  181. package/docs/reference/authoring-surface/type-thinkinglevel.md +39 -0
  182. package/docs/reference/authoring-surface/type-toparameterizedobject.md +14 -0
  183. package/docs/reference/authoring-surface/type-toprovidedactor.md +14 -0
  184. package/docs/reference/authoring-surface/type-unknown.md +21 -0
  185. package/docs/reference/authoring-surface/type-usercontainer.md +77 -0
  186. package/docs/reference/authoring-surface/type-withoutemptyindex.md +20 -0
  187. package/docs/reference/authoring-surface/type-workflowevent.md +46 -0
  188. package/docs/reference/authoring-surface/type-workspaceaccess.md +16 -0
  189. package/docs/reference/authoring-surface/type-workspaced.md +94 -0
  190. package/docs/reference/authoring-surface/type-workspacehandles.md +23 -0
  191. package/docs/reference/authoring-surface/type-workspacemachine.md +29 -0
  192. package/docs/reference/authoring-surface/type-workspaceof.md +13 -0
  193. package/docs/reference/authoring-surface/type-workspaceoptions.md +39 -0
  194. package/docs/reference/authoring-surface/type-workspacespec.md +37 -0
  195. package/docs/reference/authoring-surface/workspace.md +259 -0
  196. package/docs/reference/authoring-surface.md +197 -0
  197. package/docs/reference/cli.md +433 -0
  198. package/docs/reference/config.md +756 -0
  199. package/docs/reference/decisions/0001-operator-owned-generic-sandbox.md +113 -0
  200. package/docs/reference/decisions/0002-duplex-streaming-actor.md +110 -0
  201. package/docs/reference/decisions/0004-worktree-provisioning-model.md +124 -0
  202. package/docs/reference/decisions/0005-sandbox-pod-composition.md +230 -0
  203. package/docs/reference/decisions/0006-agent-control-surface.md +47 -0
  204. package/docs/reference/decisions/0007-durable-machine-state.md +109 -0
  205. package/docs/reference/decisions/0008-orchestrator-as-deployed-app.md +60 -0
  206. package/docs/reference/decisions/0009-cli-and-instance-interface.md +275 -0
  207. package/docs/reference/decisions/0010-bdd-acceptance-tests.md +160 -0
  208. package/docs/reference/decisions/0011-workflow-defined-events.md +141 -0
  209. package/docs/reference/decisions/0012-workspace-wrapper-machine.md +103 -0
  210. package/docs/reference/decisions/0013-the-agent-reaches-its-machine-through-a-container-it-cannot-read.md +157 -0
  211. package/docs/reference/decisions/0014-observation-is-open-run-state-is-not.md +95 -0
  212. package/docs/reference/decisions/0015-authoring-surface-absorbs-the-mechanism.md +265 -0
  213. package/docs/reference/decisions/0016-agent-turn-mechanics-are-internal.md +124 -0
  214. package/docs/reference/decisions/0017-pool-over-a-source-port.md +69 -0
  215. package/docs/reference/decisions/0018-instance-agents-are-definitions-jr2-assembles-the-harness.md +111 -0
  216. package/docs/reference/decisions/0019-one-converging-command-against-the-current-context.md +275 -0
  217. package/docs/reference/decisions/0020-private-ca-trust-is-a-named-concept.md +60 -0
  218. package/docs/reference/decisions/0021-workspace-continuity-is-a-lease-that-answers-back.md +100 -0
  219. package/docs/reference/decisions/0022-observation-is-a-level-triggered-feed.md +103 -0
  220. package/docs/reference/decisions/0023-the-harness-prints-the-conversation.md +176 -0
  221. package/docs/reference/decisions/0024-an-agents-turn-ends-with-the-state-that-asked-for-it.md +439 -0
  222. package/docs/reference/decisions/0025-cancel-ends-a-run-stop-parks-it.md +65 -0
  223. package/docs/reference/decisions/0026-a-turn-that-is-over-is-never-prompted.md +62 -0
  224. package/docs/reference/decisions/0027-the-harness-is-jr2s-own-server-flue-retires-the-wire-stays.md +237 -0
  225. package/docs/reference/decisions/0028-what-an-agent-may-do-to-the-workspace-is-part-of-its-definition.md +89 -0
  226. package/docs/reference/decisions/0029-a-menu-is-fixed-for-a-conversation-and-a-turn-is-told-its-allowed-picks.md +154 -0
  227. package/docs/reference/decisions/0030-a-snapshot-names-the-machine-it-was-written-under.md +100 -0
  228. package/docs/reference/decisions/0031-menu-only-agents-run-on-the-instance-harness.md +190 -0
  229. package/docs/reference/decisions/0032-the-console-unlocks-with-the-instance-token.md +61 -0
  230. package/docs/reference/decisions/0033-a-machine-declares-the-input-that-starts-it.md +127 -0
  231. package/docs/reference/decisions/0034-the-console-renders-with-preact-and-the-server-erases-the-types.md +57 -0
  232. package/docs/reference/decisions/0035-a-runaway-turn-is-ended-rerolled-once-then-a-fault.md +92 -0
  233. package/docs/reference/decisions/0036-a-turn-compacts-its-own-context-mid-flight.md +138 -0
  234. package/docs/reference/decisions/0037-an-instance-builds-its-sandbox-images-jr2-injects-the-harness.md +196 -0
  235. package/docs/reference/decisions/0038-jr2-up-builds-every-image-it-deploys.md +170 -0
  236. package/docs/reference/decisions/0039-image-garbage-collects-by-reachability.md +115 -0
  237. package/docs/reference/decisions/0041-a-build-the-host-already-holds-is-not-spent-again.md +64 -0
  238. package/docs/reference/decisions/0042-ready-is-not-routable-an-admission-retries-its-connection.md +142 -0
  239. package/docs/reference/decisions/0043-the-kit-is-tested-as-installed-a-local-registry-stands-in-for-npm.md +170 -0
  240. package/docs/reference/decisions/0044-kit-images-live-at-a-canonical-home-a-self-host-mirrors-it.md +85 -0
  241. package/docs/reference/decisions/0045-the-platform-joins-the-image-address-and-the-cluster-chooses-it.md +82 -0
  242. package/docs/reference/decisions/0046-a-converge-failure-carries-its-diagnosis.md +34 -0
  243. package/docs/reference/decisions/0047-the-git-ssh-key-source-is-the-users-choice.md +47 -0
  244. package/docs/reference/decisions/0048-the-orchestrator-boots-without-its-repos.md +36 -0
  245. package/docs/reference/decisions/0049-a-machine-carries-its-parts-and-composes-by-invoke.md +126 -0
  246. package/docs/reference/decisions/0050-what-code-names-config-declares-what-the-cli-names-discovery-finds.md +73 -0
  247. package/docs/reference/decisions/0051-a-repo-is-a-slot-on-the-workspace-and-a-cache-on-the-node.md +227 -0
  248. package/docs/reference/decisions/0052-a-sandbox-lands-where-an-ordinary-pod-lands-and-the-cache-follows-it.md +81 -0
  249. package/docs/reference/decisions/0053-a-fetch-inside-the-pod-asks-the-node-cache-and-the-cache-asks-the-remote.md +111 -0
  250. package/docs/reference/decisions/0054-the-kit-ships-machines-and-a-shipped-machine-leaves-its-parts-open.md +126 -0
  251. package/docs/reference/decisions/0055-a-release-is-a-pushed-tag-and-the-publish-guard-is-the-credential.md +107 -0
  252. package/docs/reference/decisions/0056-a-global-jr2-hands-off-to-the-instances-own-and-an-instance-has-one-kit-version.md +62 -0
  253. package/docs/reference/decisions/0057-a-turn-is-its-frame-its-dials-and-whether-it-continues.md +152 -0
  254. package/docs/reference/decisions/0058-a-harness-answers-the-orchestrator-alone.md +106 -0
  255. package/docs/reference/decisions/0059-a-harness-holds-stand-ins-and-the-custodian-holds-the-keys.md +384 -0
  256. package/docs/reference/decisions/0060-a-workspace-states-its-size-and-jr2-reserves-all-of-it.md +111 -0
  257. package/docs/reference/decisions/0061-a-memory-kill-ends-the-agents-processes-not-the-harness.md +83 -0
  258. package/docs/reference/decisions/0062-jr2-briefs-the-agent-on-its-seat-never-on-its-task.md +212 -0
  259. package/docs/reference/decisions/0063-the-orchestrator-watches-the-cluster.md +83 -0
  260. package/docs/reference/decisions/0064-a-workspace-waits-for-capacity.md +79 -0
  261. package/docs/reference/decisions/0065-a-persist-survives-a-crash-and-history-is-a-week.md +65 -0
  262. package/docs/reference/decisions/0066-a-model-tier-runs-a-real-model-and-a-change-to-what-it-reads-runs-the-tier.md +550 -0
  263. package/docs/reference/decisions/0067-an-effect-is-an-actor-slot-and-runs-at-most-once-unless-marked-idempotent.md +430 -0
  264. package/docs/reference/decisions/0068-an-effector-holds-an-effects-secrets-and-signs-its-wire.md +464 -0
  265. package/docs/reference/decisions/0069-the-orchestrator-is-a-kit-image-and-an-instance-publishes-its-assembly.md +180 -0
  266. package/docs/reference/decisions/0070-a-machine-lends-its-parts-to-a-chart.md +323 -0
  267. package/docs/reference/decisions/0071-a-run-starts-a-run-through-a-dispatch-effect.md +183 -0
  268. package/docs/reference/decisions/0072-the-docs-ship-inside-the-kit-and-an-instances-agents-md-indexes-them.md +144 -0
  269. package/docs/reference/decisions/0073-a-machine-fails-a-run-with-fail-and-an-uncaught-failure-ends-it-failed.md +122 -0
  270. package/docs/reference/decisions/0074-an-unrouted-mechanism-event-is-refused-at-load-and-faults-the-run.md +76 -0
  271. package/docs/reference/decisions.md +83 -0
  272. package/docs/reference/glossary.md +648 -0
  273. package/docs/reference/http-api.md +1348 -0
  274. package/docs/reference/machines.md +190 -0
  275. package/docs/reference/mechanism-events.md +72 -0
  276. package/docs/why.md +206 -0
  277. package/package.json +5 -3
  278. package/src/actor.ts +541 -79
  279. package/src/agent.ts +114 -38
  280. package/src/ambient.ts +2 -1
  281. package/src/assembly-checks.ts +189 -7
  282. package/src/cause.ts +234 -0
  283. package/src/chart.ts +169 -37
  284. package/src/charts.ts +34 -6
  285. package/src/config.ts +430 -178
  286. package/src/custodian.ts +74 -22
  287. package/src/customize.ts +188 -46
  288. package/src/dispatch-effect.ts +945 -0
  289. package/src/door-compat.ts +217 -0
  290. package/src/durability.ts +11 -4
  291. package/src/effect.ts +341 -44
  292. package/src/effector-wire.ts +160 -11
  293. package/src/fail.ts +209 -0
  294. package/src/harness-client.ts +541 -47
  295. package/src/http-effect.ts +495 -53
  296. package/src/http.ts +427 -16
  297. package/src/index.ts +60 -82
  298. package/src/instance.ts +68 -8
  299. package/src/internal.ts +84 -0
  300. package/src/machine-doc.ts +21 -3
  301. package/src/mechanism-routes.ts +168 -0
  302. package/src/model-keys.generated.ts +53 -0
  303. package/src/model-keys.ts +18 -58
  304. package/src/notices.ts +66 -13
  305. package/src/open-body.ts +159 -23
  306. package/src/open-effect.ts +81 -8
  307. package/src/open.ts +59 -6
  308. package/src/parts.ts +184 -13
  309. package/src/party.ts +68 -2
  310. package/src/pick.ts +463 -11
  311. package/src/pool.ts +247 -36
  312. package/src/registration.ts +83 -4
  313. package/src/repos.ts +2 -1
  314. package/src/run-host.ts +565 -31
  315. package/src/run-output.ts +38 -0
  316. package/src/sandbox-effect.ts +273 -38
  317. package/src/sandbox-kube.ts +3 -1
  318. package/src/secret-placement.ts +52 -17
  319. package/src/server.ts +3 -0
  320. package/src/setup.ts +239 -56
  321. package/src/size.ts +121 -9
  322. package/src/snapshot-store.ts +54 -10
  323. package/src/stub-harness.ts +44 -16
  324. package/src/timers.ts +14 -1
  325. package/src/vocabulary.ts +69 -14
  326. package/src/wire.ts +90 -16
  327. package/src/workspace.ts +697 -175
@@ -0,0 +1,361 @@
1
+ ---
2
+ title: Fix a failed converge
3
+ description: Read what jr2 up prints when it refuses or fails, and fix the cause.
4
+ ---
5
+
6
+ # Fix a failed converge
7
+
8
+ Find the cause of a failed `jr2 up` in its output, and fix it.
9
+
10
+ The examples on this page use the [Get started](../get-started/install.md) names: the
11
+ [Instance](../reference/glossary.md#instance) `my-instance` and the kubectl context `kind-jr2`.
12
+
13
+ ## Read the output
14
+
15
+ [`jr2 up`](../reference/cli.md#up) prints one line for each step. When it refuses, the line starts with `refusing:`.
16
+ When a step fails, the line starts with `error:`. In the two cases, `jr2 up` exits with the code 1, and the line tells
17
+ you what to change. Many lines end with the ADR that gives the rule.
18
+
19
+ For example, change `input.message` to `input.mesage` in the `context` line of `workflows/ping.ts`. Then run `jr2 up`:
20
+
21
+ ```sh
22
+ jr2 up
23
+ ```
24
+
25
+ ```text
26
+ …
27
+ jr2 up — instance "my-instance" → context kind-jr2 / namespace my-instance
28
+ typecheck: tsc --noEmit (the instance's own compiler)
29
+ refusing: this instance does not typecheck — nothing was built and nothing was applied
30
+ workflows/ping.ts(45,45): error TS2551: Property 'mesage' does not exist on type 'Input'. Did you mean 'message'?
31
+ ```
32
+
33
+ The first line (`…`) is the `.env` line, when `.env` sets a variable that your shell does not set. The refusal comes
34
+ before `jr2 up` reads the cluster, so the cluster did not change. Each line after it is a line from the TypeScript
35
+ compiler of the Instance. To see the same errors without `jr2 up`, run [`jr2 check`](../reference/cli.md#check).
36
+
37
+ Correct the typo. Then run `jr2 up` again. You can run `jr2 up` again after each fix. It does not build an image again
38
+ when the inputs of the image did not change.
39
+
40
+ The checks of the config, the compiler and the [Machines](../reference/glossary.md#machine) come before `jr2 up` reads
41
+ the cluster. `jr2 check` runs these checks with the same code and no cluster, and gives the same `refusing:` and
42
+ `error:` lines. Thus you, or an Assistant that cannot run `jr2 up`, can fix them before a converge. The checks of the
43
+ context, the API server, the Kubernetes version and the namespace come before `jr2 up` changes the cluster. Thus these
44
+ refusals change nothing in the cluster. The pod-level resources refusal comes after `jr2 up` makes the namespace. Other
45
+ errors can come after `jr2 up` applied some parts. When you fix the cause, run `jr2 up` again. A converge that fails
46
+ removes no image. [Converge](../concepts/converge.md#what-jr2-up-does) gives the order of the steps.
47
+
48
+ ## Fix a rollout that does not complete
49
+
50
+ After `jr2 up` applies each part, it waits for the rollout of that part. When a rollout does not complete in time,
51
+ `jr2 up` reads the pods and prints what they say. In this example, the
52
+ [`kitRegistry`](../reference/config.md#kitregistry) mirror does not hold the image of the Orchestrator:
53
+
54
+ ```text
55
+ …
56
+ orchestrator: applying (image <registry>/jr2-orchestrator:<version>)
57
+ orchestrator: waiting for rollout
58
+ error: jr2-orchestrator: rollout did not complete in namespace my-instance — the pods say:
59
+
60
+ pod jr2-orchestrator-5cd48ff77f-m7qhw (Pending) on node jr2-control-plane (amd64)
61
+ container orchestrator: ImagePullBackOff
62
+ image <registry>/jr2-orchestrator:<version>
63
+ Back-off pulling image "<registry>/jr2-orchestrator:<version>": ErrImagePull: rpc error: code = NotFound desc = failed to pull and unpack image "<registry>/jr2-orchestrator:<version>": failed to resolve reference "<registry>/jr2-orchestrator:<version>": <registry>/jr2-orchestrator:<version>: not found
64
+ event Warning Failed: Error: ImagePullBackOff
65
+ event Normal Pulling: Pulling image "<registry>/jr2-orchestrator:<version>"
66
+ event Warning Failed: Failed to pull image "<registry>/jr2-orchestrator:<version>": rpc error: code = NotFound desc = failed to pull and unpack image "<registry>/jr2-orchestrator:<version>": failed to resolve reference "<registry>/jr2-orchestrator:<version>": <registry>/jr2-orchestrator:<version>: not found
67
+ event Warning Failed: Error: ErrImagePull
68
+
69
+ diagnosis: the kubelet could not pull <registry>/jr2-orchestrator:<version>.
70
+ it resolves to <registry>/jr2-orchestrator:<version>
71
+ check the push landed there and that this cluster may pull from it (credentials, network, mirror).
72
+
73
+ Command failed: kubectl --namespace my-instance rollout status deployment/jr2-orchestrator --timeout=180s
74
+ error: timed out waiting for the condition
75
+ ```
76
+
77
+ `<registry>` is the value of `kitRegistry`, and `<version>` is the [Kit version](../reference/glossary.md#kit-version).
78
+ The pod name of your run is different. For each pod, `jr2 up` prints its phase, its node, the state of each container
79
+ and the last events. When a container has a log, the last lines of the log come after the events. The output ends with
80
+ the error of kubectl. Here, `jr2 up` waited 180 seconds for the rollout.
81
+
82
+ The first line names the part: `jr2-orchestrator`, `jr2-controller-manager` (the operator, in `jr2-system`),
83
+ `jr2-repo-cache`, `jr2-instance-harness` or `jr2-instance-effector`. Read the reason, the events and the logs of the
84
+ pod. When `jr2 up` knows the cause, it adds a `diagnosis:` line. The diagnosis explains only the evidence above it.
85
+
86
+ | The diagnosis starts with | The cause and the fix |
87
+ | -------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
88
+ | `diagnosis: <pod> carries an image built for another platform` | The image is for a different CPU architecture than the node. Run `jr2 up --force` to build the image again. Or set [`platforms`](../reference/config.md#platforms). |
89
+ | `diagnosis: the kubelet could not pull <image>.` | The node cannot get the image. The next line gives the full address. On kind, for an image that jr2 built, run `jr2 up --force` to build the image and load it again. With a [`registry`](../reference/config.md#registry), check that the push arrived and that the cluster can pull from the registry. |
90
+ | `diagnosis: <pod> starts and exits` | The container stops after it starts. The log lines above give the reason. When there are no log lines, run the `kubectl -n <namespace> logs <pod> --previous` command that the diagnosis gives, after the pod starts again. |
91
+ | `diagnosis: the pod's env references <kind> "<name>"` | The pod names a Secret or a ConfigMap that is not in the namespace. Make it. Then run `jr2 up` again. |
92
+ | `diagnosis: the container's configuration cannot be built` | The pod names an object that the namespace does not have. The message above names the object. Make it. Then run `jr2 up` again. |
93
+
94
+ A [Kit image](../reference/glossary.md#kit-image) that the cluster cannot pull is at `ghcr.io/snapwich`, or at the
95
+ [`kitRegistry`](../reference/config.md#kitregistry) mirror. See [Mirror the Kit images](mirror-the-kit-images.md).
96
+
97
+ ## Rules
98
+
99
+ The list gives the refusals and the errors in the order that `jr2 up` meets them. Each `refusing:` line and each
100
+ `error:` line makes `jr2 up` exit with the code 1. A `warning:` line does not stop the converge.
101
+ [Give the cluster git credentials](give-the-cluster-git-credentials.md) gives the refusals of `git.credentials` and of
102
+ the git ssh key. [Use a hosted provider](use-a-hosted-provider.md) gives the other refusals of `secrets` and
103
+ `harness.env`. [Run a command or call a URL with an Effect](run-a-command-or-call-a-url.md) gives the refusals of an
104
+ [Effect secret](../reference/glossary.md#effect-secret). [Write a Workflow](write-a-workflow.md) gives the refusals of a
105
+ [Workflow](../reference/glossary.md#workflow) module. [Push and sign a branch](push-and-sign-a-branch.md) gives the
106
+ refusals of a push and of the [Effector](../reference/glossary.md#effector) image.
107
+ [Use a local model](use-a-local-model.md) gives the refusals of `caBundle`.
108
+
109
+ - `jr2 up` runs only in an Instance folder:
110
+ `error: not inside a jr2 instance — no jr2.config.ts found walking up from cwd`
111
+ - The Instance and the [jr2 CLI](../reference/glossary.md#jr2-cli) must use the same
112
+ [Kit version](../reference/glossary.md#kit-version). If not, `jr2 up` prints
113
+ `error: Kit version mismatch — an Instance has one (ADR-0056):`, then three lines. The third line is one of these
114
+ fixes:
115
+ - `install the Instance's dependencies (<folder>/package.json pins "@jr2/orchestrator" and "@jr2/cli" at one exact version)`.
116
+ Run `npm install` in the Instance folder.
117
+ - `pin "@jr2/orchestrator" and "@jr2/cli" at ONE exact version in <folder>/package.json and reinstall`. Give the two
118
+ packages the same version. Then run `npm install`.
119
+ - `add "@jr2/cli": "<version>" to devDependencies in <folder>/package.json and reinstall — the Instance's own jr2 then runs`
120
+ - `jr2.config.ts` must have a default export:
121
+ ``error: <folder>/jr2.config.ts has no default export (use `export default defineConfig({…})`)``
122
+ - `jr2 up` checks the shape of `git`, `secrets`, `harness`, `sandbox` and `priorityClasses` when it loads
123
+ `jr2.config.ts`. The error names the field, and then the problem:
124
+ `error: <folder>/jr2.config.ts at <field>: <problem>`. See [`jr2.config.ts`](../reference/config.md).
125
+ - `jr2 up` needs a kubectl context:
126
+ `` error: no kube context — `kind create cluster` (or point kubectl at one), then re-run `jr2 up` ``. See
127
+ [Install](../get-started/install.md).
128
+ - The Instance must have the `tsconfig.json` that `jr2 init` writes:
129
+ ``error: this instance has no tsconfig.json — `jr2 init` scaffolds one that extends `@jr2/orchestrator/tsconfig.instance.json`, and `jr2 up` typechecks the folder before it builds anything``
130
+ - The Instance must install its TypeScript compiler. Run `npm install`. The refusal starts with:
131
+ ``error: this instance's TypeScript compiler is missing — install its dependencies (npm, pnpm, or bun), then re-run `jr2 up`.``
132
+ - The Instance must typecheck: `refusing: this instance does not typecheck — nothing was built and nothing was applied`
133
+ - A registered Machine with a door must be made by [`jr2Setup`](../reference/authoring-surface/jr2setup.md), because the
134
+ `setup()` of [xstate](https://xstate.js.org) does not read the `input` of `createMachine`. See
135
+ [Write a Workflow](write-a-workflow.md):
136
+ ``refusing: workflow "<workflow>": machine "<id>" has a zod `input` on createMachine, but jr2Setup did not make this Machine, so no door reads that input: a run starts with any input, and the Console start form is only a field for JSON — make the Machine with jr2Setup in place of setup() or createMachine() (leave out `events` if it takes no workflow event) (ADR-0033)``
137
+ - A registered Machine must have no [Open](../reference/glossary.md#open) part. The refusal gives the
138
+ [`customize()`](../reference/authoring-surface/customize.md) line that binds the part. Put it in
139
+ `workflows/<workflow>.ts`. Replace `<import>` with the name that you import the Machine as. Give the values in the
140
+ `<>`. See [Bind a shipped Machine's Open parts](bind-open-parts.md).
141
+ - `refusing: workflow "<workflow>" leaves Repo Slot "<slot>" open — bind it where the Machine is registered: export const machine = customize(<import>, { repos: { <slot>: "<url>" } }) (ADR-0051)`
142
+ - `refusing: workflow "<workflow>" leaves its Repo Slots open — bind it where the Machine is registered: export const machine = customize(<import>, { repos: { <slot>: "<url>" } }) (ADR-0051)`
143
+ - `refusing: workflow "<workflow>" leaves Agent "<agent>" open — bind it where the Machine is registered: export const machine = customize(<import>, { agents: { <agent>: { model: "<provider>/<model>" } } }) (ADR-0054)`
144
+ - An [Effect](../reference/glossary.md#effect). `<parts>` is `url`, `argv`, `secret`, `url and secret` or
145
+ `argv and secret`. The binding object has one sample for each part, from `url: "https://<host>/<path>"`,
146
+ `argv: ["<program>", "<arg>"]` and `secret: "<name>"`. For example:
147
+ `refusing: workflow "<workflow>" leaves the url and secret of Effect "<effect>" open — bind it where the Machine is registered: export const machine = customize(<import>, { effects: { <effect>: { url: "https://<host>/<path>", secret: "<name>" } } }) (ADR-0054)`
148
+ - When the part is on a Machine that a different Machine invokes, the refusal adds
149
+ `(on the Machine composed as "<slot>")` after `open`. Its `customize()` line binds the part through `actors`, for
150
+ example `customize(<import>, { actors: { <slot>: { repos: { <repo slot>: "<url>" } } } })`. At each deeper level,
151
+ the parenthetical adds ` → "<slot>"`, and the `customize()` line adds one more `actors`.
152
+ - When the Machine is invoked inline, no `customize()` line can reach it:
153
+ `refusing: workflow "<workflow>" leaves <part> open on a Machine invoked inline — no customize() reaches an actor without a slot key; declare that Machine under setup({ actors }) and bind it there (ADR-0049, <ADR>)`
154
+ - The [Size](../reference/glossary.md#size) of each [Workspace](../reference/glossary.md#workspace) must leave the
155
+ [Harness](../reference/glossary.md#harness) container enough memory and cpu. The refusal starts with
156
+ `refusing: workflow "<workflow>": the Size leaves the Harness container`. It gives the numbers that it subtracts and
157
+ where each one comes from, and the field to make larger. See [Size a Workspace](size-a-workspace.md). It ends with
158
+ this text:
159
+ `; a composer retunes it where the Machine is registered: export const machine = customize(<import>, { resources: { limits: { memory: "<memory>" } } })`
160
+ When the Machine is invoked inline, the refusal has no `customize()` line.
161
+ - When the Size is on a Machine that a different Machine invokes, the refusal starts with
162
+ `refusing: workflow "<workflow>" (on the Machine composed as "<slot>"): the Size leaves the Harness container`. Its
163
+ `customize()` line sets the memory of the Size through `actors`:
164
+ `customize(<import>, { actors: { <slot>: { resources: { limits: { memory: "<memory>" } } } } })`. At each deeper
165
+ level, the parenthetical adds ` → "<slot>"`, and the `customize()` line adds one more `actors`.
166
+ - `jr2 up` makes the [Assembly](../reference/glossary.md#assembly) before it reads the cluster. The Assembly must not
167
+ hold a second copy of a Kit package, such as `@jr2/orchestrator`, `xstate` or `zod`:
168
+ `error: cannot stage the Assembly: it would carry a second copy of a Kit package (ADR-0069)`. Each line after it names
169
+ one copy:
170
+ `<path> is a second copy of <package>, nested by <package>: the Orchestrator's image ships <package> for @jr2/orchestrator <version>, and an Assembly that carries its own copy loads Machines whose Menus are empty (ADR-0054) — align that dependency with the <package> @jr2/orchestrator uses, or remove it, and reinstall`.
171
+ Give the dependency that nests the copy a version that uses the same `<package>` as `@jr2/orchestrator`. Then run
172
+ `npm install`.
173
+ - A symlink in the Assembly must stay in the Assembly:
174
+ `error: cannot seal the Assembly: the symlink <path> points outside the Assembly ("<target>") — an Assembly carries only what it holds; <fix>`.
175
+ The fix is `install that dependency as a copy, not a link` for a link in `node_modules`, and
176
+ `make the link relative, with a target inside the Instance` for a different link.
177
+ - A file in the Assembly must not hold the path where `jr2 up` makes the Assembly. The refusal starts with
178
+ `error: cannot seal the Assembly: <file> holds the staging path (<path>)`. A `postinstall` step of a dependency is the
179
+ usual cause.
180
+ - The Assembly must hold each Workflow of the folder. The refusal starts with
181
+ `refusing: the staged Assembly does not hold the Workflows this folder holds (ADR-0069)`, and names each file. It ends
182
+ with ``— the Assembly holds what the Instance's install keeps; check the `files:` list in package.json``.
183
+ - `jr2 up` must reach the API server of the context:
184
+ `refusing: cannot reach the API server of <context> (<error>). Nothing was applied.` For example, with
185
+ `--context nope`, the error is `error: context "nope" does not exist`. Check the context with
186
+ `kubectl config current-context`. Check that the cluster runs.
187
+ - The cluster must run Kubernetes 1.35 or later:
188
+ `refusing: <context> runs Kubernetes <version>; jr2 needs Kubernetes 1.35 or newer (every Sandbox mounts jr2's runtime as an image volume, ADR-0037). Nothing was applied.`
189
+ For kind, install a newer kind release. Then make the cluster again.
190
+ - The namespace must not belong to a different Instance:
191
+ `refusing: namespace "<namespace>" on <context> belongs to another instance ("<owner>")`, then
192
+ ` pick a different namespace (-n) or context (--context)`. Set [`name`](../reference/config.md#name) in
193
+ `jr2.config.ts`, or add `-n <namespace>`.
194
+ - Before `jr2 up` uses a namespace for the first time, it asks:
195
+ `first contact: deploy instance "<instance>" to context <context> (create namespace "<namespace>")? [y/N]`. For a
196
+ namespace that exists but holds no Instance, it asks to `adopt existing namespace "<namespace>"`. When you do not type
197
+ `y`, it prints `aborted — nothing was changed`. When no terminal is attached, it prints
198
+ `<question> — not a tty; pass --yes to proceed non-interactively` first. In CI, add `--yes`.
199
+ - The cluster must keep pod-level resources. `jr2 up` makes the namespace, and then it stops:
200
+ `refusing: <context> (Kubernetes <version>) drops pod-level resources — the PodLevelResources feature gate is off, and a Workspace's Size cannot hold (ADR-0060). Enable the gate on the API server and kubelets. The namespace was created; nothing else was applied.`
201
+ - When `jr2 up` cannot confirm pod-level resources, it warns and continues:
202
+ `warning: could not confirm pod-level resources on <context>: <error>`
203
+ - jr2 builds only for the platforms that the Kit releases images for:
204
+ ``error: <what> — the kit releases images for <kit platforms> and nothing else, so an image built for anything else could not be joined by a Kit image in the same pod. Set `platforms` in jr2.config.ts (docker platform strings, e.g. "linux/arm64") to name the set to build for.``
205
+ `<what>` is `` `platforms` names <platforms> ``, or `this cluster's schedulable nodes report <architectures>`. Set
206
+ [`platforms`](../reference/config.md#platforms) to platforms from the list after `the kit releases images for`.
207
+ - When no node can hold a [Sandbox](../reference/glossary.md#sandbox), `jr2 up` warns and continues:
208
+ `warning: no Sandbox node right now — a Sandbox stays Pending until one appears:`. Each line after it gives a node,
209
+ and why a Sandbox cannot use it. A [Sandbox node](../reference/glossary.md#sandbox-node) can appear later. To admit a
210
+ node with a taint or a label, set [`sandbox`](../reference/config.md#sandbox) in `jr2.config.ts`.
211
+ - When no Sandbox node has the memory and cpu for a Size, `jr2 up` warns and continues:
212
+ `warning: no Sandbox node right now has the allocatable for a Size of <size> (workflow "<workflow>") — its Sandbox stays Pending until one does`
213
+ - Images for two or more platforms need a `registry`:
214
+ `` error: this cluster needs a <platforms> build, which docker buildx delivers by PUSHING a manifest list (kind load cannot carry one) — set `registry` in jr2.config.ts, or name a single platform with `platforms` ``
215
+ - A cluster that is not kind needs a [`registry`](../reference/config.md#registry):
216
+ ``error: context <context> is not a kind cluster and no `registry` is configured — set `registry` in jr2.config.ts (from env) so the image can be pushed (ADR-0019)``.
217
+ jr2 knows a kind cluster by its context name, which starts with `kind-`. See
218
+ [Move from kind to a shared cluster](move-from-kind-to-a-shared-cluster.md).
219
+ - The Instance folder must hold the lockfile of one package manager. `<folder>` is the path of the Instance folder:
220
+ - Lockfiles of two managers:
221
+ `error: <folder> holds lockfiles from more than one package manager (<manager>: <lockfile>; <manager>: <lockfile>) — delete the stale one, so the bundle installs the dependency graph the instance really uses`.
222
+ Delete the lockfile of the manager that you do not use.
223
+ - A `yarn.lock`: `error: <folder> has a yarn.lock, and yarn is not supported — use npm, pnpm, or bun`. Install with
224
+ npm, pnpm or bun, and delete `yarn.lock`.
225
+ - No lockfile:
226
+ `error: <folder> has no lockfile — jr2 installs the instance's dependencies from npm (package-lock.json), pnpm (pnpm-lock.yaml), bun (bun.lock or bun.lockb); run your package manager's install and commit the lockfile it writes`.
227
+ Run `npm install`, and commit `package-lock.json`.
228
+ - To build for a different CPU architecture, docker needs qemu emulation. The refusal gives the command that installs
229
+ it:
230
+ `error: this host cannot build for <missing platforms>: a foreign architecture's RUN steps need qemu binfmt emulation, and none is registered (this builder targets <builder platforms>). Install it, then re-run:`,
231
+ then ` docker run --privileged --rm tonistiigi/binfmt --install <arch>`
232
+ - The folder of each [Sandbox Image](../reference/glossary.md#sandbox-image) that a
233
+ [`workspace()`](../reference/authoring-surface/workspace.md) names must exist:
234
+ ``error: the Sandbox Image context <folder> cannot be read (<code>) — a `workspace()` names its image with `import.meta.resolve("./<dir>")`, so that directory must exist beside the Machine's own module (ADR-0037/0049).``
235
+ See [Add tools to the Sandbox](add-tools-to-the-sandbox.md).
236
+ - Each Secret that [`harness.envFrom`](../reference/config.md#harness-envfrom) names must exist:
237
+ `error: harness.envFrom references Secret "<name>", which does not exist in namespace "<namespace>" — create it first: kubectl -n <namespace> create secret generic <name> --from-literal=KEY=...`
238
+ - Each [`secrets`](../reference/config.md#secrets) entry that a pod or an Effect uses needs one value. A variable that
239
+ is not set in `.env` gives no value:
240
+ `error: secrets[<i>] needs exactly one of value or valueFrom — <NAME> has neither, which is what an unset .env variable reads as: set <NAME> in .env, or reference a Secret with valueFrom: { secretKeyRef: { name, key } } (ADR-0059)`.
241
+ Add the variable to `.env`. An entry with the two gives `not both` in place of the text after the dash.
242
+ - A value must not be empty: `error: secrets[<i>].value is empty — set <NAME> in .env (ADR-0059)`
243
+ - A value must hold only printable ASCII, with no space at its start or end:
244
+ `error: secrets[<i>].value holds a character a header cannot carry (outside printable ASCII) or leading or trailing space — a pasted newline, most likely; the value itself is not shown (ADR-0059)`.
245
+ Remove the newline or the space from the value in `.env`.
246
+ - The Secret that a `valueFrom` names must exist, with its key:
247
+ `error: secrets[<i>].valueFrom names Secret "<name>", which does not exist in the instance's namespace — create it first: kubectl create secret generic <name> --from-literal=<key>=... (ADR-0019, ADR-0059)`,
248
+ and `error: secrets[<i>].valueFrom names key "<key>" of Secret "<name>", which has no such key (ADR-0059)`
249
+ - When [`harness.provider`](../reference/config.md#harness-provider) is set and an
250
+ [Agent](../reference/glossary.md#agent) uses its models, a pod in the cluster asks the provider for one tool call for
251
+ each model. When a call fails:
252
+ `error: provider preflight failed for model "<model>" against <host> (from a pod on <where>, as a Turn calls it): <error>`.
253
+ Four lines follow, with the usual causes. A fifth line follows when `apiKey` is set: the key may be wrong.
254
+
255
+ ```text
256
+ - localhost never works from a pod; use a LAN address
257
+ - the model id must be exactly what the endpoint serves (vLLM: GET /v1/models)
258
+ - vLLM needs --enable-auto-tool-choice and a matching --tool-call-parser
259
+ - stop reason "length" means the model ran out of tokens before the call (a thinking model reasons first)
260
+ ```
261
+
262
+ When the endpoint refused the key (a 401 or a 403), the endpoint answered. So three of the four usual lines are left
263
+ out: the line about localhost, the line about vLLM tool calls, and the line about stop reason "length". Two lines
264
+ follow: the line about the key, and the line about the model id. When `apiKey` is set, the line about the key says
265
+ that the held secret may be wrong. When `apiKey` is not set, it says that the endpoint wants a key.
266
+
267
+ ```text
268
+ - the held secret <NAME> may be wrong (harness.provider.apiKey)
269
+ - the model id must be exactly what the endpoint serves (vLLM: GET /v1/models)
270
+ ```
271
+
272
+ See [Use a local model](use-a-local-model.md).
273
+
274
+ - When an Agent uses a model of pi's catalog (for example `anthropic/claude-haiku-5-5`), a pod in the cluster asks the
275
+ provider for one tool call for each model. The pod has the placement of the Harness pods that run the model, and a
276
+ Custodian that holds the secrets of those pods. When a call fails:
277
+ `error: provider preflight failed for model "<model>" toward <host> (from a pod on <where>, through a Custodian, as a Turn calls it): <error>`.
278
+ When the pods hold no secret, the error says `direct` in place of `through a Custodian`. Each failed model has its own
279
+ error. Lines with the usual causes follow:
280
+
281
+ ```text
282
+ - the pods may have no egress to <host> (a NetworkPolicy, a firewall, no route out of the cluster)
283
+ - the held secret <NAME> may be empty, wrong, or without access to this model (`secrets` in jr2.config.ts)
284
+ - a private CA on that path must be in harness.caBundle
285
+ ```
286
+
287
+ When the provider refused the key (a 401 or a 403), the line about the held secret comes first, and the line about
288
+ egress is left out, because the provider answered. When no Harness pod holds a key of the provider, the line about the
289
+ key says which key to add to `secrets`. With a [`harness.catalog`](../reference/config.md#harness-catalog) gateway for
290
+ the provider, a line also says that the gateway may not answer, or may not serve the model. A 503 is an error: a
291
+ gateway with no backend, or a server that still loads its model, answers 503.
292
+
293
+ When the check pod cannot start, the error says why:
294
+ - a node cannot pull an image;
295
+ - a Secret or a key that `harness.envFrom` or a `harness.env` valueFrom names is missing;
296
+ - a Secret or a key that a `secrets` valueFrom names is missing (the volume does not mount);
297
+ - the Custodian refused a held value;
298
+ - a container ran out of memory.
299
+
300
+ While the check pod waits to start, `jr2 up` writes why, for example
301
+ `provider: the check pod is not running yet — Unschedulable: …`. A provider that is busy after the retries (a 429, a
302
+ 529, an overload) is a warning, not an error. A model that answers the request of a Turn in text, not with a tool
303
+ call, is a warning too. When a model of the custom provider, or behind a `harness.catalog` gateway, gives no answer in
304
+ time (`no answer in 120 s`), the error adds that it can be a model that loads on first use: run `jr2 up` again once it
305
+ has loaded. A provider that answers 429 and then never answers a retry is a warning; for Gemini and Vertex it is an
306
+ error, because their tries are not seen. When the check pod stops before the end, the error says which model the check
307
+ was on, and `not checked` for each model that it never reached.
308
+
309
+ The check has a limit. The check pod has labels of its own, so a NetworkPolicy that selects the Harness pods by label
310
+ does not select the check pod. When such a policy closes the egress of the Harness pods, the check can pass while a
311
+ Turn fails.
312
+
313
+ A check can fail when the model works, for example a model that loads for longer than the check waits. When you know
314
+ that the models work, run `jr2 up --skip-provider-preflight`. No check pod runs, and the converge goes on. `jr2 up`
315
+ writes one line:
316
+ `warning: provider: preflight skipped (--skip-provider-preflight) — these models were not checked: <model>, …`. A
317
+ model that does not work then fails in a run, as `agent.fault`, and not at the converge. Remove the flag when the
318
+ check works again.
319
+
320
+ - Each rollout must complete. The error starts with
321
+ `error: <part>: rollout did not complete in namespace <namespace> — the pods say:`. See
322
+ [Fix a rollout that does not complete](#fix-a-rollout-that-does-not-complete). Every rollout comes after the provider
323
+ check, the rollout of the operator (`jr2-controller-manager`) too.
324
+ - When the rollout made no pod, the error says:
325
+ `no pod matches <selector> — the ReplicaSet made none (check quota, node taints, and the selector)`. For the Repo
326
+ cache and the [Instance Harness](../reference/glossary.md#instance-harness), it names the DaemonSet or the
327
+ StatefulSet.
328
+ - After each rollout, the pods must run the image that `jr2 up` expected. `<layer>` is `operator`, `orchestrator`,
329
+ `repo cache`, `instance harness` or `instance effector`:
330
+ ``error: <layer>: rollout reported success, but the running pod carries <images> — expected <image>. The cluster is serving code this converge did not deploy; `kubectl -n <namespace> rollout restart deploy` and re-run `jr2 up` to resolve it.``
331
+ - When the rollout completes but no pod matches, `jr2 up` cannot check the image. It continues:
332
+ `<layer>: WARNING — rollout succeeded but no pod matched <selector> (nothing verified)`
333
+ - Before the publish, the Orchestrator must read the image map that `jr2 up` wrote. When it does not read it in time,
334
+ `jr2 up` publishes nothing:
335
+ ``refusing: after <seconds>s the Orchestrator still reads an older <maps> from its mount — the kubelet has not refreshed it; nothing was published, and the previous Assembly is still current. Run `jr2 up` again``
336
+ - The Orchestrator checks the Assembly again before it makes it current. It loads each Workflow and `jr2.config.ts`. It
337
+ refuses an [Open](../reference/glossary.md#open) part that nobody bound, a secret that the config does not declare, a
338
+ Kit version that is not its own, and a zod `input` that no door reads (a Machine that `jr2Setup` did not make). The
339
+ refusal gives the status code and the reason, then one line for each problem:
340
+ `refusing: the Orchestrator refused Assembly <hash> (HTTP <status>): <error> — the previous Assembly is still current`.
341
+ Fix each problem. Then run `jr2 up` again.
342
+
343
+ ## Read next
344
+
345
+ - [Converge](../concepts/converge.md)
346
+ - [ADR-0046](../reference/decisions/0046-a-converge-failure-carries-its-diagnosis.md): why a failed rollout prints the
347
+ evidence of its pods.
348
+ - [ADR-0050](../reference/decisions/0050-what-code-names-config-declares-what-the-cli-names-discovery-finds.md): why
349
+ `jr2 up` typechecks the Instance first.
350
+ - [ADR-0054](../reference/decisions/0054-the-kit-ships-machines-and-a-shipped-machine-leaves-its-parts-open.md): why
351
+ `jr2 up` refuses an Open part.
352
+ - [ADR-0056](../reference/decisions/0056-a-global-jr2-hands-off-to-the-instances-own-and-an-instance-has-one-kit-version.md):
353
+ why an Instance has one Kit version.
354
+ - [ADR-0069](../reference/decisions/0069-the-orchestrator-is-a-kit-image-and-an-instance-publishes-its-assembly.md): why
355
+ `jr2 up` makes an Assembly and publishes it.
356
+ - [ADR-0019](../reference/decisions/0019-one-converging-command-against-the-current-context.md): the current context and
357
+ the namespace.
358
+ - [ADR-0045](../reference/decisions/0045-the-platform-joins-the-image-address-and-the-cluster-chooses-it.md): how
359
+ `jr2 up` chooses the platforms.
360
+ - [`jr2 up`](../reference/cli.md#up), [`jr2.config.ts`](../reference/config.md)
361
+ - [Clean up](clean-up.md)
@@ -0,0 +1,222 @@
1
+ ---
2
+ title: Give the cluster git credentials
3
+ description: Give the cluster a token or an ssh key to clone and push your Repos, and choose which Repos a run can name.
4
+ ---
5
+
6
+ # Give the cluster git credentials
7
+
8
+ Give the cluster the credentials that it uses to clone and push your [Repos](../reference/glossary.md#repo).
9
+
10
+ The same list also sets which Repos a run can name. The credentials are the entries of
11
+ [`git.credentials`](../reference/config.md#git-credentials) in `jr2.config.ts`. It is not a list of Repos: a
12
+ [Machine](../reference/glossary.md#machine) names its Repos in the [Repo Slots](../reference/glossary.md#repo-slot) of
13
+ its [`workspace()`](../reference/authoring-surface/workspace.md). This example has three entries:
14
+
15
+ ```ts
16
+ import { defineConfig } from "@jr2/orchestrator";
17
+
18
+ export default defineConfig({
19
+ git: {
20
+ credentials: [
21
+ // Your repositories on GitHub. Over https://, the cluster uses the token in GITHUB_TOKEN, from .env.
22
+ // Over ssh, it uses the deploy key in the Secret github-deploy-key.
23
+ { match: "github.com/<you>/", token: "GITHUB_TOKEN", sshKey: "github-deploy-key" },
24
+ // The repositories of your team on a GitLab server, over ssh only.
25
+ { match: "gitlab.example.com/team/", sshKey: "gitlab-deploy-key" },
26
+ // Public repositories that a run can name. No credential: the cluster clones them anonymously.
27
+ { match: "github.com/snapwich/" },
28
+ ],
29
+ },
30
+ });
31
+ ```
32
+
33
+ Write your GitHub user name in place of `<you>`.
34
+
35
+ ## How an entry matches a Repo
36
+
37
+ `jr2 up` and the [Orchestrator](../reference/glossary.md#orchestrator) find the entry for a Repo from its identity. The
38
+ identity is the host and the path of the url, with no scheme, no user and no `.git`. For example,
39
+ `https://github.com/<you>/app.git` and `git@github.com:<you>/app.git` have the same identity, `github.com/<you>/app`.
40
+
41
+ - `match` is a prefix of the identity, such as `github.com/<you>/`, or `*` for each Repo.
42
+ - When two or more entries match, the longest `match` wins. When two have the same length, the first entry wins.
43
+ - The scheme of the url selects the credential. An `https://` url uses `token`. An ssh url uses `sshKey`.
44
+ - An entry with no `token` and no `sshKey` lets its Repos through the fence. The cluster clones them with no credential.
45
+ If the entry also has no `push` field, the cluster never pushes to them.
46
+
47
+ `jr2 init` writes one entry, `{ match: "*", token: "JR2_GIT_TOKEN", sshKey: "jr2-git-ssh" }`. It matches each Repo.
48
+
49
+ ## Use a token over https
50
+
51
+ Make a token at your git host. On GitHub, make a fine-grained personal access token for the repositories that the
52
+ cluster uses. Give it "Contents: Read-only" to clone, or "Contents: Read and write" to clone and push.
53
+
54
+ Put the token in `.env`, under the name that the entry gives in `token`:
55
+
56
+ ```sh
57
+ GITHUB_TOKEN=<token>
58
+ ```
59
+
60
+ Run `jr2 up`:
61
+
62
+ ```sh
63
+ jr2 up
64
+ ```
65
+
66
+ When a registered Machine has a [Workspace](../reference/glossary.md#workspace), `jr2 up` writes the token into a Secret
67
+ for its entry:
68
+
69
+ ```text
70
+ …
71
+ git.credentials "github.com/<you>/": clone Secret jr2-git-<hash>
72
+ …
73
+ ```
74
+
75
+ `<hash>` comes from the `match` of the entry, so it does not change between runs of `jr2 up`. Only the Repo cache reads
76
+ this Secret. The [Agent](../reference/glossary.md#agent) never sees the token. The token goes to the git host with the
77
+ user name `x-access-token`.
78
+
79
+ When the variable is not set, `jr2 up` writes no Secret for the entry, and the cluster clones with no credential. A
80
+ private Repo then fails to clone, and `jr2 status` shows the error of the Repo.
81
+
82
+ ## Use an ssh deploy key
83
+
84
+ An ssh url uses the key in the Kubernetes Secret that `sshKey` names. The Secret holds the key under the key names that
85
+ Flux uses: `identity` (the private key), and, optionally, `identity.pub` and `known_hosts`.
86
+
87
+ ### Let jr2 up make the key
88
+
89
+ A Machine can bind a Repo Slot to an ssh url. When the Secret of its entry does not exist, `jr2 up` asks where the key
90
+ comes from:
91
+
92
+ ```text
93
+ git@github.com:<you>/app.git bind over ssh and the "github-deploy-key" Secret their git.credentials entry names does not exist.
94
+ whichever key you pick lands in a Secret in namespace "my-instance" — readable by anyone with
95
+ Secret read there, and at rest in etcd. A deploy key leaks read access to the repos you
96
+ register it on; a personal key leaks everything it can reach.
97
+ where should the git ssh key come from?
98
+ ❯ generate a fresh in-cluster deploy keypair (recommended — one registration per repo)
99
+ use /home/<user>/.ssh/id_rsa
100
+ use another local key (type a path)
101
+ paste a private key (input hidden)
102
+ (↑/↓ move · enter selects · esc cancels)
103
+ ```
104
+
105
+ The list shows each private key in `~/.ssh`, so your list can be different. Select one of these choices:
106
+
107
+ - **Generate.** `jr2 up` makes a new ed25519 key pair in the Secret. This is the recommended choice. `jr2 up --yes`
108
+ always selects it.
109
+ - **Use a local key.** `jr2 up` copies a key from your computer into the Secret.
110
+ - **Paste a private key.** `jr2 up` reads the key from the terminal and does not show it.
111
+
112
+ A deploy key that leaks gives read access only to the repositories that you register it on. A personal key that leaks
113
+ gives access to all that it can reach. Thus use a deploy key.
114
+
115
+ When you select "generate", `jr2 up` shows the public key and waits:
116
+
117
+ ```text
118
+ generated deploy key SHA256:6AcfwCiKJORn3xak1nSIVWl6AxZ0F7xzDKm6OlpAoU8 — register this PUBLIC key (read access):
119
+ ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGeFTbAhIVF4+h0L0T+jix9DjRb6fZJuTO+YB/TLHYyk jr2-git-ssh
120
+ register this public key with your git host, then press enter to continue:
121
+ ```
122
+
123
+ Each run of "generate" makes a new key, so your key and its fingerprint are different.
124
+
125
+ Add the public key to the repository as a deploy key. Then push Enter. At the end, `jr2 up` shows the key again:
126
+
127
+ ```text
128
+ …
129
+ converged — `jr2 run <workflow>` when ready
130
+ git ssh: a deploy key was generated into "github-deploy-key" this converge and nothing has registered it yet:
131
+ ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGeFTbAhIVF4+h0L0T+jix9DjRb6fZJuTO+YB/TLHYyk jr2-git-ssh
132
+ until it is registered, git@github.com:<you>/app.git will not sync (the Orchestrator serves anyway)
133
+ the cache agent retries on its own — `jr2 status` reports each Repo's last error per node
134
+ ```
135
+
136
+ `jr2 up` asks once for each Secret that does not exist. When the Secret exists, it does not ask again.
137
+
138
+ ### Make the Secret yourself
139
+
140
+ Make the Secret yourself in these cases:
141
+
142
+ - A run gives the ssh url in its input. `jr2 up` does not see that url, so it does not ask.
143
+ - A script runs `jr2 up`, and you want a key other than a new one.
144
+
145
+ First, get the host keys of your git host into a `known_hosts` file. Write the host, such as `github.com`, in place of
146
+ `<host>`:
147
+
148
+ ```sh
149
+ ssh-keyscan <host> > known_hosts
150
+ ssh-keygen -lf known_hosts
151
+ ```
152
+
153
+ `ssh-keygen -lf` shows the fingerprints. Compare them with the fingerprints that your git host publishes. Do not use the
154
+ file if they are different.
155
+
156
+ Then make the Secret. Write the namespace of the [Instance](../reference/glossary.md#instance), the name that `sshKey`
157
+ gives, and the path to the private key:
158
+
159
+ ```sh
160
+ kubectl -n <namespace> create secret generic <name> --from-file=identity=<private key> --from-file=known_hosts=known_hosts
161
+ ```
162
+
163
+ With `known_hosts`, the Repo cache accepts only the host keys in that file. With no `known_hosts`, it accepts the host
164
+ key on the first connection, and keeps it while the Repo cache agent runs.
165
+
166
+ ## Narrow the fence
167
+
168
+ The list is also a fence. A url that a Machine binds is code that your Instance typechecked. It needs no entry, and with
169
+ no entry it clones with no credential. A url that comes from the run input is different: a run could name any host. So
170
+ the url of a per-run Repo Slot must match an entry, or the [Sandbox](../reference/glossary.md#sandbox) refuses it.
171
+
172
+ The `*` entry of `jr2 init` lets each url through. Narrow it to your hosts before a person or a system that you do not
173
+ trust can start a run. The example on this page lets a run name only the repositories under `github.com/<you>/`,
174
+ `gitlab.example.com/team/` and `github.com/snapwich/`.
175
+
176
+ ## Push with the same credentials
177
+
178
+ A [`push`](../reference/authoring-surface/push.md) [Effect](../reference/glossary.md#effect) uses the entry that its url
179
+ matches. By default, the clone credential of the entry pushes too. To push with a different credential, give the entry a
180
+ `push` field. The guide [Push and sign a branch](push-and-sign-a-branch.md) gives the push, the signing key and their
181
+ rules.
182
+
183
+ `jr2 up` tells you to give the key that it makes read access, and its Secret has no `known_hosts`. A push over ssh needs
184
+ write access and `known_hosts`. Thus, to push over ssh, make the Secret yourself.
185
+
186
+ ## Rules
187
+
188
+ `jr2 up` prints each refusal after `error: `.
189
+
190
+ - The Sandbox refuses a per-run url that matches no entry, when it attaches the Repo. The run then faults:
191
+ `Sandbox "<name>" refuses the per-run repo <url> for slot "<slot>": no git.credentials entry matches "<identity>" (entries: <entries>). A per-run url can spend the cluster's credential against any host, so jr2.config.ts must admit it by prefix (ADR-0051).`
192
+ - When `jr2 up` or the Orchestrator loads the config, it refuses an entry with a wrong shape:
193
+ `<file> at git.credentials[<i>]<path>: <problem> — an entry is { match, token?, sshKey?, push?: { sshKey } | { token }, sign?: { sshKey | gpgKey, name, email }, committer?: { name, email } } (ADR-0051)`.
194
+ - `jr2 up` stops when you select no key source:
195
+ `<urls> bind over ssh and need the "<secret>" Secret — re-run and pick a key source, create the Secret yourself (kubectl -n <namespace> create secret generic <secret> --from-file=identity=<path>), or bind the urls over https (+ a token in git.credentials)`.
196
+ - With no terminal and no `--yes`, `jr2 up` cannot ask. It prints this line, then stops with the refusal above:
197
+ `where should the git ssh key come from? — not a tty; pass --yes to take the recommended option non-interactively`.
198
+ - `jr2 up` refuses a key that has a passphrase:
199
+ `refusing the key from <where>: it is passphrase-protected. The in-cluster clone runs unattended and cannot answer a passphrase, and jr2 will not store a decrypted copy — use an unencrypted key, or let jr2 generate a deploy key`.
200
+ - When a [Workflow](../reference/glossary.md#workflow) pushes, `jr2 up` checks each push and signing Secret. It warns
201
+ when a Secret does not exist, or when it does not hold a key that it needs, such as `known_hosts`. The Orchestrator
202
+ then refuses a push under that entry until the Secret holds the key and you run `jr2 up` again:
203
+ `warning: git.credentials "<match>": <why> — a push that needs it is refused at provision until it exists and jr2 up runs again (ADR-0051)`.
204
+ `<why>` is `the Secret "<name>" does not exist in namespace <namespace>` or `the Secret "<name>" holds no key <key>`.
205
+ - `jr2 up` warns about an ssh url whose entry names no `sshKey`:
206
+ `<url> is an ssh url and no git.credentials entry names a key for it — its cache clone will fail unless the host allows anonymous ssh`.
207
+ - `jr2 up` refuses a push over `https://` to a url that a Machine binds, when the token variable is not set:
208
+ `Workspace of workflow "<workflow>": the push of Repo Slot "<slot>" (<url>): git.credentials entry "<match>" cannot push — its token's variable <NAME> is not set — set it in .env (ADR-0051)`.
209
+ For a Workspace inside a different Machine, `Workspace of workflow "<workflow>"` continues with its route, such as
210
+ ` → "<state>"`.
211
+
212
+ ## Read next
213
+
214
+ - [Secrets and trust](../concepts/secrets-and-trust.md): who holds each credential.
215
+ - [Workspaces](../concepts/workspaces.md): Repos and Repo Slots.
216
+ - [Architecture](../concepts/architecture.md): the Repo cache.
217
+ - [Push and sign a branch](push-and-sign-a-branch.md): the `push` Effect.
218
+ - [`git.credentials`](../reference/config.md#git-credentials) in the `jr2.config.ts` Reference, and
219
+ [`jr2 up`](../reference/cli.md#up) in the CLI Reference.
220
+ - [ADR-0051](../reference/decisions/0051-a-repo-is-a-slot-on-the-workspace-and-a-cache-on-the-node.md): the entries, and
221
+ the fence.
222
+ - [ADR-0047](../reference/decisions/0047-the-git-ssh-key-source-is-the-users-choice.md): the choice of the ssh key.