@usine/executor 0.1.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +52 -21
- package/dist/child-command.d.ts +8 -5
- package/dist/child-command.d.ts.map +1 -1
- package/dist/child-command.js +10 -7
- package/dist/child-command.js.map +1 -1
- package/dist/exe-dev/channel.d.ts +8 -4
- package/dist/exe-dev/channel.d.ts.map +1 -1
- package/dist/exe-dev/channel.js +16 -19
- package/dist/exe-dev/channel.js.map +1 -1
- package/dist/exe-dev/commands.d.ts +1 -1
- package/dist/exe-dev/commands.d.ts.map +1 -1
- package/dist/exe-dev/commands.js +7 -8
- package/dist/exe-dev/commands.js.map +1 -1
- package/dist/exe-dev/exe-dev.d.ts +8 -0
- package/dist/exe-dev/exe-dev.d.ts.map +1 -0
- package/dist/exe-dev/exe-dev.js +154 -0
- package/dist/exe-dev/exe-dev.js.map +1 -0
- package/dist/exe-dev/grants.d.ts +3 -4
- package/dist/exe-dev/grants.d.ts.map +1 -1
- package/dist/exe-dev/grants.js +31 -15
- package/dist/exe-dev/grants.js.map +1 -1
- package/dist/exe-dev/model.d.ts +8 -23
- package/dist/exe-dev/model.d.ts.map +1 -1
- package/dist/exe-dev/model.js +5 -12
- package/dist/exe-dev/model.js.map +1 -1
- package/dist/exe-dev/preflight.d.ts +3 -2
- package/dist/exe-dev/preflight.d.ts.map +1 -1
- package/dist/exe-dev/preflight.js +8 -8
- package/dist/exe-dev/preflight.js.map +1 -1
- package/dist/exe-dev/shell.d.ts +5 -5
- package/dist/exe-dev/shell.d.ts.map +1 -1
- package/dist/exe-dev/shell.js +7 -7
- package/dist/exe-dev/shell.js.map +1 -1
- package/dist/exe-dev/sweep.d.ts +3 -5
- package/dist/exe-dev/sweep.d.ts.map +1 -1
- package/dist/exe-dev/sweep.js +8 -10
- package/dist/exe-dev/sweep.js.map +1 -1
- package/dist/executor.d.ts +122 -0
- package/dist/executor.d.ts.map +1 -0
- package/dist/executor.js +100 -0
- package/dist/executor.js.map +1 -0
- package/dist/guard.d.ts +11 -0
- package/dist/guard.d.ts.map +1 -0
- package/dist/guard.js +74 -0
- package/dist/guard.js.map +1 -0
- package/dist/harness-preflight.d.ts +6 -0
- package/dist/harness-preflight.d.ts.map +1 -0
- package/dist/harness-preflight.js +50 -0
- package/dist/harness-preflight.js.map +1 -0
- package/dist/invalid-frame.d.ts +1 -1
- package/dist/invalid-frame.d.ts.map +1 -1
- package/dist/invalid-frame.js +2 -1
- package/dist/invalid-frame.js.map +1 -1
- package/dist/keyed-lock.d.ts +2 -2
- package/dist/keyed-lock.js +2 -2
- package/dist/local/local.d.ts +20 -0
- package/dist/local/local.d.ts.map +1 -0
- package/dist/local/{index.js → local.js} +87 -115
- package/dist/local/local.js.map +1 -0
- package/dist/prepared-attempt.d.ts +5 -0
- package/dist/prepared-attempt.d.ts.map +1 -0
- package/dist/prepared-attempt.js +32 -0
- package/dist/prepared-attempt.js.map +1 -0
- package/dist/provision.d.ts +20 -10
- package/dist/provision.d.ts.map +1 -1
- package/dist/provision.js +94 -23
- package/dist/provision.js.map +1 -1
- package/dist/run-host-session.d.ts +13 -8
- package/dist/run-host-session.d.ts.map +1 -1
- package/dist/run-host-session.js +116 -41
- package/dist/run-host-session.js.map +1 -1
- package/package.json +11 -11
- package/dist/exe-dev/index.d.ts +0 -8
- package/dist/exe-dev/index.d.ts.map +0 -1
- package/dist/exe-dev/index.js +0 -239
- package/dist/exe-dev/index.js.map +0 -1
- package/dist/index.d.ts +0 -82
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -82
- package/dist/index.js.map +0 -1
- package/dist/local/index.d.ts +0 -15
- package/dist/local/index.d.ts.map +0 -1
- package/dist/local/index.js.map +0 -1
|
@@ -1,16 +1,20 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
1
|
+
import * as AttemptChannel from "@usine/core/attempt/channel";
|
|
2
|
+
import { RepositoryName } from "@usine/core/repository";
|
|
3
|
+
import { InstanceDirectory } from "@usine/core/instance";
|
|
4
|
+
import { Effect, FileSystem, Layer, Path, Redacted, Result, Schema, Stream, } from "effect";
|
|
3
5
|
import { ChildProcess, ChildProcessSpawner } from "effect/unstable/process";
|
|
4
6
|
import { allowlistedEnvironment, collectCommand, requireSuccess } from "../child-command.js";
|
|
5
|
-
import { CheckoutRequest, CredentialProvider, Executor, ExecutorError, ExecutorOperationError, logPreflightFailure, WorkerCapabilityError, } from "../
|
|
7
|
+
import { CheckoutRequest, CredentialProvider, Executor, ExecutorError, ExecutorOperationError, logPreflightFailure, WorkerCapabilityError, } from "../executor.js";
|
|
8
|
+
import { verifyHarnesses } from "../harness-preflight.js";
|
|
9
|
+
import { prepareAttempt } from "../prepared-attempt.js";
|
|
6
10
|
import { keyedLockFor } from "../keyed-lock.js";
|
|
7
|
-
import { provisionWorktree, safeSegment } from "../provision.js";
|
|
11
|
+
import { cacheDirectoryName, isCacheDirectoryName, provisionWorktree, safeSegment, } from "../provision.js";
|
|
8
12
|
import { runHostSessionFor } from "../run-host-session.js";
|
|
9
13
|
const isExecutorError = Schema.is(ExecutorError);
|
|
10
14
|
/**
|
|
11
|
-
* The run host
|
|
12
|
-
*
|
|
13
|
-
* (ADR 0011
|
|
15
|
+
* The run host inherits only these variables. The App private key and every
|
|
16
|
+
* other orchestrator secret stay out; the single-repo worker token is the only
|
|
17
|
+
* credential it receives (ADR 0011).
|
|
14
18
|
*/
|
|
15
19
|
const HOST_ENVIRONMENT_ALLOWLIST = [
|
|
16
20
|
"HOME",
|
|
@@ -22,7 +26,7 @@ const HOST_ENVIRONMENT_ALLOWLIST = [
|
|
|
22
26
|
"USER",
|
|
23
27
|
];
|
|
24
28
|
const executorError = (operation, message, cause) => new ExecutorOperationError({ operation, message, cause });
|
|
25
|
-
/**
|
|
29
|
+
/** Removes the credential from text before it can reach a persisted error message. */
|
|
26
30
|
const scrubbed = (text, credential) => text.replaceAll(Redacted.value(credential), "[REDACTED]");
|
|
27
31
|
const credentialEnvironment = (base, credential) => {
|
|
28
32
|
const token = Redacted.value(credential);
|
|
@@ -41,7 +45,6 @@ const makeLocalExecutor = (options) => Effect.gen(function* () {
|
|
|
41
45
|
const path = yield* Path.Path;
|
|
42
46
|
const spawner = yield* ChildProcessSpawner.ChildProcessSpawner;
|
|
43
47
|
const fetches = yield* keyedLockFor();
|
|
44
|
-
const preparedStates = yield* Ref.make(new Map());
|
|
45
48
|
const baseEnvironment = yield* allowlistedEnvironment(HOST_ENVIRONMENT_ALLOWLIST);
|
|
46
49
|
const repositoryUrl = options.repositoryUrl ??
|
|
47
50
|
((repository) => `https://github.com/${repository}.git`);
|
|
@@ -60,9 +63,9 @@ const makeLocalExecutor = (options) => Effect.gen(function* () {
|
|
|
60
63
|
const run = Effect.fn("LocalExecutor.run")(function* (operation, command, args, commandOptions = {}) {
|
|
61
64
|
yield* executeCommand(operation, command, args, commandOptions);
|
|
62
65
|
});
|
|
63
|
-
//
|
|
64
|
-
// leaves
|
|
65
|
-
//
|
|
66
|
+
// Worktrees never outlive their Attempt (ADR 0006). A crashed orchestrator
|
|
67
|
+
// leaves directories and bare-cache registrations behind; the sweep reclaims
|
|
68
|
+
// them at the next layer build, before new Attempts start.
|
|
66
69
|
const sweepAbandonedWorktrees = Effect.fn("LocalExecutor.sweepAbandonedWorktrees")(function* () {
|
|
67
70
|
if (!(yield* fileSystem.exists(workersRoot)))
|
|
68
71
|
return;
|
|
@@ -83,27 +86,52 @@ const makeLocalExecutor = (options) => Effect.gen(function* () {
|
|
|
83
86
|
}
|
|
84
87
|
const reposRoot = path.join(workersRoot, worker, "repos");
|
|
85
88
|
if (yield* fileSystem.exists(reposRoot)) {
|
|
86
|
-
const
|
|
87
|
-
|
|
88
|
-
|
|
89
|
+
const entries = yield* fileSystem.readDirectory(reposRoot);
|
|
90
|
+
let pruned = 0;
|
|
91
|
+
let skipped = 0;
|
|
92
|
+
let failed = 0;
|
|
93
|
+
for (const entry of entries) {
|
|
94
|
+
if (!isCacheDirectoryName(entry)) {
|
|
95
|
+
yield* Effect.logDebug("Skipping a non-cache entry during the local cache sweep", {
|
|
96
|
+
worker,
|
|
97
|
+
host: "local",
|
|
98
|
+
entry,
|
|
99
|
+
});
|
|
100
|
+
skipped += 1;
|
|
101
|
+
continue;
|
|
102
|
+
}
|
|
103
|
+
const result = yield* run("cleanup", "git", [
|
|
89
104
|
"--git-dir",
|
|
90
|
-
path.join(reposRoot,
|
|
105
|
+
path.join(reposRoot, entry),
|
|
91
106
|
"worktree",
|
|
92
107
|
"prune",
|
|
93
108
|
]).pipe(Effect.tapError((error) => Effect.logWarning("Could not prune a bare cache during the sweep", {
|
|
94
109
|
worker,
|
|
95
110
|
host: "local",
|
|
96
|
-
cache,
|
|
111
|
+
cache: entry,
|
|
97
112
|
message: error.message,
|
|
98
|
-
})), Effect.
|
|
113
|
+
})), Effect.result);
|
|
114
|
+
if (Result.isSuccess(result)) {
|
|
115
|
+
pruned += 1;
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
failed += 1;
|
|
119
|
+
}
|
|
99
120
|
}
|
|
121
|
+
yield* Effect.logInfo("Local cache sweep completed", {
|
|
122
|
+
worker,
|
|
123
|
+
host: "local",
|
|
124
|
+
pruned,
|
|
125
|
+
skipped,
|
|
126
|
+
failed,
|
|
127
|
+
});
|
|
100
128
|
}
|
|
101
129
|
}
|
|
102
130
|
});
|
|
103
131
|
yield* sweepAbandonedWorktrees().pipe(Effect.tapError((error) => Effect.logWarning("Abandoned-worktree sweep failed; continuing", {
|
|
104
132
|
message: String(error),
|
|
105
133
|
})), Effect.ignore);
|
|
106
|
-
const preflight = Effect.fn("LocalExecutor.preflight")(function* (worker) {
|
|
134
|
+
const preflight = Effect.fn("LocalExecutor.preflight")(function* (worker, brains) {
|
|
107
135
|
yield* Effect.annotateCurrentSpan({ worker, host: "local" });
|
|
108
136
|
const gitVersion = (yield* executeCommand("preflight", "git", ["--version"])).trim();
|
|
109
137
|
if (!gitVersion.startsWith("git version ")) {
|
|
@@ -126,6 +154,7 @@ const makeLocalExecutor = (options) => Effect.gen(function* () {
|
|
|
126
154
|
cause: new Error("run-host protocol mismatch"),
|
|
127
155
|
});
|
|
128
156
|
}
|
|
157
|
+
yield* verifyHarnesses(worker, brains, runHost, (command, args) => executeCommand("preflight", command, args));
|
|
129
158
|
yield* Effect.logInfo("Worker preflight verified", {
|
|
130
159
|
worker,
|
|
131
160
|
host: "local",
|
|
@@ -140,9 +169,12 @@ const makeLocalExecutor = (options) => Effect.gen(function* () {
|
|
|
140
169
|
host: "local",
|
|
141
170
|
repository: request.repository,
|
|
142
171
|
});
|
|
143
|
-
|
|
172
|
+
yield* verifyHarnesses(request.worker, [request.agent.brain], runHost, (command, args) => executeCommand("preflight", command, args));
|
|
173
|
+
const credential = yield* Effect.acquireRelease(credentials.issue(request.repository, request.attemptId), (token) => Effect.sync(() => {
|
|
174
|
+
Redacted.wipeUnsafe(token);
|
|
175
|
+
}), { interruptible: true });
|
|
144
176
|
const workerRoot = path.join(workersRoot, request.worker);
|
|
145
|
-
const cache = path.join(workerRoot, "repos",
|
|
177
|
+
const cache = path.join(workerRoot, "repos", cacheDirectoryName(request.repository));
|
|
146
178
|
const worktree = path.join(workerRoot, "attempts", safeSegment(request.attemptId));
|
|
147
179
|
const environment = credentialEnvironment(baseEnvironment, credential);
|
|
148
180
|
const commandOptions = { env: environment, extendEnv: false };
|
|
@@ -154,13 +186,22 @@ const makeLocalExecutor = (options) => Effect.gen(function* () {
|
|
|
154
186
|
cache,
|
|
155
187
|
worktree,
|
|
156
188
|
});
|
|
157
|
-
const remove = (target) => fileSystem.remove(target, { recursive: true, force: true });
|
|
189
|
+
const remove = (_operation, target) => fileSystem.remove(target, { recursive: true, force: true });
|
|
158
190
|
const ops = {
|
|
159
191
|
ensureRoots: Effect.andThen(fileSystem.makeDirectory(path.dirname(cache), { recursive: true }), fileSystem.makeDirectory(path.dirname(worktree), { recursive: true })),
|
|
160
192
|
removePath: remove,
|
|
161
193
|
cacheExists: fileSystem.exists(cache),
|
|
162
194
|
promoteStaging: fileSystem.rename(`${cache}.cloning`, cache),
|
|
163
|
-
git: (args) =>
|
|
195
|
+
git: (operation, args) => Effect.gen(function* () {
|
|
196
|
+
// Git can echo the ambient token in diagnostics. Scrub before forming
|
|
197
|
+
// an error or passing its stdout to the revision parser.
|
|
198
|
+
const result = yield* collectCommand(spawner, operation, "git", args, commandOptions);
|
|
199
|
+
return yield* requireSuccess(operation, "local", "git", args, {
|
|
200
|
+
...result,
|
|
201
|
+
stdout: scrubbed(result.stdout, credential),
|
|
202
|
+
stderr: scrubbed(result.stderr, credential),
|
|
203
|
+
});
|
|
204
|
+
}),
|
|
164
205
|
};
|
|
165
206
|
const prepared = yield* fetches
|
|
166
207
|
.withLock(request.repository)(provisionWorktree({
|
|
@@ -172,131 +213,62 @@ const makeLocalExecutor = (options) => Effect.gen(function* () {
|
|
|
172
213
|
}))
|
|
173
214
|
.pipe(Effect.mapError((error) => isExecutorError(error)
|
|
174
215
|
? error
|
|
175
|
-
: executorError("prepare", "Attempt workspace preparation failed", error))
|
|
176
|
-
yield* fileSystem.remove(worktree, { recursive: true, force: true }).pipe(Effect.tapError((error) => Effect.logWarning("Could not remove a partial local workspace", {
|
|
177
|
-
attemptId: request.attemptId,
|
|
178
|
-
worker: request.worker,
|
|
179
|
-
host: "local",
|
|
180
|
-
worktree,
|
|
181
|
-
message: String(error),
|
|
182
|
-
})), Effect.ignore);
|
|
183
|
-
Redacted.wipeUnsafe(credential);
|
|
184
|
-
})));
|
|
185
|
-
yield* Ref.update(preparedStates, (current) => {
|
|
186
|
-
const next = new Map(current);
|
|
187
|
-
next.set(request.attemptId, { cache, credential });
|
|
188
|
-
return next;
|
|
189
|
-
});
|
|
216
|
+
: executorError("prepare", "Attempt workspace preparation failed", error)));
|
|
190
217
|
yield* Effect.logInfo("Attempt workspace ready", {
|
|
191
218
|
attemptId: request.attemptId,
|
|
192
219
|
baseCommit: prepared.spec.baseCommit,
|
|
193
220
|
worktree,
|
|
194
221
|
});
|
|
195
|
-
return
|
|
196
|
-
|
|
197
|
-
|
|
222
|
+
return {
|
|
223
|
+
workspace: prepared,
|
|
224
|
+
launch: (io) => session.launch(prepared, io, (input) => spawn(prepared, credential, input)),
|
|
225
|
+
};
|
|
226
|
+
}, prepareAttempt);
|
|
227
|
+
const spawn = Effect.fn("LocalExecutor.spawnRunHost")(function* (prepared, credential, input) {
|
|
198
228
|
const attemptId = prepared.spec.attemptId;
|
|
199
229
|
yield* Effect.annotateCurrentSpan({
|
|
200
230
|
attemptId,
|
|
201
231
|
worker: prepared.worker,
|
|
202
232
|
host: "local",
|
|
203
233
|
});
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
}
|
|
234
|
+
// A linked worktree's git common dir is the bare cache itself, and Turbo
|
|
235
|
+
// puts its cache next to the common dir, so an unscoped run from the
|
|
236
|
+
// worktree would write `repos/.turbo` beside the bare caches. The Worker
|
|
237
|
+
// cache is shared across that Worker's Attempts and stays out of the
|
|
238
|
+
// directory the startup sweep treats as cache storage.
|
|
239
|
+
const turboCache = path.join(workersRoot, prepared.worker, "turbo");
|
|
211
240
|
yield* Effect.logInfo("Launching the run host", {
|
|
212
241
|
attemptId,
|
|
213
242
|
worker: prepared.worker,
|
|
214
243
|
host: "local",
|
|
215
244
|
command: runHost.command,
|
|
216
245
|
worktree: prepared.worktree,
|
|
246
|
+
turboCache,
|
|
217
247
|
});
|
|
218
248
|
const handle = yield* spawner.spawn(ChildProcess.make(runHost.command, runHost.args, {
|
|
219
249
|
cwd: prepared.worktree,
|
|
220
|
-
env:
|
|
250
|
+
env: {
|
|
251
|
+
...credentialEnvironment(baseEnvironment, credential),
|
|
252
|
+
TURBO_CACHE_DIR: turboCache,
|
|
253
|
+
},
|
|
221
254
|
extendEnv: false,
|
|
222
255
|
stdin: { stream: Stream.fromQueue(input), endOnDone: true },
|
|
223
256
|
}));
|
|
224
257
|
return {
|
|
225
258
|
handle,
|
|
226
259
|
host: "local",
|
|
227
|
-
scrub: (text) => scrubbed(text,
|
|
260
|
+
scrub: (text) => scrubbed(text, credential),
|
|
228
261
|
};
|
|
229
262
|
});
|
|
230
|
-
const session = yield* runHostSessionFor({ interruptGrace
|
|
231
|
-
const cleanup = Effect.fn("LocalExecutor.cleanup")(function* (prepared) {
|
|
232
|
-
const attemptId = prepared.spec.attemptId;
|
|
233
|
-
yield* Effect.annotateCurrentSpan({
|
|
234
|
-
attemptId,
|
|
235
|
-
worker: prepared.worker,
|
|
236
|
-
host: "local",
|
|
237
|
-
});
|
|
238
|
-
yield* Effect.logInfo("Cleaning Attempt workspace", {
|
|
239
|
-
attemptId,
|
|
240
|
-
worker: prepared.worker,
|
|
241
|
-
host: "local",
|
|
242
|
-
worktree: prepared.worktree,
|
|
243
|
-
});
|
|
244
|
-
const state = (yield* Ref.get(preparedStates)).get(attemptId);
|
|
245
|
-
if (state === undefined) {
|
|
246
|
-
yield* fileSystem
|
|
247
|
-
.remove(prepared.worktree, { recursive: true, force: true })
|
|
248
|
-
.pipe(Effect.mapError((cause) => executorError("cleanup", `Could not remove ${prepared.worktree}`, cause)));
|
|
249
|
-
return;
|
|
250
|
-
}
|
|
251
|
-
const finish = Effect.gen(function* () {
|
|
252
|
-
const removedFromGit = yield* run("cleanup", "git", [
|
|
253
|
-
"--git-dir",
|
|
254
|
-
state.cache,
|
|
255
|
-
"worktree",
|
|
256
|
-
"remove",
|
|
257
|
-
"--force",
|
|
258
|
-
prepared.worktree,
|
|
259
|
-
]).pipe(Effect.result);
|
|
260
|
-
const removedFromDisk = yield* fileSystem
|
|
261
|
-
.remove(prepared.worktree, { recursive: true, force: true })
|
|
262
|
-
.pipe(Effect.mapError((cause) => executorError("cleanup", `Could not remove ${prepared.worktree}`, cause)), Effect.result);
|
|
263
|
-
const pruned = yield* run("cleanup", "git", [
|
|
264
|
-
"--git-dir",
|
|
265
|
-
state.cache,
|
|
266
|
-
"worktree",
|
|
267
|
-
"prune",
|
|
268
|
-
]).pipe(Effect.result);
|
|
269
|
-
for (const result of [removedFromGit, removedFromDisk, pruned]) {
|
|
270
|
-
if (Result.isFailure(result)) {
|
|
271
|
-
return yield* result.failure;
|
|
272
|
-
}
|
|
273
|
-
}
|
|
274
|
-
}).pipe(Effect.mapError((cause) => isExecutorError(cause)
|
|
275
|
-
? cause
|
|
276
|
-
: executorError("cleanup", `Could not clean Attempt ${attemptId}`, cause)));
|
|
277
|
-
yield* finish.pipe(Effect.ensuring(Effect.gen(function* () {
|
|
278
|
-
yield* Ref.update(preparedStates, (current) => {
|
|
279
|
-
const next = new Map(current);
|
|
280
|
-
next.delete(attemptId);
|
|
281
|
-
return next;
|
|
282
|
-
});
|
|
283
|
-
Redacted.wipeUnsafe(state.credential);
|
|
284
|
-
})));
|
|
285
|
-
yield* Effect.logInfo("Attempt cleanup completed", {
|
|
286
|
-
attemptId,
|
|
287
|
-
worker: prepared.worker,
|
|
288
|
-
host: "local",
|
|
289
|
-
});
|
|
290
|
-
});
|
|
263
|
+
const session = yield* runHostSessionFor({ interruptGrace });
|
|
291
264
|
return Executor.of({
|
|
292
265
|
kind: "local",
|
|
293
266
|
cancel: session.cancel,
|
|
294
|
-
|
|
295
|
-
launch: session.launch,
|
|
267
|
+
intervene: session.intervene,
|
|
296
268
|
preflight,
|
|
297
269
|
prepare,
|
|
298
270
|
});
|
|
299
271
|
});
|
|
300
|
-
/**
|
|
272
|
+
/** Runs Attempts in isolated checkouts on the local machine. Requires Node; worker contracts are platform-free. */
|
|
301
273
|
export const layer = (options) => Layer.effect(Executor, makeLocalExecutor(options));
|
|
302
|
-
//# sourceMappingURL=
|
|
274
|
+
//# sourceMappingURL=local.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"local.js","sourceRoot":"","sources":["../../src/local/local.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { Effect, Scope } from "effect";
|
|
2
|
+
import type { CheckoutRequest, ExecutorError, PreparedAttempt } from "./executor.ts";
|
|
3
|
+
/** Owns partial preparation and the run host in one child scope, released at the Attempt's end. */
|
|
4
|
+
export declare const prepareAttempt: (acquire: Effect.Effect<PreparedAttempt, ExecutorError, Scope.Scope>, request: CheckoutRequest) => Effect.Effect<PreparedAttempt, ExecutorError, Scope.Scope>;
|
|
5
|
+
//# sourceMappingURL=prepared-attempt.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prepared-attempt.d.ts","sourceRoot":"","sources":["../src/prepared-attempt.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAoB,KAAK,EAAE,MAAM,QAAQ,CAAC;AACzD,OAAO,KAAK,EAAE,eAAe,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAGrF,mGAAmG;AACnG,eAAO,MAAM,cAAc,YAChB,MAAM,CAAC,MAAM,CAAC,eAAe,EAAE,aAAa,EAAE,KAAK,CAAC,KAAK,CAAC,WAC1D,eAAe,KACvB,MAAM,CAAC,MAAM,CAAC,eAAe,EAAE,aAAa,EAAE,KAAK,CAAC,KAAK,CAqCzD,CAAC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { InfraFailure } from "@usine/core/attempt/failure";
|
|
2
|
+
import { Effect, Exit, Fiber, Ref, Scope } from "effect";
|
|
3
|
+
import { withAttemptGuard } from "./guard.js";
|
|
4
|
+
/** Owns partial preparation and the run host in one child scope, released at the Attempt's end. */
|
|
5
|
+
export const prepareAttempt = (acquire, request) => Effect.uninterruptibleMask((restore) => Effect.gen(function* () {
|
|
6
|
+
const scope = yield* Scope.fork(yield* Effect.scope);
|
|
7
|
+
// acquireRelease masks acquisition by default in Effect rc.111. Only the
|
|
8
|
+
// ownership transfer is masked here; clone, fetch, and lock waits must stop
|
|
9
|
+
// promptly. Each acquiring implementation registers its own finalizers.
|
|
10
|
+
const prepared = yield* restore(acquire).pipe(Scope.provide(scope), Effect.onError((cause) => Scope.close(scope, Exit.failCause(cause))));
|
|
11
|
+
const unavailable = yield* Ref.make(false);
|
|
12
|
+
yield* Scope.addFinalizer(scope, Ref.set(unavailable, true));
|
|
13
|
+
return {
|
|
14
|
+
workspace: prepared.workspace,
|
|
15
|
+
launch: Effect.fn("PreparedAttempt.launch")(function* (io) {
|
|
16
|
+
const attemptId = prepared.workspace.spec.attemptId;
|
|
17
|
+
yield* Effect.annotateCurrentSpan({ attemptId, worker: prepared.workspace.worker });
|
|
18
|
+
if (yield* Ref.getAndSet(unavailable, true)) {
|
|
19
|
+
yield* Effect.logWarning("Attempt was already launched or released", { attemptId });
|
|
20
|
+
return yield* new InfraFailure({
|
|
21
|
+
message: `Attempt ${attemptId} was already launched or released`,
|
|
22
|
+
cause: new Error("prepared Attempt is no longer available"),
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
// Closing the owner's scope interrupts the session before checkout and
|
|
26
|
+
// credential finalizers. Interrupting a caller waiting on join must also
|
|
27
|
+
// stop that scoped fiber, so timeout/cancel completes the handshake first.
|
|
28
|
+
return yield* Effect.acquireUseRelease(Effect.forkIn(withAttemptGuard(request, io, prepared.launch), scope), Fiber.join, Fiber.interrupt).pipe(Effect.onExit((exit) => Scope.close(scope, exit)));
|
|
29
|
+
}),
|
|
30
|
+
};
|
|
31
|
+
}));
|
|
32
|
+
//# sourceMappingURL=prepared-attempt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prepared-attempt.js","sourceRoot":"","sources":["../src/prepared-attempt.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC3D,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAC;AAEzD,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAE9C,mGAAmG;AACnG,MAAM,CAAC,MAAM,cAAc,GAAG,CAC5B,OAAmE,EACnE,OAAwB,EACoC,EAAE,CAC9D,MAAM,CAAC,mBAAmB,CAAC,CAAC,OAAO,EAAE,EAAE,CACrC,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;IAClB,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACrD,yEAAyE;IACzE,4EAA4E;IAC5E,wEAAwE;IACxE,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,IAAI,CAC3C,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EACpB,MAAM,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CACrE,CAAC;IACF,MAAM,WAAW,GAAG,KAAK,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC3C,KAAK,CAAC,CAAC,KAAK,CAAC,YAAY,CAAC,KAAK,EAAE,GAAG,CAAC,GAAG,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC,CAAC;IAE7D,OAAO;QACL,SAAS,EAAE,QAAQ,CAAC,SAAS;QAC7B,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC,wBAAwB,CAAC,CAAC,QAAQ,CAAC,EAAE,EAAE;YACvD,MAAM,SAAS,GAAG,QAAQ,CAAC,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC;YACpD,KAAK,CAAC,CAAC,MAAM,CAAC,mBAAmB,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC;YACpF,IAAI,KAAK,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,WAAW,EAAE,IAAI,CAAC,EAAE,CAAC;gBAC5C,KAAK,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,0CAA0C,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC;gBACpF,OAAO,KAAK,CAAC,CAAC,IAAI,YAAY,CAAC;oBAC7B,OAAO,EAAE,WAAW,SAAS,mCAAmC;oBAChE,KAAK,EAAE,IAAI,KAAK,CAAC,yCAAyC,CAAC;iBAC5D,CAAC,CAAC;YACL,CAAC;YACD,uEAAuE;YACvE,yEAAyE;YACzE,2EAA2E;YAC3E,OAAO,KAAK,CAAC,CAAC,MAAM,CAAC,iBAAiB,CACpC,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,EAAE,EAAE,QAAQ,CAAC,MAAM,CAAC,EAAE,KAAK,CAAC,EACpE,KAAK,CAAC,IAAI,EACV,KAAK,CAAC,SAAS,CAChB,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC;QAC5D,CAAC,CAAC;KACuB,CAAC;AAC9B,CAAC,CAAC,CACH,CAAC"}
|
package/dist/provision.d.ts
CHANGED
|
@@ -1,7 +1,17 @@
|
|
|
1
|
+
import { RepositoryName } from "@usine/core/repository";
|
|
1
2
|
import { Effect } from "effect";
|
|
2
|
-
import { ExecutorOperationError,
|
|
3
|
+
import { ExecutorOperationError, AttemptWorkspace, type CheckoutRequest } from "./executor.ts";
|
|
3
4
|
export declare const safeSegment: (value: string) => string;
|
|
4
|
-
|
|
5
|
+
/** The bare cache directory name for a repository under `repos/`, shared by every adapter. */
|
|
6
|
+
export declare const cacheDirectoryName: (repository: RepositoryName) => string;
|
|
7
|
+
/**
|
|
8
|
+
* Whether a `repos/` entry is one of our bare caches, decided by the name we
|
|
9
|
+
* mint rather than by probing contents: a `HEAD` lookup fails with ENOTDIR on
|
|
10
|
+
* a stray file, and a `.cloning` leftover or a tool's scratch directory must
|
|
11
|
+
* never reach `git worktree prune`.
|
|
12
|
+
*/
|
|
13
|
+
export declare const isCacheDirectoryName: (entry: string) => boolean;
|
|
14
|
+
interface WorkspaceLayout {
|
|
5
15
|
readonly cache: string;
|
|
6
16
|
readonly staging: string;
|
|
7
17
|
readonly worktree: string;
|
|
@@ -9,11 +19,11 @@ export interface WorkspaceLayout {
|
|
|
9
19
|
/** The adapter-specific primitives; everything else about provisioning is shared. */
|
|
10
20
|
export interface WorkspaceOps<E> {
|
|
11
21
|
readonly ensureRoots: Effect.Effect<void, E>;
|
|
12
|
-
readonly removePath: (target: string) => Effect.Effect<void, E>;
|
|
22
|
+
readonly removePath: (operation: "prepare" | "cleanup", target: string) => Effect.Effect<void, E>;
|
|
13
23
|
readonly cacheExists: Effect.Effect<boolean, E>;
|
|
14
24
|
/** Atomically promote the finished staging clone to the cache path. */
|
|
15
25
|
readonly promoteStaging: Effect.Effect<void, E>;
|
|
16
|
-
readonly git: (args: ReadonlyArray<string>) => Effect.Effect<string, E>;
|
|
26
|
+
readonly git: (operation: "prepare" | "cleanup", args: ReadonlyArray<string>) => Effect.Effect<string, E>;
|
|
17
27
|
}
|
|
18
28
|
export interface ProvisionOptions<E> {
|
|
19
29
|
readonly request: CheckoutRequest;
|
|
@@ -23,11 +33,11 @@ export interface ProvisionOptions<E> {
|
|
|
23
33
|
readonly ops: WorkspaceOps<E>;
|
|
24
34
|
}
|
|
25
35
|
/**
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
* revision, and check out a detached worktree at the resolved commit.
|
|
36
|
+
* The clone-to-worktree sequence every Executor shares: clone into a staging
|
|
37
|
+
* sibling and promote it on success, so an interrupted clone never leaves a
|
|
38
|
+
* half-initialized cache that later fetches would poison; then fetch the
|
|
39
|
+
* requested revision and check out a detached worktree at the resolved commit.
|
|
31
40
|
*/
|
|
32
|
-
export declare const provisionWorktree: <E>(options: ProvisionOptions<E>) => Effect.Effect<
|
|
41
|
+
export declare const provisionWorktree: <E>(options: ProvisionOptions<E>) => Effect.Effect<AttemptWorkspace, E | ExecutorOperationError, import("effect/Scope").Scope>;
|
|
42
|
+
export {};
|
|
33
43
|
//# sourceMappingURL=provision.d.ts.map
|
package/dist/provision.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"provision.d.ts","sourceRoot":"","sources":["../src/provision.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAU,MAAM,QAAQ,CAAC;AACxC,OAAO,EACL,sBAAsB,EACtB,
|
|
1
|
+
{"version":3,"file":"provision.d.ts","sourceRoot":"","sources":["../src/provision.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAa,MAAM,wBAAwB,CAAC;AACnE,OAAO,EAAE,MAAM,EAAU,MAAM,QAAQ,CAAC;AACxC,OAAO,EACL,sBAAsB,EACtB,gBAAgB,EAEhB,KAAK,eAAe,EACrB,MAAM,eAAe,CAAC;AAEvB,eAAO,MAAM,WAAW,UAAW,MAAM,KAAG,MAAoD,CAAC;AAIjG,8FAA8F;AAC9F,eAAO,MAAM,kBAAkB,eAAgB,cAAc,KAAG,MACT,CAAC;AAExD;;;;;GAKG;AACH,eAAO,MAAM,oBAAoB,UAAW,MAAM,KAAG,OACmC,CAAC;AAIzF,UAAU,eAAe;IACvB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B;AAED,qFAAqF;AACrF,MAAM,WAAW,YAAY,CAAC,CAAC;IAC7B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IAC7C,QAAQ,CAAC,UAAU,EAAE,CAAC,SAAS,EAAE,SAAS,GAAG,SAAS,EAAE,MAAM,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IAClG,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;IAChD,uEAAuE;IACvE,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IAChD,QAAQ,CAAC,GAAG,EAAE,CACZ,SAAS,EAAE,SAAS,GAAG,SAAS,EAChC,IAAI,EAAE,aAAa,CAAC,MAAM,CAAC,KACxB,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;CAC/B;AAED,MAAM,WAAW,gBAAgB,CAAC,CAAC;IACjC,QAAQ,CAAC,OAAO,EAAE,eAAe,CAAC;IAClC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,eAAe,CAAC;IACjC,QAAQ,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC;CAC/B;AAED;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,GAAsD,CAAC,4HAwJnF,CAAC"}
|
package/dist/provision.js
CHANGED
|
@@ -1,14 +1,24 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as AttemptChannel from "@usine/core/attempt/channel";
|
|
2
|
+
import { RepositoryName, CommitSha } from "@usine/core/repository";
|
|
2
3
|
import { Effect, Schema } from "effect";
|
|
3
|
-
import { ExecutorOperationError,
|
|
4
|
+
import { ExecutorOperationError, AttemptWorkspace, WorktreePath, } from "./executor.js";
|
|
4
5
|
export const safeSegment = (value) => value.replaceAll(/[^A-Za-z0-9_.-]/gu, "_");
|
|
5
|
-
const
|
|
6
|
+
const CACHE_DIRECTORY_SUFFIX = ".git";
|
|
7
|
+
/** The bare cache directory name for a repository under `repos/`, shared by every adapter. */
|
|
8
|
+
export const cacheDirectoryName = (repository) => `${safeSegment(repository)}${CACHE_DIRECTORY_SUFFIX}`;
|
|
6
9
|
/**
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
|
|
10
|
+
* Whether a `repos/` entry is one of our bare caches, decided by the name we
|
|
11
|
+
* mint rather than by probing contents: a `HEAD` lookup fails with ENOTDIR on
|
|
12
|
+
* a stray file, and a `.cloning` leftover or a tool's scratch directory must
|
|
13
|
+
* never reach `git worktree prune`.
|
|
14
|
+
*/
|
|
15
|
+
export const isCacheDirectoryName = (entry) => entry.length > CACHE_DIRECTORY_SUFFIX.length && entry.endsWith(CACHE_DIRECTORY_SUFFIX);
|
|
16
|
+
const decodeCommit = Schema.decodeUnknownEffect(CommitSha);
|
|
17
|
+
/**
|
|
18
|
+
* The clone-to-worktree sequence every Executor shares: clone into a staging
|
|
19
|
+
* sibling and promote it on success, so an interrupted clone never leaves a
|
|
20
|
+
* half-initialized cache that later fetches would poison; then fetch the
|
|
21
|
+
* requested revision and check out a detached worktree at the resolved commit.
|
|
12
22
|
*/
|
|
13
23
|
export const provisionWorktree = Effect.fn("Executor.provisionWorktree")(function* (options) {
|
|
14
24
|
const { layout, ops, request } = options;
|
|
@@ -18,23 +28,77 @@ export const provisionWorktree = Effect.fn("Executor.provisionWorktree")(functio
|
|
|
18
28
|
host: options.host,
|
|
19
29
|
repository: request.repository,
|
|
20
30
|
});
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
31
|
+
const cleanup = (resource, effect) => effect.pipe(Effect.tapError((error) => Effect.logError("Attempt cleanup operation failed", {
|
|
32
|
+
attemptId: request.attemptId,
|
|
33
|
+
worker: request.worker,
|
|
34
|
+
host: options.host,
|
|
35
|
+
worktree: layout.worktree,
|
|
36
|
+
resource,
|
|
37
|
+
message: String(error),
|
|
38
|
+
})), Effect.ignore);
|
|
39
|
+
// Register before any filesystem mutation. This also covers failed worktree
|
|
40
|
+
// creation, which can leave both a directory and a bare-cache registration.
|
|
41
|
+
yield* Effect.addFinalizer(Effect.fn("Executor.releaseWorktree")(function* () {
|
|
42
|
+
yield* Effect.annotateCurrentSpan({
|
|
43
|
+
attemptId: request.attemptId,
|
|
44
|
+
worker: request.worker,
|
|
45
|
+
repository: request.repository,
|
|
46
|
+
host: options.host,
|
|
47
|
+
});
|
|
48
|
+
yield* Effect.logInfo("Cleaning Attempt workspace", {
|
|
29
49
|
attemptId: request.attemptId,
|
|
30
50
|
worker: request.worker,
|
|
31
51
|
host: options.host,
|
|
32
|
-
|
|
52
|
+
worktree: layout.worktree,
|
|
53
|
+
});
|
|
54
|
+
const cacheExists = yield* ops.cacheExists.pipe(Effect.tapError((error) => Effect.logWarning("Could not inspect cache during cleanup", {
|
|
55
|
+
attemptId: request.attemptId,
|
|
33
56
|
message: String(error),
|
|
34
|
-
})), Effect.
|
|
35
|
-
|
|
57
|
+
})), Effect.orElseSucceed(() => false));
|
|
58
|
+
if (cacheExists) {
|
|
59
|
+
yield* cleanup("git-worktree", ops.git("cleanup", [
|
|
60
|
+
"--git-dir",
|
|
61
|
+
layout.cache,
|
|
62
|
+
"worktree",
|
|
63
|
+
"remove",
|
|
64
|
+
"--force",
|
|
65
|
+
layout.worktree,
|
|
66
|
+
]));
|
|
67
|
+
}
|
|
68
|
+
yield* cleanup("worktree-directory", ops.removePath("cleanup", layout.worktree));
|
|
69
|
+
if (cacheExists) {
|
|
70
|
+
yield* cleanup("cache-registration", ops.git("cleanup", ["--git-dir", layout.cache, "worktree", "prune"]));
|
|
71
|
+
}
|
|
72
|
+
}));
|
|
73
|
+
yield* ops.ensureRoots;
|
|
74
|
+
yield* ops.removePath("prepare", layout.worktree);
|
|
75
|
+
if (yield* ops.cacheExists) {
|
|
76
|
+
yield* ops.git("prepare", [
|
|
77
|
+
"--git-dir",
|
|
78
|
+
layout.cache,
|
|
79
|
+
"remote",
|
|
80
|
+
"set-url",
|
|
81
|
+
"origin",
|
|
82
|
+
options.url,
|
|
83
|
+
]);
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
// Staging belongs to this locked clone only. Release it before unlocking,
|
|
87
|
+
// including interruption between clone completion and cache promotion.
|
|
88
|
+
yield* Effect.scoped(Effect.gen(function* () {
|
|
89
|
+
yield* Effect.addFinalizer(() => cleanup("partial-clone", ops.removePath("cleanup", layout.staging)));
|
|
90
|
+
yield* ops.removePath("prepare", layout.staging);
|
|
91
|
+
yield* ops.git("prepare", [
|
|
92
|
+
"clone",
|
|
93
|
+
"--bare",
|
|
94
|
+
"--filter=blob:none",
|
|
95
|
+
options.url,
|
|
96
|
+
layout.staging,
|
|
97
|
+
]);
|
|
98
|
+
yield* ops.promoteStaging;
|
|
99
|
+
}));
|
|
36
100
|
}
|
|
37
|
-
yield* ops.git([
|
|
101
|
+
yield* ops.git("prepare", [
|
|
38
102
|
"--git-dir",
|
|
39
103
|
layout.cache,
|
|
40
104
|
"fetch",
|
|
@@ -43,13 +107,18 @@ export const provisionWorktree = Effect.fn("Executor.provisionWorktree")(functio
|
|
|
43
107
|
"origin",
|
|
44
108
|
request.revision,
|
|
45
109
|
]);
|
|
46
|
-
const resolved = (yield* ops.git(
|
|
110
|
+
const resolved = (yield* ops.git("prepare", [
|
|
111
|
+
"--git-dir",
|
|
112
|
+
layout.cache,
|
|
113
|
+
"rev-parse",
|
|
114
|
+
"FETCH_HEAD",
|
|
115
|
+
])).trim();
|
|
47
116
|
const baseCommit = yield* decodeCommit(resolved).pipe(Effect.mapError((cause) => new ExecutorOperationError({
|
|
48
117
|
operation: "prepare",
|
|
49
118
|
message: "git returned an invalid object id",
|
|
50
119
|
cause,
|
|
51
120
|
})));
|
|
52
|
-
yield* ops.git([
|
|
121
|
+
yield* ops.git("prepare", [
|
|
53
122
|
"--git-dir",
|
|
54
123
|
layout.cache,
|
|
55
124
|
"worktree",
|
|
@@ -58,7 +127,7 @@ export const provisionWorktree = Effect.fn("Executor.provisionWorktree")(functio
|
|
|
58
127
|
layout.worktree,
|
|
59
128
|
baseCommit,
|
|
60
129
|
]);
|
|
61
|
-
return new
|
|
130
|
+
return new AttemptWorkspace({
|
|
62
131
|
worker: request.worker,
|
|
63
132
|
spec: new AttemptChannel.RunSpec({
|
|
64
133
|
attemptId: request.attemptId,
|
|
@@ -69,6 +138,8 @@ export const provisionWorktree = Effect.fn("Executor.provisionWorktree")(functio
|
|
|
69
138
|
task: request.task,
|
|
70
139
|
agent: request.agent,
|
|
71
140
|
parentModel: request.parentModel,
|
|
141
|
+
maxChildren: request.maxChildren,
|
|
142
|
+
parentEffort: request.parentEffort,
|
|
72
143
|
}),
|
|
73
144
|
worktree: WorktreePath.make(layout.worktree),
|
|
74
145
|
});
|