@abelxiaoxing/cadence 1.3.0 → 1.4.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 +172 -13
- package/agents/design-explorer.md +17 -11
- package/agents/diagnosis-worker.md +9 -1
- package/agents/implementation-worker.md +3 -1
- package/config/plan-draft.example.json +122 -0
- package/config/plan-draft.multiple-tasks.example.json +345 -0
- package/package.json +9 -5
- package/prompts/abel-design.md +141 -38
- package/prompts/abel-diagnose.md +10 -1
- package/prompts/abel-implement.md +118 -20
- package/prompts/abel-init.md +9 -2
- package/src/activity-contracts.ts +82 -0
- package/src/apply-transaction.ts +16 -14
- package/src/artifact-store.ts +17 -0
- package/src/candidate-artifact.ts +143 -0
- package/src/candidate-patch.ts +33 -12
- package/src/candidate-workspace.ts +74 -0
- package/src/canonical.ts +16 -0
- package/src/change-contract-schema.ts +191 -0
- package/src/change-contract.ts +273 -0
- package/src/change-verification.ts +896 -0
- package/src/child-model.ts +129 -0
- package/src/child-session.ts +296 -328
- package/src/contracts.ts +325 -109
- package/src/control-contracts.ts +51 -1
- package/src/delivery-compiler.ts +241 -141
- package/src/delivery-revision.ts +42 -0
- package/src/design-control.ts +182 -15
- package/src/design-diagnostics.ts +150 -0
- package/src/design-journal.ts +216 -72
- package/src/durable-contracts.ts +210 -0
- package/src/durable-workflow.ts +963 -0
- package/src/evidence-draft.ts +122 -0
- package/src/implement-graph.ts +14 -16
- package/src/implement-plan.ts +70 -0
- package/src/index.ts +341 -1405
- package/src/isolation-backend.ts +84 -23
- package/src/model-source.ts +22 -0
- package/src/package-candidate.ts +224 -0
- package/src/package-delivery.ts +486 -0
- package/src/package-verification.ts +509 -0
- package/src/package-workflow.ts +253 -0
- package/src/packet-runtime.ts +27 -48
- package/src/parent-provider.ts +86 -198
- package/src/phase-execution.ts +2248 -0
- package/src/pi-adapter.ts +19 -0
- package/src/plan-draft-summary.ts +146 -0
- package/src/plan-draft.ts +493 -0
- package/src/route-policy.ts +1 -11
- package/src/run-state.ts +4 -16
- package/src/run-store.ts +5 -144
- package/src/scoped-grep-worker.mjs +23 -0
- package/src/scoped-tools.ts +312 -116
- package/src/sqlite-schema.ts +171 -0
- package/src/storage-schema.ts +352 -0
- package/src/subagent-activity.ts +46 -67
- package/src/submit-tool.ts +40 -61
- package/src/task-ledger.ts +14 -55
- package/src/transport-budget.ts +32 -0
- package/src/verification-capability.ts +298 -102
- package/src/verification-environment.ts +213 -0
- package/src/verification-identity.ts +77 -0
- package/src/worker-broker.ts +134 -91
- package/src/workflow-engine.ts +28 -8285
- package/src/workflow-policy.ts +1388 -0
- package/src/workflow-recovery-policy.ts +95 -0
- package/src/workflow-scheduling.ts +105 -0
- package/src/workflow-state-machine.ts +4086 -0
- package/src/workflow-status.ts +384 -0
- package/src/workspace-io-entry.mjs +58 -0
- package/src/workspace-io-worker.mjs +991 -0
- package/src/workspace-io.ts +84 -0
- package/src/workspace-store.ts +125 -19
- package/skills/abel-workflow/SKILL.md +0 -205
- package/src/empty-resource-loader.ts +0 -38
- package/src/parent-payload-bridge.ts +0 -523
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
import { changeContractDiagnostics } from "./change-contract-schema.ts";
|
|
2
|
+
import {
|
|
3
|
+
type ImplementTaskBoundary,
|
|
4
|
+
isValidRelativePath,
|
|
5
|
+
type StructuredVerificationContract,
|
|
6
|
+
validateVerificationContract,
|
|
7
|
+
verificationInputPaths,
|
|
8
|
+
} from "./contracts.ts";
|
|
9
|
+
import { DesignPlanValidationError } from "./design-diagnostics.ts";
|
|
10
|
+
import { canonicalJson } from "./run-state.ts";
|
|
11
|
+
|
|
12
|
+
export interface ChangeContract {
|
|
13
|
+
goal: string;
|
|
14
|
+
acceptance: Array<{
|
|
15
|
+
id: string;
|
|
16
|
+
statement: string;
|
|
17
|
+
verification: StructuredVerificationContract;
|
|
18
|
+
}>;
|
|
19
|
+
constraints: Array<{ id: string; statement: string }>;
|
|
20
|
+
policy: {
|
|
21
|
+
writeRoots: string[];
|
|
22
|
+
dependencies: string[];
|
|
23
|
+
verificationModes: Array<"behavior" | "mechanical" | "refactor">;
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function record(value: unknown): value is Record<string, unknown> {
|
|
28
|
+
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
29
|
+
}
|
|
30
|
+
function keys(value: Record<string, unknown>, expected: string[]) {
|
|
31
|
+
return (
|
|
32
|
+
canonicalJson(Object.keys(value).sort()) === canonicalJson(expected.sort())
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
function text(value: unknown): value is string {
|
|
36
|
+
return (
|
|
37
|
+
typeof value === "string" && value.trim().length > 0 && value.length <= 8192
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
const identifier = /^[a-zA-Z0-9][a-zA-Z0-9._:-]{0,127}$/u;
|
|
41
|
+
|
|
42
|
+
export function normalizeChangeContract(value: unknown): ChangeContract {
|
|
43
|
+
const diagnostics = changeContractDiagnostics(value);
|
|
44
|
+
if (diagnostics.length)
|
|
45
|
+
throw new DesignPlanValidationError("change-contract-invalid", diagnostics);
|
|
46
|
+
if (
|
|
47
|
+
!record(value) ||
|
|
48
|
+
!keys(value, ["goal", "acceptance", "constraints", "policy"]) ||
|
|
49
|
+
!text(value.goal) ||
|
|
50
|
+
!Array.isArray(value.acceptance) ||
|
|
51
|
+
value.acceptance.length < 1 ||
|
|
52
|
+
value.acceptance.length > 256 ||
|
|
53
|
+
!Array.isArray(value.constraints) ||
|
|
54
|
+
value.constraints.length > 256 ||
|
|
55
|
+
!record(value.policy)
|
|
56
|
+
)
|
|
57
|
+
throw new Error("change-contract-invalid");
|
|
58
|
+
const entries = (values: unknown[], acceptance: boolean) =>
|
|
59
|
+
values
|
|
60
|
+
.map((entry) => {
|
|
61
|
+
if (
|
|
62
|
+
!record(entry) ||
|
|
63
|
+
!keys(
|
|
64
|
+
entry,
|
|
65
|
+
acceptance
|
|
66
|
+
? ["id", "statement", "verification"]
|
|
67
|
+
: ["id", "statement"],
|
|
68
|
+
) ||
|
|
69
|
+
typeof entry.id !== "string" ||
|
|
70
|
+
!identifier.test(entry.id) ||
|
|
71
|
+
!text(entry.statement)
|
|
72
|
+
)
|
|
73
|
+
throw new Error("change-contract-invalid");
|
|
74
|
+
const verification = acceptance
|
|
75
|
+
? validateVerificationContract(entry.verification)
|
|
76
|
+
: undefined;
|
|
77
|
+
if (verification && !verification.ok)
|
|
78
|
+
throw new Error("change-contract-invalid");
|
|
79
|
+
return {
|
|
80
|
+
id: entry.id,
|
|
81
|
+
statement: entry.statement.replace(/\r\n?/gu, "\n").trim(),
|
|
82
|
+
...(verification?.ok ? { verification: verification.value } : {}),
|
|
83
|
+
};
|
|
84
|
+
})
|
|
85
|
+
.sort((a, b) => (a.id < b.id ? -1 : a.id > b.id ? 1 : 0));
|
|
86
|
+
const acceptance = entries(value.acceptance, true);
|
|
87
|
+
const constraints = entries(value.constraints, false);
|
|
88
|
+
for (const group of [acceptance, constraints])
|
|
89
|
+
if (new Set(group.map((item) => item.id)).size !== group.length)
|
|
90
|
+
throw new Error("change-contract-invalid");
|
|
91
|
+
const policy = value.policy;
|
|
92
|
+
if (!keys(policy, ["writeRoots", "dependencies", "verificationModes"]))
|
|
93
|
+
throw new Error("change-contract-invalid");
|
|
94
|
+
for (const key of ["writeRoots", "dependencies", "verificationModes"])
|
|
95
|
+
if (
|
|
96
|
+
!Array.isArray(policy[key]) ||
|
|
97
|
+
policy[key].length > 256 ||
|
|
98
|
+
!policy[key].every(text) ||
|
|
99
|
+
new Set(policy[key]).size !== policy[key].length
|
|
100
|
+
)
|
|
101
|
+
throw new Error("change-contract-invalid");
|
|
102
|
+
const roots = policy.writeRoots as string[];
|
|
103
|
+
const modes = policy.verificationModes as string[];
|
|
104
|
+
if (
|
|
105
|
+
!roots.length ||
|
|
106
|
+
!roots.every((root) => root === "." || isValidRelativePath(root)) ||
|
|
107
|
+
!modes.length ||
|
|
108
|
+
!modes.every((mode) =>
|
|
109
|
+
["behavior", "mechanical", "refactor"].includes(mode),
|
|
110
|
+
)
|
|
111
|
+
)
|
|
112
|
+
throw new Error("change-contract-invalid");
|
|
113
|
+
const result = {
|
|
114
|
+
goal: value.goal.replace(/\r\n?/gu, "\n").trim(),
|
|
115
|
+
acceptance,
|
|
116
|
+
constraints,
|
|
117
|
+
policy: {
|
|
118
|
+
writeRoots: [...roots].sort(),
|
|
119
|
+
dependencies: [...(policy.dependencies as string[])].sort(),
|
|
120
|
+
verificationModes: [...modes].sort(),
|
|
121
|
+
},
|
|
122
|
+
} as ChangeContract;
|
|
123
|
+
if (Buffer.byteLength(canonicalJson(result)) > 64 * 1024)
|
|
124
|
+
throw new Error("change-contract-invalid");
|
|
125
|
+
return result;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/** Display identities and fresh input bindings do not change a verification obligation. */
|
|
129
|
+
export function verificationObligation(
|
|
130
|
+
value: StructuredVerificationContract,
|
|
131
|
+
): string {
|
|
132
|
+
const strip = (item: unknown): unknown =>
|
|
133
|
+
Array.isArray(item)
|
|
134
|
+
? item.map(strip)
|
|
135
|
+
: record(item)
|
|
136
|
+
? Object.fromEntries(
|
|
137
|
+
Object.entries(item)
|
|
138
|
+
.filter(([key]) => !["id", "executionBindings"].includes(key))
|
|
139
|
+
.map(([key, child]) => [key, strip(child)]),
|
|
140
|
+
)
|
|
141
|
+
: item;
|
|
142
|
+
return canonicalJson(strip(value));
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
export function assertPlanWithinChangeContract(
|
|
146
|
+
contract: ChangeContract,
|
|
147
|
+
tasks: readonly (ImplementTaskBoundary & {
|
|
148
|
+
verificationMode?: string;
|
|
149
|
+
affectedVerification: StructuredVerificationContract;
|
|
150
|
+
repairVerification: StructuredVerificationContract;
|
|
151
|
+
})[],
|
|
152
|
+
verifications: readonly StructuredVerificationContract[],
|
|
153
|
+
): void {
|
|
154
|
+
const available = new Set(
|
|
155
|
+
[
|
|
156
|
+
...verifications,
|
|
157
|
+
...tasks.flatMap((task) => [
|
|
158
|
+
task.affectedVerification,
|
|
159
|
+
...Object.entries(task.phases)
|
|
160
|
+
.filter(
|
|
161
|
+
([phase]) =>
|
|
162
|
+
phase !== "red" ||
|
|
163
|
+
!task.verificationMode ||
|
|
164
|
+
task.verificationMode === "behavior",
|
|
165
|
+
)
|
|
166
|
+
.map(([, phase]) => phase.verification),
|
|
167
|
+
]),
|
|
168
|
+
].map(verificationObligation),
|
|
169
|
+
);
|
|
170
|
+
for (const accepted of contract.acceptance)
|
|
171
|
+
if (!available.has(verificationObligation(accepted.verification)))
|
|
172
|
+
throw new Error("change-contract-acceptance-missing");
|
|
173
|
+
for (const task of tasks) {
|
|
174
|
+
if (
|
|
175
|
+
!contract.policy.verificationModes.includes(
|
|
176
|
+
(task.verificationMode ?? "behavior") as "behavior",
|
|
177
|
+
)
|
|
178
|
+
)
|
|
179
|
+
throw new Error("change-contract-verification-mode");
|
|
180
|
+
if (
|
|
181
|
+
task.approvedDependencies.some(
|
|
182
|
+
(name) => !contract.policy.dependencies.includes(name),
|
|
183
|
+
)
|
|
184
|
+
)
|
|
185
|
+
throw new Error("change-contract-dependency-outside-policy");
|
|
186
|
+
if (
|
|
187
|
+
task.agents &&
|
|
188
|
+
task.agents.impact !== "none" &&
|
|
189
|
+
!contract.policy.writeRoots.includes(task.agents.target ?? "")
|
|
190
|
+
)
|
|
191
|
+
throw new Error("change-contract-agents-outside-policy");
|
|
192
|
+
const mode = task.verificationMode ?? "behavior";
|
|
193
|
+
const writes = Object.entries(task.phases)
|
|
194
|
+
.filter(([phase]) => phase !== "red" || mode === "behavior")
|
|
195
|
+
.flatMap(([, phase]) => [...phase.write, ...phase.delete]);
|
|
196
|
+
if (
|
|
197
|
+
mode !== "behavior" &&
|
|
198
|
+
task.impactClosure?.changedSurfaces.some((surface) => surface !== "none")
|
|
199
|
+
)
|
|
200
|
+
throw new Error("change-contract-behavior-requires-red");
|
|
201
|
+
if (
|
|
202
|
+
mode === "mechanical" &&
|
|
203
|
+
writes.some((file) => !/\.(?:md|txt|json|ya?ml|toml|lock)$/iu.test(file))
|
|
204
|
+
)
|
|
205
|
+
throw new Error("change-contract-mechanical-path");
|
|
206
|
+
if (
|
|
207
|
+
mode === "refactor" &&
|
|
208
|
+
contract.acceptance.some((accepted) =>
|
|
209
|
+
verificationInputPaths(accepted.verification).some((file) =>
|
|
210
|
+
writes.includes(file),
|
|
211
|
+
),
|
|
212
|
+
)
|
|
213
|
+
)
|
|
214
|
+
throw new Error("change-contract-refactor-verification-mutation");
|
|
215
|
+
for (const phase of Object.values(task.phases))
|
|
216
|
+
for (const file of [...phase.write, ...phase.delete])
|
|
217
|
+
if (
|
|
218
|
+
!contract.policy.writeRoots.some(
|
|
219
|
+
(root) =>
|
|
220
|
+
root === "." || file === root || file.startsWith(`${root}/`),
|
|
221
|
+
)
|
|
222
|
+
)
|
|
223
|
+
throw new Error("change-contract-write-outside-policy");
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
export function retainedChangeContract(plan: {
|
|
228
|
+
changeContract?: ChangeContract;
|
|
229
|
+
changeId: string;
|
|
230
|
+
tasks: readonly (ImplementTaskBoundary & {
|
|
231
|
+
affectedVerification: StructuredVerificationContract;
|
|
232
|
+
})[];
|
|
233
|
+
verification: {
|
|
234
|
+
change: {
|
|
235
|
+
fullSuite: StructuredVerificationContract;
|
|
236
|
+
postApply: StructuredVerificationContract;
|
|
237
|
+
};
|
|
238
|
+
};
|
|
239
|
+
}): ChangeContract {
|
|
240
|
+
if (plan.changeContract) return normalizeChangeContract(plan.changeContract);
|
|
241
|
+
return normalizeChangeContract({
|
|
242
|
+
goal: plan.changeId,
|
|
243
|
+
acceptance: [
|
|
244
|
+
plan.verification.change.fullSuite,
|
|
245
|
+
plan.verification.change.postApply,
|
|
246
|
+
...plan.tasks.map((task) => task.affectedVerification),
|
|
247
|
+
].map((verification, index) => ({
|
|
248
|
+
id: `legacy-${index}`,
|
|
249
|
+
statement: "Retained verification obligation",
|
|
250
|
+
verification,
|
|
251
|
+
})),
|
|
252
|
+
constraints: [],
|
|
253
|
+
policy: {
|
|
254
|
+
writeRoots: [
|
|
255
|
+
...new Set(
|
|
256
|
+
plan.tasks.flatMap((task) => [
|
|
257
|
+
...(task.agents.impact !== "none" && task.agents.target
|
|
258
|
+
? [task.agents.target]
|
|
259
|
+
: []),
|
|
260
|
+
...Object.values(task.phases).flatMap((phase) => [
|
|
261
|
+
...phase.write,
|
|
262
|
+
...phase.delete,
|
|
263
|
+
]),
|
|
264
|
+
]),
|
|
265
|
+
),
|
|
266
|
+
],
|
|
267
|
+
dependencies: [
|
|
268
|
+
...new Set(plan.tasks.flatMap((task) => task.approvedDependencies)),
|
|
269
|
+
],
|
|
270
|
+
verificationModes: ["behavior"],
|
|
271
|
+
},
|
|
272
|
+
});
|
|
273
|
+
}
|