@abelxiaoxing/cadence 1.1.1 → 1.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -2
- package/agents/implementation-worker.md +17 -11
- package/config/routes.example.json +0 -2
- package/package.json +2 -2
- package/prompts/abel-design.md +20 -16
- package/prompts/abel-implement.md +4 -3
- package/skills/abel-workflow/SKILL.md +6 -3
- package/src/agent-registry.ts +0 -1
- package/src/candidate-patch.ts +250 -0
- package/src/child-session.ts +27 -24
- package/src/contracts.ts +1 -8
- package/src/control-contracts.ts +72 -48
- package/src/design-control.ts +224 -17
- package/src/design-journal.ts +69 -22
- package/src/index.ts +81 -23
- package/src/packet-runtime.ts +6 -6
- package/src/route-policy.ts +45 -17
- package/src/run-state.ts +4 -2
- package/src/run-store.ts +22 -6
- package/src/submit-tool.ts +149 -49
- package/src/worker-broker.ts +0 -1
- package/src/workflow-engine.ts +22 -171
- package/agents/contract-reviewer.md +0 -11
package/src/submit-tool.ts
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
2
|
import { defineTool } from "@earendil-works/pi-coding-agent";
|
|
3
3
|
import { Type } from "typebox";
|
|
4
|
+
import {
|
|
5
|
+
type CandidatePatchOperation,
|
|
6
|
+
compileCandidatePatch,
|
|
7
|
+
} from "./candidate-patch.ts";
|
|
4
8
|
import {
|
|
5
9
|
type CandidateFailure,
|
|
6
10
|
type DiffResult,
|
|
@@ -11,7 +15,11 @@ import {
|
|
|
11
15
|
validateDiffResult,
|
|
12
16
|
validateEvidenceResult,
|
|
13
17
|
} from "./contracts.ts";
|
|
14
|
-
import
|
|
18
|
+
import {
|
|
19
|
+
type BeginCandidateInput,
|
|
20
|
+
TASK_LEDGER_LIMITS,
|
|
21
|
+
type TaskLedger,
|
|
22
|
+
} from "./task-ledger.ts";
|
|
15
23
|
|
|
16
24
|
const compactEvidenceSchema = Type.Object({
|
|
17
25
|
id: Type.String(),
|
|
@@ -83,17 +91,49 @@ function candidateArtifactSchema(candidateId: string) {
|
|
|
83
91
|
return Type.Union([
|
|
84
92
|
Type.Object(
|
|
85
93
|
{
|
|
86
|
-
kind: Type.Literal("candidate-
|
|
87
|
-
candidateId: Type.Literal(candidateId),
|
|
88
|
-
sequence: Type.Integer({ minimum: 0 }),
|
|
89
|
-
text: Type.String({ minLength: 1 }),
|
|
90
|
-
},
|
|
91
|
-
{ additionalProperties: false },
|
|
92
|
-
),
|
|
93
|
-
Type.Object(
|
|
94
|
-
{
|
|
95
|
-
kind: Type.Literal("candidate-seal"),
|
|
94
|
+
kind: Type.Literal("candidate-patch"),
|
|
96
95
|
candidateId: Type.Literal(candidateId),
|
|
96
|
+
operations: Type.Array(
|
|
97
|
+
Type.Union([
|
|
98
|
+
Type.Object(
|
|
99
|
+
{
|
|
100
|
+
kind: Type.Literal("replace"),
|
|
101
|
+
path: Type.String(),
|
|
102
|
+
oldText: Type.String({ minLength: 1 }),
|
|
103
|
+
newText: Type.String(),
|
|
104
|
+
},
|
|
105
|
+
{ additionalProperties: false },
|
|
106
|
+
),
|
|
107
|
+
Type.Object(
|
|
108
|
+
{
|
|
109
|
+
kind: Type.Literal("rewrite"),
|
|
110
|
+
path: Type.String(),
|
|
111
|
+
content: Type.String(),
|
|
112
|
+
},
|
|
113
|
+
{ additionalProperties: false },
|
|
114
|
+
),
|
|
115
|
+
Type.Object(
|
|
116
|
+
{
|
|
117
|
+
kind: Type.Literal("create"),
|
|
118
|
+
path: Type.String(),
|
|
119
|
+
content: Type.String({ minLength: 1 }),
|
|
120
|
+
mode: Type.Union([
|
|
121
|
+
Type.Literal("regular"),
|
|
122
|
+
Type.Literal("executable"),
|
|
123
|
+
]),
|
|
124
|
+
},
|
|
125
|
+
{ additionalProperties: false },
|
|
126
|
+
),
|
|
127
|
+
Type.Object(
|
|
128
|
+
{
|
|
129
|
+
kind: Type.Literal("delete"),
|
|
130
|
+
path: Type.String(),
|
|
131
|
+
},
|
|
132
|
+
{ additionalProperties: false },
|
|
133
|
+
),
|
|
134
|
+
]),
|
|
135
|
+
{ minItems: 1, maxItems: 128 },
|
|
136
|
+
),
|
|
97
137
|
},
|
|
98
138
|
{ additionalProperties: false },
|
|
99
139
|
),
|
|
@@ -188,6 +228,9 @@ export interface CandidateArtifactSubmission {
|
|
|
188
228
|
"beginCandidate" | "appendCandidateSegment" | "sealCandidate"
|
|
189
229
|
>;
|
|
190
230
|
identity: BeginCandidateInput;
|
|
231
|
+
workspaceRoot: string;
|
|
232
|
+
writePaths: readonly string[];
|
|
233
|
+
deletePaths: readonly string[];
|
|
191
234
|
}
|
|
192
235
|
|
|
193
236
|
export function createCandidateArtifactTool(
|
|
@@ -199,10 +242,7 @@ export function createCandidateArtifactTool(
|
|
|
199
242
|
let failure: CandidateFailure | undefined;
|
|
200
243
|
let attempts = 0;
|
|
201
244
|
let schema: SubmitSchemaState = "not-submitted";
|
|
202
|
-
let
|
|
203
|
-
let totalBytes = 0;
|
|
204
|
-
const candidateHash = createHash("sha256");
|
|
205
|
-
const identity: IdentityOutcome = {
|
|
245
|
+
let identity: IdentityOutcome = {
|
|
206
246
|
request: true,
|
|
207
247
|
role: true,
|
|
208
248
|
task: true,
|
|
@@ -212,7 +252,7 @@ export function createCandidateArtifactTool(
|
|
|
212
252
|
name: "abel_submit_result",
|
|
213
253
|
label: "Submit Abel Candidate Artifact",
|
|
214
254
|
description:
|
|
215
|
-
"Submit
|
|
255
|
+
"Submit one complete structured candidate patch or request bounded approved context. Diff generation, chunking, encoding, hashes, and atomic sealing are owned by this trusted tool.",
|
|
216
256
|
executionMode: "sequential",
|
|
217
257
|
parameters,
|
|
218
258
|
async execute(_toolCallId, params) {
|
|
@@ -220,6 +260,22 @@ export function createCandidateArtifactTool(
|
|
|
220
260
|
throw new Error("candidate terminal result already submitted");
|
|
221
261
|
}
|
|
222
262
|
attempts++;
|
|
263
|
+
if (attempts > 2) {
|
|
264
|
+
schema = "invalid";
|
|
265
|
+
failure = {
|
|
266
|
+
kind: "artifact",
|
|
267
|
+
code: "invalid-structural-result",
|
|
268
|
+
stage: "structural-submit",
|
|
269
|
+
};
|
|
270
|
+
throw new Error("structural submission correction limit exceeded");
|
|
271
|
+
}
|
|
272
|
+
identity = {
|
|
273
|
+
request: true,
|
|
274
|
+
role: true,
|
|
275
|
+
task: true,
|
|
276
|
+
phase: true,
|
|
277
|
+
};
|
|
278
|
+
failure = undefined;
|
|
223
279
|
const value = params as unknown as Record<string, unknown>;
|
|
224
280
|
if (value.candidateId !== input.identity.candidateId) {
|
|
225
281
|
identity.request = false;
|
|
@@ -232,18 +288,15 @@ export function createCandidateArtifactTool(
|
|
|
232
288
|
throw new Error("candidate identity mismatch");
|
|
233
289
|
}
|
|
234
290
|
schema = "valid";
|
|
235
|
-
if (value.kind === "candidate-
|
|
236
|
-
|
|
237
|
-
const segmentHash = createHash("sha256").update(bytes).digest("hex");
|
|
238
|
-
let accepted: ReturnType<
|
|
239
|
-
CandidateArtifactSubmission["ledger"]["appendCandidateSegment"]
|
|
240
|
-
>;
|
|
291
|
+
if (value.kind === "candidate-patch") {
|
|
292
|
+
let diff: string;
|
|
241
293
|
try {
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
294
|
+
diff = compileCandidatePatch({
|
|
295
|
+
root: input.workspaceRoot,
|
|
296
|
+
writePaths: input.writePaths,
|
|
297
|
+
deletePaths: input.deletePaths,
|
|
298
|
+
operations: value.operations as CandidatePatchOperation[],
|
|
299
|
+
maxBytes: TASK_LEDGER_LIMITS.maxCandidateBytes,
|
|
247
300
|
});
|
|
248
301
|
} catch (error) {
|
|
249
302
|
schema = "invalid";
|
|
@@ -254,34 +307,59 @@ export function createCandidateArtifactTool(
|
|
|
254
307
|
};
|
|
255
308
|
throw error;
|
|
256
309
|
}
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
310
|
+
const bytes = Buffer.from(diff, "utf8");
|
|
311
|
+
const candidateHash = createHash("sha256").update(bytes).digest("hex");
|
|
312
|
+
let sequence = 0;
|
|
313
|
+
for (
|
|
314
|
+
let offset = 0;
|
|
315
|
+
offset < bytes.length;
|
|
316
|
+
offset += TASK_LEDGER_LIMITS.maxSegmentBytes
|
|
317
|
+
) {
|
|
318
|
+
const segment = bytes.subarray(
|
|
319
|
+
offset,
|
|
320
|
+
Math.min(offset + TASK_LEDGER_LIMITS.maxSegmentBytes, bytes.length),
|
|
321
|
+
);
|
|
322
|
+
let accepted: ReturnType<
|
|
323
|
+
CandidateArtifactSubmission["ledger"]["appendCandidateSegment"]
|
|
324
|
+
>;
|
|
325
|
+
try {
|
|
326
|
+
accepted = input.ledger.appendCandidateSegment({
|
|
327
|
+
...input.identity,
|
|
328
|
+
sequence,
|
|
329
|
+
bytes: segment,
|
|
330
|
+
segmentHash: createHash("sha256").update(segment).digest("hex"),
|
|
331
|
+
});
|
|
332
|
+
} catch (error) {
|
|
333
|
+
schema = "invalid";
|
|
334
|
+
failure = {
|
|
335
|
+
kind: "artifact",
|
|
336
|
+
code: "invalid-diff",
|
|
337
|
+
stage: "candidate-diff",
|
|
338
|
+
};
|
|
339
|
+
throw error;
|
|
340
|
+
}
|
|
341
|
+
if (!accepted.ok) {
|
|
342
|
+
failure = {
|
|
343
|
+
kind: "result-limit",
|
|
344
|
+
limitBytes: accepted.limitBytes,
|
|
345
|
+
};
|
|
346
|
+
return {
|
|
347
|
+
content: [],
|
|
348
|
+
details: accepted,
|
|
349
|
+
terminate: true,
|
|
350
|
+
};
|
|
351
|
+
}
|
|
352
|
+
sequence = accepted.nextSequence;
|
|
266
353
|
}
|
|
267
|
-
return {
|
|
268
|
-
content: [
|
|
269
|
-
{ type: "text" as const, text: "Candidate segment accepted." },
|
|
270
|
-
],
|
|
271
|
-
details: accepted,
|
|
272
|
-
...(!accepted.ok ? { terminate: true } : {}),
|
|
273
|
-
};
|
|
274
|
-
}
|
|
275
|
-
if (value.kind === "candidate-seal") {
|
|
276
354
|
let sealed: ReturnType<
|
|
277
355
|
CandidateArtifactSubmission["ledger"]["sealCandidate"]
|
|
278
356
|
>;
|
|
279
357
|
try {
|
|
280
358
|
sealed = input.ledger.sealCandidate({
|
|
281
359
|
...input.identity,
|
|
282
|
-
segmentCount,
|
|
283
|
-
totalBytes,
|
|
284
|
-
candidateHash
|
|
360
|
+
segmentCount: sequence,
|
|
361
|
+
totalBytes: bytes.length,
|
|
362
|
+
candidateHash,
|
|
285
363
|
});
|
|
286
364
|
} catch (error) {
|
|
287
365
|
schema = "invalid";
|
|
@@ -318,6 +396,12 @@ export function createCandidateArtifactTool(
|
|
|
318
396
|
refs.some((relative) => !isValidRelativePath(relative)) ||
|
|
319
397
|
new Set(refs).size !== refs.length
|
|
320
398
|
) {
|
|
399
|
+
schema = "invalid";
|
|
400
|
+
failure = {
|
|
401
|
+
kind: "artifact",
|
|
402
|
+
code: "invalid-structural-result",
|
|
403
|
+
stage: "structural-submit",
|
|
404
|
+
};
|
|
321
405
|
throw new Error("context request refs are invalid");
|
|
322
406
|
}
|
|
323
407
|
result = {
|
|
@@ -377,7 +461,7 @@ export function createSubmitTool(input: {
|
|
|
377
461
|
let failure: CandidateFailure | undefined;
|
|
378
462
|
let attempts = 0;
|
|
379
463
|
let schema: SubmitSchemaState = "not-submitted";
|
|
380
|
-
|
|
464
|
+
let identity: IdentityOutcome = {
|
|
381
465
|
request: true,
|
|
382
466
|
role: true,
|
|
383
467
|
task: true,
|
|
@@ -398,6 +482,22 @@ export function createSubmitTool(input: {
|
|
|
398
482
|
: diffSchema,
|
|
399
483
|
async execute(_toolCallId, params) {
|
|
400
484
|
attempts++;
|
|
485
|
+
if (attempts > 2) {
|
|
486
|
+
schema = "invalid";
|
|
487
|
+
failure = {
|
|
488
|
+
kind: "artifact",
|
|
489
|
+
code: "invalid-structural-result",
|
|
490
|
+
stage: "structural-submit",
|
|
491
|
+
};
|
|
492
|
+
throw new Error("structural submission correction limit exceeded");
|
|
493
|
+
}
|
|
494
|
+
identity = {
|
|
495
|
+
request: true,
|
|
496
|
+
role: true,
|
|
497
|
+
task: true,
|
|
498
|
+
phase: true,
|
|
499
|
+
};
|
|
500
|
+
failure = undefined;
|
|
401
501
|
const value = params as unknown as Record<string, unknown>;
|
|
402
502
|
if (value === null || typeof value !== "object") {
|
|
403
503
|
identity.request = false;
|
package/src/worker-broker.ts
CHANGED
package/src/workflow-engine.ts
CHANGED
|
@@ -2833,13 +2833,14 @@ class DurableWorkflowComposition
|
|
|
2833
2833
|
const phase = request.task.phases[request.phase];
|
|
2834
2834
|
if (!phase) throw new Error("workflow-task-phase-invalid");
|
|
2835
2835
|
const allPhases = Object.values(request.task.phases);
|
|
2836
|
+
const approvedWritePaths = [
|
|
2837
|
+
...new Set(allPhases.flatMap((boundary) => boundary.write)),
|
|
2838
|
+
].sort();
|
|
2839
|
+
const approvedDeletePaths = [
|
|
2840
|
+
...new Set(allPhases.flatMap((boundary) => boundary.delete)),
|
|
2841
|
+
].sort();
|
|
2836
2842
|
const approvedPaths = [
|
|
2837
|
-
...new Set(
|
|
2838
|
-
allPhases.flatMap((boundary) => [
|
|
2839
|
-
...boundary.write,
|
|
2840
|
-
...boundary.delete,
|
|
2841
|
-
]),
|
|
2842
|
-
),
|
|
2843
|
+
...new Set([...approvedWritePaths, ...approvedDeletePaths]),
|
|
2843
2844
|
].sort();
|
|
2844
2845
|
const boundPaths = [
|
|
2845
2846
|
...new Set(
|
|
@@ -2915,7 +2916,13 @@ class DurableWorkflowComposition
|
|
|
2915
2916
|
task: structuredClone(request.task),
|
|
2916
2917
|
workspaceRoot: proposalRoot,
|
|
2917
2918
|
ledgerProjection,
|
|
2918
|
-
candidateArtifact: {
|
|
2919
|
+
candidateArtifact: {
|
|
2920
|
+
ledger,
|
|
2921
|
+
identity,
|
|
2922
|
+
workspaceRoot: proposalRoot,
|
|
2923
|
+
writePaths: approvedWritePaths,
|
|
2924
|
+
deletePaths: approvedDeletePaths,
|
|
2925
|
+
},
|
|
2919
2926
|
route: attempt.route,
|
|
2920
2927
|
repair,
|
|
2921
2928
|
signal: attempt.signal,
|
|
@@ -3684,7 +3691,13 @@ class DurableWorkflowComposition
|
|
|
3684
3691
|
task: structuredClone(input.task),
|
|
3685
3692
|
workspaceRoot: proposalRoot,
|
|
3686
3693
|
ledgerProjection,
|
|
3687
|
-
candidateArtifact: {
|
|
3694
|
+
candidateArtifact: {
|
|
3695
|
+
ledger,
|
|
3696
|
+
identity,
|
|
3697
|
+
workspaceRoot: proposalRoot,
|
|
3698
|
+
writePaths: phase.write,
|
|
3699
|
+
deletePaths: phase.delete,
|
|
3700
|
+
},
|
|
3688
3701
|
route: attempt.route,
|
|
3689
3702
|
signal: attempt.signal,
|
|
3690
3703
|
onHeaders: attempt.onHeaders,
|
|
@@ -4811,21 +4824,6 @@ export class WorkflowEngine {
|
|
|
4811
4824
|
)?.run_id;
|
|
4812
4825
|
}
|
|
4813
4826
|
|
|
4814
|
-
#lookupProvisionalRun(provisionalKey: string): string | undefined {
|
|
4815
|
-
return (
|
|
4816
|
-
this.#database
|
|
4817
|
-
.prepare(
|
|
4818
|
-
`SELECT run_id FROM runs
|
|
4819
|
-
WHERE root_hash = ? AND stage = 'abel-design'
|
|
4820
|
-
AND lookup_key = ?`,
|
|
4821
|
-
)
|
|
4822
|
-
.get(
|
|
4823
|
-
this.#stateRoot.consumerRootHash,
|
|
4824
|
-
`provisional:${provisionalKey}`,
|
|
4825
|
-
) as { run_id: string } | undefined
|
|
4826
|
-
)?.run_id;
|
|
4827
|
-
}
|
|
4828
|
-
|
|
4829
4827
|
#ensureEngineRun(runId: string): void {
|
|
4830
4828
|
this.#database
|
|
4831
4829
|
.prepare(
|
|
@@ -6846,118 +6844,7 @@ export class WorkflowEngine {
|
|
|
6846
6844
|
signal?: AbortSignal,
|
|
6847
6845
|
onActivity?: (event: WorkflowActivityUpdate) => void,
|
|
6848
6846
|
) {
|
|
6849
|
-
|
|
6850
|
-
const existingRun = this.#lookupProvisionalRun(command.provisionalKey);
|
|
6851
|
-
if (existingRun) {
|
|
6852
|
-
this.#ensureEngineRun(existingRun);
|
|
6853
|
-
const replay = this.#operationReplay(
|
|
6854
|
-
existingRun,
|
|
6855
|
-
command.operationId,
|
|
6856
|
-
command.command,
|
|
6857
|
-
);
|
|
6858
|
-
if (replay) return replay;
|
|
6859
|
-
const restarted = this.#runStore.startRun({
|
|
6860
|
-
stage: "abel-design",
|
|
6861
|
-
provisionalKey: command.provisionalKey,
|
|
6862
|
-
operationId: command.operationId,
|
|
6863
|
-
});
|
|
6864
|
-
const begun = this.#beginOperation(
|
|
6865
|
-
existingRun,
|
|
6866
|
-
command.operationId,
|
|
6867
|
-
command.command,
|
|
6868
|
-
);
|
|
6869
|
-
if (begun) return begun;
|
|
6870
|
-
if (restarted.state === "created") {
|
|
6871
|
-
const lease = this.#operationLease(existingRun, command.operationId);
|
|
6872
|
-
this.#transition(
|
|
6873
|
-
existingRun,
|
|
6874
|
-
"paused",
|
|
6875
|
-
`${command.operationId}:awaiting-gate-a`,
|
|
6876
|
-
"design-awaiting-gate-a",
|
|
6877
|
-
lease,
|
|
6878
|
-
);
|
|
6879
|
-
}
|
|
6880
|
-
return this.#commitOperation(
|
|
6881
|
-
existingRun,
|
|
6882
|
-
command.operationId,
|
|
6883
|
-
this.#statusByRun(existingRun),
|
|
6884
|
-
);
|
|
6885
|
-
}
|
|
6886
|
-
const created = this.#runStore.startRun({
|
|
6887
|
-
stage: "abel-design",
|
|
6888
|
-
provisionalKey: command.provisionalKey,
|
|
6889
|
-
operationId: command.operationId,
|
|
6890
|
-
});
|
|
6891
|
-
this.#ensureEngineRun(created.runId);
|
|
6892
|
-
const begun = this.#beginOperation(
|
|
6893
|
-
created.runId,
|
|
6894
|
-
command.operationId,
|
|
6895
|
-
command.command,
|
|
6896
|
-
);
|
|
6897
|
-
if (begun) return begun;
|
|
6898
|
-
const lease = this.#operationLease(created.runId, command.operationId);
|
|
6899
|
-
this.#transition(
|
|
6900
|
-
created.runId,
|
|
6901
|
-
"paused",
|
|
6902
|
-
`${command.operationId}:awaiting-gate-a`,
|
|
6903
|
-
"design-awaiting-gate-a",
|
|
6904
|
-
lease,
|
|
6905
|
-
);
|
|
6906
|
-
return this.#commitOperation(
|
|
6907
|
-
created.runId,
|
|
6908
|
-
command.operationId,
|
|
6909
|
-
this.#statusByRun(created.runId),
|
|
6910
|
-
);
|
|
6911
|
-
}
|
|
6912
|
-
let existingRun = this.#lookupRun(command.stage, command.change);
|
|
6913
|
-
const requestedProvisionalRun =
|
|
6914
|
-
command.stage === "abel-design" && command.provisionalKey
|
|
6915
|
-
? this.#lookupProvisionalRun(command.provisionalKey)
|
|
6916
|
-
: undefined;
|
|
6917
|
-
if (command.provisionalKey && !requestedProvisionalRun) {
|
|
6918
|
-
throw new Error("provisional-design-run-not-found");
|
|
6919
|
-
}
|
|
6920
|
-
if (
|
|
6921
|
-
existingRun &&
|
|
6922
|
-
requestedProvisionalRun &&
|
|
6923
|
-
existingRun !== requestedProvisionalRun
|
|
6924
|
-
) {
|
|
6925
|
-
throw new Error("provisional-design-run-conflict");
|
|
6926
|
-
}
|
|
6927
|
-
if (
|
|
6928
|
-
existingRun &&
|
|
6929
|
-
command.stage === "abel-design" &&
|
|
6930
|
-
["completed", "discarded", "rejected"].includes(
|
|
6931
|
-
this.#runStore.status(existingRun).state,
|
|
6932
|
-
)
|
|
6933
|
-
) {
|
|
6934
|
-
const restarted = this.#runStore.startRun({
|
|
6935
|
-
stage: command.stage,
|
|
6936
|
-
change: command.change,
|
|
6937
|
-
operationId: command.operationId,
|
|
6938
|
-
});
|
|
6939
|
-
existingRun = restarted.runId;
|
|
6940
|
-
this.#ensureEngineRun(existingRun);
|
|
6941
|
-
const begun = this.#beginOperation(
|
|
6942
|
-
existingRun,
|
|
6943
|
-
command.operationId,
|
|
6944
|
-
command.command,
|
|
6945
|
-
);
|
|
6946
|
-
if (begun) return begun;
|
|
6947
|
-
const lease = this.#operationLease(existingRun, command.operationId);
|
|
6948
|
-
this.#transition(
|
|
6949
|
-
existingRun,
|
|
6950
|
-
"paused",
|
|
6951
|
-
`${command.operationId}:awaiting-design-evidence`,
|
|
6952
|
-
"design-awaiting-evidence",
|
|
6953
|
-
lease,
|
|
6954
|
-
);
|
|
6955
|
-
return this.#commitOperation(
|
|
6956
|
-
existingRun,
|
|
6957
|
-
command.operationId,
|
|
6958
|
-
this.#statusByRun(existingRun),
|
|
6959
|
-
);
|
|
6960
|
-
}
|
|
6847
|
+
const existingRun = this.#lookupRun(command.stage, command.change);
|
|
6961
6848
|
if (existingRun) {
|
|
6962
6849
|
this.#ensureEngineRun(existingRun);
|
|
6963
6850
|
const replay = this.#operationReplay(
|
|
@@ -6986,17 +6873,6 @@ export class WorkflowEngine {
|
|
|
6986
6873
|
}
|
|
6987
6874
|
}
|
|
6988
6875
|
|
|
6989
|
-
if (requestedProvisionalRun) {
|
|
6990
|
-
this.#runStore.bindChange({
|
|
6991
|
-
runId: requestedProvisionalRun,
|
|
6992
|
-
change: command.change,
|
|
6993
|
-
operationId: `bind-change-${hash(
|
|
6994
|
-
requestedProvisionalRun,
|
|
6995
|
-
command.change,
|
|
6996
|
-
).slice(0, 40)}`,
|
|
6997
|
-
});
|
|
6998
|
-
existingRun = requestedProvisionalRun;
|
|
6999
|
-
}
|
|
7000
6876
|
const runId =
|
|
7001
6877
|
existingRun ??
|
|
7002
6878
|
this.#runStore.startRun({
|
|
@@ -7012,20 +6888,6 @@ export class WorkflowEngine {
|
|
|
7012
6888
|
);
|
|
7013
6889
|
if (begun) return begun;
|
|
7014
6890
|
const lease = this.#operationLease(runId, command.operationId);
|
|
7015
|
-
if (command.stage === "abel-design") {
|
|
7016
|
-
this.#transition(
|
|
7017
|
-
runId,
|
|
7018
|
-
"paused",
|
|
7019
|
-
`${command.operationId}:awaiting-design-evidence`,
|
|
7020
|
-
"design-awaiting-evidence",
|
|
7021
|
-
lease,
|
|
7022
|
-
);
|
|
7023
|
-
return this.#commitOperation(
|
|
7024
|
-
runId,
|
|
7025
|
-
command.operationId,
|
|
7026
|
-
this.#statusByRun(runId),
|
|
7027
|
-
);
|
|
7028
|
-
}
|
|
7029
6891
|
this.#transition(
|
|
7030
6892
|
runId,
|
|
7031
6893
|
"validating-delivery",
|
|
@@ -7087,17 +6949,6 @@ export class WorkflowEngine {
|
|
|
7087
6949
|
if (replay) return replay;
|
|
7088
6950
|
const lease = this.#operationLease(runId, command.operationId);
|
|
7089
6951
|
const current = this.#runStore.status(runId);
|
|
7090
|
-
if (current.stage === "abel-design") {
|
|
7091
|
-
if (current.state !== "paused") {
|
|
7092
|
-
this.#interruptOperation(runId, command.operationId);
|
|
7093
|
-
throw new Error("resume-not-allowed");
|
|
7094
|
-
}
|
|
7095
|
-
return this.#commitOperation(
|
|
7096
|
-
runId,
|
|
7097
|
-
command.operationId,
|
|
7098
|
-
this.#statusByRun(runId),
|
|
7099
|
-
);
|
|
7100
|
-
}
|
|
7101
6952
|
if (current.state === "recovering") {
|
|
7102
6953
|
emitWorkflowActivity(onActivity, {
|
|
7103
6954
|
state: "recovering",
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
# Role: contract-reviewer
|
|
2
|
-
|
|
3
|
-
You are a package-owned read-only professional Agent for terminal and checkpoint review of approved design delivery.
|
|
4
|
-
|
|
5
|
-
You inspect the approved contracts, canonical `ImplementPlan`, receipts, raw and canonical hashes, verification closure, traceability, and task DAG ONLY through the scoped `read`, `grep`, `find`, and `ls` tools.
|
|
6
|
-
You never write, mutate, or run validation.
|
|
7
|
-
|
|
8
|
-
Your output is a compact structured evidence object returned through `abel_submit_result`, containing the review identity, the exact artifact hashes you verified, suite-evidence status, and typed `delivery-invalid` or `approval-boundary` facts (empty when the delivery is sound).
|
|
9
|
-
|
|
10
|
-
You never patch product code, AGENTS files, or task state.
|
|
11
|
-
Review evidence is read-only; the parent resolves it without a stage selection, Gate decision, or recovery recommendation from you.
|