@abelxiaoxing/cadence 1.4.0 → 1.5.0

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 (66) hide show
  1. package/README.md +130 -8
  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/config/plan-draft.quick.example.json +78 -0
  8. package/package.json +10 -4
  9. package/prompts/abel-design.md +101 -44
  10. package/prompts/abel-implement.md +9 -0
  11. package/src/activity-contracts.ts +82 -0
  12. package/src/candidate-artifact.ts +143 -0
  13. package/src/candidate-patch.ts +31 -11
  14. package/src/candidate-workspace.ts +74 -0
  15. package/src/change-contract-schema.ts +191 -0
  16. package/src/change-contract.ts +5 -0
  17. package/src/change-verification.ts +920 -0
  18. package/src/child-budget.ts +58 -0
  19. package/src/child-model.ts +142 -0
  20. package/src/child-session.ts +289 -326
  21. package/src/contracts.ts +200 -76
  22. package/src/delivery-compiler.ts +105 -120
  23. package/src/delivery-revision.ts +42 -0
  24. package/src/design-control.ts +113 -4
  25. package/src/design-diagnostics.ts +150 -0
  26. package/src/durable-contracts.ts +213 -0
  27. package/src/durable-workflow.ts +148 -3570
  28. package/src/evidence-draft.ts +122 -0
  29. package/src/execution-profile.ts +38 -0
  30. package/src/implement-graph.ts +3 -0
  31. package/src/implement-plan.ts +70 -0
  32. package/src/index.ts +59 -522
  33. package/src/isolation-backend.ts +62 -40
  34. package/src/model-source.ts +22 -0
  35. package/src/operator-cli-entry.mjs +24 -0
  36. package/src/operator-cli.mjs +1421 -0
  37. package/src/operator-tools.ts +249 -0
  38. package/src/package-candidate.ts +227 -0
  39. package/src/package-verification.ts +86 -8
  40. package/src/package-workflow.ts +291 -0
  41. package/src/packet-runtime.ts +27 -48
  42. package/src/parent-provider.ts +86 -198
  43. package/src/phase-execution.ts +2248 -0
  44. package/src/pi-adapter.ts +19 -0
  45. package/src/plan-draft-summary.ts +149 -0
  46. package/src/plan-draft.ts +493 -0
  47. package/src/single-task-draft.ts +142 -0
  48. package/src/subagent-activity.ts +32 -66
  49. package/src/submit-tool.ts +20 -59
  50. package/src/transport-budget.ts +52 -0
  51. package/src/verification-capability.ts +5 -3
  52. package/src/verification-diagnostics.ts +76 -0
  53. package/src/verification-environment-io.ts +280 -0
  54. package/src/verification-environment.ts +56 -154
  55. package/src/verification-scan.ts +64 -0
  56. package/src/worker-broker.ts +39 -57
  57. package/src/workflow-policy.ts +14 -53
  58. package/src/workflow-recovery-policy.ts +95 -0
  59. package/src/workflow-scheduling.ts +105 -0
  60. package/src/workflow-state-machine.ts +105 -497
  61. package/src/workflow-status.ts +384 -0
  62. package/src/workspace-io-entry.mjs +19 -1
  63. package/src/workspace-io-worker.mjs +275 -50
  64. package/src/workspace-io.ts +6 -1
  65. package/src/empty-resource-loader.ts +0 -38
  66. package/src/parent-payload-bridge.ts +0 -523
@@ -0,0 +1,150 @@
1
+ import { canonicalJson, compareCanonicalStrings } from "./canonical.ts";
2
+ import { isValidRelativePath } from "./contracts.ts";
3
+
4
+ export type SafeDesignDiagnostic = Record<string, string | boolean | string[]>;
5
+ const CODE = /^[a-z0-9](?:[a-z0-9._:-]{0,126}[a-z0-9])?$/iu;
6
+ const IDENTITIES = new Set([
7
+ "code",
8
+ "taskId",
9
+ "phase",
10
+ "field",
11
+ "category",
12
+ "owner",
13
+ "verificationId",
14
+ "outputId",
15
+ "dependencyTaskId",
16
+ "producerTaskId",
17
+ "producerPhase",
18
+ "command",
19
+ "reason",
20
+ "systemCode",
21
+ "exitCode",
22
+ ]);
23
+ const HINTS = new Map<string, string>(
24
+ Object.entries({
25
+ "change-contract-acceptance-missing":
26
+ "Read the current approved ChangeContract from Design status and include each accepted verification obligation in the plan's phase, affected, full-suite or post-apply verification. Command, arguments, inputs and classification must match; copying only its ID is insufficient. Keep accepted IDs, statements and scope unchanged.",
27
+ "script-command-mismatch":
28
+ "command must equal the literal package.json scripts[script] value, not an invocation such as npm run test. In PlanDraft, omit command to bind it from the manifest. Explicit commands, including approved Gate acceptance verifiers, remain exact and must be corrected rather than silently replaced.",
29
+ "design-traceability-input-unavailable":
30
+ "Write tasks.md with author task checkboxes and exact owned Scenario references, plus the referenced spec artifacts, before compilation and finalization.",
31
+ "traceability-managed-region-invalid":
32
+ "Repair the paired ABEL:VERIFICATION-BINDINGS markers in tasks.md without removing author evidence, then compile again. Code replaces only one complete managed region.",
33
+ "traceability-managed-region-stale":
34
+ "Compile the current draft again to regenerate phase verification bindings; do not copy verifier identities by hand.",
35
+ "traceability-task-unmapped":
36
+ "Put each planned task ID in backticks on its author checkbox outside the generated bindings region.",
37
+ "traceability-verification-unmapped":
38
+ "Compile after writing tasks.md so code installs phase verification bindings while preserving the author evidence.",
39
+ "traceability-reference-empty":
40
+ "Add exact backticked specs/<capability>/spec.md#Requirement title/Scenario title references under the owning author tasks. Code does not infer Scenario ownership.",
41
+ "change-contract-field-invalid":
42
+ "Correct the indicated ChangeContract field using the tool schema. Keep accepted scope and evidence unchanged.",
43
+ "design-control-field-invalid":
44
+ "Use the exact operation envelope and returned runId; inspect the indicated field in the tool schema.",
45
+ "verification-reference-unavailable":
46
+ "Use a declared verificationDefinitions name or an explicit verification contract.",
47
+ "verification-reference-invalid":
48
+ "A verification reference contains only use and optional Red expectedFailure. Put executable fields in its definition.",
49
+ "verification-definition-invalid":
50
+ "Define one existing atomic verifier without id, classification, executionBindings or references.",
51
+ "current-task-outside-write-set":
52
+ "Omit disposition to derive the test owner from task writes. Keep path and evidence; do not widen writes to satisfy this label.",
53
+ "related-test-owner-ambiguous":
54
+ "Several other tasks edit this test. Choose the intended regression-task owner explicitly, or resolve overlapping task ownership.",
55
+ "verification-input-binding-mismatch":
56
+ "Omit verificationInputs to derive exact bindings from the verification contract and declared outputs. Keep supporting source files in read, not in verificationInputs.",
57
+ "workspace-input-has-producer":
58
+ "Omit verificationInputs or bind this path to its declared outputId instead of workspace.",
59
+ "multiple-output-producers":
60
+ "Declare one producer per output path before deriving input bindings. Do not choose a producer by list order.",
61
+ "producer-not-dependency":
62
+ "The producing task must be an explicit dependency of this task. Input inference does not add dependency authority.",
63
+ "producer-phase-after-consumer":
64
+ "This verification needs an output from a later phase. Correct the producer or phase order; input inference cannot make that output available earlier.",
65
+ "verification-input-not-declared":
66
+ "The verification contract requires a path outside this phase's read/write declarations. Correct the contract or explicitly declare the approved input path.",
67
+ "workspace-input-unavailable":
68
+ "The required workspace input is missing or not a safe regular file. Correct its path or declare its planned producer.",
69
+ }),
70
+ );
71
+ function safePath(value: unknown): value is string {
72
+ return isValidRelativePath(value) && !/[\p{Cc}\p{Cf}]/u.test(value);
73
+ }
74
+
75
+ /** One bounded projection for tool feedback and TUI; guidance is code-owned. */
76
+ export function projectDesignDiagnostic(
77
+ value: unknown,
78
+ ): SafeDesignDiagnostic | undefined {
79
+ if (typeof value === "string") value = { code: value.split(":", 1)[0] };
80
+ if (!value || typeof value !== "object" || Array.isArray(value))
81
+ return undefined;
82
+ const record = value as Record<string, unknown>;
83
+ if (typeof record.code !== "string" || !CODE.test(record.code))
84
+ return undefined;
85
+ const result: SafeDesignDiagnostic = {};
86
+ for (const [key, entry] of Object.entries(record)) {
87
+ if (IDENTITIES.has(key) && typeof entry === "string" && CODE.test(entry))
88
+ result[key] = entry;
89
+ else if (
90
+ (key === "retryable" || key === "pathsTruncated") &&
91
+ typeof entry === "boolean"
92
+ )
93
+ result[key] =
94
+ key === "pathsTruncated"
95
+ ? result.pathsTruncated === true || entry
96
+ : entry;
97
+ else if (key === "path" && safePath(entry)) result.path = entry;
98
+ else if (
99
+ (key === "expectedPaths" || key === "actualPaths") &&
100
+ Array.isArray(entry)
101
+ ) {
102
+ const paths = [...new Set(entry.filter(safePath))].sort(
103
+ compareCanonicalStrings,
104
+ );
105
+ result[key] = paths.slice(0, 32);
106
+ if (entry.some((path) => !safePath(path)) || paths.length > 32)
107
+ result.pathsTruncated = true;
108
+ }
109
+ }
110
+ const hint = HINTS.get(String(result.category)) ?? HINTS.get(record.code);
111
+ if (hint) result.hint = hint;
112
+ return result;
113
+ }
114
+
115
+ export interface DesignPlanDiagnostic {
116
+ code: string;
117
+ taskId?: string;
118
+ phase?: string;
119
+ field?: string;
120
+ category?: string;
121
+ owner?: string;
122
+ verificationId?: string;
123
+ outputId?: string;
124
+ dependencyTaskId?: string;
125
+ producerTaskId?: string;
126
+ producerPhase?: string;
127
+ path?: string;
128
+ expectedPaths?: string[];
129
+ actualPaths?: string[];
130
+ }
131
+
132
+ export class DesignPlanValidationError extends Error {
133
+ readonly diagnostics: readonly DesignPlanDiagnostic[];
134
+
135
+ constructor(message: string, diagnostics: readonly DesignPlanDiagnostic[]) {
136
+ const normalized = [
137
+ ...new Map(
138
+ diagnostics
139
+ .map((diagnostic) => structuredClone(diagnostic))
140
+ .sort((left, right) =>
141
+ compareCanonicalStrings(canonicalJson(left), canonicalJson(right)),
142
+ )
143
+ .map((diagnostic) => [canonicalJson(diagnostic), diagnostic]),
144
+ ).values(),
145
+ ];
146
+ super(message);
147
+ this.name = "DesignPlanValidationError";
148
+ this.diagnostics = Object.freeze(normalized);
149
+ }
150
+ }
@@ -0,0 +1,213 @@
1
+ import type { ArtifactStore } from "./artifact-store.ts";
2
+ import type { StructuredVerificationContract } from "./contracts.ts";
3
+ import type { ImplementPlan, PlanTaskDraft } from "./delivery-compiler.ts";
4
+ import type { RoutePolicy, WorkerRoutePolicy } from "./route-policy.ts";
5
+
6
+ import type { ResolvedStateRoot } from "./state-root.ts";
7
+ import type { CandidateArtifactSubmission } from "./submit-tool.ts";
8
+ import type { TaskLedger } from "./task-ledger.ts";
9
+
10
+ import type {
11
+ DurableCandidateProposal,
12
+ DurableVerificationScope,
13
+ RedArtifactCorrection,
14
+ WorkflowAttemptOutcome,
15
+ WorkflowContextRequest,
16
+ WorkflowDeliverySource,
17
+ WorkflowRecoveryFeedback,
18
+ } from "./workflow-policy.ts";
19
+
20
+ import type { WorkspaceStore } from "./workspace-store.ts";
21
+
22
+ export interface DurableResourceInput {
23
+ runId: string;
24
+ deliveryRevision: number;
25
+ plan?: ImplementPlan;
26
+ baselineRevisionId?: string;
27
+ currentWorkspaceRevisionId?: string;
28
+ }
29
+
30
+ export type DurablePhaseVerificationResult =
31
+ | {
32
+ ok: true;
33
+ exitCode: number;
34
+ classification: "expected-red" | "expected-green" | "expected-refactor";
35
+ diagnostic: { kind: "assertion" | "compiler"; id: string };
36
+ }
37
+ | {
38
+ ok: false;
39
+ kind: "paused" | "retryable" | "approval-needed";
40
+ code: string;
41
+ };
42
+
43
+ export type DurableChangeVerificationResult =
44
+ | {
45
+ ok: true;
46
+ exitCode: 0;
47
+ classification: string;
48
+ failureIdentities?: string[];
49
+ attributionReliable?: boolean;
50
+ }
51
+ | {
52
+ ok: false;
53
+ kind:
54
+ | "artifact"
55
+ | "environment"
56
+ | "verification"
57
+ | "verification-adapter"
58
+ | "approval-boundary"
59
+ | "cancelled";
60
+ code: string;
61
+ failureIdentities?: string[];
62
+ attributionReliable?: boolean;
63
+ };
64
+
65
+ export interface DurableVerificationObservation {
66
+ status: "passed" | "failed";
67
+ verificationId: string;
68
+ failureIdentities: string[];
69
+ code?: string;
70
+ attributionReliable?: boolean;
71
+ }
72
+
73
+ export interface DurableVerificationBaseline {
74
+ revisionId: string;
75
+ targetContracts: Array<{
76
+ taskId: string;
77
+ verificationId: string;
78
+ expectedFailure: string;
79
+ }>;
80
+ affected: Array<{
81
+ taskId: string;
82
+ observation: DurableVerificationObservation;
83
+ }>;
84
+ fullSuite: DurableVerificationObservation;
85
+ }
86
+
87
+ export type DurableObservedVerification =
88
+ | { ok: true; observation: DurableVerificationObservation }
89
+ | {
90
+ ok: false;
91
+ outcome:
92
+ | { kind: "paused"; code: string }
93
+ | { kind: "approval-needed"; code: string }
94
+ | { kind: "operation-cancelled"; code: "cancelled" };
95
+ };
96
+
97
+ export type DurableBaselineResult =
98
+ | { ok: true; baseline: DurableVerificationBaseline }
99
+ | Extract<DurableObservedVerification, { ok: false }>;
100
+
101
+ export type DurableAffectedResult =
102
+ | { kind: "verified"; attribution: "none" | "pre-existing" }
103
+ | {
104
+ kind: "repairable";
105
+ attribution: "introduced";
106
+ failureIdentities: string[];
107
+ }
108
+ | Extract<DurableObservedVerification, { ok: false }>["outcome"];
109
+
110
+ export interface DurableWorkflowEngineOptions {
111
+ consumerRoot: string;
112
+ stateRoot: ResolvedStateRoot;
113
+ deliverySource: WorkflowDeliverySource;
114
+ routePolicy: RoutePolicy;
115
+ proposeCandidate(input: {
116
+ runId: string;
117
+ operationId: string;
118
+ deliveryRevision: number;
119
+ taskId: string;
120
+ phase: "red" | "green" | "refactor";
121
+ task: PlanTaskDraft;
122
+ workspaceRoot: string;
123
+ ledgerProjection: unknown;
124
+ candidateArtifact: CandidateArtifactSubmission;
125
+ route: WorkerRoutePolicy;
126
+ repair?: {
127
+ attempt: number;
128
+ attribution: "introduced";
129
+ failureIdentities: string[];
130
+ };
131
+ artifactCorrection?: RedArtifactCorrection;
132
+ contextRequest?: WorkflowContextRequest;
133
+ contextReadPaths?: string[];
134
+ recoveryFeedback?: WorkflowRecoveryFeedback;
135
+ signal: AbortSignal;
136
+ onRequestStart?(): void;
137
+ onHeaders(): void;
138
+ onProgress(): void;
139
+ }): Promise<DurableCandidateProposal>;
140
+ verifyPhase(input: {
141
+ executionWritePaths?: readonly string[];
142
+ runId: string;
143
+ deliveryRevision: number;
144
+ taskId: string;
145
+ phase: "red" | "green" | "refactor";
146
+ root: string;
147
+ verification: StructuredVerificationContract;
148
+ signal: AbortSignal;
149
+ }): Promise<DurablePhaseVerificationResult>;
150
+ verifyChange(input: {
151
+ runId: string;
152
+ deliveryRevision: number;
153
+ root: string;
154
+ plan: ImplementPlan;
155
+ scope?: DurableVerificationScope;
156
+ verification?: StructuredVerificationContract;
157
+ taskId?: string;
158
+ signal: AbortSignal;
159
+ }): Promise<DurableChangeVerificationResult>;
160
+ now?: () => number;
161
+ leaseTtlMs?: number;
162
+ workHardLimit?: number;
163
+ verificationPolicy?: string;
164
+ verificationEnvironment?(
165
+ plan: ImplementPlan,
166
+ signal: AbortSignal,
167
+ ): Promise<string>;
168
+ }
169
+
170
+ export interface DurableExecutionResources {
171
+ runId: string;
172
+ root: string;
173
+ plan: ImplementPlan;
174
+ deliveryRevision: number;
175
+ artifacts: ArtifactStore;
176
+ workspaces: WorkspaceStore;
177
+ ledgers: Map<number, TaskLedger>;
178
+ baselineRevisionId: string;
179
+ currentRevisionId: string;
180
+ mergeTail: Promise<void>;
181
+ verificationFact?: object;
182
+ baselinePromises: Map<number, Promise<DurableBaselineResult>>;
183
+ environmentIdentity?: string;
184
+ }
185
+
186
+ export interface DurablePhaseFact {
187
+ kind: "phase-verified" | "repair-verified";
188
+ phase: "red" | "green" | "refactor";
189
+ isolatedRevisionId: string;
190
+ outputFacts: Array<
191
+ | { path: string; kind: "absent" }
192
+ | { path: string; kind: "file"; hash: string; bytes: number }
193
+ >;
194
+ }
195
+
196
+ export interface DurableCandidateCommit {
197
+ artifactHash: string;
198
+ isolatedRevisionId: string;
199
+ exitCode: number;
200
+ classification: "expected-red" | "expected-green" | "expected-refactor";
201
+ diagnostic: { kind: "assertion" | "compiler"; id: string };
202
+ outputFacts: DurablePhaseFact["outputFacts"];
203
+ routeId: string;
204
+ routeFingerprint: string;
205
+ }
206
+
207
+ export type DurableRepairResult =
208
+ | { kind: "repair-committed"; commit: DurableCandidateCommit }
209
+ | Exclude<WorkflowAttemptOutcome, { kind: "phase-committed" }>;
210
+ export type PhaseResources = Omit<
211
+ DurableExecutionResources,
212
+ "verificationFact"
213
+ >;