@ordewell/core 0.12.0 → 0.12.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/dist/{ModeResolver-CHsaoV7M.d.ts → ModeResolver-B64aUZXJ.d.ts} +1 -1
- package/dist/{ModeResolver-b_7bPlBS.d.mts → ModeResolver-CA2fUU9h.d.mts} +1 -1
- package/dist/{Task-BTEH-ztX.d.mts → Task-CxGgN6I0.d.mts} +503 -16
- package/dist/{Task-BTEH-ztX.d.ts → Task-CxGgN6I0.d.ts} +503 -16
- package/dist/{chunk-BKTDYGIP.mjs → chunk-2IFKPYPO.mjs} +441 -17
- package/dist/chunk-2IFKPYPO.mjs.map +1 -0
- package/dist/{chunk-BFLVOYNR.mjs → chunk-FX33UKAD.mjs} +8 -6
- package/dist/chunk-FX33UKAD.mjs.map +1 -0
- package/dist/{chunk-F6WS3JLQ.mjs → chunk-PKJTN2PD.mjs} +20 -11
- package/dist/chunk-PKJTN2PD.mjs.map +1 -0
- package/dist/{chunk-HP2LNKST.mjs → chunk-RZ23BMVR.mjs} +345 -134
- package/dist/chunk-RZ23BMVR.mjs.map +1 -0
- package/dist/chunk-UDUATSCJ.mjs +48 -0
- package/dist/chunk-UDUATSCJ.mjs.map +1 -0
- package/dist/{IRunner-BwzyUVIL.d.mts → eventStore-CTCSKS9E.d.ts} +916 -129
- package/dist/{IRunner-DjJkYwko.d.ts → eventStore-CcB8yELZ.d.mts} +916 -129
- package/dist/index.d.mts +677 -97
- package/dist/index.d.ts +677 -97
- package/dist/index.js +8233 -2450
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +6951 -1772
- package/dist/index.mjs.map +1 -1
- package/dist/parsing.d.mts +2 -2
- package/dist/parsing.d.ts +2 -2
- package/dist/parsing.js +277 -21
- package/dist/parsing.js.map +1 -1
- package/dist/parsing.mjs +3 -3
- package/dist/plan-utils.d.mts +8 -5
- package/dist/plan-utils.d.ts +8 -5
- package/dist/plan-utils.js +129 -16
- package/dist/plan-utils.js.map +1 -1
- package/dist/plan-utils.mjs +17 -3
- package/dist/{runSettingsText-x-YML2ay.d.mts → runSettingsText-DFVpe6aU.d.mts} +1142 -934
- package/dist/{runSettingsText-CvZ40IPv.d.ts → runSettingsText-lKLDsyli.d.ts} +1142 -934
- package/dist/testing.d.mts +83 -4
- package/dist/testing.d.ts +83 -4
- package/dist/testing.js +142 -1
- package/dist/testing.js.map +1 -1
- package/dist/testing.mjs +126 -2
- package/dist/testing.mjs.map +1 -1
- package/docker/task.Dockerfile +22 -0
- package/package.json +2 -1
- package/skills/diagnose/SKILL.md +2 -2
- package/skills/explore/SKILL.md +1 -1
- package/dist/chunk-BFLVOYNR.mjs.map +0 -1
- package/dist/chunk-BKTDYGIP.mjs.map +0 -1
- package/dist/chunk-F6WS3JLQ.mjs.map +0 -1
- package/dist/chunk-HP2LNKST.mjs.map +0 -1
package/dist/testing.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { J as EventStore, bP as TreeEvent, bQ as TreeFact, aj as NodePath, K as ExecutionBackend, a4 as LeaseRequest, a5 as LeaseSpec, S as Guarantee, a3 as LeaseRepo, b5 as RunnerPlacement, a2 as LeaseRecord, T as GuaranteeReport, aR as ReservedLease, _ as IRunnerSession, aK as QueuedTaskMessage, bs as StructuredTurnEnd, br as StructuredEvent, by as TaskCompleteArgs, x as CheckpointAnswer, be as ScriptExit, bA as TaskMessageFrom, aX as RunnerCommand, $ as InvokedCommand, k as ApprovalDecision, V as IConfig, W as IFileSystem } from './eventStore-CcB8yELZ.mjs';
|
|
2
|
+
import { U as IntegrationDisposal, b4 as RunnerSessionCost, T as IWorktreeIsolation, W as IsolationAvailability, a2 as IsolationMergeResult, bE as TreeSnapshot, bb as SetupFailure, a5 as IsolationPruneResult, a6 as IsolationRemoval, a3 as IsolationOutcome, a9 as IsolationRevertResult, a$ as RevertCommand, aP as RepairEvidence, ab as IsolationRun, bp as Task, aH as PrepareIntent, aI as PreparedTask, J as HandoffCommit, ai as LandedWork, b0 as RevertWatch, X as IsolationHandoff } from './Task-CxGgN6I0.mjs';
|
|
3
3
|
import 'child_process';
|
|
4
4
|
import 'zod/v4';
|
|
5
5
|
|
|
@@ -107,6 +107,82 @@ declare class FakeRunnerSession implements IRunnerSession {
|
|
|
107
107
|
emitTurnEnd(reason: StructuredTurnEnd): void;
|
|
108
108
|
private deliver;
|
|
109
109
|
}
|
|
110
|
+
/** An in-memory {@link EventStore}. `failing` makes the next appends reject, as a full disk would. */
|
|
111
|
+
declare class FakeEventStore implements EventStore {
|
|
112
|
+
readonly events: TreeEvent[];
|
|
113
|
+
failing: Error | null;
|
|
114
|
+
private closed;
|
|
115
|
+
append(events: readonly TreeFact[]): Promise<void>;
|
|
116
|
+
read(after: number, path?: NodePath): AsyncIterable<TreeEvent>;
|
|
117
|
+
close(): Promise<void>;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* An in-memory {@link ExecutionBackend}, as {@link FakeWorktreeIsolation} fakes
|
|
121
|
+
* git: a count of slots and nothing else. `requests`, `opened` and `released`
|
|
122
|
+
* log what the seam was asked; `holdOpen` keeps an open waiting, `openError`
|
|
123
|
+
* fails one, `refuse` turns a role down, `provenGuarantees` is what its probe
|
|
124
|
+
* proves, and `freed` is what a release does, a pool's tick.
|
|
125
|
+
*/
|
|
126
|
+
declare class FakeExecutionBackend implements ExecutionBackend {
|
|
127
|
+
/** Slots; a planner, a merge and a delegated task take none, as a flat run's do not. */
|
|
128
|
+
limit: number;
|
|
129
|
+
held: number;
|
|
130
|
+
requests: LeaseRequest[];
|
|
131
|
+
opened: {
|
|
132
|
+
request: LeaseRequest;
|
|
133
|
+
spec: LeaseSpec;
|
|
134
|
+
}[];
|
|
135
|
+
released: {
|
|
136
|
+
id: string;
|
|
137
|
+
reason: string;
|
|
138
|
+
}[];
|
|
139
|
+
letGoCalls: {
|
|
140
|
+
taskId: string;
|
|
141
|
+
keep: boolean;
|
|
142
|
+
reason: string;
|
|
143
|
+
}[];
|
|
144
|
+
openError: Error | null;
|
|
145
|
+
refuse: {
|
|
146
|
+
role: LeaseRequest['role'];
|
|
147
|
+
reason: string;
|
|
148
|
+
} | null;
|
|
149
|
+
provenGuarantees: readonly Guarantee[];
|
|
150
|
+
/** What exportResult reports of a session, in place of what it is told. */
|
|
151
|
+
sessionState: {
|
|
152
|
+
nativeSessionId: string;
|
|
153
|
+
} | null;
|
|
154
|
+
/** The repositories an open says its worktree holds. */
|
|
155
|
+
repos: readonly LeaseRepo[];
|
|
156
|
+
/** Where an open puts its runner, for a lease that does not run it on this host. */
|
|
157
|
+
placement: RunnerPlacement | null;
|
|
158
|
+
/** Brings a task's work back; absent, it is where the attempt ran. */
|
|
159
|
+
collect?: (taskId: string) => Promise<void>;
|
|
160
|
+
/** Waits on what it has running, as a closing Session does; absent, nothing outlives a runner. */
|
|
161
|
+
settle?: () => Promise<void>;
|
|
162
|
+
/** The workspace root's repositories; absent, none is known. */
|
|
163
|
+
checkoutRepos?: () => readonly LeaseRepo[];
|
|
164
|
+
records: LeaseRecord[];
|
|
165
|
+
freed: () => void;
|
|
166
|
+
private openHold;
|
|
167
|
+
private nextId;
|
|
168
|
+
/** Make the next open wait until the returned function is called. */
|
|
169
|
+
holdOpen(): () => void;
|
|
170
|
+
probe(): Promise<GuaranteeReport>;
|
|
171
|
+
private takesSlot;
|
|
172
|
+
refusal(request: LeaseRequest): string | null;
|
|
173
|
+
reserve(request: LeaseRequest): {
|
|
174
|
+
lease: ReservedLease;
|
|
175
|
+
} | {
|
|
176
|
+
refused: string;
|
|
177
|
+
};
|
|
178
|
+
private open;
|
|
179
|
+
letGo(taskId: string, { keep, landing, reason }: {
|
|
180
|
+
keep: boolean;
|
|
181
|
+
landing?: Promise<unknown> | null;
|
|
182
|
+
reason: string;
|
|
183
|
+
}): Promise<void>;
|
|
184
|
+
list(): Promise<readonly LeaseRecord[]>;
|
|
185
|
+
}
|
|
110
186
|
type FakeIsolationCall = {
|
|
111
187
|
op: 'isActive';
|
|
112
188
|
workspaceRoot: string;
|
|
@@ -147,6 +223,8 @@ type FakeIsolationCall = {
|
|
|
147
223
|
*/
|
|
148
224
|
declare class FakeWorktreeIsolation implements IWorktreeIsolation {
|
|
149
225
|
availability: IsolationAvailability;
|
|
226
|
+
/** What `gitShortfall` answers. */
|
|
227
|
+
gitShortfallText: string | null;
|
|
150
228
|
/** The repo paths `startRun` groups: a group of one at `.` unless set. */
|
|
151
229
|
repos: string[];
|
|
152
230
|
/** Per task id, the repos it changes; every repo of the group when not listed. */
|
|
@@ -204,10 +282,11 @@ declare class FakeWorktreeIsolation implements IWorktreeIsolation {
|
|
|
204
282
|
holdRevert(): () => void;
|
|
205
283
|
/** Make `verifyRepair` for this task wait until the returned function is called. */
|
|
206
284
|
holdVerification(taskId: string): () => void;
|
|
285
|
+
gitShortfall(): Promise<string | null>;
|
|
207
286
|
isActive(workspaceRoot: string): Promise<IsolationAvailability>;
|
|
208
287
|
/** Like git: once the tracked changes are stashed, the tree is no longer dirty. */
|
|
209
288
|
stash(workspaceRoot: string): Promise<void>;
|
|
210
|
-
startRun(workspaceRoot: string): Promise<IsolationRun>;
|
|
289
|
+
startRun(workspaceRoot: string, stateRoot?: string): Promise<IsolationRun>;
|
|
211
290
|
prepare(task: Task, run: IsolationRun, _intent?: PrepareIntent, opts?: {
|
|
212
291
|
readOnly?: boolean;
|
|
213
292
|
}): Promise<PreparedTask>;
|
|
@@ -237,4 +316,4 @@ declare class FakeWorktreeIsolation implements IWorktreeIsolation {
|
|
|
237
316
|
sweep(): Promise<void>;
|
|
238
317
|
}
|
|
239
318
|
|
|
240
|
-
export { type FakeIsolationCall, FakeRunnerSession, FakeWorktreeIsolation, fakeConfig, fakeFileSystem, flushMicrotasks };
|
|
319
|
+
export { FakeEventStore, FakeExecutionBackend, type FakeIsolationCall, FakeRunnerSession, FakeWorktreeIsolation, fakeConfig, fakeFileSystem, flushMicrotasks };
|
package/dist/testing.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { J as EventStore, bP as TreeEvent, bQ as TreeFact, aj as NodePath, K as ExecutionBackend, a4 as LeaseRequest, a5 as LeaseSpec, S as Guarantee, a3 as LeaseRepo, b5 as RunnerPlacement, a2 as LeaseRecord, T as GuaranteeReport, aR as ReservedLease, _ as IRunnerSession, aK as QueuedTaskMessage, bs as StructuredTurnEnd, br as StructuredEvent, by as TaskCompleteArgs, x as CheckpointAnswer, be as ScriptExit, bA as TaskMessageFrom, aX as RunnerCommand, $ as InvokedCommand, k as ApprovalDecision, V as IConfig, W as IFileSystem } from './eventStore-CTCSKS9E.js';
|
|
2
|
+
import { U as IntegrationDisposal, b4 as RunnerSessionCost, T as IWorktreeIsolation, W as IsolationAvailability, a2 as IsolationMergeResult, bE as TreeSnapshot, bb as SetupFailure, a5 as IsolationPruneResult, a6 as IsolationRemoval, a3 as IsolationOutcome, a9 as IsolationRevertResult, a$ as RevertCommand, aP as RepairEvidence, ab as IsolationRun, bp as Task, aH as PrepareIntent, aI as PreparedTask, J as HandoffCommit, ai as LandedWork, b0 as RevertWatch, X as IsolationHandoff } from './Task-CxGgN6I0.js';
|
|
3
3
|
import 'child_process';
|
|
4
4
|
import 'zod/v4';
|
|
5
5
|
|
|
@@ -107,6 +107,82 @@ declare class FakeRunnerSession implements IRunnerSession {
|
|
|
107
107
|
emitTurnEnd(reason: StructuredTurnEnd): void;
|
|
108
108
|
private deliver;
|
|
109
109
|
}
|
|
110
|
+
/** An in-memory {@link EventStore}. `failing` makes the next appends reject, as a full disk would. */
|
|
111
|
+
declare class FakeEventStore implements EventStore {
|
|
112
|
+
readonly events: TreeEvent[];
|
|
113
|
+
failing: Error | null;
|
|
114
|
+
private closed;
|
|
115
|
+
append(events: readonly TreeFact[]): Promise<void>;
|
|
116
|
+
read(after: number, path?: NodePath): AsyncIterable<TreeEvent>;
|
|
117
|
+
close(): Promise<void>;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* An in-memory {@link ExecutionBackend}, as {@link FakeWorktreeIsolation} fakes
|
|
121
|
+
* git: a count of slots and nothing else. `requests`, `opened` and `released`
|
|
122
|
+
* log what the seam was asked; `holdOpen` keeps an open waiting, `openError`
|
|
123
|
+
* fails one, `refuse` turns a role down, `provenGuarantees` is what its probe
|
|
124
|
+
* proves, and `freed` is what a release does, a pool's tick.
|
|
125
|
+
*/
|
|
126
|
+
declare class FakeExecutionBackend implements ExecutionBackend {
|
|
127
|
+
/** Slots; a planner, a merge and a delegated task take none, as a flat run's do not. */
|
|
128
|
+
limit: number;
|
|
129
|
+
held: number;
|
|
130
|
+
requests: LeaseRequest[];
|
|
131
|
+
opened: {
|
|
132
|
+
request: LeaseRequest;
|
|
133
|
+
spec: LeaseSpec;
|
|
134
|
+
}[];
|
|
135
|
+
released: {
|
|
136
|
+
id: string;
|
|
137
|
+
reason: string;
|
|
138
|
+
}[];
|
|
139
|
+
letGoCalls: {
|
|
140
|
+
taskId: string;
|
|
141
|
+
keep: boolean;
|
|
142
|
+
reason: string;
|
|
143
|
+
}[];
|
|
144
|
+
openError: Error | null;
|
|
145
|
+
refuse: {
|
|
146
|
+
role: LeaseRequest['role'];
|
|
147
|
+
reason: string;
|
|
148
|
+
} | null;
|
|
149
|
+
provenGuarantees: readonly Guarantee[];
|
|
150
|
+
/** What exportResult reports of a session, in place of what it is told. */
|
|
151
|
+
sessionState: {
|
|
152
|
+
nativeSessionId: string;
|
|
153
|
+
} | null;
|
|
154
|
+
/** The repositories an open says its worktree holds. */
|
|
155
|
+
repos: readonly LeaseRepo[];
|
|
156
|
+
/** Where an open puts its runner, for a lease that does not run it on this host. */
|
|
157
|
+
placement: RunnerPlacement | null;
|
|
158
|
+
/** Brings a task's work back; absent, it is where the attempt ran. */
|
|
159
|
+
collect?: (taskId: string) => Promise<void>;
|
|
160
|
+
/** Waits on what it has running, as a closing Session does; absent, nothing outlives a runner. */
|
|
161
|
+
settle?: () => Promise<void>;
|
|
162
|
+
/** The workspace root's repositories; absent, none is known. */
|
|
163
|
+
checkoutRepos?: () => readonly LeaseRepo[];
|
|
164
|
+
records: LeaseRecord[];
|
|
165
|
+
freed: () => void;
|
|
166
|
+
private openHold;
|
|
167
|
+
private nextId;
|
|
168
|
+
/** Make the next open wait until the returned function is called. */
|
|
169
|
+
holdOpen(): () => void;
|
|
170
|
+
probe(): Promise<GuaranteeReport>;
|
|
171
|
+
private takesSlot;
|
|
172
|
+
refusal(request: LeaseRequest): string | null;
|
|
173
|
+
reserve(request: LeaseRequest): {
|
|
174
|
+
lease: ReservedLease;
|
|
175
|
+
} | {
|
|
176
|
+
refused: string;
|
|
177
|
+
};
|
|
178
|
+
private open;
|
|
179
|
+
letGo(taskId: string, { keep, landing, reason }: {
|
|
180
|
+
keep: boolean;
|
|
181
|
+
landing?: Promise<unknown> | null;
|
|
182
|
+
reason: string;
|
|
183
|
+
}): Promise<void>;
|
|
184
|
+
list(): Promise<readonly LeaseRecord[]>;
|
|
185
|
+
}
|
|
110
186
|
type FakeIsolationCall = {
|
|
111
187
|
op: 'isActive';
|
|
112
188
|
workspaceRoot: string;
|
|
@@ -147,6 +223,8 @@ type FakeIsolationCall = {
|
|
|
147
223
|
*/
|
|
148
224
|
declare class FakeWorktreeIsolation implements IWorktreeIsolation {
|
|
149
225
|
availability: IsolationAvailability;
|
|
226
|
+
/** What `gitShortfall` answers. */
|
|
227
|
+
gitShortfallText: string | null;
|
|
150
228
|
/** The repo paths `startRun` groups: a group of one at `.` unless set. */
|
|
151
229
|
repos: string[];
|
|
152
230
|
/** Per task id, the repos it changes; every repo of the group when not listed. */
|
|
@@ -204,10 +282,11 @@ declare class FakeWorktreeIsolation implements IWorktreeIsolation {
|
|
|
204
282
|
holdRevert(): () => void;
|
|
205
283
|
/** Make `verifyRepair` for this task wait until the returned function is called. */
|
|
206
284
|
holdVerification(taskId: string): () => void;
|
|
285
|
+
gitShortfall(): Promise<string | null>;
|
|
207
286
|
isActive(workspaceRoot: string): Promise<IsolationAvailability>;
|
|
208
287
|
/** Like git: once the tracked changes are stashed, the tree is no longer dirty. */
|
|
209
288
|
stash(workspaceRoot: string): Promise<void>;
|
|
210
|
-
startRun(workspaceRoot: string): Promise<IsolationRun>;
|
|
289
|
+
startRun(workspaceRoot: string, stateRoot?: string): Promise<IsolationRun>;
|
|
211
290
|
prepare(task: Task, run: IsolationRun, _intent?: PrepareIntent, opts?: {
|
|
212
291
|
readOnly?: boolean;
|
|
213
292
|
}): Promise<PreparedTask>;
|
|
@@ -237,4 +316,4 @@ declare class FakeWorktreeIsolation implements IWorktreeIsolation {
|
|
|
237
316
|
sweep(): Promise<void>;
|
|
238
317
|
}
|
|
239
318
|
|
|
240
|
-
export { type FakeIsolationCall, FakeRunnerSession, FakeWorktreeIsolation, fakeConfig, fakeFileSystem, flushMicrotasks };
|
|
319
|
+
export { FakeEventStore, FakeExecutionBackend, type FakeIsolationCall, FakeRunnerSession, FakeWorktreeIsolation, fakeConfig, fakeFileSystem, flushMicrotasks };
|
package/dist/testing.js
CHANGED
|
@@ -20,6 +20,8 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/testing.ts
|
|
21
21
|
var testing_exports = {};
|
|
22
22
|
__export(testing_exports, {
|
|
23
|
+
FakeEventStore: () => FakeEventStore,
|
|
24
|
+
FakeExecutionBackend: () => FakeExecutionBackend,
|
|
23
25
|
FakeRunnerSession: () => FakeRunnerSession,
|
|
24
26
|
FakeWorktreeIsolation: () => FakeWorktreeIsolation,
|
|
25
27
|
fakeConfig: () => fakeConfig,
|
|
@@ -73,6 +75,26 @@ function handoffOf(run) {
|
|
|
73
75
|
var SKILL_NAME = new RegExp(`^${SKILL_NAME_PATTERN}$`);
|
|
74
76
|
var DEFAULT_RUNNERS = ["claude-code"];
|
|
75
77
|
|
|
78
|
+
// src/services/executionLease.ts
|
|
79
|
+
var GUARANTEES = ["fs.hostHidden", "fs.writeScope", "net.allowlist", "net.noMetadata", "cred.unreadable", "kernel.separate", "limits.memory"];
|
|
80
|
+
var LeaseGuaranteeError = class extends Error {
|
|
81
|
+
constructor(unproven) {
|
|
82
|
+
super(`This session requires ${unproven.join(", ")}, which its execution backend could not prove.`);
|
|
83
|
+
this.unproven = unproven;
|
|
84
|
+
this.name = "LeaseGuaranteeError";
|
|
85
|
+
}
|
|
86
|
+
unproven;
|
|
87
|
+
};
|
|
88
|
+
function refuseUnproven(required, report) {
|
|
89
|
+
const unproven = required.filter((guarantee) => !report[guarantee].proven);
|
|
90
|
+
if (unproven.length > 0) throw new LeaseGuaranteeError(unproven);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// src/models/TreeEvent.ts
|
|
94
|
+
function isWithin(node, ancestor) {
|
|
95
|
+
return node === ancestor || node.startsWith(`${ancestor}/`);
|
|
96
|
+
}
|
|
97
|
+
|
|
76
98
|
// src/testing.ts
|
|
77
99
|
async function flushMicrotasks(rounds = 20) {
|
|
78
100
|
for (let i = 0; i < rounds; i += 1) await Promise.resolve();
|
|
@@ -344,8 +366,121 @@ var FakeRunnerSession = class {
|
|
|
344
366
|
this.emitEvent({ type: "turn_start", text, ...from ? { from } : {} });
|
|
345
367
|
}
|
|
346
368
|
};
|
|
369
|
+
var FakeEventStore = class {
|
|
370
|
+
events = [];
|
|
371
|
+
failing = null;
|
|
372
|
+
closed = false;
|
|
373
|
+
async append(events) {
|
|
374
|
+
if (this.closed) throw new Error("This event log is closed.");
|
|
375
|
+
if (this.failing) throw this.failing;
|
|
376
|
+
for (const event of events) this.events.push({ ...event, seq: this.events.length + 1 });
|
|
377
|
+
}
|
|
378
|
+
async *read(after, path) {
|
|
379
|
+
for (const event of [...this.events]) {
|
|
380
|
+
if (event.seq > after && (path === void 0 || isWithin(event.node, path))) yield event;
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
async close() {
|
|
384
|
+
this.closed = true;
|
|
385
|
+
}
|
|
386
|
+
};
|
|
387
|
+
var FakeExecutionBackend = class {
|
|
388
|
+
/** Slots; a planner, a merge and a delegated task take none, as a flat run's do not. */
|
|
389
|
+
limit = Infinity;
|
|
390
|
+
held = 0;
|
|
391
|
+
requests = [];
|
|
392
|
+
opened = [];
|
|
393
|
+
released = [];
|
|
394
|
+
letGoCalls = [];
|
|
395
|
+
openError = null;
|
|
396
|
+
refuse = null;
|
|
397
|
+
provenGuarantees = [];
|
|
398
|
+
/** What exportResult reports of a session, in place of what it is told. */
|
|
399
|
+
sessionState = null;
|
|
400
|
+
/** The repositories an open says its worktree holds. */
|
|
401
|
+
repos = [];
|
|
402
|
+
/** Where an open puts its runner, for a lease that does not run it on this host. */
|
|
403
|
+
placement = null;
|
|
404
|
+
/** Brings a task's work back; absent, it is where the attempt ran. */
|
|
405
|
+
collect;
|
|
406
|
+
/** Waits on what it has running, as a closing Session does; absent, nothing outlives a runner. */
|
|
407
|
+
settle;
|
|
408
|
+
/** The workspace root's repositories; absent, none is known. */
|
|
409
|
+
checkoutRepos;
|
|
410
|
+
records = [];
|
|
411
|
+
freed = () => void 0;
|
|
412
|
+
openHold = null;
|
|
413
|
+
nextId = 0;
|
|
414
|
+
/** Make the next open wait until the returned function is called. */
|
|
415
|
+
holdOpen() {
|
|
416
|
+
let open;
|
|
417
|
+
this.openHold = new Promise((resolve) => {
|
|
418
|
+
open = resolve;
|
|
419
|
+
});
|
|
420
|
+
return open;
|
|
421
|
+
}
|
|
422
|
+
async probe() {
|
|
423
|
+
const at = (/* @__PURE__ */ new Date(0)).toISOString();
|
|
424
|
+
return Object.fromEntries(GUARANTEES.map((g) => [g, { proven: this.provenGuarantees.includes(g), by: "fake probe", at }]));
|
|
425
|
+
}
|
|
426
|
+
takesSlot(request) {
|
|
427
|
+
return request.role === "task" || request.role === "script";
|
|
428
|
+
}
|
|
429
|
+
refusal(request) {
|
|
430
|
+
if (this.refuse?.role === request.role) return this.refuse.reason;
|
|
431
|
+
return this.takesSlot(request) && this.held >= this.limit ? `no slot for ${request.node.taskId ?? request.role}` : null;
|
|
432
|
+
}
|
|
433
|
+
reserve(request) {
|
|
434
|
+
this.requests.push(request);
|
|
435
|
+
const refused = this.refusal(request);
|
|
436
|
+
if (refused) return { refused };
|
|
437
|
+
const holdsSlot = this.takesSlot(request);
|
|
438
|
+
if (holdsSlot) this.held += 1;
|
|
439
|
+
const id = `lease-${++this.nextId}`;
|
|
440
|
+
let live = true;
|
|
441
|
+
return {
|
|
442
|
+
lease: {
|
|
443
|
+
id,
|
|
444
|
+
holdsSlot,
|
|
445
|
+
open: (spec) => this.open(request, spec),
|
|
446
|
+
release: (reason) => {
|
|
447
|
+
if (!live) return;
|
|
448
|
+
live = false;
|
|
449
|
+
this.released.push({ id, reason });
|
|
450
|
+
if (holdsSlot) this.held -= 1;
|
|
451
|
+
this.freed();
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
};
|
|
455
|
+
}
|
|
456
|
+
async open(request, spec) {
|
|
457
|
+
this.opened.push({ request, spec });
|
|
458
|
+
const guarantees = await this.probe();
|
|
459
|
+
refuseUnproven(spec.required, guarantees);
|
|
460
|
+
const hold = this.openHold;
|
|
461
|
+
this.openHold = null;
|
|
462
|
+
await hold;
|
|
463
|
+
if (this.openError) throw this.openError;
|
|
464
|
+
const worktree = spec.workspace.kind === "worktree";
|
|
465
|
+
return {
|
|
466
|
+
workspace: { cwd: worktree ? `/fake-lease/${spec.task?.id}` : "/repo", worktree, ...this.repos.length ? { repos: this.repos } : {} },
|
|
467
|
+
guarantees,
|
|
468
|
+
exportResult: (session) => ({ refs: {}, sessionState: { ...session, ...this.sessionState } }),
|
|
469
|
+
...this.placement ? { placement: this.placement } : {}
|
|
470
|
+
};
|
|
471
|
+
}
|
|
472
|
+
async letGo(taskId, { keep, landing, reason }) {
|
|
473
|
+
await landing;
|
|
474
|
+
this.letGoCalls.push({ taskId, keep, reason });
|
|
475
|
+
}
|
|
476
|
+
async list() {
|
|
477
|
+
return this.records;
|
|
478
|
+
}
|
|
479
|
+
};
|
|
347
480
|
var FakeWorktreeIsolation = class {
|
|
348
481
|
availability = { active: true };
|
|
482
|
+
/** What `gitShortfall` answers. */
|
|
483
|
+
gitShortfallText = null;
|
|
349
484
|
/** The repo paths `startRun` groups: a group of one at `.` unless set. */
|
|
350
485
|
repos = [SELF_REPO];
|
|
351
486
|
/** Per task id, the repos it changes; every repo of the group when not listed. */
|
|
@@ -423,6 +558,9 @@ var FakeWorktreeIsolation = class {
|
|
|
423
558
|
}));
|
|
424
559
|
return open;
|
|
425
560
|
}
|
|
561
|
+
async gitShortfall() {
|
|
562
|
+
return this.gitShortfallText;
|
|
563
|
+
}
|
|
426
564
|
async isActive(workspaceRoot) {
|
|
427
565
|
this.log({ op: "isActive", workspaceRoot });
|
|
428
566
|
return this.availability;
|
|
@@ -432,13 +570,14 @@ var FakeWorktreeIsolation = class {
|
|
|
432
570
|
this.log({ op: "stash", workspaceRoot });
|
|
433
571
|
if (!this.availability.active && this.availability.reason === "dirty") this.availability = { active: true };
|
|
434
572
|
}
|
|
435
|
-
async startRun(workspaceRoot) {
|
|
573
|
+
async startRun(workspaceRoot, stateRoot) {
|
|
436
574
|
this.log({ op: "startRun", workspaceRoot });
|
|
437
575
|
if (this.startRunError) throw this.startRunError;
|
|
438
576
|
const id = `run${++this.runCount}`;
|
|
439
577
|
return {
|
|
440
578
|
id,
|
|
441
579
|
workspaceRoot,
|
|
580
|
+
...stateRoot !== void 0 ? { stateRoot } : {},
|
|
442
581
|
repos: this.repos.map((repo) => ({
|
|
443
582
|
path: repo,
|
|
444
583
|
root: `${workspaceRoot}/${repo}`.replace(/\/\.$/, ""),
|
|
@@ -635,6 +774,8 @@ var FakeWorktreeIsolation = class {
|
|
|
635
774
|
};
|
|
636
775
|
// Annotate the CommonJS export names for ESM import in node:
|
|
637
776
|
0 && (module.exports = {
|
|
777
|
+
FakeEventStore,
|
|
778
|
+
FakeExecutionBackend,
|
|
638
779
|
FakeRunnerSession,
|
|
639
780
|
FakeWorktreeIsolation,
|
|
640
781
|
fakeConfig,
|