@jr2/orchestrator 0.5.1 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/console/components/app.ts +55 -15
- package/console/components/bottom-drawer.ts +259 -0
- package/console/components/drawer.ts +14 -6
- package/console/components/fleet.ts +36 -13
- package/console/components/machine-pane.ts +61 -5
- package/console/components/nav.ts +54 -8
- package/console/conversation.ts +161 -0
- package/console/login.ts +123 -0
- package/console/main.ts +600 -60
- package/console/store.ts +611 -64
- package/console/style.css +231 -0
- package/docs/agents-block.md +2 -2
- package/docs/concepts/agents-and-turns.md +142 -29
- package/docs/concepts/architecture.md +60 -34
- package/docs/concepts/callers-and-hooks.md +205 -0
- package/docs/concepts/charts.md +13 -8
- package/docs/concepts/composition.md +10 -1
- package/docs/concepts/converge.md +7 -2
- package/docs/concepts/durable-runs.md +43 -16
- package/docs/concepts/effects.md +133 -50
- package/docs/concepts/gates.md +95 -25
- package/docs/concepts/machines-and-workflows.md +14 -4
- package/docs/concepts/pools-and-sources.md +193 -17
- package/docs/concepts/secrets-and-trust.md +186 -62
- package/docs/concepts/the-menu.md +14 -0
- package/docs/concepts/workspaces.md +135 -56
- package/docs/get-started/a-model-decides.md +14 -13
- package/docs/get-started/an-agent-in-a-sandbox.md +46 -35
- package/docs/get-started/connect-a-model.md +1 -1
- package/docs/get-started/create-an-instance.md +17 -14
- package/docs/get-started/have-your-assistant-write-a-machine.md +111 -40
- package/docs/get-started/install.md +4 -0
- package/docs/guides/add-tools-to-the-sandbox.md +72 -15
- package/docs/guides/answer-a-gate-from-a-forge.md +304 -0
- package/docs/guides/answer-a-gate.md +74 -37
- package/docs/guides/bind-open-parts.md +29 -12
- package/docs/guides/call-an-mcp-tool-from-a-machine.md +572 -0
- package/docs/guides/cancel-a-run.md +26 -16
- package/docs/guides/cut-a-worktree.md +560 -0
- package/docs/guides/fix-a-failed-converge.md +19 -7
- package/docs/guides/give-a-caller-a-scope.md +203 -0
- package/docs/guides/give-an-agent-mcp-tools.md +422 -0
- package/docs/guides/iterate-on-a-machine-on-kind.md +10 -9
- package/docs/guides/let-an-agent-write-a-chart.md +14 -7
- package/docs/guides/look-inside-a-sandbox.md +115 -42
- package/docs/guides/move-from-kind-to-a-shared-cluster.md +16 -0
- package/docs/guides/open-the-console.md +63 -14
- package/docs/guides/push-and-sign-a-branch.md +67 -21
- package/docs/guides/read-a-conversation.md +225 -0
- package/docs/guides/run-a-chart-by-name.md +17 -16
- package/docs/guides/run-a-command-or-call-a-url.md +84 -41
- package/docs/guides/run-one-worker-per-item.md +34 -27
- package/docs/guides/set-an-agents-access-and-dials.md +69 -22
- package/docs/guides/size-a-workspace.md +19 -6
- package/docs/guides/start-a-run-for-each-alert.md +290 -0
- package/docs/guides/start-a-run-from-a-run.md +18 -16
- package/docs/guides/start-a-run.md +24 -18
- package/docs/guides/steer-an-agent.md +332 -0
- package/docs/guides/use-a-hosted-provider.md +7 -1
- package/docs/guides/watch-a-run.md +146 -117
- package/docs/guides/write-a-hook-kind.md +238 -0
- package/docs/guides/write-a-tool-as-an-mcp-server.md +351 -0
- package/docs/guides/write-a-workflow.md +18 -8
- package/docs/llms.txt +110 -23
- package/docs/reference/authoring-surface/agent.md +35 -12
- package/docs/reference/authoring-surface/answer.md +20 -4
- package/docs/reference/authoring-surface/arg.md +28 -6
- package/docs/reference/authoring-surface/basic.md +1 -1
- package/docs/reference/authoring-surface/bearer.md +1 -1
- package/docs/reference/authoring-surface/branchname.md +15 -0
- package/docs/reference/authoring-surface/carry.md +23 -0
- package/docs/reference/authoring-surface/chartschema.md +1 -1
- package/docs/reference/authoring-surface/chartschemafor.md +1 -1
- package/docs/reference/authoring-surface/command.md +37 -22
- package/docs/reference/authoring-surface/customize.md +4 -1
- package/docs/reference/authoring-surface/defineconfig.md +1 -1
- package/docs/reference/authoring-surface/defineevent.md +1 -1
- package/docs/reference/authoring-surface/dispatch.md +5 -4
- package/docs/reference/authoring-surface/fail.md +18 -5
- package/docs/reference/authoring-surface/file.md +37 -17
- package/docs/reference/authoring-surface/frompick.md +1 -1
- package/docs/reference/authoring-surface/gate.md +118 -0
- package/docs/reference/authoring-surface/group-agents.md +15 -0
- package/docs/reference/authoring-surface/group-charts.md +16 -0
- package/docs/reference/authoring-surface/group-composition.md +25 -0
- package/docs/reference/authoring-surface/group-config.md +17 -0
- package/docs/reference/authoring-surface/group-effects.md +48 -0
- package/docs/reference/authoring-surface/group-failure.md +13 -0
- package/docs/reference/authoring-surface/group-gates.md +16 -0
- package/docs/reference/authoring-surface/group-machine-and-events.md +15 -0
- package/docs/reference/authoring-surface/group-steering.md +12 -0
- package/docs/reference/authoring-surface/group-types-these-signatures-name.md +137 -0
- package/docs/reference/authoring-surface/group-workspaces-and-repos.md +15 -0
- package/docs/reference/authoring-surface/http.md +109 -9
- package/docs/reference/authoring-surface/isfailure.md +1 -1
- package/docs/reference/authoring-surface/isready.md +14 -0
- package/docs/reference/authoring-surface/jr2setup.md +14 -4
- package/docs/reference/authoring-surface/mcp.md +107 -0
- package/docs/reference/authoring-surface/open.md +41 -8
- package/docs/reference/authoring-surface/openbody.md +1 -1
- package/docs/reference/authoring-surface/paramsof.md +23 -5
- package/docs/reference/authoring-surface/pool.md +79 -11
- package/docs/reference/authoring-surface/push.md +31 -13
- package/docs/reference/authoring-surface/readyof.md +21 -0
- package/docs/reference/authoring-surface/reread.md +19 -0
- package/docs/reference/authoring-surface/secret.md +26 -5
- package/docs/reference/authoring-surface/sentby.md +1 -1
- package/docs/reference/authoring-surface/skip.md +22 -0
- package/docs/reference/authoring-surface/source.md +59 -4
- package/docs/reference/authoring-surface/steer.md +93 -0
- package/docs/reference/authoring-surface/text.md +1 -1
- package/docs/reference/authoring-surface/type-agentdefinition.md +16 -3
- package/docs/reference/authoring-surface/type-agentmcpserver.md +54 -0
- package/docs/reference/authoring-surface/type-agentslots.md +4 -1
- package/docs/reference/authoring-surface/type-anyframepath.md +14 -0
- package/docs/reference/authoring-surface/type-anyworktreepath.md +15 -0
- package/docs/reference/authoring-surface/type-bindactors.md +14 -0
- package/docs/reference/authoring-surface/type-binding.md +6 -7
- package/docs/reference/authoring-surface/type-caller.md +40 -0
- package/docs/reference/authoring-surface/type-callerrecord.md +32 -0
- package/docs/reference/authoring-surface/type-carry.md +19 -0
- package/docs/reference/authoring-surface/type-chainlink.md +3 -3
- package/docs/reference/authoring-surface/type-commandinput.md +4 -3
- package/docs/reference/authoring-surface/type-commandoptions.md +0 -22
- package/docs/reference/authoring-surface/type-commandoutput.md +23 -5
- package/docs/reference/authoring-surface/type-customize.md +20 -3
- package/docs/reference/authoring-surface/type-delivered.md +17 -0
- package/docs/reference/authoring-surface/type-deliveredevent.md +18 -0
- package/docs/reference/authoring-surface/type-dispatchdefinition.md +4 -3
- package/docs/reference/authoring-surface/type-dispatchoutput.md +9 -2
- package/docs/reference/authoring-surface/type-doorlessinput.md +19 -0
- package/docs/reference/authoring-surface/type-effectbinding.md +12 -2
- package/docs/reference/authoring-surface/type-filebody.md +4 -8
- package/docs/reference/authoring-surface/type-framepath.md +14 -0
- package/docs/reference/authoring-surface/type-gatebinding.md +15 -0
- package/docs/reference/authoring-surface/type-gatehooks.md +12 -0
- package/docs/reference/authoring-surface/type-gatelook.md +37 -0
- package/docs/reference/authoring-surface/type-gateoutcome.md +32 -0
- package/docs/reference/authoring-surface/type-gatereply.md +19 -0
- package/docs/reference/authoring-surface/type-gateslot.md +21 -0
- package/docs/reference/authoring-surface/type-gateslotinput.md +13 -0
- package/docs/reference/authoring-surface/type-gateslotparts.md +18 -0
- package/docs/reference/authoring-surface/type-gateslots.md +12 -0
- package/docs/reference/authoring-surface/type-gatetypesat.md +13 -0
- package/docs/reference/authoring-surface/type-hostinjectedinput.md +3 -5
- package/docs/reference/authoring-surface/type-httpdefinition.md +6 -3
- package/docs/reference/authoring-surface/type-httpfileinput.md +20 -0
- package/docs/reference/authoring-surface/type-httpoutput.md +8 -2
- package/docs/reference/authoring-surface/type-jr2config.md +37 -2
- package/docs/reference/authoring-surface/type-lateroutcome.md +21 -0
- package/docs/reference/authoring-surface/type-lends.md +5 -1
- package/docs/reference/authoring-surface/type-lookoutput.md +14 -0
- package/docs/reference/authoring-surface/type-mcpcalloutput.md +78 -0
- package/docs/reference/authoring-surface/type-mcpnotreturned.md +42 -0
- package/docs/reference/authoring-surface/type-mcpoptions.md +47 -0
- package/docs/reference/authoring-surface/type-mcpoutput.md +50 -0
- package/docs/reference/authoring-surface/type-mcpreadoutput.md +53 -0
- package/docs/reference/authoring-surface/type-mcpremoteserver.md +50 -0
- package/docs/reference/authoring-surface/type-mcpserver.md +41 -0
- package/docs/reference/authoring-surface/type-mcpstdioserver.md +42 -0
- package/docs/reference/authoring-surface/type-namedsecret.md +4 -4
- package/docs/reference/authoring-surface/type-namestart.md +77 -0
- package/docs/reference/authoring-surface/type-noslotworkspaceoptions.md +1 -6
- package/docs/reference/authoring-surface/type-notworktreekeys.md +12 -0
- package/docs/reference/authoring-surface/type-openbodydeclaration.md +1 -1
- package/docs/reference/authoring-surface/type-openbodyoutput.md +1 -1
- package/docs/reference/authoring-surface/type-opencommandinput.md +7 -2
- package/docs/reference/authoring-surface/type-permissivenoslotworkspaceoptions.md +1 -6
- package/docs/reference/authoring-surface/type-permissiveworkspaceoptions.md +5 -10
- package/docs/reference/authoring-surface/type-poolnextinput.md +22 -0
- package/docs/reference/authoring-surface/type-poolspec.md +11 -6
- package/docs/reference/authoring-surface/type-pushinput.md +22 -3
- package/docs/reference/authoring-surface/type-pushoutput.md +33 -8
- package/docs/reference/authoring-surface/type-pushsourcespec.md +38 -0
- package/docs/reference/authoring-surface/type-readsourcespec.md +47 -0
- package/docs/reference/authoring-surface/type-reposlot.md +6 -6
- package/docs/reference/authoring-surface/type-reread.md +18 -0
- package/docs/reference/authoring-surface/type-runsconfig.md +41 -0
- package/docs/reference/authoring-surface/type-sandboxoptions.md +11 -4
- package/docs/reference/authoring-surface/type-sender.md +26 -1
- package/docs/reference/authoring-surface/type-sendercallerfield.md +14 -0
- package/docs/reference/authoring-surface/type-size.md +1 -1
- package/docs/reference/authoring-surface/type-skip.md +19 -0
- package/docs/reference/authoring-surface/type-slothandles.md +5 -13
- package/docs/reference/authoring-surface/type-sourcehooks.md +23 -0
- package/docs/reference/authoring-surface/type-sourcein.md +25 -0
- package/docs/reference/authoring-surface/type-sourcereply.md +18 -0
- package/docs/reference/authoring-surface/type-sourcespec.md +26 -17
- package/docs/reference/authoring-surface/type-sourceverdict.md +49 -0
- package/docs/reference/authoring-surface/type-standingpoolmachine.md +12 -0
- package/docs/reference/authoring-surface/type-standingpoolspec.md +51 -0
- package/docs/reference/authoring-surface/type-steerargs.md +20 -0
- package/docs/reference/authoring-surface/type-thinkinglevel.md +1 -1
- package/docs/reference/authoring-surface/type-usercontainer.md +1 -1
- package/docs/reference/authoring-surface/type-workspaced.md +30 -9
- package/docs/reference/authoring-surface/type-workspacehandles.md +5 -6
- package/docs/reference/authoring-surface/type-workspaceoptions.md +1 -13
- package/docs/reference/authoring-surface/type-worktreefound.md +16 -0
- package/docs/reference/authoring-surface/type-worktreeinput.md +56 -0
- package/docs/reference/authoring-surface/type-worktreekey.md +14 -0
- package/docs/reference/authoring-surface/type-worktreeoptions.md +29 -0
- package/docs/reference/authoring-surface/type-worktreeoutput.md +45 -0
- package/docs/reference/authoring-surface/type-worktreepath.md +16 -0
- package/docs/reference/authoring-surface/type-worktreeready.md +37 -0
- package/docs/reference/authoring-surface/type-worktreerefused.md +21 -0
- package/docs/reference/authoring-surface/workspace.md +66 -38
- package/docs/reference/authoring-surface/worktree.md +71 -0
- package/docs/reference/authoring-surface.md +88 -147
- package/docs/reference/cli.md +413 -74
- package/docs/reference/config.md +248 -6
- package/docs/reference/decisions/0001-operator-owned-generic-sandbox.md +10 -9
- package/docs/reference/decisions/0002-duplex-streaming-actor.md +81 -14
- package/docs/reference/decisions/0004-worktree-provisioning-model.md +27 -21
- package/docs/reference/decisions/0005-sandbox-pod-composition.md +39 -25
- package/docs/reference/decisions/0006-agent-control-surface.md +6 -3
- package/docs/reference/decisions/0007-durable-machine-state.md +1 -1
- package/docs/reference/decisions/0009-cli-and-instance-interface.md +150 -49
- package/docs/reference/decisions/0010-bdd-acceptance-tests.md +5 -3
- package/docs/reference/decisions/0011-workflow-defined-events.md +256 -12
- package/docs/reference/decisions/0012-workspace-wrapper-machine.md +39 -32
- package/docs/reference/decisions/0013-the-agent-reaches-its-machine-through-a-container-it-cannot-read.md +54 -30
- package/docs/reference/decisions/0014-observation-is-open-run-state-is-not.md +53 -27
- package/docs/reference/decisions/0015-authoring-surface-absorbs-the-mechanism.md +26 -16
- package/docs/reference/decisions/0016-agent-turn-mechanics-are-internal.md +9 -7
- package/docs/reference/decisions/0017-pool-over-a-source-port.md +226 -10
- package/docs/reference/decisions/0018-instance-agents-are-definitions-jr2-assembles-the-harness.md +15 -7
- package/docs/reference/decisions/0019-one-converging-command-against-the-current-context.md +53 -27
- package/docs/reference/decisions/0021-workspace-continuity-is-a-lease-that-answers-back.md +16 -2
- package/docs/reference/decisions/0022-observation-is-a-level-triggered-feed.md +4 -4
- package/docs/reference/decisions/0023-the-harness-prints-the-conversation.md +124 -43
- package/docs/reference/decisions/0024-an-agents-turn-ends-with-the-state-that-asked-for-it.md +36 -38
- package/docs/reference/decisions/0025-cancel-ends-a-run-stop-parks-it.md +10 -5
- package/docs/reference/decisions/0027-the-harness-is-jr2s-own-server-flue-retires-the-wire-stays.md +16 -7
- package/docs/reference/decisions/0028-what-an-agent-may-do-to-the-workspace-is-part-of-its-definition.md +36 -19
- package/docs/reference/decisions/0029-a-menu-is-fixed-for-a-conversation-and-a-turn-is-told-its-allowed-picks.md +18 -10
- package/docs/reference/decisions/0030-a-snapshot-names-the-machine-it-was-written-under.md +3 -2
- package/docs/reference/decisions/0031-menu-only-agents-run-on-the-instance-harness.md +23 -15
- package/docs/reference/decisions/0032-the-console-unlocks-with-a-callers-credential.md +101 -0
- package/docs/reference/decisions/0033-a-machine-declares-the-input-that-starts-it.md +22 -22
- package/docs/reference/decisions/0034-the-console-renders-with-preact-and-the-server-erases-the-types.md +6 -6
- package/docs/reference/decisions/0037-an-instance-builds-its-sandbox-images-jr2-injects-the-harness.md +13 -12
- package/docs/reference/decisions/0049-a-machine-carries-its-parts-and-composes-by-invoke.md +23 -23
- package/docs/reference/decisions/0050-what-code-names-config-declares-what-the-cli-names-discovery-finds.md +6 -1
- package/docs/reference/decisions/0051-a-repo-is-a-slot-on-the-workspace-and-a-cache-on-the-node.md +57 -46
- package/docs/reference/decisions/0052-a-sandbox-lands-where-an-ordinary-pod-lands-and-the-cache-follows-it.md +5 -0
- package/docs/reference/decisions/0053-a-fetch-inside-the-pod-asks-the-node-cache-and-the-cache-asks-the-remote.md +20 -8
- package/docs/reference/decisions/0054-the-kit-ships-machines-and-a-shipped-machine-leaves-its-parts-open.md +55 -40
- package/docs/reference/decisions/0055-a-release-is-a-pushed-tag-and-the-publish-guard-is-the-credential.md +14 -13
- package/docs/reference/decisions/0057-a-turn-is-its-frame-its-dials-and-whether-it-continues.md +31 -24
- package/docs/reference/decisions/0058-a-harness-answers-the-orchestrator-alone.md +18 -10
- package/docs/reference/decisions/0059-a-harness-holds-stand-ins-and-the-custodian-holds-the-keys.md +137 -86
- package/docs/reference/decisions/0062-jr2-briefs-the-agent-on-its-seat-never-on-its-task.md +165 -91
- package/docs/reference/decisions/0063-the-orchestrator-watches-the-cluster.md +7 -7
- package/docs/reference/decisions/0064-a-workspace-waits-for-capacity.md +2 -2
- package/docs/reference/decisions/0065-a-persist-survives-a-crash-and-history-is-kept-for-a-set-time.md +109 -0
- package/docs/reference/decisions/0066-a-model-tier-runs-a-real-model-and-a-change-to-what-it-reads-runs-the-tier.md +53 -23
- package/docs/reference/decisions/0067-an-effect-is-an-actor-slot-and-runs-at-most-once-unless-marked-idempotent.md +221 -153
- package/docs/reference/decisions/0068-an-effector-holds-an-effects-secrets-and-signs-its-wire.md +161 -96
- package/docs/reference/decisions/0069-the-orchestrator-is-a-kit-image-and-an-instance-publishes-its-assembly.md +32 -9
- package/docs/reference/decisions/0070-a-machine-lends-its-parts-to-a-chart.md +48 -33
- package/docs/reference/decisions/0071-a-run-starts-a-run-through-a-dispatch-effect.md +56 -30
- package/docs/reference/decisions/0072-the-docs-ship-inside-the-kit-and-an-instances-agents-md-indexes-them.md +35 -25
- package/docs/reference/decisions/0073-a-machine-fails-a-run-with-fail-and-an-uncaught-failure-ends-it-failed.md +1 -1
- package/docs/reference/decisions/0075-a-machine-cuts-a-worktree-and-the-workspace-only-clones.md +296 -0
- package/docs/reference/decisions/0076-an-agents-control-credential-lives-only-where-no-workspace-code-runs.md +347 -0
- package/docs/reference/decisions/0077-jr2-requires-landlock-on-every-sandbox-node.md +79 -0
- package/docs/reference/decisions/0078-a-caller-comes-from-one-authenticator-seam-and-acts-within-its-scopes.md +285 -0
- 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
- package/docs/reference/decisions.md +9 -4
- package/docs/reference/glossary.md +138 -45
- package/docs/reference/hooks.md +1077 -0
- package/docs/reference/http-api.md +988 -123
- package/docs/reference/machines.md +0 -1
- package/docs/why.md +7 -5
- package/package.json +10 -3
- package/src/actor.ts +194 -42
- package/src/agent.ts +56 -6
- package/src/ambient.ts +3 -5
- package/src/assembly-checks.ts +530 -4
- package/src/callers.ts +245 -0
- package/src/chart.ts +238 -26
- package/src/charts.ts +9 -2
- package/src/config.ts +566 -7
- package/src/conversations.ts +453 -0
- package/src/custodian.lua +17 -5
- package/src/custodian.ts +257 -77
- package/src/customize.ts +154 -7
- package/src/dispatch-effect.ts +142 -26
- package/src/durability.ts +2 -0
- package/src/duration.ts +20 -0
- package/src/effect-checks.ts +52 -4
- package/src/effect.ts +401 -132
- package/src/effector-wire.ts +278 -30
- package/src/fail.ts +17 -4
- package/src/gate-brand.ts +16 -0
- package/src/gate.ts +634 -48
- package/src/harness-client.ts +84 -35
- package/src/harness-env.ts +33 -0
- package/src/held-secrets.ts +197 -39
- package/src/holds.ts +5 -2
- package/src/hook-kinds/discord.ts +92 -0
- package/src/hook-kinds/door.ts +107 -0
- package/src/hook-kinds/github.ts +89 -0
- package/src/hook-kinds/gitlab.ts +72 -0
- package/src/hook-kinds/hook.ts +7 -0
- package/src/hook-kinds/index.ts +465 -0
- package/src/hook-kinds/slack.ts +151 -0
- package/src/hook-kinds/webhook.ts +113 -0
- package/src/hooks.ts +506 -0
- package/src/http-effect.ts +164 -70
- package/src/http.ts +933 -99
- package/src/index.ts +30 -5
- package/src/instance.ts +196 -26
- package/src/internal.ts +23 -3
- package/src/kube-client.ts +6 -3
- package/src/machine-doc.ts +29 -5
- package/src/mcp-effect.ts +424 -0
- package/src/model-keys.ts +24 -0
- package/src/mount-digest.ts +41 -7
- package/src/names.ts +82 -7
- package/src/notices.ts +576 -59
- package/src/open-body.ts +110 -30
- package/src/open-effect.ts +17 -4
- package/src/open.ts +40 -7
- package/src/parts.ts +125 -35
- package/src/party.ts +35 -1
- package/src/pick.ts +43 -9
- package/src/pool.ts +1172 -172
- package/src/registration.ts +249 -17
- package/src/repo-identity.ts +7 -3
- package/src/repos.ts +20 -2
- package/src/run-host.ts +1614 -190
- package/src/run-list.ts +191 -0
- package/src/sandbox-effect.ts +217 -66
- package/src/sandbox-kube.ts +116 -21
- package/src/secret-placement.ts +248 -35
- package/src/server.ts +53 -4
- package/src/setup.ts +158 -38
- package/src/snapshot-store.ts +565 -48
- package/src/steer.ts +111 -0
- package/src/stub-harness.ts +6 -2
- package/src/tokens.ts +362 -46
- package/src/vocabulary.ts +23 -4
- package/src/wire.ts +27 -10
- package/src/workspace.ts +314 -259
- package/src/worktree.ts +249 -0
- package/docs/reference/authoring-surface/type-noslotspec.md +0 -26
- package/docs/reference/authoring-surface/type-workspacespec.md +0 -37
- package/docs/reference/decisions/0032-the-console-unlocks-with-the-instance-token.md +0 -61
- package/docs/reference/decisions/0065-a-persist-survives-a-crash-and-history-is-a-week.md +0 -65
|
@@ -111,8 +111,14 @@ can differ when your Assistant used other names. Other Workflows of the Instance
|
|
|
111
111
|
…
|
|
112
112
|
typecheck: tsc --noEmit (the instance's own compiler)
|
|
113
113
|
effects: workflow "fix" — what it runs outside itself (ADR-0067)
|
|
114
|
+
cut: worktree — 600s, in the Harness
|
|
114
115
|
tests: command ["node","--test","docs/site/tutorial/greet/test/*.test.js"] — 300s, in the Harness
|
|
115
116
|
publish: push — 300s, in the Sandbox Effector
|
|
117
|
+
…
|
|
118
|
+
failures: workflow "fix" — the states that fail the run (ADR-0073)
|
|
119
|
+
fix.notCut: invokes fail
|
|
120
|
+
fix.lost: invokes fail
|
|
121
|
+
…
|
|
116
122
|
seats: workflow "fix" — who may send what, per state (ADR-0015)
|
|
117
123
|
fix.working agent:coder: [finish]
|
|
118
124
|
fix.review gate: [approve, request_changes]
|
|
@@ -126,8 +132,9 @@ git.credentials "*": push Secret jr2-git-push-684888c0 — pushes over https
|
|
|
126
132
|
|
|
127
133
|
Read these lines as a first check:
|
|
128
134
|
|
|
129
|
-
- `effects` shows
|
|
135
|
+
- `effects` shows three Effects: the cut, a command and a push. A Workflow that pushes with no
|
|
130
136
|
[Gate](../reference/glossary.md#gate) before the push shows the same lines. The graph shows where the push is.
|
|
137
|
+
- `failures` shows the two states that end the run as `failed`.
|
|
131
138
|
- `seats` shows that the coder can send only `finish`. Only the Gate in `review` can send `approve` and
|
|
132
139
|
`request_changes`.
|
|
133
140
|
- The `warning` line is about git over ssh. The `jr2-git-ssh` Secret is for an ssh key, and it does not exist. Your fork
|
|
@@ -199,7 +206,7 @@ jr2 run fix --input '{"prompt":"In docs/site/tutorial/greet, one test fails. Fix
|
|
|
199
206
|
```text
|
|
200
207
|
…
|
|
201
208
|
→ context kind-jr2 / namespace my-instance
|
|
202
|
-
run
|
|
209
|
+
run 790ad78a-db4e-4b09-a248-ab62da088cde (fix) — attached
|
|
203
210
|
→ active "placing"
|
|
204
211
|
→ active "provisioning"
|
|
205
212
|
→ active "attaching"
|
|
@@ -221,12 +228,14 @@ jr2 status <run id>
|
|
|
221
228
|
|
|
222
229
|
[`jr2 status`](../reference/cli.md#status) prints the status of the run as one line of JSON. Its `gates` list holds the
|
|
223
230
|
Gate of `review`. Its `gate` is `body.review`. Give that value to `--gate`. The `meta` of the Gate gives the coder's
|
|
224
|
-
`summary`, the `branch` and the `worktree
|
|
231
|
+
`summary`, the `branch` and the `worktree`. After the JSON, `jr2 status` prints one line for each Worktree that the run
|
|
232
|
+
cut:
|
|
225
233
|
|
|
226
234
|
```text
|
|
227
235
|
…
|
|
228
236
|
→ context kind-jr2 / namespace my-instance
|
|
229
|
-
{…,"gates":[{"gate":"body.review",…,"meta":{"summary":"Fixed the \"trims the name\" test failure in docs/site/tutorial/greet
|
|
237
|
+
{…,"gates":[{"gate":"body.review",…,"meta":{"summary":"Fixed the \"trims the name\" test failure in docs/site/tutorial/greet. The bug was that the `greet` function didn't trim whitespace from the name argument. Added `.trim()` to the name extraction so that `greet([\" ada \"])` correctly returns `\"hello, ada\"` instead of `\"hello, ada \"`.","branch":"jr2/fix-a78c793e-607a-4b33-9784-ccf2cfb6f395","worktree":"/work/target/fix"}}]}
|
|
238
|
+
worktree: /work/target/fix (target), branch jr2/fix-a78c793e-607a-4b33-9784-ccf2cfb6f395
|
|
230
239
|
```
|
|
231
240
|
|
|
232
241
|
The `summary` is in the words of the model, so your summary is different.
|
|
@@ -242,7 +251,7 @@ jr2 send <run id> --gate body.review --event approve
|
|
|
242
251
|
```text
|
|
243
252
|
…
|
|
244
253
|
→ context kind-jr2 / namespace my-instance
|
|
245
|
-
delivered approve to gate "body.review" on
|
|
254
|
+
delivered approve to gate "body.review" on 790ad78a-db4e-4b09-a248-ab62da088cde
|
|
246
255
|
```
|
|
247
256
|
|
|
248
257
|
The run goes to `pushing`, and the push Effect pushes the branch. Then the run ends, and jr2 removes the
|
|
@@ -253,7 +262,7 @@ status as one line of JSON:
|
|
|
253
262
|
…
|
|
254
263
|
→ active "teardown"
|
|
255
264
|
→ done "done"
|
|
256
|
-
{"runId":"
|
|
265
|
+
{"runId":"790ad78a-db4e-4b09-a248-ab62da088cde","workflow":"fix",…,"output":{"outcome":"pushed","branch":"jr2/fix-a78c793e-607a-4b33-9784-ccf2cfb6f395","commit":"ee7f5d8084db32c3610efb5c9b889a710ef30f70"},"worktrees":[{"slot":"target","path":"/work/target/fix","branch":"jr2/fix-a78c793e-607a-4b33-9784-ccf2cfb6f395"}]}
|
|
257
266
|
```
|
|
258
267
|
|
|
259
268
|
In that JSON, `context.output` and `output` are the output of `fix`. In this result, it is
|
|
@@ -289,9 +298,11 @@ import {
|
|
|
289
298
|
command,
|
|
290
299
|
defineEvent,
|
|
291
300
|
fail,
|
|
301
|
+
isReady,
|
|
292
302
|
jr2Setup,
|
|
293
303
|
push,
|
|
294
304
|
workspace,
|
|
305
|
+
worktree,
|
|
295
306
|
type CommandOutput,
|
|
296
307
|
type HostInjectedInput,
|
|
297
308
|
type PushOutput,
|
|
@@ -339,6 +350,15 @@ type Context = BodyInput & {
|
|
|
339
350
|
// The output of a run that ends `done`. A lost Sandbox fails the run, with no output of this type.
|
|
340
351
|
type Output = { outcome: "pushed"; branch: string; commit: string };
|
|
341
352
|
|
|
353
|
+
// The Worktree of the coder. The Machine names the folder, and each Effect that works there names it.
|
|
354
|
+
function fixTree(context: BodyInput) {
|
|
355
|
+
return `${context.workspace.repos.target}/fix` as const;
|
|
356
|
+
}
|
|
357
|
+
// One branch for each run, from its seed Instance ID.
|
|
358
|
+
function branchOf(context: BodyInput): string {
|
|
359
|
+
return `jr2/fix-${context.instanceId}`;
|
|
360
|
+
}
|
|
361
|
+
|
|
342
362
|
// Two guards. A guard with a name shows that name on its arrow in the Console's graph.
|
|
343
363
|
function testsPassed({ event }: { event: { output: CommandOutput } }): boolean {
|
|
344
364
|
return event.output.outcome === "exited" && event.output.code === 0;
|
|
@@ -362,7 +382,9 @@ const body = jr2Setup({
|
|
|
362
382
|
- Make the smallest change that fixes the bug.
|
|
363
383
|
- End your turn with exactly one call to \`finish\`.`,
|
|
364
384
|
}),
|
|
365
|
-
//
|
|
385
|
+
// Cut a Worktree of `target`: the Workspace only clones.
|
|
386
|
+
cut: worktree(),
|
|
387
|
+
// A program in the Harness container of the Sandbox, in the Worktree that its input names. Node expands the glob itself.
|
|
366
388
|
tests: command(["node", "--test", "docs/site/tutorial/greet/test/*.test.js"], { timeout: "5m" }),
|
|
367
389
|
// Push the tip of the coder's branch to the Repo of `target`, with the token of `git.credentials`.
|
|
368
390
|
publish: push(),
|
|
@@ -372,16 +394,24 @@ const body = jr2Setup({
|
|
|
372
394
|
}).createMachine({
|
|
373
395
|
id: "fix",
|
|
374
396
|
context: ({ input }) => ({ ...input, fresh: true }),
|
|
375
|
-
initial: "
|
|
397
|
+
initial: "cutting",
|
|
376
398
|
// The Sandbox is gone, and every commit that was not pushed went with it.
|
|
377
399
|
on: { "workspace.lost": { target: ".lost" } },
|
|
378
400
|
states: {
|
|
401
|
+
// The Workspace only clones. The Machine cuts the Worktree that the Agent works in.
|
|
402
|
+
cutting: {
|
|
403
|
+
invoke: {
|
|
404
|
+
src: "cut",
|
|
405
|
+
input: ({ context }) => ({ path: fixTree(context), branch: branchOf(context) }),
|
|
406
|
+
onDone: [{ guard: ({ event }) => isReady(event.output), target: "working" }, { target: "notCut" }],
|
|
407
|
+
},
|
|
408
|
+
},
|
|
379
409
|
working: {
|
|
380
410
|
invoke: {
|
|
381
411
|
src: "coder",
|
|
382
412
|
input: ({ context }) => ({
|
|
383
413
|
prompt: promptOf(context),
|
|
384
|
-
cwd: context
|
|
414
|
+
cwd: fixTree(context),
|
|
385
415
|
// Each Turn continues the coder's one conversation, so the coder remembers its work.
|
|
386
416
|
continue: true,
|
|
387
417
|
}),
|
|
@@ -406,6 +436,7 @@ const body = jr2Setup({
|
|
|
406
436
|
testing: {
|
|
407
437
|
invoke: {
|
|
408
438
|
src: "tests",
|
|
439
|
+
input: ({ context }) => ({ worktree: fixTree(context) }),
|
|
409
440
|
onDone: [
|
|
410
441
|
{ guard: testsPassed, target: "review" },
|
|
411
442
|
{
|
|
@@ -423,8 +454,8 @@ const body = jr2Setup({
|
|
|
423
454
|
meta: {
|
|
424
455
|
...(context.summary !== undefined ? { summary: context.summary } : {}),
|
|
425
456
|
...(context.reason !== undefined ? { reason: context.reason } : {}),
|
|
426
|
-
branch: context
|
|
427
|
-
worktree: context
|
|
457
|
+
branch: branchOf(context),
|
|
458
|
+
worktree: fixTree(context),
|
|
428
459
|
},
|
|
429
460
|
}),
|
|
430
461
|
},
|
|
@@ -442,6 +473,7 @@ const body = jr2Setup({
|
|
|
442
473
|
pushing: {
|
|
443
474
|
invoke: {
|
|
444
475
|
src: "publish",
|
|
476
|
+
input: ({ context }) => ({ worktree: fixTree(context) }),
|
|
445
477
|
onDone: [
|
|
446
478
|
{
|
|
447
479
|
guard: pushed,
|
|
@@ -457,11 +489,12 @@ const body = jr2Setup({
|
|
|
457
489
|
type: "final",
|
|
458
490
|
output: ({ context }): Output => ({
|
|
459
491
|
outcome: "pushed",
|
|
460
|
-
branch: context
|
|
492
|
+
branch: branchOf(context),
|
|
461
493
|
commit: context.commit ?? "",
|
|
462
494
|
}),
|
|
463
495
|
},
|
|
464
|
-
// Not
|
|
496
|
+
// Not final states: the run ends `failed`, and jr2 deletes the Sandbox.
|
|
497
|
+
notCut: { invoke: { src: "fail", input: { reason: "the Worktree was not cut" } } },
|
|
465
498
|
lost: { invoke: { src: "fail", input: { reason: "the Sandbox was lost, with every commit that was not pushed" } } },
|
|
466
499
|
},
|
|
467
500
|
// The output of the run. xstate reads only this root `output` as the output of the Machine. It
|
|
@@ -476,14 +509,14 @@ function promptOf(context: Context): string {
|
|
|
476
509
|
const reason = context.reason ? `\n\nThe last attempt ended: ${context.reason}` : "";
|
|
477
510
|
return (
|
|
478
511
|
`${context.prompt}${reason}${feedback ? `\n\n${feedback}` : ""}\n\n` +
|
|
479
|
-
`Work in ${context
|
|
512
|
+
`Work in ${fixTree(context)}, on the branch ${branchOf(context)}. ` +
|
|
480
513
|
"Commit your fix there, then call finish."
|
|
481
514
|
);
|
|
482
515
|
}
|
|
483
516
|
|
|
484
517
|
// What the coder reads when the tests fail: the end of the output of `node --test`.
|
|
485
518
|
function testFeedback(output: CommandOutput): string {
|
|
486
|
-
const text =
|
|
519
|
+
const text = "tail" in output ? output.tail : output.reason;
|
|
487
520
|
return (
|
|
488
521
|
`The tests do not pass (${output.outcome}). The end of their output:\n${text}\n\n` +
|
|
489
522
|
"Fix the code, commit, then call finish."
|
|
@@ -503,8 +536,6 @@ function pushFailure(output: PushOutput): string {
|
|
|
503
536
|
export const machine = workspace(body, {
|
|
504
537
|
input: door,
|
|
505
538
|
repos: { target: { url: "https://github.com/<you>/jr2.git", ref: "v<version>" } },
|
|
506
|
-
// One branch for each run, from its seed Instance ID: `input.instanceId`.
|
|
507
|
-
spec: ({ input }) => ({ branch: `jr2/fix-${input.instanceId}` }),
|
|
508
539
|
});
|
|
509
540
|
```
|
|
510
541
|
|
|
@@ -518,9 +549,11 @@ import {
|
|
|
518
549
|
command,
|
|
519
550
|
defineEvent,
|
|
520
551
|
fail,
|
|
552
|
+
isReady,
|
|
521
553
|
jr2Setup,
|
|
522
554
|
push,
|
|
523
555
|
workspace,
|
|
556
|
+
worktree,
|
|
524
557
|
type CommandOutput,
|
|
525
558
|
type HostInjectedInput,
|
|
526
559
|
type PushOutput,
|
|
@@ -568,6 +601,15 @@ type Context = BodyInput & {
|
|
|
568
601
|
// The output of a run that ends `done`. A lost Sandbox fails the run, with no output of this type.
|
|
569
602
|
type Output = { outcome: "pushed"; branch: string; commit: string };
|
|
570
603
|
|
|
604
|
+
// The Worktree of the coder. The Machine names the folder, and each Effect that works there names it.
|
|
605
|
+
function fixTree(context: BodyInput) {
|
|
606
|
+
return `${context.workspace.repos.target}/fix` as const;
|
|
607
|
+
}
|
|
608
|
+
// One branch for each run, from its seed Instance ID.
|
|
609
|
+
function branchOf(context: BodyInput): string {
|
|
610
|
+
return `jr2/fix-${context.instanceId}`;
|
|
611
|
+
}
|
|
612
|
+
|
|
571
613
|
// Two guards. A guard with a name shows that name on its arrow in the Console's graph.
|
|
572
614
|
function testsPassed({ event }: { event: { output: CommandOutput } }): boolean {
|
|
573
615
|
return event.output.outcome === "exited" && event.output.code === 0;
|
|
@@ -591,7 +633,9 @@ const body = jr2Setup({
|
|
|
591
633
|
- Make the smallest change that fixes the bug.
|
|
592
634
|
- End your turn with exactly one call to \`finish\`.`,
|
|
593
635
|
}),
|
|
594
|
-
//
|
|
636
|
+
// Cut a Worktree of `target`: the Workspace only clones.
|
|
637
|
+
cut: worktree(),
|
|
638
|
+
// A program in the Harness container of the Sandbox, in the Worktree that its input names. Node expands the glob itself.
|
|
595
639
|
tests: command(["node", "--test", "docs/site/tutorial/greet/test/*.test.js"], { timeout: "5m" }),
|
|
596
640
|
// Push the tip of the coder's branch to the Repo of `target`, with the token of `git.credentials`.
|
|
597
641
|
publish: push(),
|
|
@@ -601,16 +645,24 @@ const body = jr2Setup({
|
|
|
601
645
|
}).createMachine({
|
|
602
646
|
id: "fix",
|
|
603
647
|
context: ({ input }) => ({ ...input, fresh: true }),
|
|
604
|
-
initial: "
|
|
648
|
+
initial: "cutting",
|
|
605
649
|
// The Sandbox is gone, and every commit that was not pushed went with it.
|
|
606
650
|
on: { "workspace.lost": { target: ".lost" } },
|
|
607
651
|
states: {
|
|
652
|
+
// The Workspace only clones. The Machine cuts the Worktree that the Agent works in.
|
|
653
|
+
cutting: {
|
|
654
|
+
invoke: {
|
|
655
|
+
src: "cut",
|
|
656
|
+
input: ({ context }) => ({ path: fixTree(context), branch: branchOf(context) }),
|
|
657
|
+
onDone: [{ guard: ({ event }) => isReady(event.output), target: "working" }, { target: "notCut" }],
|
|
658
|
+
},
|
|
659
|
+
},
|
|
608
660
|
working: {
|
|
609
661
|
invoke: {
|
|
610
662
|
src: "coder",
|
|
611
663
|
input: ({ context }) => ({
|
|
612
664
|
prompt: promptOf(context),
|
|
613
|
-
cwd: context
|
|
665
|
+
cwd: fixTree(context),
|
|
614
666
|
// Each Turn continues the coder's one conversation, so the coder remembers its work.
|
|
615
667
|
continue: true,
|
|
616
668
|
}),
|
|
@@ -635,6 +687,7 @@ const body = jr2Setup({
|
|
|
635
687
|
testing: {
|
|
636
688
|
invoke: {
|
|
637
689
|
src: "tests",
|
|
690
|
+
input: ({ context }) => ({ worktree: fixTree(context) }),
|
|
638
691
|
onDone: [
|
|
639
692
|
{ guard: testsPassed, target: "review" },
|
|
640
693
|
{
|
|
@@ -652,8 +705,8 @@ const body = jr2Setup({
|
|
|
652
705
|
meta: {
|
|
653
706
|
...(context.summary !== undefined ? { summary: context.summary } : {}),
|
|
654
707
|
...(context.reason !== undefined ? { reason: context.reason } : {}),
|
|
655
|
-
branch: context
|
|
656
|
-
worktree: context
|
|
708
|
+
branch: branchOf(context),
|
|
709
|
+
worktree: fixTree(context),
|
|
657
710
|
},
|
|
658
711
|
}),
|
|
659
712
|
},
|
|
@@ -671,6 +724,7 @@ const body = jr2Setup({
|
|
|
671
724
|
pushing: {
|
|
672
725
|
invoke: {
|
|
673
726
|
src: "publish",
|
|
727
|
+
input: ({ context }) => ({ worktree: fixTree(context) }),
|
|
674
728
|
onDone: [
|
|
675
729
|
{
|
|
676
730
|
guard: pushed,
|
|
@@ -686,11 +740,12 @@ const body = jr2Setup({
|
|
|
686
740
|
type: "final",
|
|
687
741
|
output: ({ context }): Output => ({
|
|
688
742
|
outcome: "pushed",
|
|
689
|
-
branch: context
|
|
743
|
+
branch: branchOf(context),
|
|
690
744
|
commit: context.commit ?? "",
|
|
691
745
|
}),
|
|
692
746
|
},
|
|
693
|
-
// Not
|
|
747
|
+
// Not final states: the run ends `failed`, and jr2 deletes the Sandbox.
|
|
748
|
+
notCut: { invoke: { src: "fail", input: { reason: "the Worktree was not cut" } } },
|
|
694
749
|
lost: { invoke: { src: "fail", input: { reason: "the Sandbox was lost, with every commit that was not pushed" } } },
|
|
695
750
|
},
|
|
696
751
|
// The output of the run. xstate reads only this root `output` as the output of the Machine. It
|
|
@@ -705,14 +760,14 @@ function promptOf(context: Context): string {
|
|
|
705
760
|
const reason = context.reason ? `\n\nThe last attempt ended: ${context.reason}` : "";
|
|
706
761
|
return (
|
|
707
762
|
`${context.prompt}${reason}${feedback ? `\n\n${feedback}` : ""}\n\n` +
|
|
708
|
-
`Work in ${context
|
|
763
|
+
`Work in ${fixTree(context)}, on the branch ${branchOf(context)}. ` +
|
|
709
764
|
"Commit your fix there, then call finish."
|
|
710
765
|
);
|
|
711
766
|
}
|
|
712
767
|
|
|
713
768
|
// What the coder reads when the tests fail: the end of the output of `node --test`.
|
|
714
769
|
function testFeedback(output: CommandOutput): string {
|
|
715
|
-
const text =
|
|
770
|
+
const text = "tail" in output ? output.tail : output.reason;
|
|
716
771
|
return (
|
|
717
772
|
`The tests do not pass (${output.outcome}). The end of their output:\n${text}\n\n` +
|
|
718
773
|
"Fix the code, commit, then call finish."
|
|
@@ -732,8 +787,6 @@ function pushFailure(output: PushOutput): string {
|
|
|
732
787
|
export const machine = workspace(body, {
|
|
733
788
|
input: door,
|
|
734
789
|
repos: { target: { url: "https://github.com/<you>/jr2.git", ref: "v<version>" } },
|
|
735
|
-
// One branch for each run, from its seed Instance ID: `input.instanceId`.
|
|
736
|
-
spec: ({ input }) => ({ branch: `jr2/fix-${input.instanceId}` }),
|
|
737
790
|
});
|
|
738
791
|
```
|
|
739
792
|
|
|
@@ -765,16 +818,19 @@ const requestChanges = defineEvent({
|
|
|
765
818
|
});
|
|
766
819
|
```
|
|
767
820
|
|
|
768
|
-
**The Effects.** `tests` and `publish` are actor slots, as the coder is. A state runs one when it invokes it.
|
|
769
|
-
[`
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
[`push()`](../reference/authoring-surface/push.md) pushes the
|
|
821
|
+
**The Effects.** `cut`, `tests` and `publish` are actor slots, as the coder is. A state runs one when it invokes it.
|
|
822
|
+
[`worktree()`](../reference/authoring-surface/worktree.md) cuts a [Worktree](../reference/glossary.md#worktree) of the
|
|
823
|
+
[Repo Slot](../reference/glossary.md#repo-slot). [`command()`](../reference/authoring-surface/command.md) takes a list
|
|
824
|
+
of arguments, not a line of shell text. Its input names the Worktree. A command runs in the root of the Worktree, so
|
|
825
|
+
`tests` names the test files by their path from that root. [`push()`](../reference/authoring-surface/push.md) pushes the
|
|
826
|
+
tip of the coder's branch. Its input names the Worktree too, and jr2 reads the branch from the cut.
|
|
773
827
|
[`fail()`](../reference/authoring-surface/fail.md) is a Part, not an Effect. The `lost` state invokes it to end the run
|
|
774
828
|
`failed`, because a final state means `done`.
|
|
775
829
|
|
|
776
830
|
```ts
|
|
777
|
-
//
|
|
831
|
+
// Cut a Worktree of `target`: the Workspace only clones.
|
|
832
|
+
cut: worktree(),
|
|
833
|
+
// A program in the Harness container of the Sandbox, in the Worktree that its input names. Node expands the glob itself.
|
|
778
834
|
tests: command(["node", "--test", "docs/site/tutorial/greet/test/*.test.js"], { timeout: "5m" }),
|
|
779
835
|
// Push the tip of the coder's branch to the Repo of `target`, with the token of `git.credentials`.
|
|
780
836
|
publish: push(),
|
|
@@ -782,6 +838,21 @@ publish: push(),
|
|
|
782
838
|
fail: fail(),
|
|
783
839
|
```
|
|
784
840
|
|
|
841
|
+
**The cut.** The Workspace only clones. `cutting` is the first state, and it makes the coder's Worktree. The path is
|
|
842
|
+
`/work/target/fix`, and the branch has the Instance ID of the run in it. See
|
|
843
|
+
[Cut a Worktree](../guides/cut-a-worktree.md).
|
|
844
|
+
|
|
845
|
+
```ts
|
|
846
|
+
// The Workspace only clones. The Machine cuts the Worktree that the Agent works in.
|
|
847
|
+
cutting: {
|
|
848
|
+
invoke: {
|
|
849
|
+
src: "cut",
|
|
850
|
+
input: ({ context }) => ({ path: fixTree(context), branch: branchOf(context) }),
|
|
851
|
+
onDone: [{ guard: ({ event }) => isReady(event.output), target: "working" }, { target: "notCut" }],
|
|
852
|
+
},
|
|
853
|
+
},
|
|
854
|
+
```
|
|
855
|
+
|
|
785
856
|
**The coder's state.** `working` invokes the coder. Each [Turn](../reference/glossary.md#turn) gets a prompt and the
|
|
786
857
|
folder to work in. `continue: true` keeps one conversation, so the coder remembers its last Turn. `finish` is the
|
|
787
858
|
coder's pick: the run goes to `testing`. [`agent.fault`](../reference/mechanism-events.md#agent-fault) is an event from
|
|
@@ -793,7 +864,7 @@ working: {
|
|
|
793
864
|
src: "coder",
|
|
794
865
|
input: ({ context }) => ({
|
|
795
866
|
prompt: promptOf(context),
|
|
796
|
-
cwd: context
|
|
867
|
+
cwd: fixTree(context),
|
|
797
868
|
// Each Turn continues the coder's one conversation, so the coder remembers its work.
|
|
798
869
|
continue: true,
|
|
799
870
|
}),
|
|
@@ -825,6 +896,7 @@ catches every other outcome. See [`CommandOutput`](../reference/authoring-surfac
|
|
|
825
896
|
testing: {
|
|
826
897
|
invoke: {
|
|
827
898
|
src: "tests",
|
|
899
|
+
input: ({ context }) => ({ worktree: fixTree(context) }),
|
|
828
900
|
onDone: [
|
|
829
901
|
{ guard: testsPassed, target: "review" },
|
|
830
902
|
{
|
|
@@ -849,8 +921,8 @@ review: {
|
|
|
849
921
|
meta: {
|
|
850
922
|
...(context.summary !== undefined ? { summary: context.summary } : {}),
|
|
851
923
|
...(context.reason !== undefined ? { reason: context.reason } : {}),
|
|
852
|
-
branch: context
|
|
853
|
-
worktree: context
|
|
924
|
+
branch: branchOf(context),
|
|
925
|
+
worktree: fixTree(context),
|
|
854
926
|
},
|
|
855
927
|
}),
|
|
856
928
|
},
|
|
@@ -875,6 +947,7 @@ commits in it. See [`PushOutput`](../reference/authoring-surface/type-pushoutput
|
|
|
875
947
|
pushing: {
|
|
876
948
|
invoke: {
|
|
877
949
|
src: "publish",
|
|
950
|
+
input: ({ context }) => ({ worktree: fixTree(context) }),
|
|
878
951
|
onDone: [
|
|
879
952
|
{
|
|
880
953
|
guard: pushed,
|
|
@@ -890,15 +963,13 @@ pushing: {
|
|
|
890
963
|
|
|
891
964
|
**The Workspace.** [`workspace()`](../reference/authoring-surface/workspace.md) runs the body in a Sandbox. `input` is
|
|
892
965
|
the schema of the run input that `jr2 run --input` sends. `repos` binds the Repo Slot `target` to your fork, at the
|
|
893
|
-
release tag.
|
|
966
|
+
release tag. A new branch starts from that tag. The body also gets `instanceId`, an id that jr2 makes for each run, so
|
|
894
967
|
each run gets a branch of its own.
|
|
895
968
|
|
|
896
969
|
```ts
|
|
897
970
|
export const machine = workspace(body, {
|
|
898
971
|
input: door,
|
|
899
972
|
repos: { target: { url: "https://github.com/<you>/jr2.git", ref: "v<version>" } },
|
|
900
|
-
// One branch for each run, from its seed Instance ID: `input.instanceId`.
|
|
901
|
-
spec: ({ input }) => ({ branch: `jr2/fix-${input.instanceId}` }),
|
|
902
973
|
});
|
|
903
974
|
```
|
|
904
975
|
|
|
@@ -20,6 +20,10 @@ This is the first page of the tutorial. You need a computer with these tools:
|
|
|
20
20
|
kind makes the cluster from Docker containers. `jr2 up` builds an image with Docker and loads it into the kind cluster.
|
|
21
21
|
kubectl is the tool that `jr2 up`, `jr2 run` and the other commands use to speak to the cluster.
|
|
22
22
|
|
|
23
|
+
The kind cluster uses the Linux kernel of Docker: the kernel of your computer, or on macOS and Windows, the kernel of
|
|
24
|
+
the virtual machine of Docker. jr2 needs Landlock in that kernel: Linux 6.2 or later, with `landlock` in its list of
|
|
25
|
+
security modules. `jr2 up` refuses to converge without Landlock.
|
|
26
|
+
|
|
23
27
|
## Check Node.js
|
|
24
28
|
|
|
25
29
|
Run:
|
|
@@ -12,16 +12,17 @@ Put the programs that your [Agents](../reference/glossary.md#agent) and
|
|
|
12
12
|
A [Workspace](../reference/glossary.md#workspace) runs its body in a [Sandbox](../reference/glossary.md#sandbox): a pod
|
|
13
13
|
of its own. The Sandbox Image is the image of the pod's `harness` container. The Agent's
|
|
14
14
|
[Working tools](../reference/glossary.md#working-tools) run in that container, and so do the `command` Effects and the
|
|
15
|
-
shell that you get with `
|
|
15
|
+
shell that you get with `jr2 workspace shell`. Thus a program that is in the image is a program that they can run.
|
|
16
16
|
|
|
17
17
|
Use this table to choose:
|
|
18
18
|
|
|
19
|
-
| You want | Do this
|
|
20
|
-
| ---------------------------------------------- |
|
|
21
|
-
| The same tools for each Workspace | Change `images/default/Dockerfile`.
|
|
22
|
-
| Different tools for the Workspaces of one file | Put a docker context beside the workflow module, and name it in the `image` option.
|
|
23
|
-
| An image that you build and push yourself | Write its registry ref in the `image` option.
|
|
24
|
-
| A service that runs beside the Agent | Name its image in the `user` option. It runs in the [User Container](../reference/glossary.md#user-container).
|
|
19
|
+
| You want | Do this |
|
|
20
|
+
| ---------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
|
|
21
|
+
| The same tools for each Workspace | Change `images/default/Dockerfile`. |
|
|
22
|
+
| Different tools for the Workspaces of one file | Put a docker context beside the workflow module, and name it in the `image` option. |
|
|
23
|
+
| An image that you build and push yourself | Write its registry ref in the `image` option. |
|
|
24
|
+
| A service that runs beside the Agent | Name its image in the `user` option. It runs in the [User Container](../reference/glossary.md#user-container). |
|
|
25
|
+
| A tool that the model calls by name | Put an MCP server in the image, and declare it in `jr2.config.ts`. See [Write a tool as an MCP server](write-a-tool-as-an-mcp-server.md). |
|
|
25
26
|
|
|
26
27
|
## Add a tool to the default image
|
|
27
28
|
|
|
@@ -137,26 +138,39 @@ RUN pip install --no-cache-dir pytest ruff
|
|
|
137
138
|
|
|
138
139
|
```ts
|
|
139
140
|
import { z } from "zod";
|
|
140
|
-
import { command, fail, jr2Setup, workspace, type Workspaced } from "@jr2/orchestrator";
|
|
141
|
+
import { command, fail, isReady, jr2Setup, workspace, worktree, type Workspaced } from "@jr2/orchestrator";
|
|
141
142
|
|
|
142
143
|
const runInput = z.object({ branch: z.string() });
|
|
143
144
|
type BodyInput = Workspaced<z.infer<typeof runInput>, "app">;
|
|
144
145
|
|
|
146
|
+
// The Worktree that the tests run in.
|
|
147
|
+
const testTree = (context: BodyInput) => `${context.workspace.repos.app}/test` as const;
|
|
148
|
+
|
|
145
149
|
const body = jr2Setup({
|
|
146
|
-
types: {} as { input: BodyInput },
|
|
150
|
+
types: {} as { input: BodyInput; context: BodyInput },
|
|
147
151
|
actors: {
|
|
152
|
+
cut: worktree(),
|
|
148
153
|
// python and pytest come from the Sandbox Image in ./python.
|
|
149
154
|
tests: command(["python", "-m", "pytest"], { timeout: "15m" }),
|
|
150
155
|
fail: fail(),
|
|
151
156
|
},
|
|
152
157
|
}).createMachine({
|
|
153
158
|
id: "pytest",
|
|
159
|
+
context: ({ input }) => input,
|
|
154
160
|
on: { "workspace.lost": ".lost" },
|
|
155
|
-
initial: "
|
|
161
|
+
initial: "cutting",
|
|
156
162
|
states: {
|
|
163
|
+
cutting: {
|
|
164
|
+
invoke: {
|
|
165
|
+
src: "cut",
|
|
166
|
+
input: ({ context }) => ({ path: testTree(context), branch: context.branch }),
|
|
167
|
+
onDone: [{ guard: ({ event }) => isReady(event.output), target: "testing" }, { target: "notCut" }],
|
|
168
|
+
},
|
|
169
|
+
},
|
|
157
170
|
testing: {
|
|
158
171
|
invoke: {
|
|
159
172
|
src: "tests",
|
|
173
|
+
input: ({ context }) => ({ worktree: testTree(context) }),
|
|
160
174
|
onDone: [
|
|
161
175
|
{
|
|
162
176
|
guard: ({ event }) => event.output.outcome === "exited" && event.output.code === 0,
|
|
@@ -169,6 +183,7 @@ const body = jr2Setup({
|
|
|
169
183
|
passed: { type: "final" },
|
|
170
184
|
// Not final states: each one fails the run, and the run ends `failed`.
|
|
171
185
|
failed: { invoke: { src: "fail", input: { reason: "pytest did not pass" } } },
|
|
186
|
+
notCut: { invoke: { src: "fail", input: { reason: "the Worktree was not cut" } } },
|
|
172
187
|
lost: { invoke: { src: "fail", input: { reason: "the Sandbox was lost" } } },
|
|
173
188
|
},
|
|
174
189
|
});
|
|
@@ -178,7 +193,6 @@ export const machine = workspace(body, {
|
|
|
178
193
|
// The docker context in the folder beside this file. jr2 up builds it.
|
|
179
194
|
image: import.meta.resolve("./python"),
|
|
180
195
|
repos: { app: "https://github.com/you/app.git" },
|
|
181
|
-
spec: ({ input }) => ({ branch: input.branch }),
|
|
182
196
|
});
|
|
183
197
|
```
|
|
184
198
|
|
|
@@ -226,17 +240,23 @@ RUN apk add --no-cache git
|
|
|
226
240
|
# The Worktrees under /work belong to a different user. Tell git to trust them.
|
|
227
241
|
RUN git config --system --add safe.directory '*'
|
|
228
242
|
|
|
229
|
-
# jr2 does not replace this command. It must keep running: when it ends,
|
|
243
|
+
# jr2 does not replace this command. It must keep running: when it ends, Kubernetes starts the container again.
|
|
230
244
|
CMD ["sh", "-c", "while true; do sleep 3600; done"]
|
|
231
245
|
```
|
|
232
246
|
|
|
233
247
|
Save it as `workflows/shell/Dockerfile`. Name it in the `workspace()` options with
|
|
234
248
|
`user: import.meta.resolve("./shell")`. `user` takes the same two forms as `image`, and `jr2 up` builds a `file:`
|
|
235
|
-
context in the same way. Open the shell with `
|
|
249
|
+
context in the same way. Open the shell with [`jr2 workspace shell`](../reference/cli.md#workspace-shell) and `--user`.
|
|
250
|
+
[Look inside a Sandbox](look-inside-a-sandbox.md#find-the-sandbox) tells how to find `<workspace>`:
|
|
251
|
+
|
|
252
|
+
```sh
|
|
253
|
+
jr2 workspace shell <workspace> --user
|
|
254
|
+
```
|
|
236
255
|
|
|
237
256
|
The User Container is not a second Sandbox Image:
|
|
238
257
|
|
|
239
|
-
- Its own `ENTRYPOINT` and `CMD` run. Its process must keep running
|
|
258
|
+
- Its own `ENTRYPOINT` and `CMD` run. Its process must keep running. When it ends, Kubernetes starts the container
|
|
259
|
+
again, so a `CMD` that ends at once restarts again and again.
|
|
240
260
|
- jr2 gives it `/work`, which it can write, and `/repos` and `/opt/jr2`, which it can only read. jr2 gives it no other
|
|
241
261
|
mount, no environment variable and no command.
|
|
242
262
|
- It has no floor: an Alpine base is correct here. It runs as the `USER` of its image, and root is permitted.
|
|
@@ -253,6 +273,42 @@ container, the [Sandbox Effector](../reference/glossary.md#sandbox-effector). By
|
|
|
253
273
|
[Run a command or call a URL with an Effect](run-a-command-or-call-a-url.md) and
|
|
254
274
|
[Push and sign a branch](push-and-sign-a-branch.md).
|
|
255
275
|
|
|
276
|
+
### Reach a service in the User Container
|
|
277
|
+
|
|
278
|
+
No Service of the cluster goes to the User Container. To reach a port in the Sandbox pod, run
|
|
279
|
+
[`jr2 workspace forward`](../reference/cli.md#workspace-forward). It forwards a port on your computer to the port in the
|
|
280
|
+
pod, through the API server of the cluster, until you push Ctrl-C:
|
|
281
|
+
|
|
282
|
+
```sh
|
|
283
|
+
jr2 workspace forward <workspace> 3000
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
```text
|
|
287
|
+
→ context <context> / namespace <namespace>
|
|
288
|
+
127.0.0.1:36779
|
|
289
|
+
forwarding 127.0.0.1:36779 → 7a0e8b50/x:0:3000 — Ctrl-C ends it
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
The address on stdout is the local address. The port changes on each run.
|
|
293
|
+
|
|
294
|
+
When the User Container runs an sshd on port `22`, `ssh` can go through `jr2 workspace forward --stdio`. Add this entry
|
|
295
|
+
to `~/.ssh/config`. Replace `<namespace>` with the namespace of your Instance:
|
|
296
|
+
|
|
297
|
+
```text
|
|
298
|
+
Host *.jr2
|
|
299
|
+
ProxyCommand jr2 workspace forward %h 22 --stdio -n <namespace>
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
Then connect with the name of the Sandbox, which `jr2 workspace ls` prints, and `.jr2`:
|
|
303
|
+
|
|
304
|
+
```sh
|
|
305
|
+
ssh <sandbox>.jr2
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
With `-n`, `jr2 workspace forward` needs no Instance folder, so `ssh` can run it from each folder. The sshd and its keys
|
|
309
|
+
are yours: jr2 gives the User Container no key. With `ssh -A`, your `ssh-agent` goes only to the User Container, and the
|
|
310
|
+
Agent runs nothing there.
|
|
311
|
+
|
|
256
312
|
## Rules
|
|
257
313
|
|
|
258
314
|
- `workspace()` refuses an `image` that is empty or not a string:
|
|
@@ -290,6 +346,7 @@ container, the [Sandbox Effector](../reference/glossary.md#sandbox-effector). By
|
|
|
290
346
|
[`UserContainer`](../reference/authoring-surface/type-usercontainer.md), [`jr2 up`](../reference/cli.md#up)
|
|
291
347
|
- [ADR-0037](../reference/decisions/0037-an-instance-builds-its-sandbox-images-jr2-injects-the-harness.md): the Instance
|
|
292
348
|
builds its Sandbox Images, and jr2 injects the Harness.
|
|
293
|
-
- [ADR-0005](../reference/decisions/0005-sandbox-pod-composition.md): the containers of the Sandbox pod
|
|
349
|
+
- [ADR-0005](../reference/decisions/0005-sandbox-pod-composition.md): the containers of the Sandbox pod, and how you
|
|
350
|
+
reach the User Container.
|
|
294
351
|
- [ADR-0049](../reference/decisions/0049-a-machine-carries-its-parts-and-composes-by-invoke.md): a Machine carries its
|
|
295
352
|
images.
|