@jr2/orchestrator 0.6.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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 +86 -9
- package/docs/concepts/architecture.md +41 -28
- package/docs/concepts/callers-and-hooks.md +205 -0
- package/docs/concepts/charts.md +7 -5
- package/docs/concepts/composition.md +10 -1
- package/docs/concepts/converge.md +4 -2
- package/docs/concepts/durable-runs.md +43 -16
- package/docs/concepts/effects.md +50 -22
- package/docs/concepts/gates.md +95 -25
- package/docs/concepts/machines-and-workflows.md +5 -4
- package/docs/concepts/pools-and-sources.md +187 -11
- package/docs/concepts/secrets-and-trust.md +73 -33
- package/docs/concepts/the-menu.md +11 -0
- package/docs/concepts/workspaces.md +6 -5
- package/docs/get-started/a-model-decides.md +14 -13
- package/docs/get-started/an-agent-in-a-sandbox.md +43 -34
- package/docs/get-started/connect-a-model.md +1 -1
- package/docs/get-started/create-an-instance.md +17 -14
- package/docs/guides/add-tools-to-the-sandbox.md +55 -11
- 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 +24 -8
- 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/fix-a-failed-converge.md +18 -6
- 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 +9 -6
- package/docs/guides/look-inside-a-sandbox.md +101 -31
- package/docs/guides/open-the-console.md +63 -14
- package/docs/guides/read-a-conversation.md +225 -0
- package/docs/guides/run-a-chart-by-name.md +17 -16
- package/docs/guides/run-one-worker-per-item.md +15 -9
- package/docs/guides/set-an-agents-access-and-dials.md +2 -0
- 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 +1 -1
- package/docs/guides/watch-a-run.md +127 -121
- 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 +17 -7
- package/docs/llms.txt +81 -15
- package/docs/reference/authoring-surface/agent.md +1 -1
- package/docs/reference/authoring-surface/answer.md +1 -1
- package/docs/reference/authoring-surface/arg.md +1 -1
- 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 +1 -1
- 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 +1 -1
- 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 +1 -1
- package/docs/reference/authoring-surface/file.md +1 -1
- 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 +1 -1
- package/docs/reference/authoring-surface/isfailure.md +1 -1
- package/docs/reference/authoring-surface/isready.md +1 -1
- package/docs/reference/authoring-surface/jr2setup.md +13 -3
- package/docs/reference/authoring-surface/mcp.md +107 -0
- package/docs/reference/authoring-surface/open.md +5 -3
- package/docs/reference/authoring-surface/openbody.md +1 -1
- package/docs/reference/authoring-surface/paramsof.md +1 -1
- package/docs/reference/authoring-surface/pool.md +77 -9
- package/docs/reference/authoring-surface/push.md +1 -1
- package/docs/reference/authoring-surface/readyof.md +1 -1
- package/docs/reference/authoring-surface/reread.md +19 -0
- package/docs/reference/authoring-surface/secret.md +1 -1
- 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 +56 -1
- 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 +14 -1
- package/docs/reference/authoring-surface/type-agentmcpserver.md +54 -0
- package/docs/reference/authoring-surface/type-anyframepath.md +1 -1
- package/docs/reference/authoring-surface/type-anyworktreepath.md +1 -1
- package/docs/reference/authoring-surface/type-binding.md +1 -1
- 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-commandoutput.md +1 -1
- package/docs/reference/authoring-surface/type-customize.md +16 -1
- 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 +1 -1
- package/docs/reference/authoring-surface/type-effectbinding.md +12 -2
- package/docs/reference/authoring-surface/type-framepath.md +1 -1
- 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 +1 -1
- package/docs/reference/authoring-surface/type-httpoutput.md +1 -1
- package/docs/reference/authoring-surface/type-jr2config.md +37 -2
- package/docs/reference/authoring-surface/type-lateroutcome.md +1 -1
- 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-openbodydeclaration.md +1 -1
- package/docs/reference/authoring-surface/type-openbodyoutput.md +1 -1
- package/docs/reference/authoring-surface/type-poolnextinput.md +1 -1
- package/docs/reference/authoring-surface/type-poolspec.md +11 -6
- package/docs/reference/authoring-surface/type-pushoutput.md +1 -1
- 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 +1 -1
- 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-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-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 +16 -7
- 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 +1 -1
- package/docs/reference/authoring-surface/type-worktreefound.md +3 -3
- package/docs/reference/authoring-surface/type-worktreeinput.md +1 -1
- package/docs/reference/authoring-surface/type-worktreeoptions.md +1 -1
- package/docs/reference/authoring-surface/type-worktreeoutput.md +1 -1
- package/docs/reference/authoring-surface/type-worktreepath.md +1 -1
- package/docs/reference/authoring-surface/type-worktreeready.md +1 -1
- package/docs/reference/authoring-surface/type-worktreerefused.md +4 -4
- package/docs/reference/authoring-surface/workspace.md +1 -1
- package/docs/reference/authoring-surface/worktree.md +1 -1
- package/docs/reference/authoring-surface.md +88 -167
- package/docs/reference/cli.md +413 -74
- package/docs/reference/config.md +235 -2
- package/docs/reference/decisions/0002-duplex-streaming-actor.md +71 -11
- package/docs/reference/decisions/0005-sandbox-pod-composition.md +14 -10
- package/docs/reference/decisions/0006-agent-control-surface.md +4 -4
- 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 +9 -2
- package/docs/reference/decisions/0013-the-agent-reaches-its-machine-through-a-container-it-cannot-read.md +20 -14
- 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 +18 -14
- package/docs/reference/decisions/0017-pool-over-a-source-port.md +226 -12
- 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 +32 -18
- package/docs/reference/decisions/0021-workspace-continuity-is-a-lease-that-answers-back.md +14 -1
- 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 +116 -34
- package/docs/reference/decisions/0024-an-agents-turn-ends-with-the-state-that-asked-for-it.md +38 -37
- 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 +7 -6
- package/docs/reference/decisions/0028-what-an-agent-may-do-to-the-workspace-is-part-of-its-definition.md +23 -7
- 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 -18
- 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 +4 -3
- 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 +5 -4
- package/docs/reference/decisions/0049-a-machine-carries-its-parts-and-composes-by-invoke.md +19 -19
- package/docs/reference/decisions/0050-what-code-names-config-declares-what-the-cli-names-discovery-finds.md +6 -1
- 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 +7 -0
- package/docs/reference/decisions/0058-a-harness-answers-the-orchestrator-alone.md +13 -7
- package/docs/reference/decisions/0059-a-harness-holds-stand-ins-and-the-custodian-holds-the-keys.md +38 -30
- package/docs/reference/decisions/0062-jr2-briefs-the-agent-on-its-seat-never-on-its-task.md +64 -17
- package/docs/reference/decisions/0063-the-orchestrator-watches-the-cluster.md +2 -1
- 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 +51 -23
- package/docs/reference/decisions/0067-an-effect-is-an-actor-slot-and-runs-at-most-once-unless-marked-idempotent.md +94 -54
- package/docs/reference/decisions/0068-an-effector-holds-an-effects-secrets-and-signs-its-wire.md +101 -47
- 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 +17 -13
- 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/0075-a-machine-cuts-a-worktree-and-the-workspace-only-clones.md +4 -3
- package/docs/reference/decisions/0076-an-agents-control-credential-lives-only-where-no-workspace-code-runs.md +37 -10
- 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 +6 -4
- package/docs/reference/glossary.md +96 -42
- package/docs/reference/hooks.md +1077 -0
- package/docs/reference/http-api.md +976 -149
- package/docs/why.md +2 -1
- package/package.json +10 -3
- package/src/actor.ts +36 -10
- package/src/agent.ts +50 -0
- package/src/assembly-checks.ts +530 -4
- package/src/callers.ts +245 -0
- package/src/chart.ts +52 -7
- package/src/config.ts +550 -1
- package/src/conversations.ts +453 -0
- package/src/custodian.ts +8 -2
- package/src/customize.ts +143 -4
- package/src/dispatch-effect.ts +142 -26
- package/src/durability.ts +2 -0
- package/src/duration.ts +20 -0
- package/src/effect-checks.ts +2 -1
- package/src/effect.ts +60 -7
- package/src/effector-wire.ts +272 -27
- package/src/gate-brand.ts +16 -0
- package/src/gate.ts +634 -48
- package/src/harness-client.ts +10 -4
- package/src/held-secrets.ts +72 -23
- package/src/holds.ts +2 -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 +76 -38
- package/src/http.ts +889 -94
- package/src/index.ts +16 -5
- package/src/instance.ts +196 -26
- package/src/internal.ts +22 -3
- package/src/machine-doc.ts +26 -1
- package/src/mcp-effect.ts +424 -0
- package/src/mount-digest.ts +41 -7
- package/src/names.ts +64 -2
- package/src/notices.ts +138 -10
- package/src/open-body.ts +25 -11
- package/src/open-effect.ts +17 -4
- package/src/open.ts +4 -2
- package/src/parts.ts +87 -9
- package/src/party.ts +2 -1
- package/src/pick.ts +2 -2
- package/src/pool.ts +1142 -163
- package/src/registration.ts +203 -13
- package/src/run-host.ts +1509 -171
- package/src/run-list.ts +191 -0
- package/src/sandbox-kube.ts +53 -5
- package/src/secret-placement.ts +239 -33
- package/src/server.ts +53 -4
- package/src/setup.ts +72 -32
- package/src/snapshot-store.ts +565 -48
- package/src/steer.ts +111 -0
- package/src/stub-harness.ts +6 -2
- package/src/tokens.ts +263 -22
- package/src/wire.ts +17 -0
- package/src/workspace.ts +50 -6
- package/src/worktree.ts +3 -3
- 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
|
@@ -51,10 +51,15 @@ export default defineConfig({
|
|
|
51
51
|
```
|
|
52
52
|
|
|
53
53
|
- A pod claims a Held secret when its [`workspace()`](../reference/authoring-surface/workspace.md) lists the name under
|
|
54
|
-
`secrets`. A pod also claims the key of each provider that an Agent in that pod uses
|
|
54
|
+
`secrets`. A pod also claims the key of each provider that an Agent in that pod uses, and the `secret` of each MCP
|
|
55
|
+
server that an Agent in that pod names.
|
|
55
56
|
- The [Instance Harness](../reference/glossary.md#instance-harness) claims only the model keys of the Menu-only Agents
|
|
56
|
-
that it hosts.
|
|
57
|
-
- An Effect claims an Effect secret when it names it with [`secret()`](../reference/authoring-surface/secret.md).
|
|
57
|
+
that it hosts, and the secrets of the MCP servers that they name.
|
|
58
|
+
- An Effect claims an Effect secret when it names it with [`secret()`](../reference/authoring-surface/secret.md). An
|
|
59
|
+
`mcp` Effect claims the `secret` of its server for the
|
|
60
|
+
[Instance Effector](../reference/glossary.md#instance-effector).
|
|
61
|
+
- A [Hook](../reference/glossary.md#hook) that checks a signature with a shared secret (`mac`) claims that secret for
|
|
62
|
+
the Instance Effector, as an Effect does.
|
|
58
63
|
- One entry can be a Held secret and an Effect secret at the same time. The placement is a fact of each place that names
|
|
59
64
|
it, not of the entry.
|
|
60
65
|
- An entry that nothing names goes nowhere, and [`jr2 up`](../reference/cli.md#up) warns about it.
|
|
@@ -81,13 +86,17 @@ these things:
|
|
|
81
86
|
2. It replaces the Stand-in with the value, in the headers that the entry names.
|
|
82
87
|
3. It opens its own TLS connection to the host, and verifies the certificate of the host.
|
|
83
88
|
|
|
84
|
-
|
|
85
|
-
|
|
89
|
+
Two Held secrets can go to one host in one header, such as the tokens of two MCP servers of one service. The Custodian
|
|
90
|
+
chooses the value by the Stand-in that the header holds. The Custodian sends the traffic to each other host with no
|
|
91
|
+
change. It refuses a loopback, link-local or unspecified address. A request to a bound host that has no Stand-in in its
|
|
92
|
+
headers does not leave the pod.
|
|
86
93
|
|
|
87
94
|
These fields of an entry bind a Held secret. They do not place it:
|
|
88
95
|
|
|
89
96
|
- [`hosts`](../reference/config.md#secrets-hosts): the hosts that the value can go to. A known model key with one
|
|
90
|
-
default host, such as `ANTHROPIC_API_KEY`, can leave it out. It then goes only to the host of its provider.
|
|
97
|
+
default host, such as `ANTHROPIC_API_KEY`, can leave it out. It then goes only to the host of its provider. The
|
|
98
|
+
`secret` of an MCP server can leave it out too. It then goes only to the host of the server's URL, in the header
|
|
99
|
+
`authorization`.
|
|
91
100
|
- [`headers`](../reference/config.md#secrets-headers): the headers in which the Custodian replaces the Stand-in.
|
|
92
101
|
- [`paths`](../reference/config.md#secrets-paths): the path prefixes that the value can go to.
|
|
93
102
|
|
|
@@ -128,9 +137,9 @@ The Instance Harness has a token of its own for the Menu. It runs no program of
|
|
|
128
137
|
The Harness runs the [Turns](../reference/glossary.md#turn) of each Agent of the Sandbox. The Harness process itself
|
|
129
138
|
runs only jr2's code. Each other process in the Harness container runs confined with Landlock: each command of the
|
|
130
139
|
Agent's shell, and so the tests, the builds, git and its hooks; the search tools; the I/O of the read, write and edit
|
|
131
|
-
tools; jr2's own git; and each `command` Effect that names no Effect secret. Code that one Agent
|
|
132
|
-
run in a program of a different Agent, for example when a reviewer runs the tests of a coder. Thus
|
|
133
|
-
such program, and not only the programs of one Agent.
|
|
140
|
+
tools; jr2's own git; each stdio MCP server; and each `command` Effect that names no Effect secret. Code that one Agent
|
|
141
|
+
writes in `/work` can run in a program of a different Agent, for example when a reviewer runs the tests of a coder. Thus
|
|
142
|
+
jr2 confines each such program, and not only the programs of one Agent.
|
|
134
143
|
|
|
135
144
|
All these programs are in one Landlock domain. They can see, signal and trace each other, as the programs of one user on
|
|
136
145
|
a computer can. Thus a later shell command can find and stop a server that an earlier command started. When the process
|
|
@@ -212,46 +221,71 @@ make the Sandbox. [Give the cluster git credentials](../guides/give-the-cluster-
|
|
|
212
221
|
## The tokens
|
|
213
222
|
|
|
214
223
|
jr2 makes its own tokens. `jr2 up` makes the Instance token and the signing key the first time, and keeps them in the
|
|
215
|
-
`jr2-instance` Secret. Each
|
|
224
|
+
`jr2-instance` Secret. Each token of a pod comes from the signing key, so the Orchestrator stores no token for each pod.
|
|
216
225
|
|
|
217
|
-
| Token
|
|
218
|
-
|
|
|
219
|
-
| Instance token
|
|
220
|
-
|
|
|
221
|
-
|
|
|
222
|
-
|
|
|
223
|
-
|
|
|
226
|
+
| Token | Who holds it | What it lets the holder do |
|
|
227
|
+
| ------------------ | ----------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- |
|
|
228
|
+
| Instance token | You and the CLI, through the Kubernetes API | Everything: start a run, read its full state, answer a Gate, cancel a run, and the routes that no scope opens. |
|
|
229
|
+
| Named Caller token | A [Caller](../reference/glossary.md#caller) that has no access to the cluster, such as a CI job | The scopes that `callers.tokens` gives its name, for the Workflows that each scope names. |
|
|
230
|
+
| Control token | The Custodian of one Sandbox, as a file | Read the Menu and send the picks of the Agents in that Sandbox, for the Agent that the Harness names. |
|
|
231
|
+
| Fetch token | The Custodian of one Sandbox, as a file | Ask for a fetch of a Repo that the Sandbox mounts. |
|
|
232
|
+
| Harness bearer | The Orchestrator. The Harness holds only its SHA-256 digest. | Call the Harness in one pod: start a Turn, read it, stop it, set up a Worktree, and run a `command` Effect. |
|
|
233
|
+
| Effector key | The Orchestrator, and the Effector of one placement | Sign a request to that Effector, and sign its answer. |
|
|
224
234
|
|
|
225
235
|
- The Instance token enters no Harness pod. The CLI reads it from the `jr2-instance` Secret over the Kubernetes API.
|
|
226
|
-
Thus Kubernetes RBAC decides who holds it.
|
|
236
|
+
Thus Kubernetes RBAC decides who holds it. The CLI is the Caller `token/instance`. It also sends the name of your
|
|
237
|
+
Kubernetes user, and the run records it as the party that the Caller acts for.
|
|
238
|
+
- [`callers.tokens`](../reference/config.md#callers-tokens) declares each named Caller token. `jr2 up` makes its value
|
|
239
|
+
one time, in a Secret of its own, `jr2-caller-<name>`. The Orchestrator holds only the SHA-256 digest of each value,
|
|
240
|
+
in the `jr2-caller-digests` Secret, which it mounts. `jr2 caller token <name>` prints the value, which it reads over
|
|
241
|
+
the Kubernetes API.
|
|
242
|
+
- `jr2 caller rotate <name>` makes a new value. The Orchestrator reads the digests again when the mount changes. The
|
|
243
|
+
kubelet updates the mount in about one minute, and `jr2 caller rotate` waits for it. When it returns, the old value no
|
|
244
|
+
longer works. No pod restarts.
|
|
245
|
+
- When `callers.tokens` no longer declares a name, the next `jr2 up` deletes its Secret, and its value stops working.
|
|
227
246
|
- A control token or a fetch token cannot answer a Gate, and cannot speak for a different pod. The Orchestrator accepts
|
|
228
247
|
each one only on its own routes. Thus an Agent cannot approve its own work, and a Sandbox cannot send a pick for an
|
|
229
|
-
Agent in a different Sandbox.
|
|
248
|
+
Agent in a different Sandbox. No token of a pod is a Caller.
|
|
230
249
|
- A Harness can check its bearer, but it cannot make a bearer. Thus an Agent cannot drive a conversation in a different
|
|
231
250
|
pod.
|
|
232
251
|
|
|
252
|
+
[Callers and Hooks](callers-and-hooks.md) tells how jr2 knows a Caller, and what each scope opens.
|
|
253
|
+
[Give a Caller a scope](../guides/give-a-caller-a-scope.md) declares a named Caller token and uses it.
|
|
254
|
+
|
|
233
255
|
## Open observation, guarded control
|
|
234
256
|
|
|
235
|
-
Each route of the [HTTP API](../reference/http-api.md) is in one of
|
|
257
|
+
Each route of the [HTTP API](../reference/http-api.md) is in one of these access bands:
|
|
236
258
|
|
|
237
259
|
- [**Open**](../reference/http-api.md#band-open), with no token: the [Workflows](../reference/glossary.md#workflow), the
|
|
238
260
|
structure of each Machine, and the live runs of a Workflow with their states. An open route shows no context of a run,
|
|
239
261
|
and an [Emit](../reference/glossary.md#emit) shows only its type.
|
|
240
262
|
- [**Authenticated**](../reference/http-api.md#band-authenticated), with the Instance token or a token of a Sandbox: the
|
|
241
263
|
routes of the Agent's Menu and the fetch. A token of a Sandbox reaches only its own routes, in its own pod.
|
|
242
|
-
- [**
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
264
|
+
- [**A Caller with a scope**](../reference/http-api.md#band-guarded): the start of a run, the full state of a run, the
|
|
265
|
+
Gates, and cancel. Each route needs one scope of a Caller (`start`, `read`, `answer`, `cancel` or `steer`) for the
|
|
266
|
+
Workflow of the run. The Instance token has each scope for each Workflow. A named Caller token has the scopes that its
|
|
267
|
+
entry gives it. A token of a Sandbox is not a Caller.
|
|
268
|
+
- [**Instance token only**](../reference/http-api.md#band-instanceonly): the routes that no scope opens, such as a
|
|
269
|
+
runtime Chart, the report of the Repos and the log of a Hook (`GET /hooks/:name`).
|
|
270
|
+
- [**A Hook's verifier**](../reference/http-api.md#band-hook), with no bearer token: `POST /hooks/:name`. The verifier
|
|
271
|
+
of the Hook checks each delivery.
|
|
272
|
+
|
|
273
|
+
Thus the Console shows the Machines and the runs without a token. When you type a Caller's token in the Console, or log
|
|
274
|
+
in at an issuer that the Instance declares, the Console also shows the controls that the Caller's scopes open: start,
|
|
275
|
+
the Gates, cancel and steer. The Console keeps the credential in the session storage of the browser tab, and forgets it
|
|
276
|
+
when you close the tab. [Open the Console](../guides/open-the-console.md) tells how.
|
|
248
277
|
|
|
249
278
|
"Open" means open to each caller that can reach the Service of the Orchestrator: a port forward, a pod in the cluster,
|
|
250
279
|
or an ingress. The names of the states and the types of the Emits are open.
|
|
251
280
|
|
|
252
281
|
The Harness writes each Agent's conversation to its container log. The log has the prompts, the model's text and
|
|
253
|
-
thinking, its tool calls and the answers to its picks. It does not write the results of the Working tools
|
|
254
|
-
who can read the pod logs of the namespace can read these conversations.
|
|
282
|
+
thinking, its tool calls and the answers to its picks. It does not write the results of the Working tools or of the MCP
|
|
283
|
+
tools. Each person who can read the pod logs of the namespace can read these conversations.
|
|
284
|
+
|
|
285
|
+
The Orchestrator also keeps each conversation, with the same cut, for `runs.retain` (30 days by default). Thus the kept
|
|
286
|
+
copy has the same residual as the log: an answer to a pick can carry a held value that an upstream wrote into a
|
|
287
|
+
`command` output, or a secret in a form that the scrub does not catch. A Caller with `read` on the Workflow can read the
|
|
288
|
+
kept copy with `GET /runs/:runId/conversations`.
|
|
255
289
|
|
|
256
290
|
## Rules
|
|
257
291
|
|
|
@@ -264,7 +298,10 @@ who can read the pod logs of the namespace can read these conversations.
|
|
|
264
298
|
- A file that the Harness process reads, such as the one that `AWS_CONFIG_FILE` or `GOOGLE_APPLICATION_CREDENTIALS`
|
|
265
299
|
names in `harness.env`, cannot be in `/work`, `/tmp`, `/dev/shm` or `/home/jr2`: `jr2 up` refuses it. In another
|
|
266
300
|
folder, `jr2 up` gives a warning: make sure that the user of the Sandbox cannot write the file.
|
|
267
|
-
- A Held secret must name its `hosts`, unless it is a known model key with one default host
|
|
301
|
+
- A Held secret must name its `hosts`, unless it is a known model key with one default host, or the `secret` of an MCP
|
|
302
|
+
server.
|
|
303
|
+
- An MCP server with a `secret` has an `https://` URL. When an entry sets `hosts`, `headers` or `paths`, they must let
|
|
304
|
+
the Stand-in through to the URL of each server that names the entry.
|
|
268
305
|
- A name that a `workspace()` lists must be in the `secrets` list. A name that an Effect gives to `secret()` must be in
|
|
269
306
|
it too.
|
|
270
307
|
- An Effect secret has 8 characters or more.
|
|
@@ -285,22 +322,25 @@ who can read the pod logs of the namespace can read these conversations.
|
|
|
285
322
|
|
|
286
323
|
## Read next
|
|
287
324
|
|
|
325
|
+
- [Give a Caller a scope](../guides/give-a-caller-a-scope.md)
|
|
288
326
|
- [Use a local model](../guides/use-a-local-model.md)
|
|
289
327
|
- [Use a hosted provider or a gateway](../guides/use-a-hosted-provider.md)
|
|
290
328
|
- [Give the cluster git credentials](../guides/give-the-cluster-git-credentials.md)
|
|
291
329
|
- [Run a command or call a URL with an Effect](../guides/run-a-command-or-call-a-url.md)
|
|
330
|
+
- [Give an Agent MCP tools](../guides/give-an-agent-mcp-tools.md)
|
|
292
331
|
- [Open the Console](../guides/open-the-console.md)
|
|
293
|
-
- [Architecture](architecture.md) and [Effects](effects.md)
|
|
332
|
+
- [Callers and Hooks](callers-and-hooks.md), [Architecture](architecture.md) and [Effects](effects.md)
|
|
294
333
|
- The [`secrets`](../reference/config.md#secrets), [`git`](../reference/config.md#git) and
|
|
295
334
|
[`harness`](../reference/config.md#harness) fields of `jr2.config.ts`,
|
|
296
335
|
[`secret()`](../reference/authoring-surface/secret.md), and the [HTTP API](../reference/http-api.md)
|
|
297
336
|
- [ADR-0013](../reference/decisions/0013-the-agent-reaches-its-machine-through-a-container-it-cannot-read.md),
|
|
298
337
|
[ADR-0014](../reference/decisions/0014-observation-is-open-run-state-is-not.md),
|
|
299
338
|
[ADR-0023](../reference/decisions/0023-the-harness-prints-the-conversation.md),
|
|
300
|
-
[ADR-0032](../reference/decisions/0032-the-console-unlocks-with-
|
|
339
|
+
[ADR-0032](../reference/decisions/0032-the-console-unlocks-with-a-callers-credential.md),
|
|
301
340
|
[ADR-0051](../reference/decisions/0051-a-repo-is-a-slot-on-the-workspace-and-a-cache-on-the-node.md),
|
|
302
341
|
[ADR-0058](../reference/decisions/0058-a-harness-answers-the-orchestrator-alone.md),
|
|
303
342
|
[ADR-0059](../reference/decisions/0059-a-harness-holds-stand-ins-and-the-custodian-holds-the-keys.md),
|
|
304
343
|
[ADR-0068](../reference/decisions/0068-an-effector-holds-an-effects-secrets-and-signs-its-wire.md),
|
|
305
|
-
[ADR-0076](../reference/decisions/0076-an-agents-control-credential-lives-only-where-no-workspace-code-runs.md)
|
|
306
|
-
[ADR-0077](../reference/decisions/0077-jr2-requires-landlock-on-every-sandbox-node.md)
|
|
344
|
+
[ADR-0076](../reference/decisions/0076-an-agents-control-credential-lives-only-where-no-workspace-code-runs.md),
|
|
345
|
+
[ADR-0077](../reference/decisions/0077-jr2-requires-landlock-on-every-sandbox-node.md) and
|
|
346
|
+
[ADR-0079](../reference/decisions/0079-an-agent-holds-mcp-tools-a-machine-calls-them-as-an-effect-and-the-machine-is-the-approval.md)
|
|
@@ -21,6 +21,11 @@ and the tools block is first in it. A change to the tools block makes the provid
|
|
|
21
21
|
Thus jr2 keeps the Menu the same, and tells each [Turn](../reference/glossary.md#turn) which part of it the Turn can
|
|
22
22
|
pick now.
|
|
23
23
|
|
|
24
|
+
The Menu is the last part of the tools block. The [Working tools](../reference/glossary.md#working-tools) come first,
|
|
25
|
+
then the [MCP tools](../reference/glossary.md#mcp-tools), then the Menu. The model reads a Menu tool as
|
|
26
|
+
`mcp__jr2__<event>`, and an MCP tool as `mcp__<server>__<tool>`, where `<server>` is never `jr2`. Only a call of a Menu
|
|
27
|
+
tool is a pick. A call of an MCP tool acts on a service outside the Machine, and the Turn goes on after it.
|
|
28
|
+
|
|
24
29
|
## Where the Menu comes from
|
|
25
30
|
|
|
26
31
|
You do not write the Menu. `jr2Setup` makes the Menu from the Machine when you call `createMachine`:
|
|
@@ -336,6 +341,11 @@ Each event that a party sends carries its [Sender](../reference/glossary.md#send
|
|
|
336
341
|
[`Sender`](../reference/authoring-surface/type-sender.md)). The [Orchestrator](../reference/glossary.md#orchestrator)
|
|
337
342
|
writes it on each event that a party delivers. An event that the Machine sends to itself has no Sender.
|
|
338
343
|
|
|
344
|
+
A Gate's event also carries the [Caller](../reference/glossary.md#caller) that answered it: `via`, `name`, and
|
|
345
|
+
`onBehalfOf` when the Caller says that it acts for a person or a service. `checked` names the fields that jr2 verified.
|
|
346
|
+
jr2 always verifies `via` and `name`. It does not verify `onBehalfOf`, except for a Hook, whose signature covers it. So
|
|
347
|
+
do not use an unchecked `onBehalfOf` to decide who may do something.
|
|
348
|
+
|
|
339
349
|
Use the Sender when two parties can send the same event to one state. The guard
|
|
340
350
|
[`sentBy(id)`](../reference/authoring-surface/sentby.md) is true for an event from that party, and for an event with no
|
|
341
351
|
Sender. It is false for an event from a different party, so xstate tries the next transition. `sentBy` can only make a
|
|
@@ -344,6 +354,7 @@ transition refuse other senders. It never gives an event to a party. The positio
|
|
|
344
354
|
## Rules
|
|
345
355
|
|
|
346
356
|
- jr2 refuses a pick that is not on the Menu.
|
|
357
|
+
- A call of an MCP tool is not a pick. It does not move the Machine, and it does not end the Turn.
|
|
347
358
|
- A pick that is on the Menu but not in the Allowed picks moves nothing. Its answer gives the Allowed picks.
|
|
348
359
|
- While a pick is outstanding, or while the Agent's state is not at Rest, jr2 refuses each pick and delivers nothing.
|
|
349
360
|
This includes a pick that would end the Turn.
|
|
@@ -583,7 +583,8 @@ In a Workspace with no Repo:
|
|
|
583
583
|
- A `worktree()` needs a Repo Slot, a `push` needs a branch, and a `command` with an Effect secret runs on a commit.
|
|
584
584
|
Thus `jr2 up` refuses all three.
|
|
585
585
|
|
|
586
|
-
jr2 deletes `/work` with the Sandbox. Send what must stay before the body ends, as the example does with `upload`.
|
|
586
|
+
jr2 deletes `/work` with the Sandbox. Send what must stay before the body ends, as the example does with `upload`. The
|
|
587
|
+
secret `files` that `upload` names is an entry of the `secrets` list of `jr2.config.ts`, as each Effect secret is. A
|
|
587
588
|
Lost Sandbox has lost all of its work, because no commit was pushed.
|
|
588
589
|
|
|
589
590
|
## The pod
|
|
@@ -600,10 +601,10 @@ A Sandbox pod has two containers, and two more when the Machine needs them:
|
|
|
600
601
|
### The Sandbox Image
|
|
601
602
|
|
|
602
603
|
The [Sandbox Image](../reference/glossary.md#sandbox-image) is the image of the Harness container. It holds the tools
|
|
603
|
-
that an Agent's Working tools can use, and the shell that you get
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
604
|
+
that an Agent's Working tools can use, and the shell that you get with `jr2 workspace shell`. The image is yours. Its
|
|
605
|
+
floor is glibc, git and a writable `HOME`. [Add tools to the Sandbox](../guides/add-tools-to-the-sandbox.md) gives the
|
|
606
|
+
full list. jr2 adds nothing to the image. It mounts its own runtime into the pod at `/opt/jr2`, and starts the Harness
|
|
607
|
+
from there. Thus the `ENTRYPOINT` and the `CMD` of the image do not run.
|
|
607
608
|
|
|
608
609
|
`image` names it in one of two forms:
|
|
609
610
|
|
|
@@ -406,8 +406,7 @@ there:
|
|
|
406
406
|
```text
|
|
407
407
|
…
|
|
408
408
|
→ context kind-jr2 / namespace my-instance
|
|
409
|
-
run
|
|
410
|
-
→ active "triaging"
|
|
409
|
+
run f40a189e-b554-4310-b6e5-3b92c74e414e (triage) — attached
|
|
411
410
|
→ active "triaging"
|
|
412
411
|
→ active "clarify"
|
|
413
412
|
```
|
|
@@ -427,10 +426,10 @@ can show the same state. `jr2 run` does not return while the run waits. Keep it
|
|
|
427
426
|
> ```text
|
|
428
427
|
> …
|
|
429
428
|
> → context kind-jr2 / namespace my-instance
|
|
430
|
-
> run
|
|
429
|
+
> run 4eafe1a5-b45d-4613-8ae3-4c85b26eeb0c (triage) — attached
|
|
431
430
|
> → active "triaging"
|
|
432
431
|
> → done "accepted"
|
|
433
|
-
> {"runId":"
|
|
432
|
+
> {"runId":"4eafe1a5-b45d-4613-8ae3-4c85b26eeb0c","workflow":"triage","instanceId":"d4daa575-f8ac-4ba9-af2e-406084adbd89","startedAt":"2026-11-06T19:24:22.161Z","startedBy":{"kind":"caller","via":"token","name":"instance","onBehalfOf":"kubernetes-admin"},"status":"done","value":"accepted","context":{"request":"Add a --version flag to the CLI. It prints the installed version and exits.","exchange":[],"summary":"Add a --version flag to the CLI that prints the installed version and exits."},"children":[],"waiting":[],"held":[],"assembly":"9ff0a4d3c5da","output":{"outcome":"accepted","summary":"Add a --version flag to the CLI that prints the installed version and exits."}}
|
|
434
433
|
> ```
|
|
435
434
|
>
|
|
436
435
|
> Your run id and your [Instance ID](../reference/glossary.md#instance-id) are different, and so is the `summary`, the
|
|
@@ -444,14 +443,15 @@ The Gate holds the question of the Agent in its `meta`. In the send terminal, ru
|
|
|
444
443
|
jr2 status <run id>
|
|
445
444
|
```
|
|
446
445
|
|
|
447
|
-
`<run id>` is the run id that `jr2 run` printed. You can give its first 4 characters or more, such as `
|
|
446
|
+
`<run id>` is the run id that `jr2 run` printed. You can give its first 4 characters or more, such as `f40a189e`.
|
|
448
447
|
[`jr2 status`](../reference/cli.md#status) prints the status of the run as one line of JSON. The Gate is in `gates`, at
|
|
449
448
|
the end:
|
|
450
449
|
|
|
451
450
|
```text
|
|
452
451
|
…
|
|
453
452
|
→ context kind-jr2 / namespace my-instance
|
|
454
|
-
{"runId":"
|
|
453
|
+
{"runId":"f40a189e-b554-4310-b6e5-3b92c74e414e","workflow":"triage","instanceId":"6a6fb1c4-d6d8-4867-a51b-693c0772cc7b","startedAt":"2026-11-06T19:23:30.814Z","startedBy":{"kind":"caller","via":"token","name":"instance","onBehalfOf":"kubernetes-admin"},"status":"active","value":"clarify","context":{"request":"People keep asking what version they are running.","exchange":[{"question":"Where should the version number be displayed to users (e.g., a specific command like `--version`, an 'About' screen, or a startup log message)?"}]},"children":[],"waiting":[],"held":[],"assembly":"9ff0a4d3c5da","gates":[{"gate":"clarify","path":["clarify"],"accepts":[{"name":"answer","description":"Answer the triager's question. It triages the request again with the answer in hand.","input":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"info":{"type":"string","description":"The answer, in prose."}},"required":["info"],"additionalProperties":false}}],"acceptsNow":["answer"],"meta":{"question":"Where should the version number be displayed to users (e.g., a specific command like `--version`, an 'About' screen, or a startup log message)?"}}]}
|
|
454
|
+
started by: token/instance on behalf of kubernetes-admin
|
|
455
455
|
```
|
|
456
456
|
|
|
457
457
|
The `question` is in the words of the model, so your question is different. Your instance id is different too. The Gate
|
|
@@ -470,7 +470,7 @@ jr2 send <run id> --gate clarify --event answer --input '{"info":"Add a --versio
|
|
|
470
470
|
```text
|
|
471
471
|
…
|
|
472
472
|
→ context kind-jr2 / namespace my-instance
|
|
473
|
-
delivered answer to gate "clarify" on
|
|
473
|
+
delivered answer to gate "clarify" on f40a189e-b554-4310-b6e5-3b92c74e414e
|
|
474
474
|
```
|
|
475
475
|
|
|
476
476
|
The run goes back to `triaging`, and the Agent reads your answer. Look at the first terminal. When the Agent picks
|
|
@@ -481,7 +481,7 @@ The run goes back to `triaging`, and the Agent reads your answer. Look at the fi
|
|
|
481
481
|
→ active "triaging"
|
|
482
482
|
→ active "triaging"
|
|
483
483
|
→ done "accepted"
|
|
484
|
-
{"runId":"
|
|
484
|
+
{"runId":"f40a189e-b554-4310-b6e5-3b92c74e414e","workflow":"triage","instanceId":"6a6fb1c4-d6d8-4867-a51b-693c0772cc7b","startedAt":"2026-11-06T19:23:30.814Z","startedBy":{"kind":"caller","via":"token","name":"instance","onBehalfOf":"kubernetes-admin"},"status":"done","value":"accepted","context":{"request":"People keep asking what version they are running.","exchange":[{"question":"Where should the version number be displayed to users (e.g., a specific command like `--version`, an 'About' screen, or a startup log message)?","info":"Add a --version flag to the CLI. It prints the installed version and exits."}],"summary":"Add a --version flag to the CLI that prints the installed version and exits."},"children":[],"waiting":[],"held":[],"answers":[{"gate":"clarify","type":"answer","at":"2026-11-06T19:24:02.957Z","answeredBy":{"via":"token","name":"instance","onBehalfOf":"kubernetes-admin"}}],"assembly":"9ff0a4d3c5da","output":{"outcome":"accepted","summary":"Add a --version flag to the CLI that prints the installed version and exits."}}
|
|
485
485
|
```
|
|
486
486
|
|
|
487
487
|
`summary` is the request as the model wrote it again, in one sentence. Your summary is different. The `output` of the
|
|
@@ -502,24 +502,25 @@ This request does not say what is wrong. The run goes to `clarify` and waits, as
|
|
|
502
502
|
```text
|
|
503
503
|
…
|
|
504
504
|
→ context kind-jr2 / namespace my-instance
|
|
505
|
-
run
|
|
505
|
+
run 7e6c9deb-ca65-4103-b517-abf6b0028aff (triage) — attached
|
|
506
506
|
→ active "triaging"
|
|
507
507
|
→ active "clarify"
|
|
508
508
|
```
|
|
509
509
|
|
|
510
|
-
`
|
|
510
|
+
`7e6c9deb-ca65-4103-b517-abf6b0028aff` is the id of the second run. Your run id is different. If the Agent picks
|
|
511
511
|
`accept` or `reject`, start the run again.
|
|
512
512
|
|
|
513
513
|
## Answer from the Console
|
|
514
514
|
|
|
515
|
-
Open `http://localhost:4000` in your browser. If the
|
|
516
|
-
step. If the
|
|
515
|
+
Open `http://localhost:4000` in your browser. If the nav shows `as token/instance` and the badge `live`, go to the next
|
|
516
|
+
step. If the nav shows the `Caller token` box, get the token. In the send terminal, run:
|
|
517
517
|
|
|
518
518
|
```sh
|
|
519
519
|
kubectl -n my-instance get secret jr2-instance -o jsonpath='{.data.JR2_INSTANCE_TOKEN}' | base64 -d
|
|
520
520
|
```
|
|
521
521
|
|
|
522
|
-
Type the token in the `
|
|
522
|
+
Type the token in the `Caller token` box. Push Enter. The badge after the box shows `live`, and the nav shows
|
|
523
|
+
`as token/instance`.
|
|
523
524
|
|
|
524
525
|
Click `triage` in the Fleet rail on the left. The center shows the Machine of `triage`, with its states and transitions.
|
|
525
526
|
Click the run in the rail. The Console lights the state of the run, `clarify`.
|
|
@@ -137,7 +137,7 @@ seats: workflow "task" — who may send what, per state (ADR-0015)
|
|
|
137
137
|
task.working agent:coder: [finish]
|
|
138
138
|
task.review gate: [approve, request_changes]
|
|
139
139
|
…
|
|
140
|
-
sandbox image "default": building jr2-sandbox-my-instance-default:
|
|
140
|
+
sandbox image "default": building jr2-sandbox-my-instance-default:5e601a543032-amd64
|
|
141
141
|
no USER declared — the pod's uid-1000 fallback applies
|
|
142
142
|
kind load → cluster "jr2"
|
|
143
143
|
…
|
|
@@ -161,7 +161,7 @@ jr2 run task --input '{"prompt":"In docs/site/tutorial/greet, one test fails. Fi
|
|
|
161
161
|
```text
|
|
162
162
|
…
|
|
163
163
|
→ context kind-jr2 / namespace my-instance
|
|
164
|
-
run
|
|
164
|
+
run 79b90360-cdbf-4538-8611-d52da1b8b914 (task) — attached
|
|
165
165
|
→ active "placing"
|
|
166
166
|
→ active "provisioning"
|
|
167
167
|
→ active "attaching"
|
|
@@ -187,8 +187,9 @@ the Gate. Its `gate` is `body.review`, and the line ends with its `meta`. After
|
|
|
187
187
|
for each Worktree that the run cut:
|
|
188
188
|
|
|
189
189
|
```text
|
|
190
|
-
…"gate":"body.review",…,"meta":{"summary":"Fixed
|
|
191
|
-
|
|
190
|
+
…"gate":"body.review",…,"meta":{"summary":"Fixed the failing \"trims the name\" test in docs/site/tutorial/greet. The bug was in src/greet.js where the name argument wasn't being trimmed, causing `greet([\" ada \"])` to output `'hello, ada '` instead of `'hello, ada'`. Added `.trim()` to the name extraction line. All 6 tests now pass.","branch":"jr2/task-1e805d38-68ac-4ec9-acc8-fc5ce6a68f6b","worktree":"/work/target/task"}}]}
|
|
191
|
+
started by: token/instance on behalf of kubernetes-admin
|
|
192
|
+
worktree: /work/target/task (target), branch jr2/task-1e805d38-68ac-4ec9-acc8-fc5ce6a68f6b
|
|
192
193
|
```
|
|
193
194
|
|
|
194
195
|
Run the command again until `gates` holds the Gate.
|
|
@@ -198,7 +199,7 @@ Run the command again until `gates` holds the Gate.
|
|
|
198
199
|
- `worktree` is the folder in the Sandbox that holds the branch. It is
|
|
199
200
|
[the Worktree](../reference/glossary.md#worktree).
|
|
200
201
|
|
|
201
|
-
Copy `branch` and `worktree` from your output. The part after `jr2/task-`, here `
|
|
202
|
+
Copy `branch` and `worktree` from your output. The part after `jr2/task-`, here `1e805d38-68ac-4ec9-acc8-fc5ce6a68f6b`,
|
|
202
203
|
is the [Instance ID](../reference/glossary.md#instance-id) of the run. `jr2 status` prints it as `instanceId`. It is not
|
|
203
204
|
the run id. Do not make the branch name from the run id. With the Instance token, the drawer of the
|
|
204
205
|
[Console](../reference/glossary.md#console) shows the same `meta`.
|
|
@@ -208,27 +209,30 @@ If `meta` has a `reason` and no `summary`, the [Turn](../reference/glossary.md#t
|
|
|
208
209
|
|
|
209
210
|
## Find the Sandbox
|
|
210
211
|
|
|
211
|
-
|
|
212
|
-
line `run <run id> (task) — attached` in the first terminal:
|
|
212
|
+
List the Workspaces of the run with [`jr2 workspace ls`](../reference/cli.md#workspace-ls):
|
|
213
213
|
|
|
214
214
|
```sh
|
|
215
|
-
|
|
215
|
+
jr2 workspace ls <run id>
|
|
216
216
|
```
|
|
217
217
|
|
|
218
218
|
```text
|
|
219
|
-
|
|
220
|
-
|
|
219
|
+
…
|
|
220
|
+
→ context kind-jr2 / namespace my-instance
|
|
221
|
+
WORKSPACE SANDBOX WORKFLOW PHASE AGE RUN
|
|
222
|
+
79b90360/x:23 ws-79b90360-x-23-1gex8om task Ready 81s held
|
|
221
223
|
```
|
|
222
224
|
|
|
223
|
-
`
|
|
224
|
-
|
|
225
|
+
`79b90360/x:23` is the handle of the Workspace: the first 8 characters of the run id, then the path of the Workspace in
|
|
226
|
+
the run. `ws-79b90360-x-23-1gex8om` is the name of the Sandbox. The name of the Sandbox is a handle too. Your values are
|
|
227
|
+
different. The commands below write the handle as `<workspace>`. `held` tells that the run holds the Sandbox.
|
|
225
228
|
|
|
226
229
|
## Look inside the Sandbox
|
|
227
230
|
|
|
228
|
-
|
|
231
|
+
Open a shell in the Sandbox with [`jr2 workspace shell`](../reference/cli.md#workspace-shell). The shell runs as the
|
|
232
|
+
Agent's tools run: in the same container, with the same files and the same limits:
|
|
229
233
|
|
|
230
234
|
```sh
|
|
231
|
-
|
|
235
|
+
jr2 workspace shell <workspace>
|
|
232
236
|
```
|
|
233
237
|
|
|
234
238
|
In the Sandbox, go to the fixture in the Worktree. Then run its tests. `<worktree>` is the `worktree` that you copied:
|
|
@@ -239,12 +243,12 @@ node --test
|
|
|
239
243
|
```
|
|
240
244
|
|
|
241
245
|
```text
|
|
242
|
-
✔ greets the world by default (1.
|
|
243
|
-
✔ greets a name (0.
|
|
244
|
-
✔ shouts (0.
|
|
245
|
-
✔ trims the name (0.
|
|
246
|
-
✔ prints help (
|
|
247
|
-
✔ refuses an unknown flag (0.
|
|
246
|
+
✔ greets the world by default (1.208079ms)
|
|
247
|
+
✔ greets a name (0.113673ms)
|
|
248
|
+
✔ shouts (0.070218ms)
|
|
249
|
+
✔ trims the name (0.054069ms)
|
|
250
|
+
✔ prints help (0.712678ms)
|
|
251
|
+
✔ refuses an unknown flag (0.242712ms)
|
|
248
252
|
ℹ tests 6
|
|
249
253
|
ℹ suites 0
|
|
250
254
|
ℹ pass 6
|
|
@@ -252,18 +256,18 @@ node --test
|
|
|
252
256
|
ℹ cancelled 0
|
|
253
257
|
ℹ skipped 0
|
|
254
258
|
ℹ todo 0
|
|
255
|
-
ℹ duration_ms
|
|
259
|
+
ℹ duration_ms 49.489997
|
|
256
260
|
```
|
|
257
261
|
|
|
258
262
|
Your times are different. Read the commits of the coder. The branch starts at the release tag, so the commits after the
|
|
259
263
|
tag are the commits of the coder:
|
|
260
264
|
|
|
261
265
|
```sh
|
|
262
|
-
git log --oneline v<version>..HEAD
|
|
266
|
+
git --no-pager log --oneline v<version>..HEAD
|
|
263
267
|
```
|
|
264
268
|
|
|
265
269
|
```text
|
|
266
|
-
|
|
270
|
+
8afef7d (HEAD -> jr2/task-1e805d38-68ac-4ec9-acc8-fc5ce6a68f6b) fix: trim name in greet to handle leading/trailing whitespace
|
|
267
271
|
```
|
|
268
272
|
|
|
269
273
|
Each line is one commit. The commit ids and the messages come from the model. The author of each commit is
|
|
@@ -285,7 +289,7 @@ jr2 send <run id> --gate body.review --event request_changes --input '{"notes":"
|
|
|
285
289
|
```text
|
|
286
290
|
…
|
|
287
291
|
→ context kind-jr2 / namespace my-instance
|
|
288
|
-
delivered request_changes to gate "body.review" on
|
|
292
|
+
delivered request_changes to gate "body.review" on 79b90360-cdbf-4538-8611-d52da1b8b914
|
|
289
293
|
```
|
|
290
294
|
|
|
291
295
|
The coder continues the same conversation, with your notes as its next prompt. The Sandbox and the branch stay. Run
|
|
@@ -294,10 +298,10 @@ The coder continues the same conversation, with your notes as its next prompt. T
|
|
|
294
298
|
## Push the branch
|
|
295
299
|
|
|
296
300
|
`task` does not push, and the Agent has no credential to push with. While the run waits at `review`, you push the branch
|
|
297
|
-
from the Sandbox.
|
|
301
|
+
from the Sandbox. Open a shell in the Sandbox again:
|
|
298
302
|
|
|
299
303
|
```sh
|
|
300
|
-
|
|
304
|
+
jr2 workspace shell <workspace>
|
|
301
305
|
```
|
|
302
306
|
|
|
303
307
|
In the Sandbox, go to the Worktree. Then push the branch. `<branch>` is the `branch` that you copied:
|
|
@@ -314,7 +318,7 @@ Username for 'https://github.com': <you>
|
|
|
314
318
|
Password for 'https://<you>@github.com':
|
|
315
319
|
…
|
|
316
320
|
To https://github.com/<you>/jr2.git
|
|
317
|
-
* [new branch] jr2/task-
|
|
321
|
+
* [new branch] jr2/task-1e805d38-68ac-4ec9-acc8-fc5ce6a68f6b -> jr2/task-1e805d38-68ac-4ec9-acc8-fc5ce6a68f6b
|
|
318
322
|
```
|
|
319
323
|
|
|
320
324
|
`origin` fetches through the Repo cache of the node, and pushes to your fork. Open your fork on GitHub to see the
|
|
@@ -339,7 +343,7 @@ jr2 send <run id> --gate body.review --event approve
|
|
|
339
343
|
```text
|
|
340
344
|
…
|
|
341
345
|
→ context kind-jr2 / namespace my-instance
|
|
342
|
-
delivered approve to gate "body.review" on
|
|
346
|
+
delivered approve to gate "body.review" on 79b90360-cdbf-4538-8611-d52da1b8b914
|
|
343
347
|
```
|
|
344
348
|
|
|
345
349
|
In the first terminal, `jr2 run` prints the end of the run, then the final status as one line of JSON, and stops:
|
|
@@ -348,21 +352,25 @@ In the first terminal, `jr2 run` prints the end of the run, then the final statu
|
|
|
348
352
|
…
|
|
349
353
|
→ active "teardown"
|
|
350
354
|
→ done "done"
|
|
351
|
-
{"runId":"
|
|
355
|
+
{"runId":"79b90360-cdbf-4538-8611-d52da1b8b914","workflow":"task",…,"output":{"branch":"jr2/task-1e805d38-68ac-4ec9-acc8-fc5ce6a68f6b"},"worktrees":[{"slot":"target","path":"/work/target/task","branch":"jr2/task-1e805d38-68ac-4ec9-acc8-fc5ce6a68f6b"}]}
|
|
352
356
|
```
|
|
353
357
|
|
|
354
358
|
## Make sure that the Sandbox is gone
|
|
355
359
|
|
|
356
|
-
|
|
360
|
+
List the Workspaces of the run again:
|
|
357
361
|
|
|
358
362
|
```sh
|
|
359
|
-
|
|
363
|
+
jr2 workspace ls <run id>
|
|
360
364
|
```
|
|
361
365
|
|
|
362
366
|
```text
|
|
363
|
-
|
|
367
|
+
…
|
|
368
|
+
→ context kind-jr2 / namespace my-instance
|
|
369
|
+
WORKSPACE SANDBOX WORKFLOW PHASE AGE RUN
|
|
364
370
|
```
|
|
365
371
|
|
|
372
|
+
The list has no row, because the run removed its Sandbox.
|
|
373
|
+
|
|
366
374
|
## What happened
|
|
367
375
|
|
|
368
376
|
- `task` is a Machine in a Workspace. The run made a Sandbox for the Workspace and cloned your fork into it. It cut the
|
|
@@ -373,8 +381,9 @@ No resources found in my-instance namespace.
|
|
|
373
381
|
- The `review` Gate kept the Sandbox while the run waited. `request_changes` sent the coder back to the same
|
|
374
382
|
conversation. `approve` ended the run, and the end of the Workspace removed the Sandbox. See
|
|
375
383
|
[Gates](../concepts/gates.md) and [ADR-0012](../reference/decisions/0012-workspace-wrapper-machine.md).
|
|
376
|
-
- You used `
|
|
377
|
-
gives the same
|
|
384
|
+
- You used `jr2 workspace shell` to go into the Sandbox. The shell runs as the Agent runs, so it cannot read the
|
|
385
|
+
credential of the Agent. The guide [Look inside a Sandbox](../guides/look-inside-a-sandbox.md) gives the same
|
|
386
|
+
commands.
|
|
378
387
|
- You pushed by hand, because `task` does not push. On the next page, a Machine pushes the branch with an
|
|
379
388
|
[Effect](../reference/glossary.md#effect).
|
|
380
389
|
|
|
@@ -183,7 +183,7 @@ jr2 up
|
|
|
183
183
|
→ .env: ANTHROPIC_API_KEY
|
|
184
184
|
jr2 up — instance "my-instance" → context kind-jr2 / namespace my-instance
|
|
185
185
|
…
|
|
186
|
-
warning: secrets[0] (ANTHROPIC_API_KEY) is named by nothing; goes nowhere — no workspace() lists it, no Agent's provider reads it, and no Effect names it (ADR-0059, ADR-0068)
|
|
186
|
+
warning: secrets[0] (ANTHROPIC_API_KEY) is named by nothing; goes nowhere — no workspace() lists it, no Agent's provider reads it, and no Effect or Hook names it (ADR-0059, ADR-0068)
|
|
187
187
|
…
|
|
188
188
|
converged — `jr2 run <workflow>` when ready
|
|
189
189
|
```
|