@jr2/orchestrator 0.5.1 → 0.6.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/docs/agents-block.md +2 -2
- package/docs/concepts/agents-and-turns.md +56 -20
- package/docs/concepts/architecture.md +30 -17
- package/docs/concepts/charts.md +6 -3
- package/docs/concepts/converge.md +3 -0
- package/docs/concepts/effects.md +86 -31
- package/docs/concepts/machines-and-workflows.md +9 -0
- package/docs/concepts/pools-and-sources.md +6 -6
- package/docs/concepts/secrets-and-trust.md +126 -42
- package/docs/concepts/the-menu.md +3 -0
- package/docs/concepts/workspaces.md +129 -51
- package/docs/get-started/an-agent-in-a-sandbox.md +21 -19
- package/docs/get-started/have-your-assistant-write-a-machine.md +111 -40
- package/docs/get-started/install.md +4 -0
- package/docs/guides/add-tools-to-the-sandbox.md +17 -4
- package/docs/guides/bind-open-parts.md +5 -4
- package/docs/guides/cut-a-worktree.md +560 -0
- package/docs/guides/fix-a-failed-converge.md +1 -1
- package/docs/guides/let-an-agent-write-a-chart.md +5 -1
- package/docs/guides/look-inside-a-sandbox.md +18 -15
- package/docs/guides/move-from-kind-to-a-shared-cluster.md +16 -0
- package/docs/guides/push-and-sign-a-branch.md +67 -21
- package/docs/guides/run-a-command-or-call-a-url.md +84 -41
- package/docs/guides/run-one-worker-per-item.md +19 -18
- package/docs/guides/set-an-agents-access-and-dials.md +67 -22
- package/docs/guides/size-a-workspace.md +19 -6
- package/docs/guides/use-a-hosted-provider.md +6 -0
- package/docs/guides/watch-a-run.md +47 -24
- package/docs/guides/write-a-workflow.md +1 -1
- package/docs/llms.txt +33 -12
- package/docs/reference/authoring-surface/agent.md +34 -11
- package/docs/reference/authoring-surface/answer.md +19 -3
- package/docs/reference/authoring-surface/arg.md +27 -5
- package/docs/reference/authoring-surface/branchname.md +15 -0
- package/docs/reference/authoring-surface/command.md +36 -21
- package/docs/reference/authoring-surface/fail.md +17 -4
- package/docs/reference/authoring-surface/file.md +36 -16
- package/docs/reference/authoring-surface/http.md +108 -8
- package/docs/reference/authoring-surface/isready.md +14 -0
- package/docs/reference/authoring-surface/jr2setup.md +1 -1
- package/docs/reference/authoring-surface/open.md +36 -5
- package/docs/reference/authoring-surface/paramsof.md +22 -4
- package/docs/reference/authoring-surface/pool.md +4 -4
- package/docs/reference/authoring-surface/push.md +30 -12
- package/docs/reference/authoring-surface/readyof.md +21 -0
- package/docs/reference/authoring-surface/secret.md +25 -4
- package/docs/reference/authoring-surface/source.md +3 -3
- package/docs/reference/authoring-surface/type-agentdefinition.md +2 -2
- package/docs/reference/authoring-surface/type-agentslots.md +4 -1
- package/docs/reference/authoring-surface/type-anyframepath.md +14 -0
- package/docs/reference/authoring-surface/type-anyworktreepath.md +15 -0
- package/docs/reference/authoring-surface/type-bindactors.md +14 -0
- package/docs/reference/authoring-surface/type-binding.md +5 -6
- package/docs/reference/authoring-surface/type-commandinput.md +4 -3
- package/docs/reference/authoring-surface/type-commandoptions.md +0 -22
- package/docs/reference/authoring-surface/type-commandoutput.md +22 -4
- package/docs/reference/authoring-surface/type-customize.md +4 -2
- package/docs/reference/authoring-surface/type-dispatchoutput.md +8 -1
- package/docs/reference/authoring-surface/type-doorlessinput.md +19 -0
- package/docs/reference/authoring-surface/type-filebody.md +4 -8
- package/docs/reference/authoring-surface/type-framepath.md +14 -0
- package/docs/reference/authoring-surface/type-hostinjectedinput.md +2 -4
- package/docs/reference/authoring-surface/type-httpdefinition.md +6 -3
- package/docs/reference/authoring-surface/type-httpfileinput.md +20 -0
- package/docs/reference/authoring-surface/type-httpoutput.md +7 -1
- package/docs/reference/authoring-surface/type-lateroutcome.md +21 -0
- package/docs/reference/authoring-surface/type-namestart.md +77 -0
- package/docs/reference/authoring-surface/type-noslotworkspaceoptions.md +1 -6
- package/docs/reference/authoring-surface/type-notworktreekeys.md +12 -0
- package/docs/reference/authoring-surface/type-opencommandinput.md +7 -2
- package/docs/reference/authoring-surface/type-permissivenoslotworkspaceoptions.md +1 -6
- package/docs/reference/authoring-surface/type-permissiveworkspaceoptions.md +5 -10
- package/docs/reference/authoring-surface/type-poolnextinput.md +22 -0
- package/docs/reference/authoring-surface/type-poolspec.md +2 -2
- package/docs/reference/authoring-surface/type-pushinput.md +22 -3
- package/docs/reference/authoring-surface/type-pushoutput.md +32 -7
- package/docs/reference/authoring-surface/type-reposlot.md +5 -5
- package/docs/reference/authoring-surface/type-sandboxoptions.md +11 -4
- package/docs/reference/authoring-surface/type-slothandles.md +5 -13
- package/docs/reference/authoring-surface/type-sourcespec.md +10 -10
- package/docs/reference/authoring-surface/type-workspaced.md +29 -8
- package/docs/reference/authoring-surface/type-workspacehandles.md +5 -6
- package/docs/reference/authoring-surface/type-workspaceoptions.md +1 -13
- package/docs/reference/authoring-surface/type-worktreefound.md +16 -0
- package/docs/reference/authoring-surface/type-worktreeinput.md +56 -0
- package/docs/reference/authoring-surface/type-worktreekey.md +14 -0
- package/docs/reference/authoring-surface/type-worktreeoptions.md +29 -0
- package/docs/reference/authoring-surface/type-worktreeoutput.md +45 -0
- package/docs/reference/authoring-surface/type-worktreepath.md +16 -0
- package/docs/reference/authoring-surface/type-worktreeready.md +37 -0
- package/docs/reference/authoring-surface/type-worktreerefused.md +21 -0
- package/docs/reference/authoring-surface/workspace.md +65 -37
- package/docs/reference/authoring-surface/worktree.md +71 -0
- package/docs/reference/authoring-surface.md +30 -10
- package/docs/reference/cli.md +1 -1
- package/docs/reference/config.md +13 -4
- package/docs/reference/decisions/0001-operator-owned-generic-sandbox.md +10 -9
- package/docs/reference/decisions/0002-duplex-streaming-actor.md +17 -10
- package/docs/reference/decisions/0004-worktree-provisioning-model.md +27 -21
- package/docs/reference/decisions/0005-sandbox-pod-composition.md +29 -19
- package/docs/reference/decisions/0006-agent-control-surface.md +6 -3
- package/docs/reference/decisions/0012-workspace-wrapper-machine.md +30 -30
- package/docs/reference/decisions/0013-the-agent-reaches-its-machine-through-a-container-it-cannot-read.md +35 -17
- package/docs/reference/decisions/0015-authoring-surface-absorbs-the-mechanism.md +8 -2
- package/docs/reference/decisions/0016-agent-turn-mechanics-are-internal.md +9 -7
- package/docs/reference/decisions/0017-pool-over-a-source-port.md +6 -4
- package/docs/reference/decisions/0019-one-converging-command-against-the-current-context.md +21 -9
- package/docs/reference/decisions/0021-workspace-continuity-is-a-lease-that-answers-back.md +2 -1
- package/docs/reference/decisions/0023-the-harness-prints-the-conversation.md +8 -9
- package/docs/reference/decisions/0024-an-agents-turn-ends-with-the-state-that-asked-for-it.md +62 -65
- package/docs/reference/decisions/0027-the-harness-is-jr2s-own-server-flue-retires-the-wire-stays.md +9 -1
- package/docs/reference/decisions/0028-what-an-agent-may-do-to-the-workspace-is-part-of-its-definition.md +13 -12
- package/docs/reference/decisions/0031-menu-only-agents-run-on-the-instance-harness.md +4 -1
- package/docs/reference/decisions/0033-a-machine-declares-the-input-that-starts-it.md +18 -19
- package/docs/reference/decisions/0037-an-instance-builds-its-sandbox-images-jr2-injects-the-harness.md +8 -8
- package/docs/reference/decisions/0049-a-machine-carries-its-parts-and-composes-by-invoke.md +4 -4
- package/docs/reference/decisions/0051-a-repo-is-a-slot-on-the-workspace-and-a-cache-on-the-node.md +57 -46
- package/docs/reference/decisions/0052-a-sandbox-lands-where-an-ordinary-pod-lands-and-the-cache-follows-it.md +5 -0
- package/docs/reference/decisions/0053-a-fetch-inside-the-pod-asks-the-node-cache-and-the-cache-asks-the-remote.md +20 -8
- package/docs/reference/decisions/0057-a-turn-is-its-frame-its-dials-and-whether-it-continues.md +24 -24
- package/docs/reference/decisions/0058-a-harness-answers-the-orchestrator-alone.md +5 -3
- package/docs/reference/decisions/0059-a-harness-holds-stand-ins-and-the-custodian-holds-the-keys.md +110 -67
- package/docs/reference/decisions/0062-jr2-briefs-the-agent-on-its-seat-never-on-its-task.md +101 -74
- package/docs/reference/decisions/0063-the-orchestrator-watches-the-cluster.md +5 -6
- package/docs/reference/decisions/0066-a-model-tier-runs-a-real-model-and-a-change-to-what-it-reads-runs-the-tier.md +2 -0
- package/docs/reference/decisions/0067-an-effect-is-an-actor-slot-and-runs-at-most-once-unless-marked-idempotent.md +181 -153
- package/docs/reference/decisions/0068-an-effector-holds-an-effects-secrets-and-signs-its-wire.md +74 -63
- package/docs/reference/decisions/0070-a-machine-lends-its-parts-to-a-chart.md +31 -20
- package/docs/reference/decisions/0073-a-machine-fails-a-run-with-fail-and-an-uncaught-failure-ends-it-failed.md +1 -1
- package/docs/reference/decisions/0075-a-machine-cuts-a-worktree-and-the-workspace-only-clones.md +295 -0
- package/docs/reference/decisions/0076-an-agents-control-credential-lives-only-where-no-workspace-code-runs.md +320 -0
- package/docs/reference/decisions/0077-jr2-requires-landlock-on-every-sandbox-node.md +79 -0
- package/docs/reference/decisions.md +3 -0
- package/docs/reference/glossary.md +51 -12
- package/docs/reference/http-api.md +45 -7
- package/docs/reference/machines.md +0 -1
- package/docs/why.md +5 -4
- package/package.json +3 -3
- package/src/actor.ts +161 -35
- package/src/agent.ts +6 -6
- package/src/ambient.ts +3 -5
- package/src/chart.ts +186 -19
- package/src/charts.ts +9 -2
- package/src/config.ts +16 -6
- package/src/custodian.lua +17 -5
- package/src/custodian.ts +251 -77
- package/src/customize.ts +11 -3
- package/src/effect-checks.ts +50 -3
- package/src/effect.ts +343 -127
- package/src/effector-wire.ts +6 -3
- package/src/fail.ts +17 -4
- package/src/harness-client.ts +74 -31
- package/src/harness-env.ts +33 -0
- package/src/held-secrets.ts +125 -16
- package/src/holds.ts +3 -0
- package/src/http-effect.ts +88 -32
- package/src/http.ts +56 -17
- package/src/index.ts +15 -1
- package/src/internal.ts +1 -0
- package/src/kube-client.ts +6 -3
- package/src/machine-doc.ts +3 -4
- package/src/model-keys.ts +24 -0
- package/src/names.ts +19 -6
- package/src/notices.ts +443 -54
- package/src/open-body.ts +85 -19
- package/src/open.ts +36 -5
- package/src/parts.ts +40 -28
- package/src/party.ts +33 -0
- package/src/pick.ts +41 -7
- package/src/pool.ts +44 -23
- package/src/registration.ts +53 -11
- package/src/repo-identity.ts +7 -3
- package/src/repos.ts +20 -2
- package/src/run-host.ts +106 -20
- package/src/sandbox-effect.ts +217 -66
- package/src/sandbox-kube.ts +63 -16
- package/src/secret-placement.ts +9 -2
- package/src/setup.ts +86 -6
- package/src/tokens.ts +107 -32
- package/src/vocabulary.ts +23 -4
- package/src/wire.ts +10 -10
- package/src/workspace.ts +264 -253
- package/src/worktree.ts +249 -0
- package/docs/reference/authoring-surface/type-noslotspec.md +0 -26
- package/docs/reference/authoring-surface/type-workspacespec.md +0 -37
|
@@ -10,23 +10,18 @@ Type, in `@jr2/orchestrator/src/workspace.ts`. The signature of an export, or a
|
|
|
10
10
|
```ts
|
|
11
11
|
type PermissiveWorkspaceOptions<TSlots extends string, TInput = unknown> = SandboxOptions<TSlots, TInput> & {
|
|
12
12
|
input?: never;
|
|
13
|
-
spec: (args: { input: TInput }) => WorkspaceSpec;
|
|
14
13
|
};
|
|
15
14
|
```
|
|
16
15
|
|
|
17
|
-
The options of a `workspace()` with no `input`: it starts with any input. The `input` of
|
|
18
|
-
is then `unknown`, and
|
|
16
|
+
The options of a `workspace()` with no `input`: it starts with any input. The `input` of a
|
|
17
|
+
per-run Repo Slot is then `unknown`, and the mapper must check it before it reads a field.
|
|
19
18
|
|
|
20
|
-
Use it for a Workspace that a Pool or another Machine starts.
|
|
21
|
-
|
|
22
|
-
|
|
19
|
+
Use it for a Workspace that a Pool or another Machine starts. The body's `input` type says what
|
|
20
|
+
that input is, and that also types the input of the Workspace. For a Workspace that a caller
|
|
21
|
+
starts, declare `input`.
|
|
23
22
|
|
|
24
23
|
**Fields**: each field of [`SandboxOptions`](type-sandboxoptions.md), and these:
|
|
25
24
|
|
|
26
25
|
- `input` (optional): `never`
|
|
27
26
|
|
|
28
27
|
Not present: a `workspace()` without `input` starts with any input.
|
|
29
|
-
- `spec`: `(args: { input: TInput; }) => WorkspaceSpec`
|
|
30
|
-
|
|
31
|
-
A function from the input to the Workspace's [`WorkspaceSpec`](type-workspacespec.md). Its `input` is
|
|
32
|
-
`unknown` unless you give the parameter a type: `spec: ({ input }: { input: Item }) => …`.
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: PoolNextInput
|
|
3
|
+
description: "The input of a Source's `next`: the ids of the items that workers have now, the ids of the items that settled, and the Pool's input."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# `PoolNextInput`
|
|
7
|
+
|
|
8
|
+
Type, in `@jr2/orchestrator/src/pool.ts`. It is an export of `@jr2/orchestrator`, on the [Authoring surface](../authoring-surface.md) page, in Composition.
|
|
9
|
+
|
|
10
|
+
```ts
|
|
11
|
+
type PoolNextInput<TInput = unknown> = { active: string[]; settled: string[]; input: TInput };
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
The input of a Source's `next`: the ids of the items that workers have now, the ids of the items
|
|
15
|
+
that settled, and the Pool's input. So a Source over a list that a Machine holds needs no state
|
|
16
|
+
of its own.
|
|
17
|
+
|
|
18
|
+
**Fields**
|
|
19
|
+
|
|
20
|
+
- `active`: `string[]`
|
|
21
|
+
- `settled`: `string[]`
|
|
22
|
+
- `input`: `TInput`
|
|
@@ -11,7 +11,7 @@ Type, in `@jr2/orchestrator/src/pool.ts`. The signature of an export, or a type
|
|
|
11
11
|
type PoolSpec<T, TInput = unknown> = {
|
|
12
12
|
id?: string;
|
|
13
13
|
input?: z.ZodObject;
|
|
14
|
-
source: SourceSpec<T>;
|
|
14
|
+
source: SourceSpec<T, TInput> | SourceSpec<T>;
|
|
15
15
|
itemId: (item: T) => string;
|
|
16
16
|
cap?: number | ((args: { input: TInput }) => number);
|
|
17
17
|
itemInput?: (item: T, args: { input: TInput }) => unknown;
|
|
@@ -33,7 +33,7 @@ each worker gets.
|
|
|
33
33
|
The run input of the Pool, as a zod object: what a caller sends to start a run. `cap` and
|
|
34
34
|
`itemInput` read it, typed by it. A worker never gets it: each worker gets its item. Default:
|
|
35
35
|
none, and then their `input` is `unknown`.
|
|
36
|
-
- `source`: `SourceSpec<T>`
|
|
36
|
+
- `source`: `SourceSpec<T, TInput> | SourceSpec<T>`
|
|
37
37
|
|
|
38
38
|
Where the items come from. Make it with [`source`](source.md).
|
|
39
39
|
- `itemId`: `(item: T) => string`
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: PushInput
|
|
3
|
-
description: "The input of a `push` Effect: `{ sha }` with `pin`, and `{ message }` with `squash`."
|
|
3
|
+
description: "The input of a `push` Effect: the Worktree that a cut made, `{ sha }` with `pin`, and `{ message }` with `squash`."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# `PushInput`
|
|
@@ -8,8 +8,27 @@ description: "The input of a `push` Effect: `{ sha }` with `pin`, and `{ message
|
|
|
8
8
|
Type, in `@jr2/orchestrator/src/sandbox-effect.ts`. The signature of an export, or a type that it names, names this type. The [Authoring surface](../authoring-surface.md) page lists each export. This type is not an export of `@jr2/orchestrator`, so a workflow module does not import it by name.
|
|
9
9
|
|
|
10
10
|
```ts
|
|
11
|
-
type PushInput<O extends PushOptions> =
|
|
11
|
+
type PushInput<O extends PushOptions> = {
|
|
12
|
+
worktree: O extends { slot: infer S extends string } ? `/work/${S}/${string}` : AnyWorktreePath;
|
|
13
|
+
branch?: never;
|
|
14
|
+
to?: never;
|
|
15
|
+
cwd?: never;
|
|
16
|
+
path?: never;
|
|
17
|
+
} & (O["pin"] extends true ? { sha: string } : unknown) &
|
|
12
18
|
(O["squash"] extends true ? { message: string } : unknown);
|
|
13
19
|
```
|
|
14
20
|
|
|
15
|
-
The input of a `push` Effect:
|
|
21
|
+
The input of a `push` Effect: the Worktree that a cut made, `{ sha }` with `pin`, and
|
|
22
|
+
`{ message }` with `squash`. It names no branch: jr2 reads it from the cut's record, so no word of
|
|
23
|
+
a Chart reaches a remote branch. The other keys are refused by name, because each is a key of a
|
|
24
|
+
cut or a Turn, and a mapper's excess key is no compile error otherwise.
|
|
25
|
+
|
|
26
|
+
**Fields**
|
|
27
|
+
|
|
28
|
+
- `worktree`: ``O extends { slot: infer S extends string; } ? `/work/${S}/${string}` : AnyWorktreePath``
|
|
29
|
+
|
|
30
|
+
The Worktree to push: `event.output.path` of its cut, of the push's Repo Slot.
|
|
31
|
+
- `branch` (optional): `never`
|
|
32
|
+
- `to` (optional): `never`
|
|
33
|
+
- `cwd` (optional): `never`
|
|
34
|
+
- `path` (optional): `never`
|
|
@@ -10,7 +10,8 @@ Type, in `@jr2/orchestrator/src/sandbox-effect.ts`. It is an export of `@jr2/orc
|
|
|
10
10
|
```ts
|
|
11
11
|
type PushOutput =
|
|
12
12
|
| Exclude<PushWireOutput, { outcome: "pushed" }>
|
|
13
|
-
| (Omit<Extract<PushWireOutput, { outcome: "pushed" }>, "bundle"> & { sync: SyncState; syncReason?: string })
|
|
13
|
+
| (Omit<Extract<PushWireOutput, { outcome: "pushed" }>, "bundle"> & { sync: SyncState; syncReason?: string })
|
|
14
|
+
| LaterOutcome;
|
|
14
15
|
```
|
|
15
16
|
|
|
16
17
|
The output of a `push` Effect: what the `onDone` of its state gets as `event.output`. Every
|
|
@@ -40,6 +41,8 @@ Beside `pushed`, `sync` tells what jr2 did to the Agent's branch after the push:
|
|
|
40
41
|
|
|
41
42
|
With `busy` or `not-synced`, `syncReason` tells why, and jr2 tries again before the next push.
|
|
42
43
|
|
|
44
|
+
The union is open (`LaterOutcome`): give the rest a last arm with no guard.
|
|
45
|
+
|
|
43
46
|
**Forms**: it is one of these objects.
|
|
44
47
|
|
|
45
48
|
- Form 1: `outcome`, `stage`, `reason`, `detail`
|
|
@@ -70,13 +73,28 @@ With `busy` or `not-synced`, `syncReason` tells why, and jr2 tries again before
|
|
|
70
73
|
- `squashed` (optional): `"signed" | "unsigned"`
|
|
71
74
|
- `sync`: [`SyncState`](type-syncstate.md)
|
|
72
75
|
- `syncReason` (optional): `string`
|
|
76
|
+
- Form 5: `outcome`, `reason`
|
|
77
|
+
|
|
78
|
+
- `outcome`: `"(a later outcome)"`
|
|
79
|
+
- `reason` (optional): `string`
|
|
73
80
|
|
|
74
81
|
**Example**
|
|
75
82
|
|
|
76
83
|
```ts
|
|
77
|
-
import {
|
|
84
|
+
import {
|
|
85
|
+
fail,
|
|
86
|
+
isReady,
|
|
87
|
+
jr2Setup,
|
|
88
|
+
push,
|
|
89
|
+
type PushOutput,
|
|
90
|
+
workspace,
|
|
91
|
+
worktree,
|
|
92
|
+
type Workspaced,
|
|
93
|
+
} from "@jr2/orchestrator";
|
|
94
|
+
|
|
95
|
+
type Input = Workspaced<{ branch: string; sha: string }, "app">;
|
|
78
96
|
|
|
79
|
-
|
|
97
|
+
const releaseTree = (context: Input) => `${context.workspace.repos.app}/release` as const;
|
|
80
98
|
|
|
81
99
|
// A push that did not happen (`rejected` or `diverged`) is a different problem from one jr2
|
|
82
100
|
// cannot see (`unknown`).
|
|
@@ -85,17 +103,24 @@ const notPushed = (output: PushOutput): boolean =>
|
|
|
85
103
|
|
|
86
104
|
const body = jr2Setup({
|
|
87
105
|
types: {} as { context: Input; input: Input },
|
|
88
|
-
actors: { publish: push({ pin: true }), fail: fail() },
|
|
106
|
+
actors: { cut: worktree({ expect: "existing" }), publish: push({ pin: true }), fail: fail() },
|
|
89
107
|
}).createMachine({
|
|
90
108
|
id: "release",
|
|
91
109
|
context: ({ input }) => input,
|
|
92
110
|
on: { "workspace.lost": ".lost" },
|
|
93
|
-
initial: "
|
|
111
|
+
initial: "cutting",
|
|
94
112
|
states: {
|
|
113
|
+
cutting: {
|
|
114
|
+
invoke: {
|
|
115
|
+
src: "cut",
|
|
116
|
+
input: ({ context }) => ({ path: releaseTree(context), branch: context.branch }),
|
|
117
|
+
onDone: [{ guard: ({ event }) => isReady(event.output), target: "publishing" }, { target: "notCut" }],
|
|
118
|
+
},
|
|
119
|
+
},
|
|
95
120
|
publishing: {
|
|
96
121
|
invoke: {
|
|
97
122
|
src: "publish",
|
|
98
|
-
input: ({ context }) => ({ sha: context.sha }),
|
|
123
|
+
input: ({ context }) => ({ worktree: releaseTree(context), sha: context.sha }),
|
|
99
124
|
onDone: [
|
|
100
125
|
{ guard: ({ event }) => event.output.outcome === "pushed", target: "published" },
|
|
101
126
|
{ guard: ({ event }) => notPushed(event.output), target: "notPushed" },
|
|
@@ -107,13 +132,13 @@ const body = jr2Setup({
|
|
|
107
132
|
// Not final states: each one fails the run, with its own reason.
|
|
108
133
|
notPushed: { invoke: { src: "fail", input: { reason: "the remote refused the push" } } },
|
|
109
134
|
unknown: { invoke: { src: "fail", input: { reason: "jr2 cannot tell if the push happened" } } },
|
|
135
|
+
notCut: { invoke: { src: "fail", input: { reason: "the Worktree was not cut" } } },
|
|
110
136
|
lost: { invoke: { src: "fail", input: { reason: "the Sandbox is gone" } } },
|
|
111
137
|
},
|
|
112
138
|
});
|
|
113
139
|
|
|
114
140
|
export const machine = workspace(body, {
|
|
115
141
|
repos: { app: { url: "https://github.com/you/app.git" } },
|
|
116
|
-
spec: () => ({ branch: "release" }),
|
|
117
142
|
});
|
|
118
143
|
```
|
|
119
144
|
|
|
@@ -24,10 +24,11 @@ The value of one Repo Slot in `workspace({ repos })`. One of:
|
|
|
24
24
|
- a function of the run input, `({ input }) => url` or a [`Binding`](type-binding.md): each run chooses. The
|
|
25
25
|
url must match an entry of `git.credentials` in `jr2.config.ts`, or the run cannot use it.
|
|
26
26
|
|
|
27
|
-
The key of the slot is a directory name under `/work`. It starts with a letter,
|
|
28
|
-
`workspace()` and `customize()` refuse a key that does
|
|
29
|
-
not a directory name — a slot becomes `/work/<slot
|
|
30
|
-
|
|
27
|
+
The key of the slot is a directory name under `/work`. It starts with a letter, so never with
|
|
28
|
+
`.`: `/work/.jr2/` is reserved for jr2. `workspace()` and `customize()` refuse a key that does
|
|
29
|
+
not: ``<where>: Repo Slot key "<key>" is not a directory name — a slot becomes `/work/<slot>`,
|
|
30
|
+
`/work/.jr2/` is reserved for jr2, and its order matters, so it starts with a letter and matches
|
|
31
|
+
/^[A-Za-z][A-Za-z0-9._-]*$/ (ADR-0051, ADR-0075).`` They refuse a value of another
|
|
31
32
|
shape: ``<where>: Repo Slot "<slot>" is <what> — a slot is `open`, a url, `{ url, ref? }`, or a
|
|
32
33
|
mapper `({ input }) => url | { url, ref? }` over the door (ADR-0051).``
|
|
33
34
|
|
|
@@ -58,7 +59,6 @@ export const deploy = workspace(body, {
|
|
|
58
59
|
docs: "https://github.com/you/docs.git",
|
|
59
60
|
config: open,
|
|
60
61
|
},
|
|
61
|
-
spec: ({ input }) => ({ branch: `deploy/${input.service}` }),
|
|
62
62
|
});
|
|
63
63
|
```
|
|
64
64
|
|
|
@@ -10,6 +10,7 @@ Type, in `@jr2/orchestrator/src/workspace.ts`. The signature of an export, or a
|
|
|
10
10
|
```ts
|
|
11
11
|
type SandboxOptions<TSlots extends string, TInput = unknown> = {
|
|
12
12
|
image?: string;
|
|
13
|
+
workGroup?: number;
|
|
13
14
|
user?: string | UserContainer;
|
|
14
15
|
resources?: Size;
|
|
15
16
|
repos: Record<TSlots, RepoSlot<TInput>> | typeof open;
|
|
@@ -30,6 +31,9 @@ clones. They are the same for each run.
|
|
|
30
31
|
(`import.meta.resolve("./image")`), which `jr2 up` builds, or a registry ref. Its floor is
|
|
31
32
|
glibc and git; jr2 adds its own runtime at `/opt/jr2`. Default: the Instance's
|
|
32
33
|
`images/default`, then jr2's Harness image.
|
|
34
|
+
- `workGroup` (optional): `number`
|
|
35
|
+
|
|
36
|
+
The group id that owns the files in `/work`. Default: 2000. A non-negative integer.
|
|
33
37
|
- `user` (optional): `string | UserContainer`
|
|
34
38
|
|
|
35
39
|
The User Container: a third container in the Sandbox, for a service that must run beside the
|
|
@@ -52,8 +56,8 @@ clones. They are the same for each run.
|
|
|
52
56
|
choice. The name is the key of `workspace.repos` in the body and the directory under `/work`.
|
|
53
57
|
At least one slot. Leave `repos` out for a Workspace with no Repo Slot (see
|
|
54
58
|
[`NoSlotWorkspaceOptions`](type-noslotworkspaceoptions.md)). Each value is one of:
|
|
55
|
-
- a url, or `{ url, ref }`, where `ref` is the branch or commit that the
|
|
56
|
-
(default: the Repo's default branch);
|
|
59
|
+
- a url, or `{ url, ref }`, where `ref` is the branch, the tag or the commit that the clone
|
|
60
|
+
stays on, and that a new branch starts from (default: the Repo's default branch);
|
|
57
61
|
- `open`, for the Instance that registers the Machine to bind with `customize()`;
|
|
58
62
|
- a function of the run input, `({ input }) => url` or `{ url, ref }`, when each run chooses.
|
|
59
63
|
|
|
@@ -63,8 +67,11 @@ clones. They are the same for each run.
|
|
|
63
67
|
|
|
64
68
|
The Held secrets that this Sandbox can use: names from the `secrets` list in `jr2.config.ts`.
|
|
65
69
|
The Sandbox's Custodian holds each value and puts it into requests to the hosts of that Held
|
|
66
|
-
secret.
|
|
67
|
-
|
|
70
|
+
secret. Listing a name also gives its Stand-in to the Agent's programs — each `bash` call, test,
|
|
71
|
+
build and `command` — in their env under that name, so code in `/work` can spend it ([ADR-0076](../decisions/0076-an-agents-control-credential-lives-only-where-no-workspace-code-runs.md)).
|
|
72
|
+
You need not list the model key of an Agent that runs here: its provider claims it, and the
|
|
73
|
+
Harness gives it to the model calls alone. List the model key only when code in `/work` must
|
|
74
|
+
call the model itself: such a call is outside the Turn's usage record. Each name once.
|
|
68
75
|
- `effector` (optional): `object`
|
|
69
76
|
|
|
70
77
|
The image of the Sandbox Effector. This container runs three kinds of Effect for this
|
|
@@ -9,9 +9,7 @@ Type, in `@jr2/orchestrator/src/workspace.ts`. The signature of an export, or a
|
|
|
9
9
|
|
|
10
10
|
```ts
|
|
11
11
|
type SlotHandles<TSlots extends string> = {
|
|
12
|
-
repos:
|
|
13
|
-
branch: string;
|
|
14
|
-
review?: Partial<Record<TSlots, string>>;
|
|
12
|
+
repos: { [K in TSlots]: `/work/${K}` };
|
|
15
13
|
};
|
|
16
14
|
```
|
|
17
15
|
|
|
@@ -19,14 +17,8 @@ The handles of a Workspace that declares Repo Slots. @internal
|
|
|
19
17
|
|
|
20
18
|
**Fields**
|
|
21
19
|
|
|
22
|
-
- `repos`:
|
|
20
|
+
- `repos`: ``{ [K in TSlots]: `/work/${K}`; }``
|
|
23
21
|
|
|
24
|
-
The
|
|
25
|
-
`
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
The branch that the Workspace works on: the `branch` of the spec.
|
|
29
|
-
- `review` (optional): `Partial<Record<TSlots, string>>`
|
|
30
|
-
|
|
31
|
-
The path of each Repo Slot's review Worktree. Present only when the spec has `reviewSha`.
|
|
32
|
-
Give one to a reviewer's Turn as its `cwd`.
|
|
22
|
+
The folder of each Repo Slot, `/work/<slot>`, in the order that `repos` declares the slots.
|
|
23
|
+
`${handle}/default` is the clone, on the Binding's base. Any other Worktree is one the Machine
|
|
24
|
+
cut with `worktree()`.
|
|
@@ -8,12 +8,12 @@ description: "Where a Pool gets its work items: the Source."
|
|
|
8
8
|
Type, in `@jr2/orchestrator/src/pool.ts`. The signature of an export, or a type that it names, names this type. The [Authoring surface](../authoring-surface.md) page lists each export. This type is not an export of `@jr2/orchestrator`, so a workflow module does not import it by name.
|
|
9
9
|
|
|
10
10
|
```ts
|
|
11
|
-
type SourceSpec<T> = {
|
|
11
|
+
type SourceSpec<T, TInput = unknown> = {
|
|
12
12
|
next:
|
|
13
|
-
| PromiseActorLogic<SourceNextResult<T>,
|
|
14
|
-
| PromiseActorLogic<{ item: T | null; open: number },
|
|
15
|
-
| PromiseActorLogic<T | null,
|
|
16
|
-
| PromiseActorLogic<null,
|
|
13
|
+
| PromiseActorLogic<SourceNextResult<T>, PoolNextInput<TInput>>
|
|
14
|
+
| PromiseActorLogic<{ item: T | null; open: number }, PoolNextInput<TInput>>
|
|
15
|
+
| PromiseActorLogic<T | null, PoolNextInput<TInput>>
|
|
16
|
+
| PromiseActorLogic<null, PoolNextInput<TInput>>;
|
|
17
17
|
wake?: EventDef;
|
|
18
18
|
pollEvery?: number;
|
|
19
19
|
};
|
|
@@ -23,13 +23,13 @@ Where a Pool gets its work items: the Source. Make one with [`source`](source.md
|
|
|
23
23
|
|
|
24
24
|
**Fields**
|
|
25
25
|
|
|
26
|
-
- `next`: `PromiseActorLogic<SourceNextResult<T>,
|
|
26
|
+
- `next`: `PromiseActorLogic<SourceNextResult<T>, PoolNextInput<TInput>> | PromiseActorLogic<{ item: T | null; open: number; }, PoolNextInput<TInput>> | PromiseActorLogic<T | null, PoolNextInput<TInput>> | PromiseActorLogic<null, PoolNextInput<TInput>>`
|
|
27
27
|
|
|
28
28
|
Claim the next ready item. Write it as an xstate promise actor,
|
|
29
|
-
`fromPromise(async ({ input }) => …)`. Its input is `
|
|
30
|
-
workers have now,
|
|
31
|
-
|
|
32
|
-
starts, after each claim, and when a worker settles. While workers run and no item is ready, it
|
|
29
|
+
`fromPromise(async ({ input }) => …)`. Its input is [`PoolNextInput`](type-poolnextinput.md): `active`, the ids of
|
|
30
|
+
the items that workers have now, `settled`, the ids of the items that finished or failed, and
|
|
31
|
+
`input`, the Pool's input. It must not give again an item in `active` or `settled`. It resolves
|
|
32
|
+
to a [`SourceNextResult`](type-sourcenextresult.md). The Pool calls it when the run starts, after each claim, and when a worker settles. While workers run and no item is ready, it
|
|
33
33
|
also calls it on `wake` and every `pollEvery`.
|
|
34
34
|
- `wake` (optional): [`EventDef`](type-eventdef.md)
|
|
35
35
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: Workspaced
|
|
3
|
-
description: "The input of a `workspace()` body: the run input, plus `workspace`, the handles that the Workspace adds (`workspace.repos`,
|
|
3
|
+
description: "The input of a `workspace()` body: the run input, plus `workspace`, the handles that the Workspace adds (`workspace.repos`, the folder of each Repo Slot)."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# `Workspaced`
|
|
@@ -14,7 +14,7 @@ type Workspaced<TInput, TSlots extends string> = WithoutEmptyIndex<TInput> & {
|
|
|
14
14
|
```
|
|
15
15
|
|
|
16
16
|
The input of a `workspace()` body: the run input, plus `workspace`, the handles that the
|
|
17
|
-
Workspace adds (`workspace.repos`,
|
|
17
|
+
Workspace adds (`workspace.repos`, the folder of each Repo Slot). Use it as the type of
|
|
18
18
|
the body's input.
|
|
19
19
|
|
|
20
20
|
The first argument is the run input: the `input` schema of the `workspace()`. The second is the
|
|
@@ -36,16 +36,29 @@ Its fields are the fields of the run input, and `workspace`. The run input can h
|
|
|
36
36
|
|
|
37
37
|
```ts
|
|
38
38
|
import { z } from "zod";
|
|
39
|
-
import {
|
|
39
|
+
import {
|
|
40
|
+
agent,
|
|
41
|
+
defineEvent,
|
|
42
|
+
fail,
|
|
43
|
+
isReady,
|
|
44
|
+
jr2Setup,
|
|
45
|
+
workspace,
|
|
46
|
+
worktree,
|
|
47
|
+
type Workspaced,
|
|
48
|
+
} from "@jr2/orchestrator";
|
|
40
49
|
|
|
41
50
|
const done = defineEvent({
|
|
42
51
|
name: "done",
|
|
43
52
|
description: "Call this when REVIEW.md is written.",
|
|
44
53
|
input: z.object({}),
|
|
45
54
|
});
|
|
46
|
-
const runInput = z.object({
|
|
55
|
+
const runInput = z.object({ sha: z.string() });
|
|
47
56
|
type BodyInput = Workspaced<z.infer<typeof runInput>, "app">;
|
|
48
57
|
|
|
58
|
+
// A handle is the slot's folder: `/work/app`. A helper returns `as const`, so that the compiler
|
|
59
|
+
// sees the slot.
|
|
60
|
+
const reviewTree = (context: BodyInput) => `${context.workspace.repos.app}/review` as const;
|
|
61
|
+
|
|
49
62
|
const body = jr2Setup({
|
|
50
63
|
types: {} as { input: BodyInput; context: BodyInput },
|
|
51
64
|
events: [done],
|
|
@@ -55,25 +68,34 @@ const body = jr2Setup({
|
|
|
55
68
|
instructions: "You review one commit and write REVIEW.md.",
|
|
56
69
|
workspace: "read",
|
|
57
70
|
}),
|
|
71
|
+
cut: worktree(),
|
|
58
72
|
fail: fail(),
|
|
59
73
|
},
|
|
60
74
|
}).createMachine({
|
|
61
75
|
id: "review",
|
|
62
76
|
context: ({ input }) => input,
|
|
63
77
|
on: { "workspace.lost": ".lost", "agent.fault": ".failed" },
|
|
64
|
-
initial: "
|
|
78
|
+
initial: "cutting",
|
|
65
79
|
states: {
|
|
80
|
+
cutting: {
|
|
81
|
+
invoke: {
|
|
82
|
+
src: "cut",
|
|
83
|
+
input: ({ context }) => ({ path: reviewTree(context), detach: context.sha }),
|
|
84
|
+
onDone: [{ guard: ({ event }) => isReady(event.output), target: "reviewing" }, { target: "notCut" }],
|
|
85
|
+
},
|
|
86
|
+
},
|
|
66
87
|
reviewing: {
|
|
67
88
|
invoke: {
|
|
68
89
|
src: "reviewer",
|
|
69
90
|
input: ({ context }) => ({
|
|
70
|
-
prompt: `Review commit ${context.sha}
|
|
71
|
-
cwd: context
|
|
91
|
+
prompt: `Review commit ${context.sha}.`,
|
|
92
|
+
cwd: reviewTree(context),
|
|
72
93
|
}),
|
|
73
94
|
},
|
|
74
95
|
on: { done: "finished" },
|
|
75
96
|
},
|
|
76
97
|
finished: { type: "final" },
|
|
98
|
+
notCut: { invoke: { src: "fail", input: { reason: "the Worktree was not cut" } } },
|
|
77
99
|
failed: { invoke: { src: "fail", input: { reason: "the Agent's Turn could not go on" } } },
|
|
78
100
|
lost: { invoke: { src: "fail", input: { reason: "the Sandbox is gone" } } },
|
|
79
101
|
},
|
|
@@ -82,7 +104,6 @@ const body = jr2Setup({
|
|
|
82
104
|
export const machine = workspace(body, {
|
|
83
105
|
input: runInput,
|
|
84
106
|
repos: { app: "https://github.com/you/app.git" },
|
|
85
|
-
spec: ({ input }) => ({ branch: input.branch, reviewSha: input.sha }),
|
|
86
107
|
});
|
|
87
108
|
```
|
|
88
109
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: WorkspaceHandles
|
|
3
|
-
description: "What the body of a `workspace()` gets as `input.workspace`: the
|
|
3
|
+
description: "What the body of a `workspace()` gets as `input.workspace`: the folder of each Repo Slot."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# `WorkspaceHandles`
|
|
@@ -13,11 +13,10 @@ type WorkspaceHandles<TSlots extends string> = [TSlots] extends [never]
|
|
|
13
13
|
: SlotHandles<TSlots>;
|
|
14
14
|
```
|
|
15
15
|
|
|
16
|
-
What the body of a `workspace()` gets as `input.workspace`: the
|
|
17
|
-
|
|
16
|
+
What the body of a `workspace()` gets as `input.workspace`: the folder of each Repo Slot. A path
|
|
17
|
+
is correct in each Instance that registers the Machine.
|
|
18
18
|
|
|
19
19
|
`TSlots` is the names of the Repo Slots that the body reads. `workspace()` refuses a body that
|
|
20
20
|
names a slot that the Workspace does not have. Write `string` for a body that names no slot and
|
|
21
|
-
reads the
|
|
22
|
-
Workspace with no Repo Slot: its handles are `{ repos: {} }`,
|
|
23
|
-
in `/work`.
|
|
21
|
+
reads the folders in the order of `repos`, as under `repos: open`. Write `never` for a
|
|
22
|
+
Workspace with no Repo Slot: its handles are `{ repos: {} }`, and its Agents work in `/work`.
|
|
@@ -13,7 +13,6 @@ type WorkspaceOptions<TSchema extends z.ZodObject, TSlots extends string> = Sand
|
|
|
13
13
|
z.infer<TSchema>
|
|
14
14
|
> & {
|
|
15
15
|
input: TSchema;
|
|
16
|
-
spec: (args: { input: WithoutEmptyIndex<z.infer<TSchema>> & HostInjectedInput }) => WorkspaceSpec;
|
|
17
16
|
};
|
|
18
17
|
```
|
|
19
18
|
|
|
@@ -24,16 +23,5 @@ The options of a `workspace()` that declares the input that starts a run.
|
|
|
24
23
|
- `input`: `TSchema`
|
|
25
24
|
|
|
26
25
|
The input that starts a run, as a `z.object`. jr2 checks each start against it. It also types
|
|
27
|
-
the `input` of
|
|
26
|
+
the `input` of a per-run Repo Slot, and the body must accept it plus the
|
|
28
27
|
`workspace` handles. Write it here, not on the body.
|
|
29
|
-
- `spec`: `(args: { input: WithoutEmptyIndex<z.infer<TSchema>> & HostInjectedInput; }) => WorkspaceSpec`
|
|
30
|
-
|
|
31
|
-
A function from the run input to the Workspace's [`WorkspaceSpec`](type-workspacespec.md): the `branch` it works
|
|
32
|
-
on, and optionally `reviewSha` and `workGroup`. jr2 calls it when the run enters the
|
|
33
|
-
Workspace.
|
|
34
|
-
|
|
35
|
-
The input of `spec` also holds `instanceId`, the seed Instance ID of the run (see
|
|
36
|
-
[`HostInjectedInput`](type-hostinjectedinput.md)). Use it to give each run a branch of its own:
|
|
37
|
-
``spec: ({ input }) => ({ branch: `fix/${input.instanceId}` })``. Only a root `workspace()` gets
|
|
38
|
-
it from jr2. A `workspace()` that a different Machine invokes gets only the input that its
|
|
39
|
-
parent gives it, so that parent must give `instanceId` when `spec` reads it.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: WorktreeFound
|
|
3
|
+
description: "What a cut found: `held`, a cut made this Worktree earlier, so what is in it is earlier work; `local`, a local branch; `remote`, `origin/<branch>`, now tracked; `none`, a new branch with no upstream; `commit`, a detached cut."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# `WorktreeFound`
|
|
7
|
+
|
|
8
|
+
Type, in `@jr2/orchestrator/src/worktree.ts`. It is an export of `@jr2/orchestrator`, on the [Authoring surface](../authoring-surface.md) page, in Effects.
|
|
9
|
+
|
|
10
|
+
```ts
|
|
11
|
+
type WorktreeFound = "held" | "local" | "remote" | "none" | "commit" | (string & {});
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
What a cut found: `held`, a cut made this Worktree earlier, so what is in it is earlier work;
|
|
15
|
+
`local`, a local branch; `remote`, `origin/<branch>`, now tracked; `none`, a new branch with no
|
|
16
|
+
upstream; `commit`, a detached cut. Open: a later value does not break an author's code.
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: WorktreeInput
|
|
3
|
+
description: "The input of a `worktree()`: a branch Worktree, or a detached one."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# `WorktreeInput`
|
|
7
|
+
|
|
8
|
+
Type, in `@jr2/orchestrator/src/worktree.ts`. It is an export of `@jr2/orchestrator`, on the [Authoring surface](../authoring-surface.md) page, in Effects.
|
|
9
|
+
|
|
10
|
+
```ts
|
|
11
|
+
type WorktreeInput =
|
|
12
|
+
| {
|
|
13
|
+
path: AnyWorktreePath;
|
|
14
|
+
branch: string;
|
|
15
|
+
from?: string;
|
|
16
|
+
detach?: never;
|
|
17
|
+
expect?: never;
|
|
18
|
+
}
|
|
19
|
+
| {
|
|
20
|
+
path: AnyWorktreePath;
|
|
21
|
+
detach: string;
|
|
22
|
+
branch?: never;
|
|
23
|
+
from?: never;
|
|
24
|
+
expect?: never;
|
|
25
|
+
};
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
The input of a `worktree()`: a branch Worktree, or a detached one.
|
|
29
|
+
|
|
30
|
+
**Forms**: it is one of these objects.
|
|
31
|
+
|
|
32
|
+
- Form 1: `path`, `branch`, `from`, `detach`, `expect`
|
|
33
|
+
|
|
34
|
+
- `path`: [`AnyWorktreePath`](type-anyworktreepath.md)
|
|
35
|
+
|
|
36
|
+
The root of the Worktree: `${context.workspace.repos.app}/<name>`, a constant word.
|
|
37
|
+
- `branch`: `string`
|
|
38
|
+
|
|
39
|
+
The branch. It resolves as a local branch, then `origin/<branch>` (tracked), then a new
|
|
40
|
+
branch.
|
|
41
|
+
- `from` (optional): `string`
|
|
42
|
+
|
|
43
|
+
Where a new branch starts. Default: the Binding's base. On a branch that exists, it must
|
|
44
|
+
be that branch's tip, or the cut is `refused`.
|
|
45
|
+
- `detach` (optional): `never`
|
|
46
|
+
- `expect` (optional): `never`
|
|
47
|
+
- Form 2: `path`, `detach`, `branch`, `from`, `expect`
|
|
48
|
+
|
|
49
|
+
- `path`: [`AnyWorktreePath`](type-anyworktreepath.md)
|
|
50
|
+
- `detach`: `string`
|
|
51
|
+
|
|
52
|
+
The commit to check out, with no branch. The Worktree is forced to it and cleaned on each
|
|
53
|
+
cut. Ignored files stay, so that a reviewer can run the tests.
|
|
54
|
+
- `branch` (optional): `never`
|
|
55
|
+
- `from` (optional): `never`
|
|
56
|
+
- `expect` (optional): `never`
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: WorktreeKey
|
|
3
|
+
description: A type that the Authoring surface names.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# `WorktreeKey`
|
|
7
|
+
|
|
8
|
+
Type, in `@jr2/orchestrator/src/effect.ts`. It is type plumbing: it computes a type from the types of a Machine or of its parts, and a workflow module does not write it. The signature of an export, or a type that it names, names this type, so its declaration is here. The [Authoring surface](../authoring-surface.md) page lists each export.
|
|
9
|
+
|
|
10
|
+
```ts
|
|
11
|
+
type WorktreeKey<Opt> = [Opt] extends [{ readonly env: object }]
|
|
12
|
+
? { worktree: AnyWorktreePath }
|
|
13
|
+
: { worktree?: AnyWorktreePath };
|
|
14
|
+
```
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: WorktreeOptions
|
|
3
|
+
description: The options of `worktree()`.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# `WorktreeOptions`
|
|
7
|
+
|
|
8
|
+
Type, in `@jr2/orchestrator/src/worktree.ts`. It is an export of `@jr2/orchestrator`, on the [Authoring surface](../authoring-surface.md) page, in Effects.
|
|
9
|
+
|
|
10
|
+
```ts
|
|
11
|
+
type WorktreeOptions = {
|
|
12
|
+
expect?: "new" | "existing";
|
|
13
|
+
timeout?: Duration;
|
|
14
|
+
};
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
The options of `worktree()`.
|
|
18
|
+
|
|
19
|
+
**Fields**
|
|
20
|
+
|
|
21
|
+
- `expect` (optional): `"new" | "existing"`
|
|
22
|
+
|
|
23
|
+
`"new"`: refuse a branch that exists, local or on the remote. For a name that a planner or a
|
|
24
|
+
door chose for new work: a collision is a refusal, not someone else's branch. `"existing"`:
|
|
25
|
+
refuse a branch that does not exist, and make nothing. For a run that must continue a branch.
|
|
26
|
+
A Chart cannot change it, and a cut lent to a Chart must state it.
|
|
27
|
+
- `timeout` (optional): [`Duration`](type-duration.md)
|
|
28
|
+
|
|
29
|
+
How long the fetch and the cut can take. Default `"10m"`.
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: WorktreeOutput
|
|
3
|
+
description: The output of a `worktree()`.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# `WorktreeOutput`
|
|
7
|
+
|
|
8
|
+
Type, in `@jr2/orchestrator/src/worktree.ts`. It is an export of `@jr2/orchestrator`, on the [Authoring surface](../authoring-surface.md) page, in Effects.
|
|
9
|
+
|
|
10
|
+
```ts
|
|
11
|
+
type WorktreeOutput<S extends string = string> = WorktreeReady<S> | WorktreeRefused | Unknown | LaterOutcome;
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
The output of a `worktree()`. `unknown`: its state exited while it ran, or the cut did not end.
|
|
15
|
+
|
|
16
|
+
**Forms**: it is one of these objects.
|
|
17
|
+
|
|
18
|
+
- Form 1: `outcome`, `reason`
|
|
19
|
+
|
|
20
|
+
- `outcome`: `"unknown"`
|
|
21
|
+
- `reason`: `string`
|
|
22
|
+
- Form 2: `outcome`, `slot`, `path`, `branch`, `head`, `found`, `stale`
|
|
23
|
+
|
|
24
|
+
- `outcome`: `"ready"`
|
|
25
|
+
- `slot`: `S`
|
|
26
|
+
- `path`: `WorktreePath<S>`
|
|
27
|
+
- `branch`: `string | null`
|
|
28
|
+
|
|
29
|
+
The branch of the cut, from git and the cut's record, never from the folder or HEAD. `null`
|
|
30
|
+
when the Worktree is detached.
|
|
31
|
+
- `head`: `string`
|
|
32
|
+
|
|
33
|
+
The tip of `branch` (of the commit, when detached). Never HEAD.
|
|
34
|
+
- `found`: [`WorktreeFound`](type-worktreefound.md)
|
|
35
|
+
- `stale` (optional): `string`
|
|
36
|
+
|
|
37
|
+
[ADR-0053](../decisions/0053-a-fetch-inside-the-pod-asks-the-node-cache-and-the-cache-asks-the-remote.md)'s words when the remote did not answer. The cut used what the clone holds.
|
|
38
|
+
- Form 3: `outcome`, `reason`
|
|
39
|
+
|
|
40
|
+
- `outcome`: `"refused"`
|
|
41
|
+
- `reason`: `string`
|
|
42
|
+
- Form 4: `outcome`, `reason`
|
|
43
|
+
|
|
44
|
+
- `outcome`: `"(a later outcome)"`
|
|
45
|
+
- `reason` (optional): `string`
|