@usine/executor 0.2.0 → 0.3.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/README.md +115 -37
- package/dist/child-command.d.ts +4 -7
- package/dist/child-command.d.ts.map +1 -1
- package/dist/child-command.js +6 -12
- package/dist/child-command.js.map +1 -1
- package/dist/claude-login-lock.d.ts +8 -0
- package/dist/claude-login-lock.d.ts.map +1 -0
- package/dist/claude-login-lock.js +9 -0
- package/dist/claude-login-lock.js.map +1 -0
- package/dist/credential-environment.d.ts +20 -0
- package/dist/credential-environment.d.ts.map +1 -0
- package/dist/credential-environment.js +20 -0
- package/dist/credential-environment.js.map +1 -0
- package/dist/durable-session.d.ts +63 -0
- package/dist/durable-session.d.ts.map +1 -0
- package/dist/durable-session.js +491 -0
- package/dist/durable-session.js.map +1 -0
- package/dist/exe-dev/commands.d.ts +23 -13
- package/dist/exe-dev/commands.d.ts.map +1 -1
- package/dist/exe-dev/commands.js +11 -57
- package/dist/exe-dev/commands.js.map +1 -1
- package/dist/exe-dev/exe-dev.d.ts +9 -3
- package/dist/exe-dev/exe-dev.d.ts.map +1 -1
- package/dist/exe-dev/exe-dev.js +53 -127
- package/dist/exe-dev/exe-dev.js.map +1 -1
- package/dist/exe-dev/grants.d.ts.map +1 -1
- package/dist/exe-dev/grants.js +35 -15
- package/dist/exe-dev/grants.js.map +1 -1
- package/dist/exe-dev/model.d.ts +15 -19
- package/dist/exe-dev/model.d.ts.map +1 -1
- package/dist/exe-dev/model.js +9 -12
- package/dist/exe-dev/model.js.map +1 -1
- package/dist/exe-dev/preflight.d.ts +8 -4
- package/dist/exe-dev/preflight.d.ts.map +1 -1
- package/dist/exe-dev/preflight.js +23 -33
- package/dist/exe-dev/preflight.js.map +1 -1
- package/dist/executor.d.ts +141 -38
- package/dist/executor.d.ts.map +1 -1
- package/dist/executor.js +90 -17
- package/dist/executor.js.map +1 -1
- package/dist/guard.d.ts +61 -0
- package/dist/guard.d.ts.map +1 -0
- package/dist/guard.js +288 -0
- package/dist/guard.js.map +1 -0
- package/dist/harness-preflight.d.ts +25 -4
- package/dist/harness-preflight.d.ts.map +1 -1
- package/dist/harness-preflight.js +25 -29
- package/dist/harness-preflight.js.map +1 -1
- package/dist/keyed-lock.d.ts +2 -3
- package/dist/keyed-lock.d.ts.map +1 -1
- package/dist/keyed-lock.js +2 -3
- package/dist/keyed-lock.js.map +1 -1
- package/dist/leftovers.d.ts +9 -0
- package/dist/leftovers.d.ts.map +1 -0
- package/dist/leftovers.js +14 -0
- package/dist/leftovers.js.map +1 -0
- package/dist/local/credentials.d.ts +21 -0
- package/dist/local/credentials.d.ts.map +1 -0
- package/dist/local/credentials.js +39 -0
- package/dist/local/credentials.js.map +1 -0
- package/dist/local/leftovers.d.ts +8 -0
- package/dist/local/leftovers.d.ts.map +1 -0
- package/dist/local/leftovers.js +23 -0
- package/dist/local/leftovers.js.map +1 -0
- package/dist/local/local.d.ts +16 -10
- package/dist/local/local.d.ts.map +1 -1
- package/dist/local/local.js +164 -129
- package/dist/local/local.js.map +1 -1
- package/dist/memory-preflight.d.ts +25 -0
- package/dist/memory-preflight.d.ts.map +1 -0
- package/dist/memory-preflight.js +83 -0
- package/dist/memory-preflight.js.map +1 -0
- package/dist/pre-push-hook.d.ts +20 -0
- package/dist/pre-push-hook.d.ts.map +1 -0
- package/dist/pre-push-hook.js +33 -0
- package/dist/pre-push-hook.js.map +1 -0
- package/dist/prepared-attempt.d.ts +33 -3
- package/dist/prepared-attempt.d.ts.map +1 -1
- package/dist/prepared-attempt.js +109 -39
- package/dist/prepared-attempt.js.map +1 -1
- package/dist/provision.d.ts +77 -14
- package/dist/provision.d.ts.map +1 -1
- package/dist/provision.js +357 -55
- package/dist/provision.js.map +1 -1
- package/dist/remote/commands.d.ts +51 -0
- package/dist/remote/commands.d.ts.map +1 -0
- package/dist/remote/commands.js +94 -0
- package/dist/remote/commands.js.map +1 -0
- package/dist/remote/leftovers.d.ts +14 -0
- package/dist/remote/leftovers.d.ts.map +1 -0
- package/dist/remote/leftovers.js +22 -0
- package/dist/remote/leftovers.js.map +1 -0
- package/dist/remote/liveness.d.ts +33 -0
- package/dist/remote/liveness.d.ts.map +1 -0
- package/dist/remote/liveness.js +194 -0
- package/dist/remote/liveness.js.map +1 -0
- package/dist/remote/machine.d.ts +64 -0
- package/dist/remote/machine.d.ts.map +1 -0
- package/dist/remote/machine.js +2 -0
- package/dist/remote/machine.js.map +1 -0
- package/dist/remote/remote.d.ts +24 -0
- package/dist/remote/remote.d.ts.map +1 -0
- package/dist/remote/remote.js +308 -0
- package/dist/remote/remote.js.map +1 -0
- package/dist/remote/sweep.d.ts +15 -0
- package/dist/remote/sweep.d.ts.map +1 -0
- package/dist/remote/sweep.js +116 -0
- package/dist/remote/sweep.js.map +1 -0
- package/dist/renewable-credential.d.ts +17 -0
- package/dist/renewable-credential.d.ts.map +1 -0
- package/dist/renewable-credential.js +58 -0
- package/dist/renewable-credential.js.map +1 -0
- package/dist/salvage.d.ts +30 -0
- package/dist/salvage.d.ts.map +1 -0
- package/dist/salvage.js +104 -0
- package/dist/salvage.js.map +1 -0
- package/dist/ssh/credentials.d.ts +40 -0
- package/dist/ssh/credentials.d.ts.map +1 -0
- package/dist/ssh/credentials.js +83 -0
- package/dist/ssh/credentials.js.map +1 -0
- package/dist/ssh/gateway/admin.d.ts +45 -0
- package/dist/ssh/gateway/admin.d.ts.map +1 -0
- package/dist/ssh/gateway/admin.js +129 -0
- package/dist/ssh/gateway/admin.js.map +1 -0
- package/dist/ssh/gateway/attachments.d.ts +22 -0
- package/dist/ssh/gateway/attachments.d.ts.map +1 -0
- package/dist/ssh/gateway/attachments.js +154 -0
- package/dist/ssh/gateway/attachments.js.map +1 -0
- package/dist/ssh/gateway/environment.d.ts +52 -0
- package/dist/ssh/gateway/environment.d.ts.map +1 -0
- package/dist/ssh/gateway/environment.js +78 -0
- package/dist/ssh/gateway/environment.js.map +1 -0
- package/dist/ssh/gateway/forward.d.ts +74 -0
- package/dist/ssh/gateway/forward.d.ts.map +1 -0
- package/dist/ssh/gateway/forward.js +247 -0
- package/dist/ssh/gateway/forward.js.map +1 -0
- package/dist/ssh/gateway/preflight.d.ts +28 -0
- package/dist/ssh/gateway/preflight.d.ts.map +1 -0
- package/dist/ssh/gateway/preflight.js +234 -0
- package/dist/ssh/gateway/preflight.js.map +1 -0
- package/dist/ssh/model.d.ts +65 -0
- package/dist/ssh/model.d.ts.map +1 -0
- package/dist/ssh/model.js +2 -0
- package/dist/ssh/model.js.map +1 -0
- package/dist/ssh/preflight.d.ts +16 -0
- package/dist/ssh/preflight.d.ts.map +1 -0
- package/dist/ssh/preflight.js +47 -0
- package/dist/ssh/preflight.js.map +1 -0
- package/dist/ssh/ssh.d.ts +20 -0
- package/dist/ssh/ssh.d.ts.map +1 -0
- package/dist/ssh/ssh.js +78 -0
- package/dist/ssh/ssh.js.map +1 -0
- package/dist/ssh/workers.d.ts +53 -0
- package/dist/ssh/workers.d.ts.map +1 -0
- package/dist/ssh/workers.js +173 -0
- package/dist/ssh/workers.js.map +1 -0
- package/package.json +12 -4
- package/dist/exe-dev/channel.d.ts +0 -11
- package/dist/exe-dev/channel.d.ts.map +0 -1
- package/dist/exe-dev/channel.js +0 -41
- package/dist/exe-dev/channel.js.map +0 -1
- package/dist/exe-dev/shell.d.ts +0 -12
- package/dist/exe-dev/shell.d.ts.map +0 -1
- package/dist/exe-dev/shell.js +0 -31
- package/dist/exe-dev/shell.js.map +0 -1
- package/dist/exe-dev/sweep.d.ts +0 -10
- package/dist/exe-dev/sweep.d.ts.map +0 -1
- package/dist/exe-dev/sweep.js +0 -117
- package/dist/exe-dev/sweep.js.map +0 -1
- package/dist/invalid-frame.d.ts +0 -17
- package/dist/invalid-frame.d.ts.map +0 -1
- package/dist/invalid-frame.js +0 -111
- package/dist/invalid-frame.js.map +0 -1
- package/dist/run-host-session.d.ts +0 -26
- package/dist/run-host-session.d.ts.map +0 -1
- package/dist/run-host-session.js +0 -241
- package/dist/run-host-session.js.map +0 -1
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { Effect, Schema } from "effect";
|
|
2
|
+
import { type ExecutorOperationError, WorkerCapabilityError } from "./executor.ts";
|
|
3
|
+
/** Swap that the OS allocates on demand, as on macOS. */
|
|
4
|
+
export declare const SwapOnDemand: Schema.TaggedStruct<"SwapOnDemand", {}>;
|
|
5
|
+
declare const WorkerMemory_base: Schema.Class<WorkerMemory, Schema.Struct<{
|
|
6
|
+
readonly totalBytes: Schema.Int;
|
|
7
|
+
readonly swap: Schema.Union<readonly [Schema.TaggedStruct<"NoSwap", {}>, Schema.TaggedStruct<"SwapSpace", {
|
|
8
|
+
readonly bytes: Schema.Int;
|
|
9
|
+
}>, Schema.TaggedStruct<"SwapOnDemand", {}>]>;
|
|
10
|
+
}>, {}>;
|
|
11
|
+
export declare class WorkerMemory extends WorkerMemory_base {
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Checks that `worker`'s machine can run `maxConcurrentAttempts` concurrent Attempts. Fails
|
|
15
|
+
* below 1.5 GiB per Attempt or for more than one Attempt without swap; logs a warning below
|
|
16
|
+
* 3 GiB per Attempt.
|
|
17
|
+
*/
|
|
18
|
+
export declare const verifyWorkerMemory: (worker: string & import("effect/Brand").Brand<"WorkerName">, maxConcurrentAttempts: number, memory: WorkerMemory) => Effect.Effect<undefined, WorkerCapabilityError, never>;
|
|
19
|
+
/**
|
|
20
|
+
* Runs `verifyWorkerMemory` for a Linux machine whose `/proc/meminfo` is returned by `meminfo`.
|
|
21
|
+
* Fails if the output lacks MemTotal or SwapTotal.
|
|
22
|
+
*/
|
|
23
|
+
export declare const verifyLinuxMemory: (worker: string & import("effect/Brand").Brand<"WorkerName">, maxConcurrentAttempts: number, meminfo: Effect.Effect<string, ExecutorOperationError, never>) => Effect.Effect<undefined, WorkerCapabilityError, never>;
|
|
24
|
+
export {};
|
|
25
|
+
//# sourceMappingURL=memory-preflight.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory-preflight.d.ts","sourceRoot":"","sources":["../src/memory-preflight.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAiB,MAAM,EAAE,MAAM,QAAQ,CAAC;AACvD,OAAO,EAAE,KAAK,sBAAsB,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AAgBnF,yDAAyD;AACzD,eAAO,MAAM,YAAY,yCAA0C,CAAC;;;;;;;AAKpE,qBAAa,YAAa,SAAQ,iBAGhC;CAAG;AAiCL;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,8KA8C7B,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,iBAAiB,uNAkB5B,CAAC"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { Effect, Match, Option, Schema } from "effect";
|
|
2
|
+
import { WorkerCapabilityError } from "./executor.js";
|
|
3
|
+
const GIB = 1024 ** 3;
|
|
4
|
+
// Two Attempts running the usine monorepo gates on a 4 GB Worker without swap made sshd
|
|
5
|
+
// unresponsive (#270).
|
|
6
|
+
const MEMORY_PER_ATTEMPT_WARNING = 3 * GIB;
|
|
7
|
+
const MEMORY_PER_ATTEMPT_MINIMUM = 1.5 * GIB;
|
|
8
|
+
const NoSwap = Schema.TaggedStruct("NoSwap", {});
|
|
9
|
+
/** A fixed swap size in bytes, as reported by Linux. */
|
|
10
|
+
const SwapSpace = Schema.TaggedStruct("SwapSpace", {
|
|
11
|
+
bytes: Schema.Int.check(Schema.isGreaterThan(0)),
|
|
12
|
+
});
|
|
13
|
+
/** Swap that the OS allocates on demand, as on macOS. */
|
|
14
|
+
export const SwapOnDemand = Schema.TaggedStruct("SwapOnDemand", {});
|
|
15
|
+
const WorkerSwap = Schema.Union([NoSwap, SwapSpace, SwapOnDemand]);
|
|
16
|
+
export class WorkerMemory extends Schema.Class("@usine/executor/WorkerMemory")({
|
|
17
|
+
totalBytes: Schema.Int.check(Schema.isGreaterThan(0)),
|
|
18
|
+
swap: WorkerSwap,
|
|
19
|
+
}) {
|
|
20
|
+
}
|
|
21
|
+
const decodeWorkerMemory = Schema.decodeUnknownOption(WorkerMemory);
|
|
22
|
+
const kibibytes = (meminfo, pattern) => Option.map(Option.fromNullishOr(pattern.exec(meminfo)?.[1]), Number);
|
|
23
|
+
/** Parses `/proc/meminfo`. Returns `None` if MemTotal or SwapTotal is missing. */
|
|
24
|
+
const memoryFromMeminfo = (meminfo) => Option.flatMap(Option.all({
|
|
25
|
+
total: kibibytes(meminfo, /^MemTotal:\s+(\d+) kB$/mu),
|
|
26
|
+
swap: kibibytes(meminfo, /^SwapTotal:\s+(\d+) kB$/mu),
|
|
27
|
+
}), ({ total, swap }) => decodeWorkerMemory({
|
|
28
|
+
totalBytes: total * 1024,
|
|
29
|
+
swap: swap === 0 ? NoSwap.make({}) : SwapSpace.make({ bytes: swap * 1024 }),
|
|
30
|
+
}));
|
|
31
|
+
const gib = (bytes) => `${(bytes / GIB).toFixed(1)} GiB`;
|
|
32
|
+
const swapText = (swap) => Match.valueTags(swap, {
|
|
33
|
+
NoSwap: () => "none",
|
|
34
|
+
SwapSpace: ({ bytes }) => gib(bytes),
|
|
35
|
+
SwapOnDemand: () => "on demand",
|
|
36
|
+
});
|
|
37
|
+
const memoryError = (worker, message, cause) => new WorkerCapabilityError({ worker, capability: "memory", message, cause });
|
|
38
|
+
/**
|
|
39
|
+
* Checks that `worker`'s machine can run `maxConcurrentAttempts` concurrent Attempts. Fails
|
|
40
|
+
* below 1.5 GiB per Attempt or for more than one Attempt without swap; logs a warning below
|
|
41
|
+
* 3 GiB per Attempt.
|
|
42
|
+
*/
|
|
43
|
+
export const verifyWorkerMemory = Effect.fn("Executor.verifyWorkerMemory")(function* (worker, maxConcurrentAttempts, memory) {
|
|
44
|
+
const perAttempt = memory.totalBytes / maxConcurrentAttempts;
|
|
45
|
+
const fields = {
|
|
46
|
+
worker,
|
|
47
|
+
maxConcurrentAttempts,
|
|
48
|
+
memory: gib(memory.totalBytes),
|
|
49
|
+
swap: swapText(memory.swap),
|
|
50
|
+
perAttempt: gib(perAttempt),
|
|
51
|
+
};
|
|
52
|
+
yield* Effect.annotateCurrentSpan(fields);
|
|
53
|
+
const withoutSwap = memory.swap._tag === "NoSwap";
|
|
54
|
+
if (perAttempt < MEMORY_PER_ATTEMPT_MINIMUM) {
|
|
55
|
+
const fitting = Math.floor(memory.totalBytes / MEMORY_PER_ATTEMPT_MINIMUM);
|
|
56
|
+
const carried = withoutSwap ? Math.min(fitting, 1) : fitting;
|
|
57
|
+
const advice = carried === 0
|
|
58
|
+
? "Add memory to the machine."
|
|
59
|
+
: `Set max_concurrent_attempts to ${carried} or less, or add memory to the machine.`;
|
|
60
|
+
return yield* memoryError(worker, `Worker "${worker}" has ${gib(memory.totalBytes)} of memory, which is ${gib(perAttempt)} per attempt with max_concurrent_attempts set to ${maxConcurrentAttempts}. An attempt needs at least ${gib(MEMORY_PER_ATTEMPT_MINIMUM)}. ${advice}`, memory);
|
|
61
|
+
}
|
|
62
|
+
if (withoutSwap && maxConcurrentAttempts > 1)
|
|
63
|
+
return yield* memoryError(worker, `Worker "${worker}" has no swap, and max_concurrent_attempts is ${maxConcurrentAttempts}. Concurrent attempts without swap can make the machine thrash until SSH stops responding. Add swap, or set max_concurrent_attempts to 1.`, memory);
|
|
64
|
+
if (perAttempt < MEMORY_PER_ATTEMPT_WARNING)
|
|
65
|
+
yield* Effect.logWarning(`Worker memory is below ${gib(MEMORY_PER_ATTEMPT_WARNING)} per concurrent Attempt`, {
|
|
66
|
+
...fields,
|
|
67
|
+
suggestedMaxConcurrentAttempts: Math.max(1, Math.floor(memory.totalBytes / MEMORY_PER_ATTEMPT_WARNING)),
|
|
68
|
+
});
|
|
69
|
+
else
|
|
70
|
+
yield* Effect.logInfo("Worker memory verified", fields);
|
|
71
|
+
});
|
|
72
|
+
/**
|
|
73
|
+
* Runs `verifyWorkerMemory` for a Linux machine whose `/proc/meminfo` is returned by `meminfo`.
|
|
74
|
+
* Fails if the output lacks MemTotal or SwapTotal.
|
|
75
|
+
*/
|
|
76
|
+
export const verifyLinuxMemory = Effect.fn("Executor.verifyLinuxMemory")(function* (worker, maxConcurrentAttempts, meminfo) {
|
|
77
|
+
const output = yield* meminfo.pipe(Effect.mapError((cause) => memoryError(worker, `Can't read /proc/meminfo on worker "${worker}"`, cause)));
|
|
78
|
+
const memory = memoryFromMeminfo(output);
|
|
79
|
+
if (Option.isNone(memory))
|
|
80
|
+
return yield* memoryError(worker, `/proc/meminfo on worker "${worker}" has no MemTotal or SwapTotal`, new Error(output.slice(0, 200)));
|
|
81
|
+
yield* verifyWorkerMemory(worker, maxConcurrentAttempts, memory.value);
|
|
82
|
+
});
|
|
83
|
+
//# sourceMappingURL=memory-preflight.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory-preflight.js","sourceRoot":"","sources":["../src/memory-preflight.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { LoopName } from "@usine/core/loop";
|
|
2
|
+
import { Option } from "effect";
|
|
3
|
+
/**
|
|
4
|
+
* The hooks directory inside the checkout's git directory for `permissions: read` Loops.
|
|
5
|
+
* `git worktree remove` deletes it with the checkout.
|
|
6
|
+
*/
|
|
7
|
+
export declare const PRE_PUSH_HOOKS_DIRECTORY = "usine-hooks";
|
|
8
|
+
/**
|
|
9
|
+
* Returns a pre-push hook that rejects every push with `pushRefusal`, so the Agent sees the
|
|
10
|
+
* reason instead of GitHub's 403. `git push --no-verify` skips it; the `contents: read` token is
|
|
11
|
+
* what blocks the push (ADR 0011).
|
|
12
|
+
*/
|
|
13
|
+
export declare const prePushHook: (loop: LoopName) => string;
|
|
14
|
+
/**
|
|
15
|
+
* Returns `environment` with `core.hooksPath` set to `hooks`, if any, after the entries counted
|
|
16
|
+
* in `GIT_CONFIG_COUNT`. Environment config overrides repository config, so the hook runs even
|
|
17
|
+
* if the repository sets `core.hooksPath`.
|
|
18
|
+
*/
|
|
19
|
+
export declare const withGitHooks: (environment: Readonly<Record<string, string>>, hooks: Option.Option<string>) => Record<string, string>;
|
|
20
|
+
//# sourceMappingURL=pre-push-hook.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pre-push-hook.d.ts","sourceRoot":"","sources":["../src/pre-push-hook.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAEhC;;;GAGG;AACH,eAAO,MAAM,wBAAwB,gBAAgB,CAAC;AAQtD;;;;GAIG;AACH,eAAO,MAAM,WAAW,SAAU,QAAQ,KAAG,MACgB,CAAC;AAE9D;;;;GAIG;AACH,eAAO,MAAM,YAAY,gBACV,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,SACtC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,KAC3B,MAAM,CAAC,MAAM,EAAE,MAAM,CAYpB,CAAC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { Option } from "effect";
|
|
2
|
+
/**
|
|
3
|
+
* The hooks directory inside the checkout's git directory for `permissions: read` Loops.
|
|
4
|
+
* `git worktree remove` deletes it with the checkout.
|
|
5
|
+
*/
|
|
6
|
+
export const PRE_PUSH_HOOKS_DIRECTORY = "usine-hooks";
|
|
7
|
+
const quote = (value) => `'${value.replaceAll("'", `'"'"'`)}'`;
|
|
8
|
+
/** Returns the message printed when a push from a `permissions: read` checkout is rejected. */
|
|
9
|
+
const pushRefusal = (loop) => `usine refused this push: the Loop ${loop} has permissions: read, so its Attempts cannot push to the repository.`;
|
|
10
|
+
/**
|
|
11
|
+
* Returns a pre-push hook that rejects every push with `pushRefusal`, so the Agent sees the
|
|
12
|
+
* reason instead of GitHub's 403. `git push --no-verify` skips it; the `contents: read` token is
|
|
13
|
+
* what blocks the push (ADR 0011).
|
|
14
|
+
*/
|
|
15
|
+
export const prePushHook = (loop) => `#!/bin/sh\necho ${quote(pushRefusal(loop))} >&2\nexit 1\n`;
|
|
16
|
+
/**
|
|
17
|
+
* Returns `environment` with `core.hooksPath` set to `hooks`, if any, after the entries counted
|
|
18
|
+
* in `GIT_CONFIG_COUNT`. Environment config overrides repository config, so the hook runs even
|
|
19
|
+
* if the repository sets `core.hooksPath`.
|
|
20
|
+
*/
|
|
21
|
+
export const withGitHooks = (environment, hooks) => Option.match(hooks, {
|
|
22
|
+
onNone: () => ({ ...environment }),
|
|
23
|
+
onSome: (directory) => {
|
|
24
|
+
const index = Number(environment.GIT_CONFIG_COUNT ?? "0");
|
|
25
|
+
return {
|
|
26
|
+
...environment,
|
|
27
|
+
GIT_CONFIG_COUNT: String(index + 1),
|
|
28
|
+
[`GIT_CONFIG_KEY_${index}`]: "core.hooksPath",
|
|
29
|
+
[`GIT_CONFIG_VALUE_${index}`]: directory,
|
|
30
|
+
};
|
|
31
|
+
},
|
|
32
|
+
});
|
|
33
|
+
//# sourceMappingURL=pre-push-hook.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pre-push-hook.js","sourceRoot":"","sources":["../src/pre-push-hook.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAEhC;;;GAGG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG,aAAa,CAAC;AAEtD,MAAM,KAAK,GAAG,CAAC,KAAa,EAAU,EAAE,CAAC,IAAI,KAAK,CAAC,UAAU,CAAC,GAAG,EAAE,OAAO,CAAC,GAAG,CAAC;AAE/E,+FAA+F;AAC/F,MAAM,WAAW,GAAG,CAAC,IAAc,EAAU,EAAE,CAC7C,qCAAqC,IAAI,wEAAwE,CAAC;AAEpH;;;;GAIG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,IAAc,EAAU,EAAE,CACpD,mBAAmB,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,gBAAgB,CAAC;AAE9D;;;;GAIG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAC1B,WAA6C,EAC7C,KAA4B,EACJ,EAAE,CAC1B,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE;IAClB,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,GAAG,WAAW,EAAE,CAAC;IAClC,MAAM,EAAE,CAAC,SAAS,EAAE,EAAE;QACpB,MAAM,KAAK,GAAG,MAAM,CAAC,WAAW,CAAC,gBAAgB,IAAI,GAAG,CAAC,CAAC;QAC1D,OAAO;YACL,GAAG,WAAW;YACd,gBAAgB,EAAE,MAAM,CAAC,KAAK,GAAG,CAAC,CAAC;YACnC,CAAC,kBAAkB,KAAK,EAAE,CAAC,EAAE,gBAAgB;YAC7C,CAAC,oBAAoB,KAAK,EAAE,CAAC,EAAE,SAAS;SACzC,CAAC;IACJ,CAAC;CACF,CAAC,CAAC"}
|
|
@@ -1,5 +1,35 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { AttemptId } from "@usine/core/attempt";
|
|
2
|
+
import * as AttemptChannel from "@usine/core/attempt/channel";
|
|
3
|
+
import { type AttemptFailure, InfraFailure, type RunawayCeiling } from "@usine/core/attempt/failure";
|
|
4
|
+
import { type Duration, Effect, Scope } from "effect";
|
|
2
5
|
import type { CheckoutRequest, ExecutorError, PreparedAttempt } from "./executor.ts";
|
|
3
|
-
|
|
4
|
-
|
|
6
|
+
import { type AttemptGuardSeed } from "./guard.ts";
|
|
7
|
+
import type { ProvisionedWorktree } from "./provision.ts";
|
|
8
|
+
export type AttemptStop = {
|
|
9
|
+
readonly _tag: "Cancel";
|
|
10
|
+
} | {
|
|
11
|
+
readonly _tag: "Runaway";
|
|
12
|
+
readonly ceiling: RunawayCeiling;
|
|
13
|
+
};
|
|
14
|
+
/** The result of an executor's `acquire`: the prepared Attempt and its salvage handles. */
|
|
15
|
+
export interface AcquiredAttempt extends PreparedAttempt {
|
|
16
|
+
readonly salvaged: ProvisionedWorktree["salvaged"];
|
|
17
|
+
readonly recordSalvage: ProvisionedWorktree["recordSalvage"];
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Returns `prepare` and `cancel` for one executor's Attempts, tracked from preparation until
|
|
21
|
+
* release so `cancel` works at any stage. `cancel`, a failed `prepare`, and `launch` each return
|
|
22
|
+
* only after the Attempt's resources are released.
|
|
23
|
+
*
|
|
24
|
+
* - `stop`: stops the live session and returns whether one existed.
|
|
25
|
+
* - `registered`: completes when the launch registers the live session.
|
|
26
|
+
* - `warnParent`: sends the guard's warning steer; can wait for the parent's channel.
|
|
27
|
+
* - `guardSeed`: returns the guard's initial state. If it fails, the launch records salvage,
|
|
28
|
+
* releases the resources, and fails.
|
|
29
|
+
* - `recordUnsupervised`: persists the guard's unsupervised time for a later reattachment.
|
|
30
|
+
*/
|
|
31
|
+
export declare const preparedAttemptsFor: (stop: (attemptId: AttemptId, reason: AttemptStop) => Effect.Effect<boolean, ExecutorError>, warnParent: (attemptId: AttemptId, intervention: AttemptChannel.Intervention) => Effect.Effect<void, AttemptFailure>, registered: (attemptId: AttemptId) => Effect.Effect<void>, guardSeed: (request: CheckoutRequest, io: AttemptChannel.Sink) => Effect.Effect<AttemptGuardSeed, InfraFailure>, recordUnsupervised: (attemptId: AttemptId, unsupervised: Duration.Duration) => Effect.Effect<void, AttemptFailure>) => Effect.Effect<{
|
|
32
|
+
prepare: (acquire: Effect.Effect<AcquiredAttempt, ExecutorError, Scope.Scope>, request: CheckoutRequest) => Effect.Effect<PreparedAttempt, ExecutorError, Scope.Scope>;
|
|
33
|
+
cancel: (attemptId: string & import("effect/Brand").Brand<"AttemptId">) => Effect.Effect<void, import("./executor.ts").CredentialUnavailableError | import("./executor.ts").ExecutorOperationError | import("./executor.ts").WorkerCapabilityError, never>;
|
|
34
|
+
}, never, never>;
|
|
5
35
|
//# sourceMappingURL=prepared-attempt.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prepared-attempt.d.ts","sourceRoot":"","sources":["../src/prepared-attempt.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"prepared-attempt.d.ts","sourceRoot":"","sources":["../src/prepared-attempt.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,KAAK,cAAc,MAAM,6BAA6B,CAAC;AAC9D,OAAO,EACL,KAAK,cAAc,EACnB,YAAY,EACZ,KAAK,cAAc,EACpB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAmB,KAAK,QAAQ,EAAE,MAAM,EAAoB,KAAK,EAAE,MAAM,QAAQ,CAAC;AACzF,OAAO,KAAK,EAAE,eAAe,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AACrF,OAAO,EAAgB,KAAK,gBAAgB,EAAE,MAAM,YAAY,CAAC;AACjE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAE1D,MAAM,MAAM,WAAW,GACnB;IAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAA;CAAE,GAC3B;IAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,cAAc,CAAA;CAAE,CAAC;AAEnE,2FAA2F;AAC3F,MAAM,WAAW,eAAgB,SAAQ,eAAe;IACtD,QAAQ,CAAC,QAAQ,EAAE,mBAAmB,CAAC,UAAU,CAAC,CAAC;IACnD,QAAQ,CAAC,aAAa,EAAE,mBAAmB,CAAC,eAAe,CAAC,CAAC;CAC9D;AASD;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,mBAAmB,SACxB,CAAC,SAAS,EAAE,SAAS,EAAE,MAAM,EAAE,WAAW,KAAK,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,aAAa,CAAC,cAC9E,CACV,SAAS,EAAE,SAAS,EACpB,YAAY,EAAE,cAAc,CAAC,YAAY,KACtC,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,cAAc,CAAC,cAC5B,CAAC,SAAS,EAAE,SAAS,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,aAC9C,CACT,OAAO,EAAE,eAAe,EACxB,EAAE,EAAE,cAAc,CAAC,IAAI,KACpB,MAAM,CAAC,MAAM,CAAC,gBAAgB,EAAE,YAAY,CAAC,sBAC9B,CAClB,SAAS,EAAE,SAAS,EACpB,YAAY,EAAE,QAAQ,CAAC,QAAQ,KAC5B,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,cAAc,CAAC;uBAwB3B,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,CAAC;;gBAoH7D,CAAC"}
|
package/dist/prepared-attempt.js
CHANGED
|
@@ -1,40 +1,110 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
Effect.
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
1
|
+
import * as AttemptChannel from "@usine/core/attempt/channel";
|
|
2
|
+
import { InfraFailure, } from "@usine/core/attempt/failure";
|
|
3
|
+
import { Cause, Deferred, Effect, Exit, Fiber, Ref, Scope } from "effect";
|
|
4
|
+
import { attemptGuard } from "./guard.js";
|
|
5
|
+
/**
|
|
6
|
+
* Returns `prepare` and `cancel` for one executor's Attempts, tracked from preparation until
|
|
7
|
+
* release so `cancel` works at any stage. `cancel`, a failed `prepare`, and `launch` each return
|
|
8
|
+
* only after the Attempt's resources are released.
|
|
9
|
+
*
|
|
10
|
+
* - `stop`: stops the live session and returns whether one existed.
|
|
11
|
+
* - `registered`: completes when the launch registers the live session.
|
|
12
|
+
* - `warnParent`: sends the guard's warning steer; can wait for the parent's channel.
|
|
13
|
+
* - `guardSeed`: returns the guard's initial state. If it fails, the launch records salvage,
|
|
14
|
+
* releases the resources, and fails.
|
|
15
|
+
* - `recordUnsupervised`: persists the guard's unsupervised time for a later reattachment.
|
|
16
|
+
*/
|
|
17
|
+
export const preparedAttemptsFor = (stop, warnParent, registered, guardSeed, recordUnsupervised) => Effect.sync(() => {
|
|
18
|
+
const attempts = new Map();
|
|
19
|
+
const cancel = Effect.fn("PreparedAttempt.cancel")(function* (attemptId) {
|
|
20
|
+
yield* Effect.annotateCurrentSpan({ attemptId });
|
|
21
|
+
const active = attempts.get(attemptId);
|
|
22
|
+
if (active === undefined) {
|
|
23
|
+
yield* Effect.logDebug("Attempt cancellation was a no-op", { attemptId });
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
yield* Ref.set(active.unavailable, true);
|
|
27
|
+
// With a live session, stops it so its terminal envelope and typed errors are kept. Before
|
|
28
|
+
// registration, closing the scope interrupts preparation or process spawn.
|
|
29
|
+
if (!(yield* stop(attemptId, { _tag: "Cancel" }))) {
|
|
30
|
+
yield* Effect.logInfo("Canceling Attempt before its channel is ready", { attemptId });
|
|
31
|
+
yield* active.release(Exit.void);
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
yield* active.released;
|
|
35
|
+
}
|
|
36
|
+
}, Effect.uninterruptible);
|
|
37
|
+
/** Runs preparation and the live session in one child scope that closes when the Attempt ends. */
|
|
38
|
+
const prepare = (acquire, request) => Effect.uninterruptibleMask((restore) => Effect.gen(function* () {
|
|
39
|
+
const scope = yield* Scope.fork(yield* Effect.scope);
|
|
40
|
+
const unavailable = yield* Ref.make(false);
|
|
41
|
+
const released = yield* Deferred.make();
|
|
42
|
+
// Scope.close returns immediately when another fiber is already closing the scope, so the
|
|
43
|
+
// owner and a concurrent cancel both wait for `released`, set by the first-registered
|
|
44
|
+
// (last-run) finalizer.
|
|
45
|
+
const release = (exit) => Scope.close(scope, exit).pipe(Effect.andThen(Deferred.await(released)));
|
|
46
|
+
attempts.set(request.attemptId, {
|
|
47
|
+
unavailable,
|
|
48
|
+
release,
|
|
49
|
+
released: Deferred.await(released),
|
|
50
|
+
});
|
|
51
|
+
yield* Scope.addFinalizer(scope, Effect.suspend(() => {
|
|
52
|
+
attempts.delete(request.attemptId);
|
|
53
|
+
return Deferred.succeed(released, undefined);
|
|
54
|
+
}));
|
|
55
|
+
yield* Scope.addFinalizer(scope, Ref.set(unavailable, true));
|
|
56
|
+
// A separate child scope, so the acquiring fiber is interrupted before its resources are
|
|
57
|
+
// released.
|
|
58
|
+
const resources = yield* Scope.fork(scope);
|
|
59
|
+
const acquiring = yield* Effect.forkIn(Scope.provide(acquire, resources), scope);
|
|
60
|
+
const prepared = yield* restore(Fiber.join(acquiring)).pipe(Effect.onError((cause) => release(Exit.failCause(cause))));
|
|
61
|
+
/** Releases the Attempt's resources, then fails if its salvage couldn't be recorded. */
|
|
62
|
+
const releaseSalvaged = (exit) => release(exit).pipe(Effect.andThen(Effect.asVoid(prepared.salvaged)));
|
|
63
|
+
return {
|
|
64
|
+
workspace: prepared.workspace,
|
|
65
|
+
launch: Effect.fn("PreparedAttempt.launch")(function* (io) {
|
|
66
|
+
const attemptId = prepared.workspace.spec.attemptId;
|
|
67
|
+
yield* Effect.annotateCurrentSpan({ attemptId, worker: prepared.workspace.worker });
|
|
68
|
+
if (yield* Ref.getAndSet(unavailable, true)) {
|
|
69
|
+
yield* Effect.logWarning("Attempt was already launched or released", { attemptId });
|
|
70
|
+
return yield* new InfraFailure({
|
|
71
|
+
message: `Attempt ${attemptId} was already launched or released`,
|
|
72
|
+
cause: new Error("prepared attempt is no longer available"),
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
// If the seed can't be read, records salvage and releases the checkout without launching, so
|
|
76
|
+
// the Run's next Attempt starts from it. On interruption, such as process shutdown, the
|
|
77
|
+
// owner's scope handles the checkout.
|
|
78
|
+
const seed = yield* guardSeed(request, io).pipe(Effect.onExit((exit) => Exit.isSuccess(exit) || Cause.hasInterruptsOnly(exit.cause)
|
|
79
|
+
? Effect.void
|
|
80
|
+
: Effect.logWarning("The Attempt's runaway guard cannot start; releasing its checkout without launching it", { attemptId }).pipe(Effect.andThen(prepared.recordSalvage(io.salvage)), Effect.andThen(releaseSalvaged(exit)))));
|
|
81
|
+
const guard = yield* attemptGuard({
|
|
82
|
+
attemptId,
|
|
83
|
+
maxAttemptMinutes: request.maxAttemptMinutes,
|
|
84
|
+
maxAttemptTokens: request.maxAttemptTokens,
|
|
85
|
+
warn: (message) => warnParent(attemptId, new AttemptChannel.Intervention({
|
|
86
|
+
operator: "engine",
|
|
87
|
+
target: new AttemptChannel.ParentTarget(),
|
|
88
|
+
action: new AttemptChannel.Steer({ message }),
|
|
89
|
+
})),
|
|
90
|
+
recordUnsupervised: (unsupervised) => recordUnsupervised(attemptId, unsupervised),
|
|
91
|
+
}, io, seed);
|
|
92
|
+
// Starts the clock only after the launch registers its session. A remote launch first waits
|
|
93
|
+
// for the Worker's liveness watch, and a seed with no time left could trip before there's a
|
|
94
|
+
// session to stop.
|
|
95
|
+
const tripped = registered(attemptId).pipe(Effect.andThen(guard.tripped), Effect.tapError(({ ceiling }) => stop(attemptId, { _tag: "Runaway", ceiling }).pipe(Effect.tapError((error) => Effect.logWarning("Could not stop the runaway Attempt", {
|
|
96
|
+
attemptId,
|
|
97
|
+
ceiling,
|
|
98
|
+
errorTag: error._tag,
|
|
99
|
+
})), Effect.ignore)));
|
|
100
|
+
yield* prepared.recordSalvage(io.salvage);
|
|
101
|
+
// Closing the owner's scope interrupts the session before the checkout and credential
|
|
102
|
+
// finalizers. acquireUseRelease interrupts the forked fiber when the caller waiting on join
|
|
103
|
+
// is interrupted.
|
|
104
|
+
return yield* Effect.acquireUseRelease(Effect.forkIn(Effect.raceFirst(prepared.launch(guard.sink), tripped), scope), Fiber.join, Fiber.interrupt).pipe(Effect.onExit((exit) => releaseSalvaged(exit)));
|
|
105
|
+
}),
|
|
106
|
+
};
|
|
107
|
+
}));
|
|
108
|
+
return { prepare, cancel };
|
|
109
|
+
});
|
|
40
110
|
//# sourceMappingURL=prepared-attempt.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prepared-attempt.js","sourceRoot":"","sources":["../src/prepared-attempt.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"prepared-attempt.js","sourceRoot":"","sources":["../src/prepared-attempt.ts"],"names":[],"mappings":"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"}
|
package/dist/provision.d.ts
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
|
+
import type { AttemptFailure } from "@usine/core/attempt/failure";
|
|
2
|
+
import * as AttemptChannel from "@usine/core/attempt/channel";
|
|
3
|
+
import { type AttemptRecovery, type AttemptSalvage, SalvagePushed } from "@usine/core/attempt/salvage";
|
|
1
4
|
import { RepositoryName } from "@usine/core/repository";
|
|
2
|
-
import { Effect } from "effect";
|
|
5
|
+
import { Effect, Option } from "effect";
|
|
3
6
|
import { ExecutorOperationError, AttemptWorkspace, type CheckoutRequest } from "./executor.ts";
|
|
4
|
-
|
|
5
|
-
/** The bare cache directory name for a repository under `repos/`, shared by every adapter. */
|
|
7
|
+
/** Returns the bare cache directory name for `repository` under `repos/`. */
|
|
6
8
|
export declare const cacheDirectoryName: (repository: RepositoryName) => string;
|
|
7
9
|
/**
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* never reach `git worktree prune`.
|
|
10
|
+
* Returns whether a `repos/` entry is a bare cache, by name only. Probing `HEAD` fails with
|
|
11
|
+
* ENOTDIR on a stray file, and a `.cloning` leftover or another tool's directory must never be
|
|
12
|
+
* passed to `git worktree prune`.
|
|
12
13
|
*/
|
|
13
14
|
export declare const isCacheDirectoryName: (entry: string) => boolean;
|
|
14
15
|
interface WorkspaceLayout {
|
|
@@ -16,14 +17,16 @@ interface WorkspaceLayout {
|
|
|
16
17
|
readonly staging: string;
|
|
17
18
|
readonly worktree: string;
|
|
18
19
|
}
|
|
19
|
-
/**
|
|
20
|
+
/** Executor-specific operations for the shared provisioning code. */
|
|
20
21
|
export interface WorkspaceOps<E> {
|
|
21
22
|
readonly ensureRoots: Effect.Effect<void, E>;
|
|
22
23
|
readonly removePath: (operation: "prepare" | "cleanup", target: string) => Effect.Effect<void, E>;
|
|
23
24
|
readonly cacheExists: Effect.Effect<boolean, E>;
|
|
24
|
-
/** Atomically
|
|
25
|
+
/** Atomically moves the finished staging clone to the cache path. */
|
|
25
26
|
readonly promoteStaging: Effect.Effect<void, E>;
|
|
26
27
|
readonly git: (operation: "prepare" | "cleanup", args: ReadonlyArray<string>) => Effect.Effect<string, E>;
|
|
28
|
+
/** Writes `content` to `path` on the Worker's machine, creating its directory, and makes it executable. */
|
|
29
|
+
readonly writeExecutable: (path: string, content: string) => Effect.Effect<void, E>;
|
|
27
30
|
}
|
|
28
31
|
export interface ProvisionOptions<E> {
|
|
29
32
|
readonly request: CheckoutRequest;
|
|
@@ -32,12 +35,72 @@ export interface ProvisionOptions<E> {
|
|
|
32
35
|
readonly layout: WorkspaceLayout;
|
|
33
36
|
readonly ops: WorkspaceOps<E>;
|
|
34
37
|
}
|
|
38
|
+
export interface ProvisionedWorktree {
|
|
39
|
+
readonly workspace: AttemptWorkspace;
|
|
40
|
+
/** Waits for the workspace scope to close and returns the salvage, or `None` after a successful Attempt or a clean worktree. */
|
|
41
|
+
readonly salvaged: Effect.Effect<Option.Option<AttemptSalvage>, AttemptFailure>;
|
|
42
|
+
/** Sets the salvage sink; call before launch. If salvage isn't recorded, cleanup keeps the worktree on disk. */
|
|
43
|
+
readonly recordSalvage: (record: AttemptChannel.Sink["salvage"]) => Effect.Effect<void>;
|
|
44
|
+
/**
|
|
45
|
+
* Skips checkout removal when the scope closes, so a restart can reattach the parent task or
|
|
46
|
+
* repeat a harvest whose result was not stored.
|
|
47
|
+
*/
|
|
48
|
+
readonly keepForReattach: Effect.Effect<void>;
|
|
49
|
+
/**
|
|
50
|
+
* The hooks directory for the children's git (`withGitHooks`), set only for a
|
|
51
|
+
* `permissions: read` Loop. If `None`, the repository's own hooks apply.
|
|
52
|
+
*/
|
|
53
|
+
readonly gitHooks: Option.Option<string>;
|
|
54
|
+
}
|
|
55
|
+
interface ReleaseOptions<E> {
|
|
56
|
+
readonly request: CheckoutRequest;
|
|
57
|
+
readonly host: string;
|
|
58
|
+
readonly layout: Pick<WorkspaceLayout, "cache" | "worktree">;
|
|
59
|
+
readonly ops: Pick<WorkspaceOps<E>, "cacheExists" | "git" | "removePath">;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Clones into a staging directory and promotes it on success, fetches the requested revision,
|
|
63
|
+
* and checks out a detached worktree at the resolved commit, applying the previous Attempt's
|
|
64
|
+
* salvage if the request resumes one. Registers the release finalizer before the first
|
|
65
|
+
* filesystem change.
|
|
66
|
+
*/
|
|
67
|
+
export declare const provisionWorktree: <E extends Error>(options: ProvisionOptions<E>) => Effect.Effect<{
|
|
68
|
+
workspace: AttemptWorkspace;
|
|
69
|
+
salvaged: Effect.Effect<Option.Option<SalvagePushed | import("@usine/core/attempt/salvage").SalvageRetained>, import("@usine/core/attempt/failure").AgentFailure | import("@usine/core/attempt/failure").BlockedFailure | import("@usine/core/attempt/failure").ChildSessionBudgetFailure | import("@usine/core/attempt/failure").DefectFailure | import("@usine/core/attempt/failure").InfraFailure | import("@usine/core/attempt/failure").QuestionFailure | import("@usine/core/attempt/failure").RunawayFailure, never>;
|
|
70
|
+
recordSalvage: (record: AttemptChannel.Sink["salvage"]) => Effect.Effect<void, never, never>;
|
|
71
|
+
keepForReattach: Effect.Effect<void, never, never>;
|
|
72
|
+
gitHooks: Option.Option<string>;
|
|
73
|
+
}, E | ExecutorOperationError, import("effect/Scope").Scope>;
|
|
74
|
+
export interface ReattachOptions<E> extends ReleaseOptions<E> {
|
|
75
|
+
readonly ops: Pick<WorkspaceOps<E>, "cacheExists" | "git" | "removePath" | "writeExecutable">;
|
|
76
|
+
/** The RunSpec from the parent's durable request. */
|
|
77
|
+
readonly spec: AttemptChannel.RunSpec;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Reuses an Attempt's checkout after an orchestrator restart without cloning, fetching, or
|
|
81
|
+
* checking out. The same release as a new checkout salvages and removes it when the Attempt
|
|
82
|
+
* ends.
|
|
83
|
+
*/
|
|
84
|
+
export declare const reattachWorktree: <E extends Error>(options: ReattachOptions<E>) => Effect.Effect<{
|
|
85
|
+
workspace: AttemptWorkspace;
|
|
86
|
+
salvaged: Effect.Effect<Option.Option<SalvagePushed | import("@usine/core/attempt/salvage").SalvageRetained>, import("@usine/core/attempt/failure").AgentFailure | import("@usine/core/attempt/failure").BlockedFailure | import("@usine/core/attempt/failure").ChildSessionBudgetFailure | import("@usine/core/attempt/failure").DefectFailure | import("@usine/core/attempt/failure").InfraFailure | import("@usine/core/attempt/failure").QuestionFailure | import("@usine/core/attempt/failure").RunawayFailure, never>;
|
|
87
|
+
recordSalvage: (record: AttemptChannel.Sink["salvage"]) => Effect.Effect<void, never, never>;
|
|
88
|
+
keepForReattach: Effect.Effect<void, never, never>;
|
|
89
|
+
gitHooks: Option.Option<string>;
|
|
90
|
+
}, E, import("effect/Scope").Scope>;
|
|
91
|
+
export interface RecoveryOptions<E> {
|
|
92
|
+
readonly attempt: AttemptRecovery;
|
|
93
|
+
readonly host: string;
|
|
94
|
+
readonly worktree: string;
|
|
95
|
+
readonly cache: string;
|
|
96
|
+
/** Runs git with the Worker's repository credentials. */
|
|
97
|
+
readonly git: (args: ReadonlyArray<string>) => Effect.Effect<string, E>;
|
|
98
|
+
}
|
|
35
99
|
/**
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
* requested revision and check out a detached worktree at the resolved commit.
|
|
100
|
+
* Reconciles a checkout left by an earlier process: salvages it without a known base, records
|
|
101
|
+
* the result, and removes the worktree only after its work is pushed. Checkouts of succeeded
|
|
102
|
+
* Attempts and of `permissions: read` Loops are removed without salvage.
|
|
40
103
|
*/
|
|
41
|
-
export declare const
|
|
104
|
+
export declare const recoverWorktree: <E extends Error, RecordError>(options: RecoveryOptions<E>, record: (salvage: AttemptSalvage) => Effect.Effect<void, RecordError>) => Effect.Effect<void, E | RecordError, never>;
|
|
42
105
|
export {};
|
|
43
106
|
//# 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":"
|
|
1
|
+
{"version":3,"file":"provision.d.ts","sourceRoot":"","sources":["../src/provision.ts"],"names":[],"mappings":"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"}
|