@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
|
@@ -48,9 +48,13 @@ composition and does not replace it. The two uses stay two mechanisms.
|
|
|
48
48
|
the url and the token together, one Open part, with `customize(m, { effects: { task: { target: { url, token } } } })`
|
|
49
49
|
([ADR-0054](0054-the-kit-ships-machines-and-a-shipped-machine-leaves-its-parts-open.md)); `secret(open)` inside a
|
|
50
50
|
target is refused, since the whole target is the part. Another Instance may run another Kit version, so the HTTP door
|
|
51
|
-
is the only contract there. The token is the Instance
|
|
52
|
-
([ADR-
|
|
53
|
-
|
|
51
|
+
is the only contract there. The token is any Caller's credential of the other Instance with `start` for the callee
|
|
52
|
+
Workflow ([ADR-0078](0078-a-caller-comes-from-one-authenticator-seam-and-acts-within-its-scopes.md)): a named Caller
|
|
53
|
+
token made for this, or that Instance's Instance token. A `wait` also polls `GET /runs/<id>`, so its token needs
|
|
54
|
+
`read` for that Workflow too. The start carries the first Caller of the calling run's `startedBy` chain as
|
|
55
|
+
`onBehalfOf`, in the header `jr2-on-behalf-of`, which the other Instance records and does not check: that Caller's own
|
|
56
|
+
`onBehalfOf`, else the name that jr2 shows, else `<via>/<name>`. A chain that jr2 started, or a text that is not
|
|
57
|
+
printable ASCII of at most 256 characters, sends no claim.
|
|
54
58
|
- **Two settlements, `started` by default, and every outcome is output.** `{ outcome: "started", run }` settles when the
|
|
55
59
|
Orchestrator accepts the run; the watcher goes round again. `wait: true` settles
|
|
56
60
|
`{ outcome: "settled", run, status, output }` when that run ends, `status` in the store's own words (`done`, `failed`,
|
|
@@ -69,12 +73,12 @@ composition and does not replace it. The two uses stay two mechanisms.
|
|
|
69
73
|
a DELETE of the Effect ends that poll and never touches the run. No callback from the callee: a callback needs the
|
|
70
74
|
callee to hold its caller's address and a token for it, which inverts the trust. A door refusal is OUTPUT,
|
|
71
75
|
`{ outcome: "refused", status, report }`, with the door's status — 400 for bad input, 404 for a name the current
|
|
72
|
-
Assembly lacks, 409 for an unrunnable named Chart
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
`
|
|
77
|
-
|
|
76
|
+
Assembly lacks, 409 for an unrunnable named Chart, 422 for a Chart the door refuses, 413 for a start over the bytes an
|
|
77
|
+
Effector reads, 0 when the Effector refused it before anything was sent — as a Chart refusal is
|
|
78
|
+
([ADR-0070](0070-a-machine-lends-its-parts-to-a-chart.md)): the body may have come from a model, and the report must
|
|
79
|
+
be able to reach it through the Chain. A target no replica could reach is `{ outcome: "unreachable" }`, output, as an
|
|
80
|
+
`http` Effect's is (ADR-0067): nothing was started. The invoke's error is kept for defects: no run host or Effector,
|
|
81
|
+
input that fails the slot's schema (when no run has the key, below), a refused or malformed wire.
|
|
78
82
|
- **The two runs are independent.** Cancelling the caller never cancels the callee; the caller's end never ends it;
|
|
79
83
|
leaving the state stops a wait and never the run; the callee's Workspaces are its own. Temporal's parent-close policy
|
|
80
84
|
(`TERMINATE` by default, `REQUEST_CANCEL`, `ABANDON`) exists because a child there is both a run and a child, and its
|
|
@@ -89,7 +93,8 @@ composition and does not replace it. The two uses stay two mechanisms.
|
|
|
89
93
|
`dispatched [{ slot, run, at }]`, the chain's other direction. `jr2 runs` carries `dispatchedBy` after the id,
|
|
90
94
|
`jr2 status` prints `dispatched by:` and `dispatched:` lines, and the Console shows both. The word is **dispatched
|
|
91
95
|
by**. The callee reads nothing of its caller from its input: a Machine that wants to tell its callee something passes
|
|
92
|
-
it as input like any caller.
|
|
96
|
+
it as input like any caller. A local dispatch records its caller's run as the callee's `startedBy`,
|
|
97
|
+
`{ kind: "run", run, slot }`, and `jr2 status` walks that chain to the first Caller (ADR-0078).
|
|
93
98
|
- **A chain of dispatches is unbounded.** A run may dispatch a Workflow that dispatches another, or itself: a run that
|
|
94
99
|
dispatches its own successor and ends is Temporal's continue-as-new, the honest way to keep a watcher's snapshot
|
|
95
100
|
small, and a depth ceiling would refuse it. A runaway chain is a resource problem the cluster owner's quota and
|
|
@@ -100,24 +105,45 @@ composition and does not replace it. The two uses stay two mechanisms.
|
|
|
100
105
|
key, out of band — the `jr2-dispatched-by` header, the `dispatchedBy` record as JSON, never a body field the callee's
|
|
101
106
|
door would have to reserve — and `POST /workflows/<name>/runs` asks the key before anything else, so a re-sent start
|
|
102
107
|
answers its run even when the name would be refused now: 201 with the run for a new one, 200 with
|
|
103
|
-
`{ runId, instanceId, existing: true }` for a repeat,
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
the
|
|
119
|
-
|
|
120
|
-
|
|
108
|
+
`{ runId, instanceId, existing: true }` for a repeat, 200 with `{ existing: false }` for a key-only ask (below) with
|
|
109
|
+
no run under the key, 400 when a header does not parse, and 500, never 404, for any other throw, since a foreign
|
|
110
|
+
caller reads a 404 as "nothing was started" (ADR-0033 as amended). **The key is scoped to the callee Workflow**: the
|
|
111
|
+
store finds a key with the Workflow's name, so the same key in two Workflows is two runs, and a key never answers with
|
|
112
|
+
a run of another Workflow. A key answers `existing` while its run's row lives, in any status: live, and for
|
|
113
|
+
`runs.retain` after it ends ([ADR-0065](0065-a-persist-survives-a-crash-and-history-is-kept-for-a-set-time.md)). A
|
|
114
|
+
retry after a failure is then a person's act, not a re-sent start's. The Effect checks the key before it checks its
|
|
115
|
+
input against the slot's schema, in-process and on the foreign path, as the door does: a start sent again across a
|
|
116
|
+
change of the callee's door answers `existing`, not an error. In-process it asks the run host for the key before it
|
|
117
|
+
reads the input, within the slot's bound. On the foreign path, a body that the slot's schema refuses is never sent:
|
|
118
|
+
the start is a **key-only ask**, the header `jr2-key-only: true` beside `jr2-dispatched-by` and no body, out of band
|
|
119
|
+
as the key is. The door keeps its order: the scope check (ADR-0078), then the key. With a run under the key it answers
|
|
120
|
+
`existing`, as for any start; with none it starts nothing and answers 200 with `{ existing: false }`, which a foreign
|
|
121
|
+
caller cannot read as a refused name (404) or a defect (5xx). The Instance Effector settles that answer as `absent`,
|
|
122
|
+
an outcome of the wire alone, and the Effect makes it the slot's schema refusal, the invoke's error. So input that
|
|
123
|
+
fails the slot's schema starts nothing on either path, and a run that its key already started is answered on both. A
|
|
124
|
+
body that the slot's schema takes goes as before, in one request. This is the same for a first send and for a send
|
|
125
|
+
again (a restore, a retry): a Pool's hand-over is a first send of a new run's Effect under a key that may already name
|
|
126
|
+
a run of a callee whose door changed. A `wait` sent again under a key that answers `existing` follows that run, and
|
|
127
|
+
settles when it ends. **A Pool's worker sends its `itemId` as the key** ([ADR-0017](0017-pool-over-a-source-port.md)),
|
|
128
|
+
so a Pool's hand-over re-attaches to each live run. An author's own key (`dispatch({ key })`) is not offered now; to
|
|
129
|
+
add it later breaks nothing. The key lives in the callee's blob (a Pool's `dispatchedBy.key`, else
|
|
130
|
+
`dispatchedBy.effect`), and the store copies it and the Workflow into columns of their own (`dispatch_effect`,
|
|
131
|
+
`dispatch_workflow`) at every save and indexes the pair, not an expression index over `json_extract`: SQLite's JSON
|
|
132
|
+
parser refuses a blob nested about a thousand deep, and such an index would fail that row's save and every later open
|
|
133
|
+
of the volume. A run restore marks `lost` keeps its row and its blob, so its key keeps answering; the sweep of rows
|
|
134
|
+
older than `runs.retain` ([ADR-0065](0065-a-persist-survives-a-crash-and-history-is-kept-for-a-set-time.md)) removes
|
|
135
|
+
the key with the row, and a re-send after it starts a new run: known, and not guarded. In-process the ledger is
|
|
136
|
+
consulted directly, through the same start under the same key, with the starts in flight held so two arrivals of one
|
|
137
|
+
key before the first save are one run. So a dispatch is idempotent whatever its author writes: its intent row says
|
|
138
|
+
`idempotent: true`, a restore that cannot tell whether its start arrived sends it again under its key with what is
|
|
139
|
+
left of the bound, the Instance Effector sends a start whose answer was lost again under its key with backoff until
|
|
140
|
+
the bound, and the Effector's rollout grace is never stretched by a dispatch's wait. Once the answer names the run,
|
|
141
|
+
the intent row carries it, the Effector's `running` state carries it on the wire, and a restore with it starts
|
|
142
|
+
nothing: it settles `started` at once, or resumes the wait. Without it a watcher double-starts a run after a restart,
|
|
143
|
+
which a human notices as two pull requests. What it does not guard: a door at a Kit version before this decision
|
|
144
|
+
ignores the header, so a re-send to it starts a second run, and a door that knows the key but not the key-only ask
|
|
145
|
+
reads one as a start with no body; neither the Effector nor the preflight can tell. A capability check is named and
|
|
146
|
+
deferred.
|
|
121
147
|
- **`jr2 up` checks what it can see, and the severity follows who owns both sides.** For a same-Instance name the walk
|
|
122
148
|
resolves it in the Assembly and REFUSES a miss, naming the fix: on the host, among the Machines and the Chart files,
|
|
123
149
|
and a slashed name whose wrapper exists but whose Chart the host cannot see is a warning there, since a runtime Chart
|
|
@@ -172,7 +198,7 @@ composition and does not replace it. The two uses stay two mechanisms.
|
|
|
172
198
|
- ADR-0049's "no sub-run" is restated, not reversed: a nested Machine is reached by `import`, never by name; a run that
|
|
173
199
|
starts a run is a `dispatch`, by name, and the two are different uses. ADR-0067 gains the kind and a fourth Placement,
|
|
174
200
|
`orchestrator`. ADR-0068's Instance Effector gains the `dispatch` kind, its stop route stops a dispatch's wait too,
|
|
175
|
-
and its `running` state carries the run. ADR-0033's door gains an idempotency key.
|
|
201
|
+
and its `running` state carries the run. ADR-0033's door gains an idempotency key and the key-only ask.
|
|
176
202
|
- The GLOSSARY's **Effect** gains "or starts a run", and `_Avoid_: sub-run, child run, nested run, spawned run` for the
|
|
177
203
|
relation, which is **dispatched by**; its **Effector** and **Instance Effector** entries name the in-process exception
|
|
178
204
|
and the new kind.
|
|
@@ -180,4 +206,4 @@ composition and does not replace it. The two uses stay two mechanisms.
|
|
|
180
206
|
routing of both, without the key.
|
|
181
207
|
- An Open body may lend a `dispatch` slot as it lends any Effect (`lends.effects`), so a Chart can start a run of a
|
|
182
208
|
Workflow its wrapper chose; the Chart fills the body only.
|
|
183
|
-
- Deferred, named: a
|
|
209
|
+
- Deferred, named: a depth ceiling; a capability check for a door that ignores the key; an author's own key.
|
|
@@ -15,22 +15,27 @@ Next.js ships the same design: its docs as Markdown inside the `next` package, a
|
|
|
15
15
|
- **The bundle.** `@jr2/orchestrator` ships `docs/`: every page of the sitemap, the generated Reference, the Glossary
|
|
16
16
|
and the Decisions, as plain Markdown. No site-generator syntax reaches it. It is the main channel for an Assistant.
|
|
17
17
|
Each page is at its slug, such as `concepts/gates.md`, and each ADR is at `reference/decisions/<file>`. An Assistant
|
|
18
|
-
reads a page with its file tool, which cuts off a long file. So the Authoring surface is
|
|
19
|
-
`reference/authoring-surface.md
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
18
|
+
reads a page with its file tool, which cuts off a long file. So the Authoring surface is three parts.
|
|
19
|
+
`reference/authoring-surface.md` is a contents page that gives each group of the root's `src/index.ts`, and the
|
|
20
|
+
group of the types that the signatures name, its description and its names.
|
|
21
|
+
`reference/authoring-surface/group-<title>.md` is one page for each group, which gives each name of the group its
|
|
22
|
+
kind and the first sentence of its TSDoc. `reference/authoring-surface/<anchor>.md` is one page for each export and
|
|
23
|
+
for each type that a signature names. The `group-` prefix keeps a group page apart from an entry page, and
|
|
24
|
+
`docs:build` fails when two pages have one path. One page of all the names is about 200 KB. The contents page and
|
|
25
|
+
each group page are less than 25 KB, and each entry page is less than 15 KB. On the contents page, a type that a
|
|
26
|
+
signature names is code with no link, because there are more than a hundred of them; its group page links each one.
|
|
27
|
+
No line of a contents, group or entry page is longer than 1,000 characters, so the contents page breaks a list of
|
|
28
|
+
names into lines, and the type plumbing is a list, not a paragraph. When a group page passes 25 KB, first make the
|
|
29
|
+
long first sentences shorter; if it still passes, divide that group into two groups. The first sentence ends at a
|
|
30
|
+
stop, not at a colon, because the words before a colon often tell nothing alone ("An invoke."). A link to an entry
|
|
31
|
+
goes to its page. Each of the other generated Reference pages (CLI, config, machines, Hook kinds, mechanism events,
|
|
32
|
+
HTTP API) stays one page. Each is less than 30 KB, the size that one read of a file tool shows, with one exception:
|
|
33
|
+
the HTTP API page is about 50 KB. It is one page because its routes come first and are less than 30 KB, so one read
|
|
34
|
+
shows every route; the types of the bodies come after the routes, and an Assistant reads one of them with an offset
|
|
35
|
+
or by its heading. When the routes pass 30 KB, give the types a page of their own. The alternative, a split of the
|
|
36
|
+
HTTP API page now, is rejected because a route and the types it names are then on two pages, and one read shows all
|
|
37
|
+
routes already. The Glossary and the Decisions are not generated, and this rule does not hold them: an ADR can be
|
|
38
|
+
about 50 KB, and an Assistant reads the one ADR that a page links to.
|
|
34
39
|
- **The `AGENTS.md` block.** A compressed index of the bundle, and an instruction in five parts. jr2 is newer than
|
|
35
40
|
your training data, so read the bundled docs before you write a Machine or config. Start with the guide "Write a
|
|
36
41
|
workflow" and the contents page of the Authoring surface. Read one page with each call of the file tool. Run
|
|
@@ -63,21 +68,26 @@ Next.js ships the same design: its docs as Markdown inside the `next` package, a
|
|
|
63
68
|
exists for it. A broken marker pair is reported, and `up` does not change the file.
|
|
64
69
|
- **The Reference is generated from the code wherever the code holds the facts.**
|
|
65
70
|
|
|
66
|
-
| Page
|
|
67
|
-
|
|
|
68
|
-
| Authoring surface: a contents page, and a page per name | TSDoc on the exports, exactly the root's list
|
|
69
|
-
| `@jr2/machines`
|
|
70
|
-
|
|
|
71
|
-
|
|
|
72
|
-
|
|
|
73
|
-
|
|
|
74
|
-
|
|
|
71
|
+
| Page | Source |
|
|
72
|
+
| ------------------------------------------------------------------------- | -------------------------------------------------------------- |
|
|
73
|
+
| Authoring surface: a contents page, a page per group, and a page per name | TSDoc on the exports, exactly the root's list |
|
|
74
|
+
| `@jr2/machines` | TSDoc on the exports |
|
|
75
|
+
| `@jr2/orchestrator/hooks` | TSDoc on the exports of each module but `door`, one group each |
|
|
76
|
+
| `jr2.config.ts` | TSDoc on the `JR2Config` fields |
|
|
77
|
+
| CLI | a structured command table, which also prints `--help` |
|
|
78
|
+
| HTTP API | the route table in `http.ts`, made data |
|
|
79
|
+
| Mechanism events | the code that defines them |
|
|
80
|
+
| Glossary, Decisions | `GLOSSARY.md` and `docs/adr/`, rendered as they are |
|
|
75
81
|
|
|
76
82
|
The TSDoc on an Authoring surface export is written for the author: what it does, what it refuses, what to read next,
|
|
77
83
|
and one example. Maintainer reasoning goes in `//` comments in the body. The packages ship their `.ts` source, so an
|
|
78
84
|
Assistant that follows an import into `node_modules` reads the same text the site shows. The Authoring surface is
|
|
79
85
|
exactly what `@jr2/orchestrator` exports from its root: what the kit's packages share is internal even where it can be
|
|
80
86
|
imported, and `@jr2/machines` is not part of it, because it ships Machines, not names to author with.
|
|
87
|
+
`@jr2/orchestrator/hooks` is not part of it either, because a Hook kind is a module of its own interface, which a kind
|
|
88
|
+
from another package imports too
|
|
89
|
+
([ADR-0078](0078-a-caller-comes-from-one-authenticator-seam-and-acts-within-its-scopes.md)). Its page leaves out
|
|
90
|
+
`hook-kinds/door.ts`, which only the Orchestrator reads.
|
|
81
91
|
|
|
82
92
|
- **`docs:build` assembles the bundle at pack time.** Its inputs are the hand-written pages in `docs/site/`, the
|
|
83
93
|
generated Reference, `GLOSSARY.md`, and `docs/adr/`. It runs in `@jr2/orchestrator`'s `prepack` and before the site
|
package/docs/reference/decisions/0075-a-machine-cuts-a-worktree-and-the-workspace-only-clones.md
CHANGED
|
@@ -106,8 +106,8 @@ send: { name: "r.md", worktree: "/work/app/fix" } // http with a file body
|
|
|
106
106
|
|
|
107
107
|
### Output and the walk
|
|
108
108
|
|
|
109
|
-
- **Every Effect outcome is open.** `worktree()`, `push`, `command` and `
|
|
110
|
-
union, so that no author can write an exhaustive check. A later outcome is then no break.
|
|
109
|
+
- **Every Effect outcome is open.** `worktree()`, `push`, `command`, `http` and `mcp` each hold a stand-in member in
|
|
110
|
+
their union, so that no author can write an exhaustive check. A later outcome is then no break.
|
|
111
111
|
- **The load-time walk refuses an Effect's `onDone` with no unguarded last arm.** A type cannot see a missing arm, and
|
|
112
112
|
with no match a run stays in that state and shows no fault.
|
|
113
113
|
|
|
@@ -151,7 +151,8 @@ a pod, jr2 drops this lock and adds a `@model` claim that an Agent runs the fetc
|
|
|
151
151
|
(ADR-0021).
|
|
152
152
|
- **An Agent's commits on a side branch are not published**, and `found` says `held`. A warning field can follow after
|
|
153
153
|
v1.
|
|
154
|
-
- **`jr2 status <run>` shows each path and branch.** `jr2 ls` shows only Sandboxes, because it reads cluster
|
|
154
|
+
- **`jr2 status <run>` shows each path and branch.** `jr2 workspace ls` shows only Sandboxes, because it reads cluster
|
|
155
|
+
labels.
|
|
155
156
|
|
|
156
157
|
## Example
|
|
157
158
|
|
|
@@ -18,8 +18,8 @@ code from `/work`.
|
|
|
18
18
|
|
|
19
19
|
- **The boundary.** A credential that lets a request act for an Agent lives only where no Workspace code runs.
|
|
20
20
|
**Workspace code** is each process whose program or input comes from `/work`: the Working tools, tests, builds, git
|
|
21
|
-
(its hooks, its filters, fsmonitor, textconv and each repository-local config)
|
|
22
|
-
needs no separate container for each Agent.
|
|
21
|
+
(its hooks, its filters, fsmonitor, textconv and each repository-local config), `command` Effects and stdio MCP
|
|
22
|
+
servers. The boundary needs no separate container for each Agent.
|
|
23
23
|
- **One Harness container for each Sandbox.** It serves every workspace-ful Agent below the `workspace()`
|
|
24
24
|
([ADR-0005](0005-sandbox-pod-composition.md)). A Menu-only Agent has no Sandbox, and it runs on the Instance Harness,
|
|
25
25
|
as before ([ADR-0031](0031-menu-only-agents-run-on-the-instance-harness.md)).
|
|
@@ -33,7 +33,10 @@ code from `/work`.
|
|
|
33
33
|
([ADR-0067](0067-an-effect-is-an-actor-slot-and-runs-at-most-once-unless-marked-idempotent.md),
|
|
34
34
|
[ADR-0075](0075-a-machine-cuts-a-worktree-and-the-workspace-only-clones.md)), because a smudge filter or a textconv
|
|
35
35
|
in the shared `.git/config` runs in git's process;
|
|
36
|
-
- each `command` Effect that is placed in the Harness, which is each `command` that names no secret
|
|
36
|
+
- each `command` Effect that is placed in the Harness, which is each `command` that names no secret;
|
|
37
|
+
- each stdio MCP server of an Agent
|
|
38
|
+
([ADR-0079](0079-an-agent-holds-mcp-tools-a-machine-calls-them-as-an-effect-and-the-machine-is-the-approval.md)),
|
|
39
|
+
which the Harness starts through the spawner, never with its MCP client's own spawn.
|
|
37
40
|
|
|
38
41
|
So the trust boundary is inside the Harness container: the Harness process on one side, the domain on the other.
|
|
39
42
|
[ADR-0077](0077-jr2-requires-landlock-on-every-sandbox-node.md) makes Landlock a requirement of jr2, so no path runs a
|
|
@@ -54,17 +57,33 @@ code from `/work`.
|
|
|
54
57
|
to find what a rule allows: a link gets no rule (what it names gets its own rule where it is allowed, and the kernel
|
|
55
58
|
checks the path that a link resolves to), and the confiner refuses to start when a rule's path has a link on it. A
|
|
56
59
|
rule on a link would allow what the link names at each restart, and a confined process can change that.
|
|
60
|
+
- **A person's shell is a process of the domain.** `jr2 workspace shell`
|
|
61
|
+
([ADR-0009](0009-cli-and-instance-interface.md)) is `kubectl exec -c harness` of a small client in `/opt/jr2`, which
|
|
62
|
+
starts as the Harness starts (`effector nocore --harness-env`). The client starts nothing itself. It asks the Harness,
|
|
63
|
+
on a Unix socket in `/run/jr2/shell`, for the shell or for the one command after `--`, and the Harness asks the
|
|
64
|
+
spawner. So the shell is in the one domain, with the domain's env (the Stand-ins that the Workspace grants), its umask
|
|
65
|
+
and git identity, and the Workspace's cwd. It sees, signals and traces the Agents' processes, as a later `bash` call
|
|
66
|
+
does: a person can stop a dev server that an Agent left. With a terminal, the spawner opens a pseudo-terminal for the
|
|
67
|
+
shell, as its controlling terminal in a session of its own. The client sends the keys, the terminal's size and the
|
|
68
|
+
hang-up, and the spawner closes the terminal when the shell exits. The output has flow control: while the socket to
|
|
69
|
+
the client is full, the Harness pauses the spawn, and the spawner reads none of its output until the resume. So the
|
|
70
|
+
terminal fills and the shell's writes block, as on a slow terminal, and a fast shell does not fill the memory of the
|
|
71
|
+
Harness that serves the Agents' Turns. `/run/jr2/shell` is an emptyDir of the Harness container alone, and the domain
|
|
72
|
+
can make no file under `/run/jr2`, so no process of the domain listens in the Harness's place. A process of the domain
|
|
73
|
+
can connect to the socket, because Landlock does not control a connect. So the client proves that it is not one: its
|
|
74
|
+
first frame carries a digest of the control Stand-in, which it reads from the file and which the domain cannot read.
|
|
75
|
+
The Stand-in itself never goes on the socket. Without the proof, the Harness starts nothing.
|
|
57
76
|
- **The domain can do what the container's uid can do, except reach jr2's secrets.** The rules give every right on every
|
|
58
77
|
path, with one exception: `/run/jr2`. There the domain can list the names in each folder, and do nothing else.
|
|
59
78
|
Landlock only narrows the Unix permissions, so a confined program can do everything that the uid can do without
|
|
60
79
|
Landlock, except:
|
|
61
80
|
- reach the contents of `/run/jr2`: read, write, truncate, make, remove, move or link a file or a folder there.
|
|
62
81
|
`/run/jr2` holds the control Stand-in, each held secret's Stand-in, the folder of the Custodian's control socket,
|
|
63
|
-
and the Harness's conversations. Every path that jr2 holds for the Harness alone
|
|
64
|
-
allows a path only by its rules, so the confiner allows every sibling of `/run/jr2`
|
|
65
|
-
level at a time. It also gives the root the right to list names on its whole tree,
|
|
66
|
-
work as they do outside jr2. That right lists the names under `/run/jr2` too: a
|
|
67
|
-
file name. These names are not secrets.
|
|
82
|
+
the folder of the shell's socket, and the Harness's conversations. Every path that jr2 holds for the Harness alone
|
|
83
|
+
is under `/run/jr2`. Landlock allows a path only by its rules, so the confiner allows every sibling of `/run/jr2`
|
|
84
|
+
and of each folder above it, one level at a time. It also gives the root the right to list names on its whole tree,
|
|
85
|
+
so `ls /`, `ls /run` and `find /` work as they do outside jr2. That right lists the names under `/run/jr2` too: a
|
|
86
|
+
held secret's name, a conversation's file name. These names are not secrets.
|
|
68
87
|
- trace the Harness process, or read its `/proc/<pid>/environ` or `/proc/<pid>/mem`. A confined process cannot ptrace
|
|
69
88
|
a process outside its domain.
|
|
70
89
|
- at Landlock ABI 6 or later, connect to an abstract Unix socket that a process outside the domain made. The
|
|
@@ -167,8 +186,9 @@ code from `/work`.
|
|
|
167
186
|
the security boundary: the boundary is that only the Harness holds the credential.
|
|
168
187
|
- **Two tokens, each checked on its own routes.** This is defence in depth:
|
|
169
188
|
- The **control token** is what the Custodian puts in place of the secret control Stand-in. It is valid only on the
|
|
170
|
-
agent routes (`/agents/<iid>/surface`, `/agents/<iid>/events`, `/agents/<iid>/deliveries/<id>`,
|
|
171
|
-
|
|
189
|
+
agent routes (`/agents/<iid>/surface`, `/agents/<iid>/events`, `/agents/<iid>/deliveries/<id>`, the route on which
|
|
190
|
+
the Harness acknowledges a notice, and `/agents/<iid>/conversation`, on which it sends the entries of the
|
|
191
|
+
conversation, [ADR-0023](0023-the-harness-prints-the-conversation.md)), and it carries the stated slot.
|
|
172
192
|
- The **fetch token** is what the Custodian puts in place of the public Sandbox Stand-in that `jr2-upload-pack` holds
|
|
173
193
|
as a constant. It is valid only on `POST /sandboxes/<sandbox>/fetch`
|
|
174
194
|
([ADR-0053](0053-a-fetch-inside-the-pod-asks-the-node-cache-and-the-cache-asks-the-remote.md)). The Custodian
|
|
@@ -206,6 +226,13 @@ code from `/work`.
|
|
|
206
226
|
|
|
207
227
|
## Considered options
|
|
208
228
|
|
|
229
|
+
- **A raw `kubectl exec -c harness` shell (the old `jr2 ssh`).** Rejected: it runs outside the Landlock domain and can
|
|
230
|
+
read `/run/jr2`, so a person's shell, and any code that the person runs in it, reaches the control Stand-in.
|
|
231
|
+
`jr2 workspace shell` is a process of the spawner's domain ([ADR-0009](0009-cli-and-instance-interface.md)).
|
|
232
|
+
- **A person's shell in a sibling domain with the same rules**, which the client makes again with the confiner, so the
|
|
233
|
+
spawner needs no pseudo-terminal and the Harness needs no socket. Rejected: the shell reaches what an Agent's `bash`
|
|
234
|
+
reaches and nothing more, but it is not in the Agents' domain. It cannot trace their processes, and at ABI 6 or later
|
|
235
|
+
it cannot signal them, so a person cannot stop a runaway dev server, which is a usual reason to open a shell.
|
|
209
236
|
- **One Harness container for each agent slot, each with its own secret Stand-in.** Rejected. Kubernetes isolates one
|
|
210
237
|
container from another, but all the slots share the writable `/work`. Code that one Agent plants there runs in a
|
|
211
238
|
sibling's container when the sibling's `bash`, git or tests run, or when a `command` Effect runs there, and that code
|