@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.mjs
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
1
|
+
import {
|
|
2
|
+
GUARANTEES,
|
|
3
|
+
isWithin,
|
|
4
|
+
refuseUnproven
|
|
5
|
+
} from "./chunk-UDUATSCJ.mjs";
|
|
1
6
|
import {
|
|
2
7
|
DEFAULT_RUNNERS,
|
|
3
8
|
SELF_REPO,
|
|
4
9
|
handoffOf,
|
|
5
10
|
integrationBranchFor,
|
|
6
11
|
noRemoval
|
|
7
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-PKJTN2PD.mjs";
|
|
8
13
|
|
|
9
14
|
// src/testing.ts
|
|
10
15
|
async function flushMicrotasks(rounds = 20) {
|
|
@@ -277,8 +282,121 @@ var FakeRunnerSession = class {
|
|
|
277
282
|
this.emitEvent({ type: "turn_start", text, ...from ? { from } : {} });
|
|
278
283
|
}
|
|
279
284
|
};
|
|
285
|
+
var FakeEventStore = class {
|
|
286
|
+
events = [];
|
|
287
|
+
failing = null;
|
|
288
|
+
closed = false;
|
|
289
|
+
async append(events) {
|
|
290
|
+
if (this.closed) throw new Error("This event log is closed.");
|
|
291
|
+
if (this.failing) throw this.failing;
|
|
292
|
+
for (const event of events) this.events.push({ ...event, seq: this.events.length + 1 });
|
|
293
|
+
}
|
|
294
|
+
async *read(after, path) {
|
|
295
|
+
for (const event of [...this.events]) {
|
|
296
|
+
if (event.seq > after && (path === void 0 || isWithin(event.node, path))) yield event;
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
async close() {
|
|
300
|
+
this.closed = true;
|
|
301
|
+
}
|
|
302
|
+
};
|
|
303
|
+
var FakeExecutionBackend = class {
|
|
304
|
+
/** Slots; a planner, a merge and a delegated task take none, as a flat run's do not. */
|
|
305
|
+
limit = Infinity;
|
|
306
|
+
held = 0;
|
|
307
|
+
requests = [];
|
|
308
|
+
opened = [];
|
|
309
|
+
released = [];
|
|
310
|
+
letGoCalls = [];
|
|
311
|
+
openError = null;
|
|
312
|
+
refuse = null;
|
|
313
|
+
provenGuarantees = [];
|
|
314
|
+
/** What exportResult reports of a session, in place of what it is told. */
|
|
315
|
+
sessionState = null;
|
|
316
|
+
/** The repositories an open says its worktree holds. */
|
|
317
|
+
repos = [];
|
|
318
|
+
/** Where an open puts its runner, for a lease that does not run it on this host. */
|
|
319
|
+
placement = null;
|
|
320
|
+
/** Brings a task's work back; absent, it is where the attempt ran. */
|
|
321
|
+
collect;
|
|
322
|
+
/** Waits on what it has running, as a closing Session does; absent, nothing outlives a runner. */
|
|
323
|
+
settle;
|
|
324
|
+
/** The workspace root's repositories; absent, none is known. */
|
|
325
|
+
checkoutRepos;
|
|
326
|
+
records = [];
|
|
327
|
+
freed = () => void 0;
|
|
328
|
+
openHold = null;
|
|
329
|
+
nextId = 0;
|
|
330
|
+
/** Make the next open wait until the returned function is called. */
|
|
331
|
+
holdOpen() {
|
|
332
|
+
let open;
|
|
333
|
+
this.openHold = new Promise((resolve) => {
|
|
334
|
+
open = resolve;
|
|
335
|
+
});
|
|
336
|
+
return open;
|
|
337
|
+
}
|
|
338
|
+
async probe() {
|
|
339
|
+
const at = (/* @__PURE__ */ new Date(0)).toISOString();
|
|
340
|
+
return Object.fromEntries(GUARANTEES.map((g) => [g, { proven: this.provenGuarantees.includes(g), by: "fake probe", at }]));
|
|
341
|
+
}
|
|
342
|
+
takesSlot(request) {
|
|
343
|
+
return request.role === "task" || request.role === "script";
|
|
344
|
+
}
|
|
345
|
+
refusal(request) {
|
|
346
|
+
if (this.refuse?.role === request.role) return this.refuse.reason;
|
|
347
|
+
return this.takesSlot(request) && this.held >= this.limit ? `no slot for ${request.node.taskId ?? request.role}` : null;
|
|
348
|
+
}
|
|
349
|
+
reserve(request) {
|
|
350
|
+
this.requests.push(request);
|
|
351
|
+
const refused = this.refusal(request);
|
|
352
|
+
if (refused) return { refused };
|
|
353
|
+
const holdsSlot = this.takesSlot(request);
|
|
354
|
+
if (holdsSlot) this.held += 1;
|
|
355
|
+
const id = `lease-${++this.nextId}`;
|
|
356
|
+
let live = true;
|
|
357
|
+
return {
|
|
358
|
+
lease: {
|
|
359
|
+
id,
|
|
360
|
+
holdsSlot,
|
|
361
|
+
open: (spec) => this.open(request, spec),
|
|
362
|
+
release: (reason) => {
|
|
363
|
+
if (!live) return;
|
|
364
|
+
live = false;
|
|
365
|
+
this.released.push({ id, reason });
|
|
366
|
+
if (holdsSlot) this.held -= 1;
|
|
367
|
+
this.freed();
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
};
|
|
371
|
+
}
|
|
372
|
+
async open(request, spec) {
|
|
373
|
+
this.opened.push({ request, spec });
|
|
374
|
+
const guarantees = await this.probe();
|
|
375
|
+
refuseUnproven(spec.required, guarantees);
|
|
376
|
+
const hold = this.openHold;
|
|
377
|
+
this.openHold = null;
|
|
378
|
+
await hold;
|
|
379
|
+
if (this.openError) throw this.openError;
|
|
380
|
+
const worktree = spec.workspace.kind === "worktree";
|
|
381
|
+
return {
|
|
382
|
+
workspace: { cwd: worktree ? `/fake-lease/${spec.task?.id}` : "/repo", worktree, ...this.repos.length ? { repos: this.repos } : {} },
|
|
383
|
+
guarantees,
|
|
384
|
+
exportResult: (session) => ({ refs: {}, sessionState: { ...session, ...this.sessionState } }),
|
|
385
|
+
...this.placement ? { placement: this.placement } : {}
|
|
386
|
+
};
|
|
387
|
+
}
|
|
388
|
+
async letGo(taskId, { keep, landing, reason }) {
|
|
389
|
+
await landing;
|
|
390
|
+
this.letGoCalls.push({ taskId, keep, reason });
|
|
391
|
+
}
|
|
392
|
+
async list() {
|
|
393
|
+
return this.records;
|
|
394
|
+
}
|
|
395
|
+
};
|
|
280
396
|
var FakeWorktreeIsolation = class {
|
|
281
397
|
availability = { active: true };
|
|
398
|
+
/** What `gitShortfall` answers. */
|
|
399
|
+
gitShortfallText = null;
|
|
282
400
|
/** The repo paths `startRun` groups: a group of one at `.` unless set. */
|
|
283
401
|
repos = [SELF_REPO];
|
|
284
402
|
/** Per task id, the repos it changes; every repo of the group when not listed. */
|
|
@@ -356,6 +474,9 @@ var FakeWorktreeIsolation = class {
|
|
|
356
474
|
}));
|
|
357
475
|
return open;
|
|
358
476
|
}
|
|
477
|
+
async gitShortfall() {
|
|
478
|
+
return this.gitShortfallText;
|
|
479
|
+
}
|
|
359
480
|
async isActive(workspaceRoot) {
|
|
360
481
|
this.log({ op: "isActive", workspaceRoot });
|
|
361
482
|
return this.availability;
|
|
@@ -365,13 +486,14 @@ var FakeWorktreeIsolation = class {
|
|
|
365
486
|
this.log({ op: "stash", workspaceRoot });
|
|
366
487
|
if (!this.availability.active && this.availability.reason === "dirty") this.availability = { active: true };
|
|
367
488
|
}
|
|
368
|
-
async startRun(workspaceRoot) {
|
|
489
|
+
async startRun(workspaceRoot, stateRoot) {
|
|
369
490
|
this.log({ op: "startRun", workspaceRoot });
|
|
370
491
|
if (this.startRunError) throw this.startRunError;
|
|
371
492
|
const id = `run${++this.runCount}`;
|
|
372
493
|
return {
|
|
373
494
|
id,
|
|
374
495
|
workspaceRoot,
|
|
496
|
+
...stateRoot !== void 0 ? { stateRoot } : {},
|
|
375
497
|
repos: this.repos.map((repo) => ({
|
|
376
498
|
path: repo,
|
|
377
499
|
root: `${workspaceRoot}/${repo}`.replace(/\/\.$/, ""),
|
|
@@ -567,6 +689,8 @@ var FakeWorktreeIsolation = class {
|
|
|
567
689
|
}
|
|
568
690
|
};
|
|
569
691
|
export {
|
|
692
|
+
FakeEventStore,
|
|
693
|
+
FakeExecutionBackend,
|
|
570
694
|
FakeRunnerSession,
|
|
571
695
|
FakeWorktreeIsolation,
|
|
572
696
|
fakeConfig,
|
package/dist/testing.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/testing.ts"],"sourcesContent":["import type { IConfig } from './interfaces/IConfig';\nimport type { IFileSystem, ToolOutcome } from './interfaces/IFileSystem';\nimport type { InvokedCommand, IRunnerSession, QueuedTaskMessage, ScriptExit, StructuredEvent, StructuredTurnEnd, TaskMessageFrom } from './interfaces/IRunner';\nimport type { RunnerCommand } from './models/RunnerCommand';\nimport type { RunnerSessionCost } from './models/Usage';\nimport type { HandoffCommit } from './models/Handoff';\nimport type { ApprovalDecision } from './interfaces/IApproval';\nimport type { CheckpointAnswer, TaskCompleteArgs } from './services/mcp/tools';\nimport type {\n IsolationAvailability,\n IsolationHandoff,\n IsolationMergeResult,\n IsolationOutcome,\n IsolationPruneResult,\n IsolationRemoval,\n IsolationRevertResult,\n IsolationRun,\n IntegrationDisposal,\n LandedWork,\n PreparedTask,\n PrepareIntent,\n IWorktreeIsolation,\n RepairEvidence,\n RevertCommand,\n RevertWatch,\n SetupFailure,\n TreeSnapshot,\n} from './interfaces/IWorktreeIsolation';\nimport { DEFAULT_RUNNERS, type Task } from './models/Task';\nimport { handoffOf, integrationBranchFor, noRemoval, SELF_REPO } from './services/isolationRecord';\n\n/**\n * Let an already-queued promise chain run to its next await before asserting,\n * without a wall-clock sleep. For a chain whose length is not known, drain the\n * microtask queue repeatedly. Only helps a chain that does not wait on a timer.\n */\nexport async function flushMicrotasks(rounds = 20): Promise<void> {\n for (let i = 0; i < rounds; i += 1) await Promise.resolve();\n}\n\nexport function fakeConfig(overrides: Partial<IConfig> = {}): IConfig {\n return {\n aiProvider: 'openrouter',\n apiKey: 'sk-test',\n planningModel: 'test-model',\n enabledRunners: [...DEFAULT_RUNNERS],\n maxParallelSessions: 3,\n researchEnabled: false,\n researchMaxSteps: 10,\n researchMaxFileSize: 100_000,\n openAiBaseUrl: 'https://api.openai.com/v1',\n openAiApiKey: '',\n openrouterKey: '',\n geminiKey: '',\n openaiCompatibleBaseUrl: '',\n openaiCompatibleApiKey: '',\n orchestratorModel: '',\n researchSubagentModel: '',\n geminiModel: '',\n planMapEnabled: true,\n autonomousMode: true,\n // Off so an orchestrator built without an injected isolation never runs\n // real git against whatever repository the tests happen to run in.\n worktreeIsolation: false,\n workspaceRepos: [],\n worktreeLinks: [],\n // Off so a scripted conflict stays a conflict unless a test opts into repairing it.\n conflictRepairAttempts: 0,\n approvalMode: 'ask',\n approvalPreApproved: [],\n // Off so a test that is not about the allowlist sees every prompt it raises.\n approvalDefaults: false,\n effectAllowlist: [],\n notifyCommand: [],\n webReadBudget: 40,\n plannerNativeShell: false,\n setProviderModelLists: () => {},\n getProviderBaseUrl: () => '',\n // Every vendor holds a key, so no planner turn is refused for want of one\n // unless a test takes it away.\n getProviderApiKey: () => 'sk-test',\n ...overrides,\n };\n}\n\nconst EMPTY_OUTCOME: ToolOutcome = { success: false, output: '', truncated: false };\n\n/**\n * A complete {@link IFileSystem} stub. Lives here rather than in each package's\n * test folder so adding a tool to the interface is one edit, not one per suite.\n */\nexport function fakeFileSystem(overrides: Partial<IFileSystem> = {}): IFileSystem {\n return {\n readFile: async () => EMPTY_OUTCOME,\n readFiles: async () => EMPTY_OUTCOME,\n glob: async () => EMPTY_OUTCOME,\n grep: async () => EMPTY_OUTCOME,\n findSymbol: async () => EMPTY_OUTCOME,\n listDir: async () => EMPTY_OUTCOME,\n bash: async () => EMPTY_OUTCOME,\n getWorkspaceRoot: () => '/workspace',\n ...overrides,\n };\n}\n\nexport class FakeRunnerSession implements IRunnerSession {\n private outputCbs: Array<(text: string) => void> = [];\n private exitCbs: Array<(code: number) => void> = [];\n output = '';\n written: string[] = [];\n killed = false;\n\n state: 'working' | 'idle' = 'working';\n messages: QueuedTaskMessage[] = [];\n /** Every message a turn was started with, in order. */\n delivered: string[] = [];\n /** The ones of {@link delivered} Ordewell sent: the completion reminder (ADR-0018, W1). */\n fromOrdewell: string[] = [];\n interrupts = 0;\n private messageCount = 0;\n private turnEndCbs: Array<(reason: StructuredTurnEnd) => void> = [];\n private eventCbs: Array<(event: StructuredEvent) => void> = [];\n private completeCbs: Array<(report: TaskCompleteArgs) => void> = [];\n private checkpointHandler: ((question: string, signal: AbortSignal) => Promise<CheckpointAnswer>) | null = null;\n\n constructor(public id = 's1', public taskId = 't1', public sessionId: string | null = 'native-1') {}\n\n /** `stop()` was asked for: the runner winds its turn down, still reporting, until {@link emitExit}. */\n stopped = false;\n private markGone!: () => void;\n private readonly gone = new Promise<void>((resolve) => { this.markGone = resolve; });\n\n onOutput(cb: (text: string) => void): void { this.outputCbs.push(cb); }\n onExit(cb: (code: number) => void): void { this.exitCbs.push(cb); }\n kill(): void { this.killed = true; }\n stop(): Promise<void> {\n this.stopped = true;\n return this.gone;\n }\n getOutput(): string { return this.output; }\n\n emitOutput(text: string): void {\n this.output += text;\n for (const cb of this.outputCbs) cb(text);\n }\n emitExit(code: number): void {\n for (const cb of this.exitCbs) cb(code);\n this.markGone();\n }\n write(text: string): void {\n this.written.push(text);\n const message = text.trim();\n if (message) this.sendMessage(message);\n }\n\n turnState(): 'working' | 'idle' { return this.state; }\n onTurnEnd(cb: (reason: StructuredTurnEnd) => void): void { this.turnEndCbs.push(cb); }\n onEvent(cb: (event: StructuredEvent) => void): void { this.eventCbs.push(cb); }\n onTaskComplete(cb: (report: TaskCompleteArgs) => void): void { this.completeCbs.push(cb); }\n /**\n * The runner calls `task_complete`, as `StructuredSession` relays it. Here it\n * is published at once; a test that needs the real session's turn-end\n * ordering drives `StructuredSession` itself.\n */\n reportComplete(report: TaskCompleteArgs): void {\n for (const cb of this.completeCbs) cb(report);\n }\n onToolCheckpoint(handler: (question: string, signal: AbortSignal) => Promise<CheckpointAnswer>): void { this.checkpointHandler = handler; }\n private scriptExitCbs: Array<(exit: ScriptExit) => void> = [];\n onScriptExit(cb: (exit: ScriptExit) => void): void { this.scriptExitCbs.push(cb); }\n /** A script task's body ended, as `ScriptSession` hands it on (ADR-0035). */\n reportScriptExit(exit: ScriptExit): void {\n for (const cb of this.scriptExitCbs) cb(exit);\n }\n /** The runner calls `checkpoint`, as `StructuredSession` relays it; settles with the answer. */\n callCheckpoint(question: string, signal: AbortSignal = new AbortController().signal): Promise<CheckpointAnswer> {\n if (!this.checkpointHandler) throw new Error('no checkpoint handler attached');\n return this.checkpointHandler(question, signal);\n }\n sendMessage(text: string, from?: TaskMessageFrom): string {\n this.messageCount += 1;\n const id = `msg-${this.messageCount}`;\n if (this.state === 'idle') this.deliver(text, from);\n else this.messages.push({ id, text, ...(from ? { from } : {}) });\n return id;\n }\n /** Interrupts, and the turn that replaces the interrupted one opens with the forced message. */\n forceSend(text: string): string {\n if (this.state === 'idle') return this.sendMessage(text);\n this.messageCount += 1;\n const id = `msg-${this.messageCount}`;\n this.putForced({ id, text, forced: true });\n void this.interrupt();\n return id;\n }\n forceSendQueued(id: string): boolean {\n const message = this.messages.find((m) => m.id === id);\n if (!message) return false;\n if (message.forced) return true;\n this.messages = this.messages.filter((m) => m !== message);\n this.putForced({ ...message, forced: true });\n if (this.state === 'working') void this.interrupt();\n return true;\n }\n private putForced(message: QueuedTaskMessage): void {\n const at = this.messages.findIndex((m) => !m.forced);\n this.messages.splice(at < 0 ? this.messages.length : at, 0, message);\n }\n removeQueued(id: string): boolean {\n const before = this.messages.length;\n this.messages = this.messages.filter((m) => m.id !== id);\n return this.messages.length < before;\n }\n queued(): QueuedTaskMessage[] { return this.messages.map((m) => ({ ...m })); }\n async interrupt(): Promise<void> {\n this.interrupts += 1;\n if (this.state === 'working') this.emitTurnEnd('interrupted');\n }\n nativeSessionId(): string | null { return this.sessionId; }\n /** What `sessionCost()` reports: the runner's running cost as counted, null while unknown. */\n cost: RunnerSessionCost | null = null;\n sessionCost(): RunnerSessionCost | null { return this.cost; }\n\n /** What `commands()` reports: the runner's own commands (#66). */\n runnerCommands: RunnerCommand[] = [];\n /** Every runner command invoked, in order. */\n invoked: InvokedCommand[] = [];\n commands(): RunnerCommand[] { return [...this.runnerCommands]; }\n /** Runs it as a message that starts with it, which is what a runner reads. */\n invokeCommand(name: string, args = ''): string {\n this.invoked.push({ name, ...(args.trim() ? { args: args.trim() } : {}) });\n return this.sendMessage(args.trim() ? `/${name} ${args.trim()}` : `/${name}`);\n }\n\n /** Every answer this session was given, in order. */\n answers: Array<{ id: string; decision: ApprovalDecision }> = [];\n private readonly openPermissions = new Set<string>();\n\n /** The runner asks to use a tool, as `StructuredSession` announces it. */\n requestPermission(id: string, name: string, input: Record<string, unknown>, suggestions: unknown[] = []): void {\n this.openPermissions.add(id);\n this.emitEvent({ type: 'permission_request', id, name, detail: JSON.stringify(input), input, suggestions });\n }\n /** The runner gives up on a request, as an interrupt makes it. */\n withdrawPermission(id: string): void {\n if (this.openPermissions.delete(id)) this.emitEvent({ type: 'permission_withdrawn', id });\n }\n answerPermission(id: string, decision: ApprovalDecision): boolean {\n if (!this.openPermissions.delete(id)) return false;\n this.answers.push({ id, decision });\n this.emitEvent({ type: 'permission_decided', id, decision });\n return true;\n }\n\n emitEvent(event: StructuredEvent): void {\n for (const cb of this.eventCbs) cb(event);\n }\n /** The runner reads a queued message inside the running turn, as `StructuredSession` reports it (ADR-0023). */\n deliverMidTurn(id: string): void {\n const message = this.messages.find((m) => m.id === id);\n if (!message) return;\n this.messages = this.messages.filter((m) => m !== message);\n this.emitEvent({ type: 'message_delivered', messageId: id, text: message.text, ...(message.from ? { from: message.from } : {}) });\n }\n /**\n * The turn ends without a `task_complete` call, and so does the turn the\n * completion reminder opens if one was sent (ADR-0018, W1): the task waits for input.\n */\n waitForInput(): void {\n const reminders = this.fromOrdewell.length;\n this.emitTurnEnd('completed');\n if (this.fromOrdewell.length > reminders) this.emitTurnEnd('completed');\n }\n emitTurnEnd(reason: StructuredTurnEnd): void {\n const next = this.messages.shift();\n if (!next) this.state = 'idle';\n for (const cb of this.turnEndCbs) cb(reason);\n if (next) this.deliver(next.text, next.from);\n }\n\n private deliver(text: string, from?: TaskMessageFrom): void {\n this.state = 'working';\n this.delivered.push(text);\n if (from === 'ordewell') this.fromOrdewell.push(text);\n this.emitEvent({ type: 'turn_start', text, ...(from ? { from } : {}) });\n }\n}\n\nexport type FakeIsolationCall =\n | { op: 'isActive'; workspaceRoot: string }\n | { op: 'stash'; workspaceRoot: string }\n | { op: 'startRun'; workspaceRoot: string }\n | { op: 'prepare' | 'reopen' | 'verifyRepair'; taskId: string }\n | { op: 'integrate'; taskId: string }\n | { op: 'release'; taskId: string; keep: boolean }\n | { op: 'handoff' | 'pruneOrphans' | 'reviewDiff' | 'mergeIntoCheckedOut' | 'sweep' | 'findInHead' | 'snapshotTree' | 'changedSince' }\n | { op: 'discard'; integration: IntegrationDisposal }\n | { op: 'readLanded' | 'revert'; taskIds: readonly string[] };\n\n/**\n * An in-memory {@link IWorktreeIsolation} for scheduling tests: no git, no\n * filesystem. Every call is logged in `calls`; `prepare` hands back a\n * deterministic fake cwd. Set `availability` to exercise the fallbacks, `outcomes`\n * to script a conflict, and `holdIntegration` to keep a task un-integrated so a\n * test can observe that its dependents wait. `repos` makes the run a group of\n * several; `changes` and `stopsIn` say which of them a task changes and where\n * its landing stops. `repairEvidence` scripts what a conflict repair's\n * evidence check finds, and `removal` what a removal kept back.\n */\nexport class FakeWorktreeIsolation implements IWorktreeIsolation {\n availability: IsolationAvailability = { active: true };\n /** The repo paths `startRun` groups: a group of one at `.` unless set. */\n repos: string[] = [SELF_REPO];\n /** Per task id, the repos it changes; every repo of the group when not listed. */\n changes = new Map<string, string[]>();\n /** Per task id, the repo its landing stops in when its outcome is not `merged`; its first changed repo when not listed. */\n stopsIn = new Map<string, string>();\n /** Per task id, the files a `conflict` outcome names; empty when not listed. */\n conflictFiles = new Map<string, string[]>();\n /** What `mergeIntoCheckedOut` answers; a `merged` one also puts every landed task in HEAD, as git would. */\n mergeResult: IsolationMergeResult = { outcome: 'merged' };\n /** Task ids whose landed work `findInHead` finds in HEAD besides those a merge put there, as a merge by hand would. */\n mergedByHand = new Set<string>();\n /** What `snapshotTree` answers; null as for a workspace with no repo. */\n treeSnapshot: TreeSnapshot | null = {};\n /** What `changedSince` answers: the tracked files an ops task changed. */\n changedFiles: string[] = [];\n /** What `startRun` shares and `prepare` copies, to exercise their notices. */\n shared: string[] = [];\n sharedRepos: string[] = [];\n copied: string[] = [];\n setupFailed: SetupFailure[] = [];\n /** Set to make `startRun` throw, as git does when no repo of the group can be isolated. */\n startRunError: Error | null = null;\n /** Set to make `discard` / `sweep` throw after logging the call. */\n discardError: Error | null = null;\n sweepError: Error | null = null;\n /** What `pruneOrphans` reports as kept back from the sweep. */\n keptOnPrune: IsolationPruneResult['kept'] = [];\n /**\n * What every removal — a `release` that removes, `discard`, `pruneOrphans` —\n * reports it kept back. A refused task keeps its record, as git's does.\n */\n removal: IsolationRemoval = noRemoval();\n /** Per task id; a task not listed integrates as `merged`. */\n outcomes = new Map<string, IsolationOutcome>();\n /** What `revert` stops with; a revert that goes through when null. */\n revertStop: Exclude<IsolationRevertResult, { outcome: 'reverted' }> | null = null;\n /** What `readLanded` finds of a task's work in the user's branch, by task id. */\n inBranch = new Map<string, RevertCommand[]>();\n /** Per task id, what `verifyRepair` finds; a task not listed passes. */\n repairEvidence = new Map<string, RepairEvidence>();\n calls: FakeIsolationCall[] = [];\n private holds = new Map<string, Promise<void>>();\n private verifyHolds = new Map<string, Promise<void>>();\n private revertHold: Promise<void> | null = null;\n private runCount = 0;\n\n private log(call: FakeIsolationCall): void { this.calls.push(call); }\n\n /** Task ids in the order `op` was called for them. */\n taskIdsFor(op: 'prepare' | 'reopen' | 'verifyRepair' | 'integrate' | 'release'): string[] {\n return this.calls.flatMap((c) => (c.op === op && 'taskId' in c ? [c.taskId] : []));\n }\n\n /** Make `integrate` for this task wait until the returned function is called. */\n holdIntegration(taskId: string): () => void {\n let open!: () => void;\n this.holds.set(taskId, new Promise<void>((resolve) => { open = resolve; }));\n return open;\n }\n\n /** Make the next `revert` wait, past its `refusal`, until the returned function is called. */\n holdRevert(): () => void {\n let open!: () => void;\n this.revertHold = new Promise<void>((resolve) => { open = resolve; });\n return open;\n }\n\n /** Make `verifyRepair` for this task wait until the returned function is called. */\n holdVerification(taskId: string): () => void {\n let open!: () => void;\n this.verifyHolds.set(taskId, new Promise<void>((resolve) => { open = resolve; }));\n return open;\n }\n\n async isActive(workspaceRoot: string): Promise<IsolationAvailability> {\n this.log({ op: 'isActive', workspaceRoot });\n return this.availability;\n }\n\n /** Like git: once the tracked changes are stashed, the tree is no longer dirty. */\n async stash(workspaceRoot: string): Promise<void> {\n this.log({ op: 'stash', workspaceRoot });\n if (!this.availability.active && this.availability.reason === 'dirty') this.availability = { active: true };\n }\n\n async startRun(workspaceRoot: string): Promise<IsolationRun> {\n this.log({ op: 'startRun', workspaceRoot });\n if (this.startRunError) throw this.startRunError;\n const id = `run${++this.runCount}`;\n return {\n id,\n workspaceRoot,\n repos: this.repos.map((repo) => ({\n path: repo, root: `${workspaceRoot}/${repo}`.replace(/\\/\\.$/, ''), baseRef: 'base0000', baseBranch: 'main', integrationBranch: integrationBranchFor(id),\n })),\n shared: [...this.shared],\n sharedRepos: [...this.sharedRepos],\n tasks: {},\n keepsEveryLanding: true,\n carried: {},\n };\n }\n\n async prepare(task: Task, run: IsolationRun, _intent?: PrepareIntent, opts: { readOnly?: boolean } = {}): Promise<PreparedTask> {\n this.log({ op: 'prepare', taskId: task.id });\n const name = `${task.order}-${task.id}`;\n const cwd = `/fake-worktrees/${run.id}/${name}`;\n const branch = `ordewell/${run.id}/${name}`;\n run.tasks[task.id] = {\n taskId: task.id, order: task.order, title: task.title, branch, workspace: cwd, status: 'active',\n repos: Object.fromEntries(run.repos.map((r) => [r.path, { worktree: r.path === SELF_REPO ? cwd : `${cwd}/${r.path}`, linked: [] }])),\n ...(opts.readOnly ? { readOnly: true } : {}),\n };\n return { cwd, branch, copied: [...this.copied], ...(this.setupFailed.length > 0 ? { setupFailed: [...this.setupFailed] } : {}) };\n }\n\n /** Like git: the same cwd, each changed repo's tip recorded, the repair counted. */\n async reopen(task: Task, run: IsolationRun): Promise<PreparedTask> {\n this.log({ op: 'reopen', taskId: task.id });\n const record = run.tasks[task.id];\n if (record?.status !== 'conflict') throw new Error(`Task ${task.order} has no conflict to repair`);\n const changed = Object.entries(record.repos).filter(([repo, entry]) => entry.changed || repo === record.conflictRepo).map(([repo]) => repo);\n const files = (record.conflictFiles ?? []).map((file) => (record.conflictRepo && record.conflictRepo !== SELF_REPO ? `${record.conflictRepo}/${file}` : file));\n record.repairs = (record.repairs ?? 0) + 1;\n record.repairBase = Object.fromEntries(changed.map((repo) => [repo, `tip-${repo}`]));\n record.repairedFiles = [...new Set([...(record.repairedFiles ?? []), ...files])];\n record.status = 'repairing';\n return { cwd: record.workspace, branch: record.branch, copied: [] };\n }\n\n async verifyRepair(task: Task, _run: IsolationRun): Promise<RepairEvidence> {\n this.log({ op: 'verifyRepair', taskId: task.id });\n await this.verifyHolds.get(task.id);\n return this.repairEvidence.get(task.id) ?? { ok: true };\n }\n\n /** Like git: the landing is recorded and persisted before the (held) merge, and cleared once it settles. */\n async integrate(task: Task, run: IsolationRun, persist: () => void = () => undefined, commit?: HandoffCommit): Promise<IsolationOutcome> {\n this.log({ op: 'integrate', taskId: task.id });\n const record = run.tasks[task.id];\n if (!record) return 'failed';\n if (commit) record.commit = commit;\n if (record.readOnly) {\n record.status = 'failed';\n record.landingError = 'a read-only task lands nothing';\n return 'failed';\n }\n const changed = this.changes.get(task.id) ?? run.repos.map((r) => r.path);\n for (const [repo, entry] of Object.entries(record.repos)) entry.changed = changed.includes(repo) || (entry.changed ?? false);\n if (changed.length > 0) {\n run.landing = { taskId: task.id, tips: Object.fromEntries(changed.map((repo) => [repo, `tip-${repo}`])) };\n persist();\n }\n await this.holds.get(task.id);\n delete run.landing;\n const outcome = this.outcomes.get(task.id) ?? 'merged';\n record.status = outcome;\n delete record.repairBase;\n if (outcome === 'merged') {\n delete record.conflictRepo;\n delete record.conflictFiles;\n for (const repo of changed) {\n ((run.landings ??= {})[task.id] ??= {})[repo] = [...run.landings?.[task.id]?.[repo] ?? [], `tip-${repo}`];\n (run.landedTasks ??= {})[task.id] = { taskId: task.id, order: task.order, title: task.title };\n }\n } else {\n record.conflictRepo = this.stopsIn.get(task.id) ?? changed[0] ?? SELF_REPO;\n const files = this.conflictFiles.get(task.id);\n if (files) record.conflictFiles = files;\n else delete record.conflictFiles;\n }\n return outcome;\n }\n\n /** Newest landing first, read as the plan's highest order: scheduling tests land in plan order. */\n async readLanded(run: IsolationRun, taskIds: readonly string[]): Promise<LandedWork> {\n this.log({ op: 'readLanded', taskIds });\n const records = taskIds.flatMap((id) => run.tasks[id] ?? run.landedTasks?.[id] ?? []).sort((a, b) => b.order - a.order);\n const tasks = records.map((r) => ({\n taskId: r.taskId, order: r.order, title: r.title,\n repos: Object.keys(run.landings?.[r.taskId] ?? {}),\n }));\n return { ok: true, tasks, inBranch: records.flatMap((r) => this.inBranch.get(r.taskId) ?? []) };\n }\n\n /** Like git: the turn, then the judgement, then the records go in one step with the tasks back. */\n async revert(run: IsolationRun, taskIds: readonly string[], watch: RevertWatch): Promise<IsolationRevertResult> {\n this.log({ op: 'revert', taskIds });\n const hold = this.revertHold;\n this.revertHold = null;\n await hold;\n const reason = watch.refusal();\n if (reason) return { outcome: 'refused', reason };\n if (this.revertStop) return this.revertStop;\n const landed = await this.readLanded(run, taskIds);\n if (!landed.ok) return { outcome: 'failed', error: landed.error };\n if (landed.inBranch.length > 0) return { outcome: 'in-branch', commands: landed.inBranch };\n run.landing = { taskId: taskIds[0], tips: {}, reverts: {} };\n watch.persist();\n delete run.landing;\n for (const id of taskIds) {\n // Like git: a later attempt's record that did not land stays for its worktree, its conflict over.\n if (run.tasks[id]?.status === 'merged') delete run.tasks[id];\n else if (run.tasks[id]?.status === 'conflict') run.tasks[id].status = 'kept';\n delete run.landings?.[id];\n delete run.landedTasks?.[id];\n delete run.landedOn?.[id];\n }\n run.reverted = true;\n watch.settled(taskIds);\n return { outcome: 'reverted', tasks: landed.tasks };\n }\n\n async release(run: IsolationRun, taskId: string, opts: { keep: boolean }): Promise<IsolationRemoval> {\n this.log({ op: 'release', taskId, keep: opts.keep });\n const record = run.tasks[taskId];\n // Like git: a read-only task's record goes whole, with nothing kept (ADR-0046).\n if (record?.readOnly) {\n delete run.tasks[taskId];\n return noRemoval();\n }\n const removal = opts.keep || !record ? noRemoval() : this.removed();\n const refused = removal.refused.some((r) => r.task?.taskId === taskId);\n if (!opts.keep && !refused) delete run.tasks[taskId];\n else if (record?.status === 'active') record.status = 'kept';\n else if (record?.status === 'repairing') {\n record.status = 'conflict';\n delete record.repairBase;\n }\n return removal;\n }\n\n private removed(): IsolationRemoval {\n return { preserved: [...this.removal.preserved], refused: [...this.removal.refused] };\n }\n\n async handoff(run: IsolationRun): Promise<IsolationHandoff> {\n this.log({ op: 'handoff' });\n return handoffOf(run);\n }\n\n async pruneOrphans(): Promise<IsolationPruneResult> {\n this.log({ op: 'pruneOrphans' });\n return { kept: [...this.keptOnPrune], ...this.removed() };\n }\n async reviewDiff(): Promise<string> { this.log({ op: 'reviewDiff' }); return ''; }\n async mergeIntoCheckedOut(run: IsolationRun): Promise<IsolationMergeResult> {\n this.log({ op: 'mergeIntoCheckedOut' });\n if (this.mergeResult.outcome === 'merged') {\n for (const record of Object.values(run.tasks)) if (record.status === 'merged') this.mergedByHand.add(record.taskId);\n }\n return this.mergeResult;\n }\n async findInHead(run: IsolationRun): Promise<string[]> {\n this.log({ op: 'findInHead' });\n const changed: string[] = [];\n for (const record of Object.values(run.tasks)) {\n if (record.status !== 'merged') continue;\n const merged = this.mergedByHand.has(record.taskId);\n if (merged === !!record.inHead) continue;\n if (merged) record.inHead = true;\n else delete record.inHead;\n changed.push(record.taskId);\n }\n return changed;\n }\n async snapshotTree(): Promise<TreeSnapshot | null> { this.log({ op: 'snapshotTree' }); return this.treeSnapshot; }\n async changedSince(): Promise<string[]> { this.log({ op: 'changedSince' }); return [...this.changedFiles]; }\n async discard(_run: IsolationRun, opts: { integration: IntegrationDisposal }): Promise<IsolationRemoval> {\n this.log({ op: 'discard', integration: opts.integration });\n if (this.discardError) throw this.discardError;\n return this.removed();\n }\n async sweep(): Promise<void> {\n this.log({ op: 'sweep' });\n if (this.sweepError) throw this.sweepError;\n }\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/testing.ts"],"sourcesContent":["import type { IConfig } from './interfaces/IConfig';\nimport type { IFileSystem, ToolOutcome } from './interfaces/IFileSystem';\nimport type { InvokedCommand, IRunnerSession, QueuedTaskMessage, ScriptExit, StructuredEvent, StructuredTurnEnd, TaskMessageFrom } from './interfaces/IRunner';\nimport type { RunnerCommand } from './models/RunnerCommand';\nimport type { RunnerSessionCost } from './models/Usage';\nimport type { HandoffCommit } from './models/Handoff';\nimport type { ApprovalDecision } from './interfaces/IApproval';\nimport type { CheckpointAnswer, TaskCompleteArgs } from './services/mcp/tools';\nimport type {\n IsolationAvailability,\n IsolationHandoff,\n IsolationMergeResult,\n IsolationOutcome,\n IsolationPruneResult,\n IsolationRemoval,\n IsolationRevertResult,\n IsolationRun,\n IntegrationDisposal,\n LandedWork,\n PreparedTask,\n PrepareIntent,\n IWorktreeIsolation,\n RepairEvidence,\n RevertCommand,\n RevertWatch,\n SetupFailure,\n TreeSnapshot,\n} from './interfaces/IWorktreeIsolation';\nimport { DEFAULT_RUNNERS, type Task } from './models/Task';\nimport { GUARANTEES, refuseUnproven, type ExecutionBackend, type Guarantee, type GuaranteeReport, type LeaseRecord, type LeaseRepo, type LeaseRequest, type LeaseSpec, type OpenLease, type ReservedLease, type RunnerPlacement } from './services/executionLease';\nimport type { EventStore } from './services/eventStore';\nimport { isWithin, type NodePath, type TreeEvent, type TreeFact } from './models/TreeEvent';\nimport { handoffOf, integrationBranchFor, noRemoval, SELF_REPO } from './services/isolationRecord';\n\n/**\n * Let an already-queued promise chain run to its next await before asserting,\n * without a wall-clock sleep. For a chain whose length is not known, drain the\n * microtask queue repeatedly. Only helps a chain that does not wait on a timer.\n */\nexport async function flushMicrotasks(rounds = 20): Promise<void> {\n for (let i = 0; i < rounds; i += 1) await Promise.resolve();\n}\n\nexport function fakeConfig(overrides: Partial<IConfig> = {}): IConfig {\n return {\n aiProvider: 'openrouter',\n apiKey: 'sk-test',\n planningModel: 'test-model',\n enabledRunners: [...DEFAULT_RUNNERS],\n maxParallelSessions: 3,\n researchEnabled: false,\n researchMaxSteps: 10,\n researchMaxFileSize: 100_000,\n openAiBaseUrl: 'https://api.openai.com/v1',\n openAiApiKey: '',\n openrouterKey: '',\n geminiKey: '',\n openaiCompatibleBaseUrl: '',\n openaiCompatibleApiKey: '',\n orchestratorModel: '',\n researchSubagentModel: '',\n geminiModel: '',\n planMapEnabled: true,\n autonomousMode: true,\n // Off so an orchestrator built without an injected isolation never runs\n // real git against whatever repository the tests happen to run in.\n worktreeIsolation: false,\n workspaceRepos: [],\n worktreeLinks: [],\n // Off so a scripted conflict stays a conflict unless a test opts into repairing it.\n conflictRepairAttempts: 0,\n approvalMode: 'ask',\n approvalPreApproved: [],\n // Off so a test that is not about the allowlist sees every prompt it raises.\n approvalDefaults: false,\n effectAllowlist: [],\n notifyCommand: [],\n webReadBudget: 40,\n plannerNativeShell: false,\n setProviderModelLists: () => {},\n getProviderBaseUrl: () => '',\n // Every vendor holds a key, so no planner turn is refused for want of one\n // unless a test takes it away.\n getProviderApiKey: () => 'sk-test',\n ...overrides,\n };\n}\n\nconst EMPTY_OUTCOME: ToolOutcome = { success: false, output: '', truncated: false };\n\n/**\n * A complete {@link IFileSystem} stub. Lives here rather than in each package's\n * test folder so adding a tool to the interface is one edit, not one per suite.\n */\nexport function fakeFileSystem(overrides: Partial<IFileSystem> = {}): IFileSystem {\n return {\n readFile: async () => EMPTY_OUTCOME,\n readFiles: async () => EMPTY_OUTCOME,\n glob: async () => EMPTY_OUTCOME,\n grep: async () => EMPTY_OUTCOME,\n findSymbol: async () => EMPTY_OUTCOME,\n listDir: async () => EMPTY_OUTCOME,\n bash: async () => EMPTY_OUTCOME,\n getWorkspaceRoot: () => '/workspace',\n ...overrides,\n };\n}\n\nexport class FakeRunnerSession implements IRunnerSession {\n private outputCbs: Array<(text: string) => void> = [];\n private exitCbs: Array<(code: number) => void> = [];\n output = '';\n written: string[] = [];\n killed = false;\n\n state: 'working' | 'idle' = 'working';\n messages: QueuedTaskMessage[] = [];\n /** Every message a turn was started with, in order. */\n delivered: string[] = [];\n /** The ones of {@link delivered} Ordewell sent: the completion reminder (ADR-0018, W1). */\n fromOrdewell: string[] = [];\n interrupts = 0;\n private messageCount = 0;\n private turnEndCbs: Array<(reason: StructuredTurnEnd) => void> = [];\n private eventCbs: Array<(event: StructuredEvent) => void> = [];\n private completeCbs: Array<(report: TaskCompleteArgs) => void> = [];\n private checkpointHandler: ((question: string, signal: AbortSignal) => Promise<CheckpointAnswer>) | null = null;\n\n constructor(public id = 's1', public taskId = 't1', public sessionId: string | null = 'native-1') {}\n\n /** `stop()` was asked for: the runner winds its turn down, still reporting, until {@link emitExit}. */\n stopped = false;\n private markGone!: () => void;\n private readonly gone = new Promise<void>((resolve) => { this.markGone = resolve; });\n\n onOutput(cb: (text: string) => void): void { this.outputCbs.push(cb); }\n onExit(cb: (code: number) => void): void { this.exitCbs.push(cb); }\n kill(): void { this.killed = true; }\n stop(): Promise<void> {\n this.stopped = true;\n return this.gone;\n }\n getOutput(): string { return this.output; }\n\n emitOutput(text: string): void {\n this.output += text;\n for (const cb of this.outputCbs) cb(text);\n }\n emitExit(code: number): void {\n for (const cb of this.exitCbs) cb(code);\n this.markGone();\n }\n write(text: string): void {\n this.written.push(text);\n const message = text.trim();\n if (message) this.sendMessage(message);\n }\n\n turnState(): 'working' | 'idle' { return this.state; }\n onTurnEnd(cb: (reason: StructuredTurnEnd) => void): void { this.turnEndCbs.push(cb); }\n onEvent(cb: (event: StructuredEvent) => void): void { this.eventCbs.push(cb); }\n onTaskComplete(cb: (report: TaskCompleteArgs) => void): void { this.completeCbs.push(cb); }\n /**\n * The runner calls `task_complete`, as `StructuredSession` relays it. Here it\n * is published at once; a test that needs the real session's turn-end\n * ordering drives `StructuredSession` itself.\n */\n reportComplete(report: TaskCompleteArgs): void {\n for (const cb of this.completeCbs) cb(report);\n }\n onToolCheckpoint(handler: (question: string, signal: AbortSignal) => Promise<CheckpointAnswer>): void { this.checkpointHandler = handler; }\n private scriptExitCbs: Array<(exit: ScriptExit) => void> = [];\n onScriptExit(cb: (exit: ScriptExit) => void): void { this.scriptExitCbs.push(cb); }\n /** A script task's body ended, as `ScriptSession` hands it on (ADR-0035). */\n reportScriptExit(exit: ScriptExit): void {\n for (const cb of this.scriptExitCbs) cb(exit);\n }\n /** The runner calls `checkpoint`, as `StructuredSession` relays it; settles with the answer. */\n callCheckpoint(question: string, signal: AbortSignal = new AbortController().signal): Promise<CheckpointAnswer> {\n if (!this.checkpointHandler) throw new Error('no checkpoint handler attached');\n return this.checkpointHandler(question, signal);\n }\n sendMessage(text: string, from?: TaskMessageFrom): string {\n this.messageCount += 1;\n const id = `msg-${this.messageCount}`;\n if (this.state === 'idle') this.deliver(text, from);\n else this.messages.push({ id, text, ...(from ? { from } : {}) });\n return id;\n }\n /** Interrupts, and the turn that replaces the interrupted one opens with the forced message. */\n forceSend(text: string): string {\n if (this.state === 'idle') return this.sendMessage(text);\n this.messageCount += 1;\n const id = `msg-${this.messageCount}`;\n this.putForced({ id, text, forced: true });\n void this.interrupt();\n return id;\n }\n forceSendQueued(id: string): boolean {\n const message = this.messages.find((m) => m.id === id);\n if (!message) return false;\n if (message.forced) return true;\n this.messages = this.messages.filter((m) => m !== message);\n this.putForced({ ...message, forced: true });\n if (this.state === 'working') void this.interrupt();\n return true;\n }\n private putForced(message: QueuedTaskMessage): void {\n const at = this.messages.findIndex((m) => !m.forced);\n this.messages.splice(at < 0 ? this.messages.length : at, 0, message);\n }\n removeQueued(id: string): boolean {\n const before = this.messages.length;\n this.messages = this.messages.filter((m) => m.id !== id);\n return this.messages.length < before;\n }\n queued(): QueuedTaskMessage[] { return this.messages.map((m) => ({ ...m })); }\n async interrupt(): Promise<void> {\n this.interrupts += 1;\n if (this.state === 'working') this.emitTurnEnd('interrupted');\n }\n nativeSessionId(): string | null { return this.sessionId; }\n /** What `sessionCost()` reports: the runner's running cost as counted, null while unknown. */\n cost: RunnerSessionCost | null = null;\n sessionCost(): RunnerSessionCost | null { return this.cost; }\n\n /** What `commands()` reports: the runner's own commands (#66). */\n runnerCommands: RunnerCommand[] = [];\n /** Every runner command invoked, in order. */\n invoked: InvokedCommand[] = [];\n commands(): RunnerCommand[] { return [...this.runnerCommands]; }\n /** Runs it as a message that starts with it, which is what a runner reads. */\n invokeCommand(name: string, args = ''): string {\n this.invoked.push({ name, ...(args.trim() ? { args: args.trim() } : {}) });\n return this.sendMessage(args.trim() ? `/${name} ${args.trim()}` : `/${name}`);\n }\n\n /** Every answer this session was given, in order. */\n answers: Array<{ id: string; decision: ApprovalDecision }> = [];\n private readonly openPermissions = new Set<string>();\n\n /** The runner asks to use a tool, as `StructuredSession` announces it. */\n requestPermission(id: string, name: string, input: Record<string, unknown>, suggestions: unknown[] = []): void {\n this.openPermissions.add(id);\n this.emitEvent({ type: 'permission_request', id, name, detail: JSON.stringify(input), input, suggestions });\n }\n /** The runner gives up on a request, as an interrupt makes it. */\n withdrawPermission(id: string): void {\n if (this.openPermissions.delete(id)) this.emitEvent({ type: 'permission_withdrawn', id });\n }\n answerPermission(id: string, decision: ApprovalDecision): boolean {\n if (!this.openPermissions.delete(id)) return false;\n this.answers.push({ id, decision });\n this.emitEvent({ type: 'permission_decided', id, decision });\n return true;\n }\n\n emitEvent(event: StructuredEvent): void {\n for (const cb of this.eventCbs) cb(event);\n }\n /** The runner reads a queued message inside the running turn, as `StructuredSession` reports it (ADR-0023). */\n deliverMidTurn(id: string): void {\n const message = this.messages.find((m) => m.id === id);\n if (!message) return;\n this.messages = this.messages.filter((m) => m !== message);\n this.emitEvent({ type: 'message_delivered', messageId: id, text: message.text, ...(message.from ? { from: message.from } : {}) });\n }\n /**\n * The turn ends without a `task_complete` call, and so does the turn the\n * completion reminder opens if one was sent (ADR-0018, W1): the task waits for input.\n */\n waitForInput(): void {\n const reminders = this.fromOrdewell.length;\n this.emitTurnEnd('completed');\n if (this.fromOrdewell.length > reminders) this.emitTurnEnd('completed');\n }\n emitTurnEnd(reason: StructuredTurnEnd): void {\n const next = this.messages.shift();\n if (!next) this.state = 'idle';\n for (const cb of this.turnEndCbs) cb(reason);\n if (next) this.deliver(next.text, next.from);\n }\n\n private deliver(text: string, from?: TaskMessageFrom): void {\n this.state = 'working';\n this.delivered.push(text);\n if (from === 'ordewell') this.fromOrdewell.push(text);\n this.emitEvent({ type: 'turn_start', text, ...(from ? { from } : {}) });\n }\n}\n\n/** An in-memory {@link EventStore}. `failing` makes the next appends reject, as a full disk would. */\nexport class FakeEventStore implements EventStore {\n readonly events: TreeEvent[] = [];\n failing: Error | null = null;\n private closed = false;\n\n async append(events: readonly TreeFact[]): Promise<void> {\n if (this.closed) throw new Error('This event log is closed.');\n if (this.failing) throw this.failing;\n for (const event of events) this.events.push({ ...event, seq: this.events.length + 1 });\n }\n\n async *read(after: number, path?: NodePath): AsyncIterable<TreeEvent> {\n for (const event of [...this.events]) {\n if (event.seq > after && (path === undefined || isWithin(event.node, path))) yield event;\n }\n }\n\n async close(): Promise<void> {\n this.closed = true;\n }\n}\n\n/**\n * An in-memory {@link ExecutionBackend}, as {@link FakeWorktreeIsolation} fakes\n * git: a count of slots and nothing else. `requests`, `opened` and `released`\n * log what the seam was asked; `holdOpen` keeps an open waiting, `openError`\n * fails one, `refuse` turns a role down, `provenGuarantees` is what its probe\n * proves, and `freed` is what a release does, a pool's tick.\n */\nexport class FakeExecutionBackend implements ExecutionBackend {\n /** Slots; a planner, a merge and a delegated task take none, as a flat run's do not. */\n limit = Infinity;\n held = 0;\n requests: LeaseRequest[] = [];\n opened: { request: LeaseRequest; spec: LeaseSpec }[] = [];\n released: { id: string; reason: string }[] = [];\n letGoCalls: { taskId: string; keep: boolean; reason: string }[] = [];\n openError: Error | null = null;\n refuse: { role: LeaseRequest['role']; reason: string } | null = null;\n provenGuarantees: readonly Guarantee[] = [];\n /** What exportResult reports of a session, in place of what it is told. */\n sessionState: { nativeSessionId: string } | null = null;\n /** The repositories an open says its worktree holds. */\n repos: readonly LeaseRepo[] = [];\n /** Where an open puts its runner, for a lease that does not run it on this host. */\n placement: RunnerPlacement | null = null;\n /** Brings a task's work back; absent, it is where the attempt ran. */\n collect?: (taskId: string) => Promise<void>;\n /** Waits on what it has running, as a closing Session does; absent, nothing outlives a runner. */\n settle?: () => Promise<void>;\n /** The workspace root's repositories; absent, none is known. */\n checkoutRepos?: () => readonly LeaseRepo[];\n records: LeaseRecord[] = [];\n freed: () => void = () => undefined;\n private openHold: Promise<void> | null = null;\n private nextId = 0;\n\n /** Make the next open wait until the returned function is called. */\n holdOpen(): () => void {\n let open!: () => void;\n this.openHold = new Promise<void>((resolve) => { open = resolve; });\n return open;\n }\n\n async probe(): Promise<GuaranteeReport> {\n const at = new Date(0).toISOString();\n return Object.fromEntries(GUARANTEES.map((g) => [g, { proven: this.provenGuarantees.includes(g), by: 'fake probe', at }])) as GuaranteeReport;\n }\n\n private takesSlot(request: LeaseRequest): boolean {\n return request.role === 'task' || request.role === 'script';\n }\n\n refusal(request: LeaseRequest): string | null {\n if (this.refuse?.role === request.role) return this.refuse.reason;\n return this.takesSlot(request) && this.held >= this.limit ? `no slot for ${request.node.taskId ?? request.role}` : null;\n }\n\n reserve(request: LeaseRequest): { lease: ReservedLease } | { refused: string } {\n this.requests.push(request);\n const refused = this.refusal(request);\n if (refused) return { refused };\n const holdsSlot = this.takesSlot(request);\n if (holdsSlot) this.held += 1;\n const id = `lease-${++this.nextId}`;\n let live = true;\n return {\n lease: {\n id,\n holdsSlot,\n open: (spec) => this.open(request, spec),\n release: (reason) => {\n if (!live) return;\n live = false;\n this.released.push({ id, reason });\n if (holdsSlot) this.held -= 1;\n this.freed();\n },\n },\n };\n }\n\n private async open(request: LeaseRequest, spec: LeaseSpec): Promise<OpenLease> {\n this.opened.push({ request, spec });\n const guarantees = await this.probe();\n refuseUnproven(spec.required, guarantees);\n const hold = this.openHold;\n this.openHold = null;\n await hold;\n if (this.openError) throw this.openError;\n const worktree = spec.workspace.kind === 'worktree';\n return {\n workspace: { cwd: worktree ? `/fake-lease/${spec.task?.id}` : '/repo', worktree, ...(this.repos.length ? { repos: this.repos } : {}) },\n guarantees,\n exportResult: (session) => ({ refs: {}, sessionState: { ...session, ...this.sessionState } }),\n ...(this.placement ? { placement: this.placement } : {}),\n };\n }\n\n async letGo(taskId: string, { keep, landing, reason }: { keep: boolean; landing?: Promise<unknown> | null; reason: string }): Promise<void> {\n await landing;\n this.letGoCalls.push({ taskId, keep, reason });\n }\n\n async list(): Promise<readonly LeaseRecord[]> {\n return this.records;\n }\n}\n\nexport type FakeIsolationCall =\n | { op: 'isActive'; workspaceRoot: string }\n | { op: 'stash'; workspaceRoot: string }\n | { op: 'startRun'; workspaceRoot: string }\n | { op: 'prepare' | 'reopen' | 'verifyRepair'; taskId: string }\n | { op: 'integrate'; taskId: string }\n | { op: 'release'; taskId: string; keep: boolean }\n | { op: 'handoff' | 'pruneOrphans' | 'reviewDiff' | 'mergeIntoCheckedOut' | 'sweep' | 'findInHead' | 'snapshotTree' | 'changedSince' }\n | { op: 'discard'; integration: IntegrationDisposal }\n | { op: 'readLanded' | 'revert'; taskIds: readonly string[] };\n\n/**\n * An in-memory {@link IWorktreeIsolation} for scheduling tests: no git, no\n * filesystem. Every call is logged in `calls`; `prepare` hands back a\n * deterministic fake cwd. Set `availability` to exercise the fallbacks, `outcomes`\n * to script a conflict, and `holdIntegration` to keep a task un-integrated so a\n * test can observe that its dependents wait. `repos` makes the run a group of\n * several; `changes` and `stopsIn` say which of them a task changes and where\n * its landing stops. `repairEvidence` scripts what a conflict repair's\n * evidence check finds, and `removal` what a removal kept back.\n */\nexport class FakeWorktreeIsolation implements IWorktreeIsolation {\n availability: IsolationAvailability = { active: true };\n /** What `gitShortfall` answers. */\n gitShortfallText: string | null = null;\n /** The repo paths `startRun` groups: a group of one at `.` unless set. */\n repos: string[] = [SELF_REPO];\n /** Per task id, the repos it changes; every repo of the group when not listed. */\n changes = new Map<string, string[]>();\n /** Per task id, the repo its landing stops in when its outcome is not `merged`; its first changed repo when not listed. */\n stopsIn = new Map<string, string>();\n /** Per task id, the files a `conflict` outcome names; empty when not listed. */\n conflictFiles = new Map<string, string[]>();\n /** What `mergeIntoCheckedOut` answers; a `merged` one also puts every landed task in HEAD, as git would. */\n mergeResult: IsolationMergeResult = { outcome: 'merged' };\n /** Task ids whose landed work `findInHead` finds in HEAD besides those a merge put there, as a merge by hand would. */\n mergedByHand = new Set<string>();\n /** What `snapshotTree` answers; null as for a workspace with no repo. */\n treeSnapshot: TreeSnapshot | null = {};\n /** What `changedSince` answers: the tracked files an ops task changed. */\n changedFiles: string[] = [];\n /** What `startRun` shares and `prepare` copies, to exercise their notices. */\n shared: string[] = [];\n sharedRepos: string[] = [];\n copied: string[] = [];\n setupFailed: SetupFailure[] = [];\n /** Set to make `startRun` throw, as git does when no repo of the group can be isolated. */\n startRunError: Error | null = null;\n /** Set to make `discard` / `sweep` throw after logging the call. */\n discardError: Error | null = null;\n sweepError: Error | null = null;\n /** What `pruneOrphans` reports as kept back from the sweep. */\n keptOnPrune: IsolationPruneResult['kept'] = [];\n /**\n * What every removal — a `release` that removes, `discard`, `pruneOrphans` —\n * reports it kept back. A refused task keeps its record, as git's does.\n */\n removal: IsolationRemoval = noRemoval();\n /** Per task id; a task not listed integrates as `merged`. */\n outcomes = new Map<string, IsolationOutcome>();\n /** What `revert` stops with; a revert that goes through when null. */\n revertStop: Exclude<IsolationRevertResult, { outcome: 'reverted' }> | null = null;\n /** What `readLanded` finds of a task's work in the user's branch, by task id. */\n inBranch = new Map<string, RevertCommand[]>();\n /** Per task id, what `verifyRepair` finds; a task not listed passes. */\n repairEvidence = new Map<string, RepairEvidence>();\n calls: FakeIsolationCall[] = [];\n private holds = new Map<string, Promise<void>>();\n private verifyHolds = new Map<string, Promise<void>>();\n private revertHold: Promise<void> | null = null;\n private runCount = 0;\n\n private log(call: FakeIsolationCall): void { this.calls.push(call); }\n\n /** Task ids in the order `op` was called for them. */\n taskIdsFor(op: 'prepare' | 'reopen' | 'verifyRepair' | 'integrate' | 'release'): string[] {\n return this.calls.flatMap((c) => (c.op === op && 'taskId' in c ? [c.taskId] : []));\n }\n\n /** Make `integrate` for this task wait until the returned function is called. */\n holdIntegration(taskId: string): () => void {\n let open!: () => void;\n this.holds.set(taskId, new Promise<void>((resolve) => { open = resolve; }));\n return open;\n }\n\n /** Make the next `revert` wait, past its `refusal`, until the returned function is called. */\n holdRevert(): () => void {\n let open!: () => void;\n this.revertHold = new Promise<void>((resolve) => { open = resolve; });\n return open;\n }\n\n /** Make `verifyRepair` for this task wait until the returned function is called. */\n holdVerification(taskId: string): () => void {\n let open!: () => void;\n this.verifyHolds.set(taskId, new Promise<void>((resolve) => { open = resolve; }));\n return open;\n }\n\n async gitShortfall(): Promise<string | null> {\n return this.gitShortfallText;\n }\n\n async isActive(workspaceRoot: string): Promise<IsolationAvailability> {\n this.log({ op: 'isActive', workspaceRoot });\n return this.availability;\n }\n\n /** Like git: once the tracked changes are stashed, the tree is no longer dirty. */\n async stash(workspaceRoot: string): Promise<void> {\n this.log({ op: 'stash', workspaceRoot });\n if (!this.availability.active && this.availability.reason === 'dirty') this.availability = { active: true };\n }\n\n async startRun(workspaceRoot: string, stateRoot?: string): Promise<IsolationRun> {\n this.log({ op: 'startRun', workspaceRoot });\n if (this.startRunError) throw this.startRunError;\n const id = `run${++this.runCount}`;\n return {\n id,\n workspaceRoot,\n ...(stateRoot !== undefined ? { stateRoot } : {}),\n repos: this.repos.map((repo) => ({\n path: repo, root: `${workspaceRoot}/${repo}`.replace(/\\/\\.$/, ''), baseRef: 'base0000', baseBranch: 'main', integrationBranch: integrationBranchFor(id),\n })),\n shared: [...this.shared],\n sharedRepos: [...this.sharedRepos],\n tasks: {},\n keepsEveryLanding: true,\n carried: {},\n };\n }\n\n async prepare(task: Task, run: IsolationRun, _intent?: PrepareIntent, opts: { readOnly?: boolean } = {}): Promise<PreparedTask> {\n this.log({ op: 'prepare', taskId: task.id });\n const name = `${task.order}-${task.id}`;\n const cwd = `/fake-worktrees/${run.id}/${name}`;\n const branch = `ordewell/${run.id}/${name}`;\n run.tasks[task.id] = {\n taskId: task.id, order: task.order, title: task.title, branch, workspace: cwd, status: 'active',\n repos: Object.fromEntries(run.repos.map((r) => [r.path, { worktree: r.path === SELF_REPO ? cwd : `${cwd}/${r.path}`, linked: [] }])),\n ...(opts.readOnly ? { readOnly: true } : {}),\n };\n return { cwd, branch, copied: [...this.copied], ...(this.setupFailed.length > 0 ? { setupFailed: [...this.setupFailed] } : {}) };\n }\n\n /** Like git: the same cwd, each changed repo's tip recorded, the repair counted. */\n async reopen(task: Task, run: IsolationRun): Promise<PreparedTask> {\n this.log({ op: 'reopen', taskId: task.id });\n const record = run.tasks[task.id];\n if (record?.status !== 'conflict') throw new Error(`Task ${task.order} has no conflict to repair`);\n const changed = Object.entries(record.repos).filter(([repo, entry]) => entry.changed || repo === record.conflictRepo).map(([repo]) => repo);\n const files = (record.conflictFiles ?? []).map((file) => (record.conflictRepo && record.conflictRepo !== SELF_REPO ? `${record.conflictRepo}/${file}` : file));\n record.repairs = (record.repairs ?? 0) + 1;\n record.repairBase = Object.fromEntries(changed.map((repo) => [repo, `tip-${repo}`]));\n record.repairedFiles = [...new Set([...(record.repairedFiles ?? []), ...files])];\n record.status = 'repairing';\n return { cwd: record.workspace, branch: record.branch, copied: [] };\n }\n\n async verifyRepair(task: Task, _run: IsolationRun): Promise<RepairEvidence> {\n this.log({ op: 'verifyRepair', taskId: task.id });\n await this.verifyHolds.get(task.id);\n return this.repairEvidence.get(task.id) ?? { ok: true };\n }\n\n /** Like git: the landing is recorded and persisted before the (held) merge, and cleared once it settles. */\n async integrate(task: Task, run: IsolationRun, persist: () => void = () => undefined, commit?: HandoffCommit): Promise<IsolationOutcome> {\n this.log({ op: 'integrate', taskId: task.id });\n const record = run.tasks[task.id];\n if (!record) return 'failed';\n if (commit) record.commit = commit;\n if (record.readOnly) {\n record.status = 'failed';\n record.landingError = 'a read-only task lands nothing';\n return 'failed';\n }\n const changed = this.changes.get(task.id) ?? run.repos.map((r) => r.path);\n for (const [repo, entry] of Object.entries(record.repos)) entry.changed = changed.includes(repo) || (entry.changed ?? false);\n if (changed.length > 0) {\n run.landing = { taskId: task.id, tips: Object.fromEntries(changed.map((repo) => [repo, `tip-${repo}`])) };\n persist();\n }\n await this.holds.get(task.id);\n delete run.landing;\n const outcome = this.outcomes.get(task.id) ?? 'merged';\n record.status = outcome;\n delete record.repairBase;\n if (outcome === 'merged') {\n delete record.conflictRepo;\n delete record.conflictFiles;\n for (const repo of changed) {\n ((run.landings ??= {})[task.id] ??= {})[repo] = [...run.landings?.[task.id]?.[repo] ?? [], `tip-${repo}`];\n (run.landedTasks ??= {})[task.id] = { taskId: task.id, order: task.order, title: task.title };\n }\n } else {\n record.conflictRepo = this.stopsIn.get(task.id) ?? changed[0] ?? SELF_REPO;\n const files = this.conflictFiles.get(task.id);\n if (files) record.conflictFiles = files;\n else delete record.conflictFiles;\n }\n return outcome;\n }\n\n /** Newest landing first, read as the plan's highest order: scheduling tests land in plan order. */\n async readLanded(run: IsolationRun, taskIds: readonly string[]): Promise<LandedWork> {\n this.log({ op: 'readLanded', taskIds });\n const records = taskIds.flatMap((id) => run.tasks[id] ?? run.landedTasks?.[id] ?? []).sort((a, b) => b.order - a.order);\n const tasks = records.map((r) => ({\n taskId: r.taskId, order: r.order, title: r.title,\n repos: Object.keys(run.landings?.[r.taskId] ?? {}),\n }));\n return { ok: true, tasks, inBranch: records.flatMap((r) => this.inBranch.get(r.taskId) ?? []) };\n }\n\n /** Like git: the turn, then the judgement, then the records go in one step with the tasks back. */\n async revert(run: IsolationRun, taskIds: readonly string[], watch: RevertWatch): Promise<IsolationRevertResult> {\n this.log({ op: 'revert', taskIds });\n const hold = this.revertHold;\n this.revertHold = null;\n await hold;\n const reason = watch.refusal();\n if (reason) return { outcome: 'refused', reason };\n if (this.revertStop) return this.revertStop;\n const landed = await this.readLanded(run, taskIds);\n if (!landed.ok) return { outcome: 'failed', error: landed.error };\n if (landed.inBranch.length > 0) return { outcome: 'in-branch', commands: landed.inBranch };\n run.landing = { taskId: taskIds[0], tips: {}, reverts: {} };\n watch.persist();\n delete run.landing;\n for (const id of taskIds) {\n // Like git: a later attempt's record that did not land stays for its worktree, its conflict over.\n if (run.tasks[id]?.status === 'merged') delete run.tasks[id];\n else if (run.tasks[id]?.status === 'conflict') run.tasks[id].status = 'kept';\n delete run.landings?.[id];\n delete run.landedTasks?.[id];\n delete run.landedOn?.[id];\n }\n run.reverted = true;\n watch.settled(taskIds);\n return { outcome: 'reverted', tasks: landed.tasks };\n }\n\n async release(run: IsolationRun, taskId: string, opts: { keep: boolean }): Promise<IsolationRemoval> {\n this.log({ op: 'release', taskId, keep: opts.keep });\n const record = run.tasks[taskId];\n // Like git: a read-only task's record goes whole, with nothing kept (ADR-0046).\n if (record?.readOnly) {\n delete run.tasks[taskId];\n return noRemoval();\n }\n const removal = opts.keep || !record ? noRemoval() : this.removed();\n const refused = removal.refused.some((r) => r.task?.taskId === taskId);\n if (!opts.keep && !refused) delete run.tasks[taskId];\n else if (record?.status === 'active') record.status = 'kept';\n else if (record?.status === 'repairing') {\n record.status = 'conflict';\n delete record.repairBase;\n }\n return removal;\n }\n\n private removed(): IsolationRemoval {\n return { preserved: [...this.removal.preserved], refused: [...this.removal.refused] };\n }\n\n async handoff(run: IsolationRun): Promise<IsolationHandoff> {\n this.log({ op: 'handoff' });\n return handoffOf(run);\n }\n\n async pruneOrphans(): Promise<IsolationPruneResult> {\n this.log({ op: 'pruneOrphans' });\n return { kept: [...this.keptOnPrune], ...this.removed() };\n }\n async reviewDiff(): Promise<string> { this.log({ op: 'reviewDiff' }); return ''; }\n async mergeIntoCheckedOut(run: IsolationRun): Promise<IsolationMergeResult> {\n this.log({ op: 'mergeIntoCheckedOut' });\n if (this.mergeResult.outcome === 'merged') {\n for (const record of Object.values(run.tasks)) if (record.status === 'merged') this.mergedByHand.add(record.taskId);\n }\n return this.mergeResult;\n }\n async findInHead(run: IsolationRun): Promise<string[]> {\n this.log({ op: 'findInHead' });\n const changed: string[] = [];\n for (const record of Object.values(run.tasks)) {\n if (record.status !== 'merged') continue;\n const merged = this.mergedByHand.has(record.taskId);\n if (merged === !!record.inHead) continue;\n if (merged) record.inHead = true;\n else delete record.inHead;\n changed.push(record.taskId);\n }\n return changed;\n }\n async snapshotTree(): Promise<TreeSnapshot | null> { this.log({ op: 'snapshotTree' }); return this.treeSnapshot; }\n async changedSince(): Promise<string[]> { this.log({ op: 'changedSince' }); return [...this.changedFiles]; }\n async discard(_run: IsolationRun, opts: { integration: IntegrationDisposal }): Promise<IsolationRemoval> {\n this.log({ op: 'discard', integration: opts.integration });\n if (this.discardError) throw this.discardError;\n return this.removed();\n }\n async sweep(): Promise<void> {\n this.log({ op: 'sweep' });\n if (this.sweepError) throw this.sweepError;\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# The image a container lease runs tasks in. Build it yourself:
|
|
2
|
+
#
|
|
3
|
+
# docker build -t ordewell-task - < task.Dockerfile
|
|
4
|
+
#
|
|
5
|
+
# Ordewell publishes no image holding Claude Code: Anthropic's terms say
|
|
6
|
+
# preinstalling or running it in a product or service needs its Commercial
|
|
7
|
+
# Terms and an unmodified binary (ADR-0059 L5). Add your project's toolchain
|
|
8
|
+
# below, and rebuild when you want a newer Claude Code.
|
|
9
|
+
FROM node:22-slim
|
|
10
|
+
|
|
11
|
+
RUN apt-get update \
|
|
12
|
+
&& apt-get install -y --no-install-recommends git ca-certificates \
|
|
13
|
+
&& rm -rf /var/lib/apt/lists/*
|
|
14
|
+
|
|
15
|
+
RUN npm install -g @anthropic-ai/claude-code
|
|
16
|
+
|
|
17
|
+
# A named volume takes its owner from the folder it mounts over, and a lease
|
|
18
|
+
# runs as uid 1000, which is the `node` user here.
|
|
19
|
+
RUN mkdir -p /task /mirror /login /caches/npm /caches/pip /caches/cargo /caches/go \
|
|
20
|
+
&& chown -R node:node /task /mirror /login /caches
|
|
21
|
+
|
|
22
|
+
USER node
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ordewell/core",
|
|
3
|
-
"version": "0.12.
|
|
3
|
+
"version": "0.12.1",
|
|
4
4
|
"description": "Ordewell core — planner, orchestrator, runners and verification engine.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "Alessandro Costanzo Ciano",
|
|
@@ -68,6 +68,7 @@
|
|
|
68
68
|
},
|
|
69
69
|
"files": [
|
|
70
70
|
"dist",
|
|
71
|
+
"docker",
|
|
71
72
|
"skills",
|
|
72
73
|
"README.md",
|
|
73
74
|
"LICENSE",
|
package/skills/diagnose/SKILL.md
CHANGED
|
@@ -41,11 +41,11 @@ A hypothesis stands when its prediction was tested and held, and the rest are sh
|
|
|
41
41
|
|
|
42
42
|
## 5. Fix, checked against the reproduction
|
|
43
43
|
|
|
44
|
-
A change task for the fix. It adds the reproduction as a test if the workspace lacks one, and runs it and the wider suite itself before it completes. A research task's test was thrown away, so the fix task depends on that task and reads its report with `
|
|
44
|
+
A change task for the fix. It adds the reproduction as a test if the workspace lacks one, and runs it and the wider suite itself before it completes. A research task's test was thrown away, so the fix task depends on that task and reads its report with `read`; do not copy the test into the brief. Its brief names the cause and the files, and says to change the cause and nothing near it.
|
|
45
45
|
|
|
46
46
|
Put the fix in a loop only when the user asked to iterate until the reproduction passes, or it is a specific acceptance gate that needs independent repeated checking and fixing; say why in the outline. Then:
|
|
47
47
|
|
|
48
|
-
- If the reproduction is not yet a test the workspace holds, a first change task adds it and changes no production code. Make the loop's check depend on a research task whose test was thrown away: the body tasks may then depend on it too, and read its report with `
|
|
48
|
+
- If the reproduction is not yet a test the workspace holds, a first change task adds it and changes no production code. Make the loop's check depend on a research task whose test was thrown away: the body tasks may then depend on it too, and read its report with `read`.
|
|
49
49
|
- The check is a script task running the reproduction. Add the wider suite as a second command so a fix that breaks something else fails the round.
|
|
50
50
|
- Choose the rounds deliberately. A check that runs out of rounds blocks what follows, which is the right outcome when the fix does not converge.
|
|
51
51
|
|
package/skills/explore/SKILL.md
CHANGED
|
@@ -40,7 +40,7 @@ When the question is which of several approaches to take, explore them side by s
|
|
|
40
40
|
|
|
41
41
|
- A shared check, fixed before the explorers start: a test, a build or a measurement the same for every approach. Write it into every explorer's brief, so the candidates are compared on one bar. Only a candidate that passes it is eligible.
|
|
42
42
|
- Explorers: read-only tasks, each trying one deliberately different approach, with no dependencies between them. Each runs the shared check and reports its commands with their output. An explorer that builds a prototype keeps it with `save_patch` before it calls `task_complete`, because its worktree is thrown away with it. Tell it to.
|
|
43
|
-
- The choice: if exactly one candidate passes, no judge is needed; that one is chosen. If several pass, one judge task that depends on every explorer recommends one. It reads their handoffs with `
|
|
43
|
+
- The choice: if exactly one candidate passes, no judge is needed; that one is chosen. If several pass, one judge task that depends on every explorer recommends one. It reads their handoffs with `read` (with `include_report` where the summary is not enough), tries to break the most promising claim, and cites its evidence: the explorers' checks and its own, not its opinion. If none passes, that is a finding: say so, and plan the next round.
|
|
44
44
|
- Make the judge a research task, so that its recommendation wakes you and the build task is yours to add once you have read it. A recommendation is advice. Adding the build task on one explorer's patch is the pick, and approving that task is the user's, or at Act the supervisor's.
|
|
45
45
|
- The build task you add after the choice depends on the chosen explorer, and on the judge when there is one. It applies that explorer's patch with `apply_patch`, resolves any conflicts the tool reports, and runs the checks itself, since the explorer ran them at its own base. Say so in its brief. An explorer ran the shared check in a worktree it could write, so its patch may change the check itself: tell the builder, and the judge if there is one, to confirm that the patch leaves the check's files alone, or to run the check as the base has it. A patch that deletes or adds a file the worktree also changed applies nothing: the tool says why, and the builder applies the rest by hand.
|
|
46
46
|
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/services/PlanValidator.ts"],"sourcesContent":["import { Task, RunnerId, flattenTasksWithParents } from '../models/Task';\nimport { extractObjectsWithKey, stripTrailingCommas, escapeControlCharsInStrings, PlanParseError, PLAN_ENVELOPE_KEY } from './JsonExtractor';\nimport type { RunnerModeInfo } from './ModeResolver';\nimport { plannedTask, checkPlanInvariants, taskWhere, type PlanTaskError } from './PlannedTask';\n\nexport function parsePlanJson(\n raw: string,\n runners: RunnerId[],\n runnerModes?: Record<RunnerId, RunnerModeInfo[]>,\n autonomousDefault = false,\n): Task[] {\n const { matches, fallback, sawUnbalanced } = extractObjectsWithKey(raw, PLAN_ENVELOPE_KEY);\n\n // A reply can carry several tasks-keyed objects — a schema echo from the\n // prompt, an inline draft, then the real plan. The model's LAST emission is\n // its final answer, so candidates are tried back to front and the first one\n // that fully parses and validates wins.\n const candidates = matches.length > 0 ? [...matches].reverse() : [fallback.json];\n\n let lastError: PlanParseError | null = null;\n for (const json of candidates) {\n try {\n return parsePlanObject(json, raw, runners, runnerModes, autonomousDefault);\n } catch (err) {\n if (!(err instanceof PlanParseError)) throw err;\n // Prefer surfacing the error from the most plan-like candidate: the\n // last one carrying a tasks key (tried first).\n if (!lastError) lastError = err;\n }\n }\n\n // No usable tasks object anywhere, but an object ran off the end of the\n // text: the plan was almost certainly cut off mid-stream.\n if (matches.length === 0 && sawUnbalanced) {\n throw new PlanParseError(\n 'Plan response appears truncated: the model likely hit its output length limit before finishing the JSON.',\n raw,\n { truncated: true },\n );\n }\n throw lastError ?? new PlanParseError('Invalid plan: missing tasks array', raw);\n}\n\nfunction parsePlanObject(\n json: string,\n raw: string,\n runners: RunnerId[],\n runnerModes?: Record<RunnerId, RunnerModeInfo[]>,\n autonomousDefault = false,\n): Task[] {\n const cleaned = stripTrailingCommas(escapeControlCharsInStrings(json));\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(cleaned);\n } catch (err) {\n const detail = err instanceof Error ? err.message : String(err);\n throw new PlanParseError(`Plan response was not valid JSON: ${detail}`, raw);\n }\n\n const result = validatePlanTasks(parsed, runners, runnerModes, autonomousDefault);\n if (result.ok) return result.tasks;\n const [first] = result.errors;\n // An envelope problem (no tasks array, an empty one) keeps the generic\n // re-emit; only a rule broken by a task is worth naming in the corrective.\n throw new PlanParseError(first.message, raw, { semantic: first.taskId !== undefined });\n}\n\nexport type { PlanTaskError } from './PlannedTask';\nexport { requestedSkills } from './PlannedTask';\n\n/** `warnings` name what was accepted but not used, for a channel that can tell the planner. */\nexport type PlanTasksResult = { ok: true; tasks: Task[]; warnings?: string[] } | { ok: false; errors: PlanTaskError[] };\n\n/**\n * Every check a plan's tasks must pass, on an already-parsed `{ tasks }`\n * object — what a plan is held to whichever channel it arrived on. All\n * problems are reported, the slice classification first, so the first is the\n * one the text path's corrective names.\n */\nexport function validatePlanTasks(\n obj: unknown,\n runners: RunnerId[],\n runnerModes?: Record<RunnerId, RunnerModeInfo[]>,\n autonomousDefault = false,\n): PlanTasksResult {\n const rawTasks = isRecord(obj) ? obj.tasks : undefined;\n if (!Array.isArray(rawTasks)) {\n return { ok: false, errors: [{ field: 'tasks', message: 'Invalid plan: missing tasks array' }] };\n }\n if (rawTasks.length === 0) {\n return { ok: false, errors: [{ field: 'tasks', message: 'Plan contained no tasks' }] };\n }\n\n const planned = rawTasks.map((t) => plannedTask(t, { runners, runnerModes, autonomousDefault }));\n const tasks = planned.map((p) => p.task);\n const errors = [\n ...sliceRequired(tasks),\n ...planned.flatMap((p) => p.errors),\n ...checkPlanInvariants(tasks, runners, runnerModes),\n ];\n\n if (errors.length > 0) return { ok: false, errors };\n const ignored = planned.flatMap((p) => p.ignored);\n const warnings = [\n ...(ignored.some((i) => i.field === 'taskMode')\n ? ['\"taskMode\" is not yours to set and was ignored: each task runs in its runner\\'s mode for the user\\'s autonomy level, or its read-only mode when you set \"readOnly\": true.']\n : []),\n ...ignored.filter((i) => i.field === 'readOnly').map((i) => `${i.message}: it was ignored.`),\n ];\n return warnings.length > 0 ? { ok: true, tasks, warnings } : { ok: true, tasks };\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\n/**\n * Whether a reply that failed {@link parsePlanJson} actually LOOKED like a\n * plan attempt — a balanced tasks-keyed object, or JSON that got cut off.\n * Distinguishes \"the model tried to emit a plan and botched it\" (worth a\n * corrective retry) from prose that merely mentions `\"tasks\"` (leave alone).\n */\nexport function looksLikePlanAttempt(raw: string): boolean {\n const { matches, sawUnbalanced } = extractObjectsWithKey(raw, PLAN_ENVELOPE_KEY);\n if (matches.length > 0) return true;\n return sawUnbalanced && raw.includes(`\"${PLAN_ENVELOPE_KEY}\"`);\n}\n\n/**\n * A whole plan says how each task is sliced: an edit may leave it to the\n * task's parent or the tasks it was made from, a submitted plan may not.\n */\nfunction sliceRequired(tasks: readonly Task[]): PlanTaskError[] {\n return flattenTasksWithParents(tasks).flatMap(({ task: t, parent }) => {\n const where = taskWhere(t.title, parent?.title);\n const errors: PlanTaskError[] = [];\n if (!t.sliceType) errors.push({ taskId: t.id, field: 'sliceType', message: `${where} is missing sliceType. Every task must specify sliceType (\"AFK\" or \"HITL\").` });\n if (t.type === 'ai' && !t.autonomy) errors.push({ taskId: t.id, field: 'autonomy', message: `AI ${where} is missing autonomy. Every AI task must specify autonomy (\"AFK\" or \"HITL\").` });\n return errors;\n });\n}\n"],"mappings":"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","names":[]}
|