@abelxiaoxing/cadence 1.4.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.
Files changed (49) hide show
  1. package/README.md +58 -4
  2. package/agents/design-explorer.md +17 -11
  3. package/agents/diagnosis-worker.md +9 -1
  4. package/agents/implementation-worker.md +3 -1
  5. package/config/plan-draft.example.json +122 -0
  6. package/config/plan-draft.multiple-tasks.example.json +345 -0
  7. package/package.json +5 -3
  8. package/prompts/abel-design.md +93 -44
  9. package/src/activity-contracts.ts +82 -0
  10. package/src/candidate-artifact.ts +143 -0
  11. package/src/candidate-patch.ts +31 -11
  12. package/src/candidate-workspace.ts +74 -0
  13. package/src/change-contract-schema.ts +191 -0
  14. package/src/change-contract.ts +5 -0
  15. package/src/change-verification.ts +896 -0
  16. package/src/child-model.ts +129 -0
  17. package/src/child-session.ts +293 -326
  18. package/src/contracts.ts +184 -76
  19. package/src/delivery-compiler.ts +103 -120
  20. package/src/delivery-revision.ts +42 -0
  21. package/src/design-control.ts +113 -4
  22. package/src/design-diagnostics.ts +150 -0
  23. package/src/durable-contracts.ts +210 -0
  24. package/src/durable-workflow.ts +148 -3570
  25. package/src/evidence-draft.ts +122 -0
  26. package/src/implement-graph.ts +3 -0
  27. package/src/implement-plan.ts +70 -0
  28. package/src/index.ts +59 -522
  29. package/src/model-source.ts +22 -0
  30. package/src/package-candidate.ts +224 -0
  31. package/src/package-workflow.ts +253 -0
  32. package/src/packet-runtime.ts +27 -48
  33. package/src/parent-provider.ts +86 -198
  34. package/src/phase-execution.ts +2248 -0
  35. package/src/pi-adapter.ts +19 -0
  36. package/src/plan-draft-summary.ts +146 -0
  37. package/src/plan-draft.ts +493 -0
  38. package/src/subagent-activity.ts +32 -66
  39. package/src/submit-tool.ts +20 -59
  40. package/src/transport-budget.ts +32 -0
  41. package/src/worker-broker.ts +37 -57
  42. package/src/workflow-policy.ts +14 -53
  43. package/src/workflow-recovery-policy.ts +95 -0
  44. package/src/workflow-scheduling.ts +105 -0
  45. package/src/workflow-state-machine.ts +105 -497
  46. package/src/workflow-status.ts +384 -0
  47. package/src/workspace-io-worker.mjs +7 -0
  48. package/src/empty-resource-loader.ts +0 -38
  49. package/src/parent-payload-bridge.ts +0 -523
@@ -0,0 +1,191 @@
1
+ import { Type } from "typebox";
2
+ import { Value } from "typebox/value";
3
+ import {
4
+ isValidRelativePath,
5
+ VERIFICATION_LIMITS,
6
+ validateVerificationContract,
7
+ } from "./contracts.ts";
8
+ import type { DesignPlanDiagnostic } from "./design-diagnostics.ts";
9
+
10
+ const text = Type.String({ minLength: 1, maxLength: 8192, pattern: "\\S" });
11
+ const id = Type.String({ pattern: "^[a-zA-Z0-9][a-zA-Z0-9._:-]{0,127}$" });
12
+ const object = <T extends Parameters<typeof Type.Object>[0]>(properties: T) =>
13
+ Type.Object(properties, { additionalProperties: false });
14
+ const managers = Type.Union([
15
+ Type.Literal("bun"),
16
+ Type.Literal("npm"),
17
+ Type.Literal("pnpm"),
18
+ Type.Literal("yarn"),
19
+ ]);
20
+ const packageRunner = {
21
+ kind: Type.Literal("package-script"),
22
+ packageManager: managers,
23
+ script: text,
24
+ command: text,
25
+ };
26
+ const executable = Type.Union([
27
+ object(packageRunner),
28
+ object({ kind: Type.Literal("local-binary"), executable: text }),
29
+ object({
30
+ kind: Type.Literal("npx"),
31
+ executable: text,
32
+ noInstall: Type.Literal(true),
33
+ }),
34
+ ]);
35
+ const classification = Type.Union([
36
+ Type.Literal("expected-red"),
37
+ Type.Literal("expected-green"),
38
+ Type.Literal("expected-refactor"),
39
+ ]);
40
+ const base = {
41
+ id,
42
+ classification,
43
+ expectedFailure: Type.Optional(Type.String({ minLength: 1, maxLength: 512 })),
44
+ executionBindings: Type.Optional(
45
+ Type.Record(Type.String(), Type.Union([Type.String(), Type.Null()])),
46
+ ),
47
+ };
48
+ const args = Type.Array(Type.String(), { maxItems: 128 });
49
+ export const ATOMIC_VERIFICATION_SCHEMAS = {
50
+ vitest: object({
51
+ ...base,
52
+ kind: Type.Literal("vitest"),
53
+ runner: executable,
54
+ testFiles: Type.Array(text, {
55
+ minItems: VERIFICATION_LIMITS.minTestFiles,
56
+ maxItems: VERIFICATION_LIMITS.maxTestFiles,
57
+ uniqueItems: true,
58
+ }),
59
+ args,
60
+ minTests: Type.Integer({ minimum: 1 }),
61
+ }),
62
+ "package-script": object({ ...base, ...packageRunner, args }),
63
+ "static-check": object({
64
+ ...base,
65
+ kind: Type.Literal("static-check"),
66
+ runner: Type.Union([
67
+ executable,
68
+ object({ kind: Type.Literal("node"), script: text }),
69
+ ]),
70
+ args,
71
+ }),
72
+ };
73
+ const atomic = Type.Union(Object.values(ATOMIC_VERIFICATION_SCHEMAS));
74
+ const steps = object({
75
+ kind: Type.Literal("steps"),
76
+ id,
77
+ classification,
78
+ steps: Type.Array(atomic, {
79
+ minItems: VERIFICATION_LIMITS.minSteps,
80
+ maxItems: VERIFICATION_LIMITS.maxSteps,
81
+ }),
82
+ });
83
+ export const VERIFICATION_SCHEMA = Type.Union([atomic, steps]);
84
+ export const CHANGE_CONTRACT_SCHEMA = object({
85
+ goal: text,
86
+ acceptance: Type.Array(
87
+ object({ id, statement: text, verification: VERIFICATION_SCHEMA }),
88
+ { minItems: 1, maxItems: 256 },
89
+ ),
90
+ constraints: Type.Array(object({ id, statement: text }), { maxItems: 256 }),
91
+ policy: object({
92
+ writeRoots: Type.Array(text, {
93
+ minItems: 1,
94
+ maxItems: 256,
95
+ uniqueItems: true,
96
+ }),
97
+ dependencies: Type.Array(text, { maxItems: 256, uniqueItems: true }),
98
+ verificationModes: Type.Array(
99
+ Type.Union([
100
+ Type.Literal("behavior"),
101
+ Type.Literal("mechanical"),
102
+ Type.Literal("refactor"),
103
+ ]),
104
+ { minItems: 1, maxItems: 256, uniqueItems: true },
105
+ ),
106
+ }),
107
+ });
108
+ function record(value: unknown): value is Record<string, unknown> {
109
+ return !!value && typeof value === "object" && !Array.isArray(value);
110
+ }
111
+
112
+ const schemaFields = new Set([
113
+ "goal",
114
+ "acceptance",
115
+ "id",
116
+ "statement",
117
+ "verification",
118
+ "constraints",
119
+ "policy",
120
+ "writeRoots",
121
+ "dependencies",
122
+ "verificationModes",
123
+ "classification",
124
+ "expectedFailure",
125
+ "executionBindings",
126
+ "kind",
127
+ "runner",
128
+ "packageManager",
129
+ "script",
130
+ "command",
131
+ "executable",
132
+ "noInstall",
133
+ "testFiles",
134
+ "args",
135
+ "minTests",
136
+ "steps",
137
+ ]);
138
+ function diagnosticField(pointer: string): string {
139
+ const fields = ["contract"];
140
+ for (const part of pointer.split("/").slice(1)) {
141
+ if (!schemaFields.has(part) && !/^(0|[1-9][0-9]{0,5})$/u.test(part)) break;
142
+ fields.push(part);
143
+ // Binding keys are author data, even when they happen to look like schema fields.
144
+ if (part === "executionBindings") break;
145
+ }
146
+ return fields.join(".");
147
+ }
148
+
149
+ /** Shared shape, bounded field-only diagnostics; never return submitted values or parser messages. */
150
+ export function changeContractDiagnostics(
151
+ value: unknown,
152
+ ): DesignPlanDiagnostic[] {
153
+ const diagnostics: DesignPlanDiagnostic[] = Value.Errors(
154
+ CHANGE_CONTRACT_SCHEMA,
155
+ value,
156
+ )
157
+ .slice(0, 32)
158
+ .map((error) => ({
159
+ code: "change-contract-field-invalid",
160
+ field: diagnosticField(error.instancePath),
161
+ category: error.keyword,
162
+ }));
163
+ if (!record(value)) return diagnostics;
164
+ if (Array.isArray(value.acceptance))
165
+ value.acceptance.slice(0, 256).forEach((item, index) => {
166
+ if (!record(item)) return;
167
+ const verification = item.verification;
168
+ if (!validateVerificationContract(verification).ok) {
169
+ const field = `contract.acceptance.${index}.verification`;
170
+ if (
171
+ record(verification) &&
172
+ verification.classification === "expected-red" &&
173
+ typeof verification.expectedFailure !== "string"
174
+ )
175
+ diagnostics.push({
176
+ code: "change-contract-field-invalid",
177
+ field: `${field}.expectedFailure`,
178
+ });
179
+ else diagnostics.push({ code: "change-contract-field-invalid", field });
180
+ }
181
+ });
182
+ if (record(value.policy) && Array.isArray(value.policy.writeRoots))
183
+ value.policy.writeRoots.slice(0, 256).forEach((root, index) => {
184
+ if (root !== "." && !isValidRelativePath(root))
185
+ diagnostics.push({
186
+ code: "change-contract-field-invalid",
187
+ field: `contract.policy.writeRoots.${index}`,
188
+ });
189
+ });
190
+ return diagnostics.slice(0, 32);
191
+ }
@@ -1,3 +1,4 @@
1
+ import { changeContractDiagnostics } from "./change-contract-schema.ts";
1
2
  import {
2
3
  type ImplementTaskBoundary,
3
4
  isValidRelativePath,
@@ -5,6 +6,7 @@ import {
5
6
  validateVerificationContract,
6
7
  verificationInputPaths,
7
8
  } from "./contracts.ts";
9
+ import { DesignPlanValidationError } from "./design-diagnostics.ts";
8
10
  import { canonicalJson } from "./run-state.ts";
9
11
 
10
12
  export interface ChangeContract {
@@ -38,6 +40,9 @@ function text(value: unknown): value is string {
38
40
  const identifier = /^[a-zA-Z0-9][a-zA-Z0-9._:-]{0,127}$/u;
39
41
 
40
42
  export function normalizeChangeContract(value: unknown): ChangeContract {
43
+ const diagnostics = changeContractDiagnostics(value);
44
+ if (diagnostics.length)
45
+ throw new DesignPlanValidationError("change-contract-invalid", diagnostics);
41
46
  if (
42
47
  !record(value) ||
43
48
  !keys(value, ["goal", "acceptance", "constraints", "policy"]) ||