@abelxiaoxing/cadence 1.2.1 → 1.2.3
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 +7 -1
- package/agents/diagnosis-worker.md +6 -2
- package/agents/implementation-worker.md +9 -2
- package/config/routes.example.json +0 -1
- package/package.json +1 -1
- package/prompts/abel-design.md +15 -4
- package/skills/abel-workflow/SKILL.md +5 -3
- package/src/apply-transaction.ts +1 -5
- package/src/child-session.ts +37 -46
- package/src/contracts.ts +278 -32
- package/src/control-contracts.ts +62 -0
- package/src/delivery-compiler.ts +239 -124
- package/src/design-control.ts +72 -27
- package/src/design-journal.ts +2 -2
- package/src/file-snapshot.ts +1 -1
- package/src/index.ts +295 -58
- package/src/packet-runtime.ts +79 -21
- package/src/parent-provider.ts +63 -30
- package/src/route-policy.ts +58 -14
- package/src/run-store.ts +115 -23
- package/src/subagent-activity.ts +82 -6
- package/src/submit-tool.ts +431 -39
- package/src/task-ledger.ts +1 -2
- package/src/worker-broker.ts +72 -13
- package/src/workflow-engine.ts +782 -54
- package/src/workspace-store.ts +2 -10
package/src/design-control.ts
CHANGED
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
compileImplementPlan,
|
|
16
16
|
compileReadyReceipt,
|
|
17
17
|
type DeliveryArtifactBinding,
|
|
18
|
+
DesignPlanValidationError,
|
|
18
19
|
type GateApprovalProof,
|
|
19
20
|
parseGateAReceipt,
|
|
20
21
|
parseImplementPlan,
|
|
@@ -88,6 +89,10 @@ export type DesignControlRequest =
|
|
|
88
89
|
operationId: string;
|
|
89
90
|
gate: "gate-b";
|
|
90
91
|
}
|
|
92
|
+
| {
|
|
93
|
+
operation: "validate-plan-draft";
|
|
94
|
+
runId: string;
|
|
95
|
+
}
|
|
91
96
|
| {
|
|
92
97
|
operation: "compile-plan";
|
|
93
98
|
runId: string;
|
|
@@ -198,7 +203,10 @@ export function validateDesignControlRequest(
|
|
|
198
203
|
? { ok: true, value: structuredClone(value) as DesignControlRequest }
|
|
199
204
|
: { ok: false, code: "invalid-design-control-request" };
|
|
200
205
|
}
|
|
201
|
-
if (
|
|
206
|
+
if (
|
|
207
|
+
value.operation === "status" ||
|
|
208
|
+
value.operation === "validate-plan-draft"
|
|
209
|
+
) {
|
|
202
210
|
return exactKeys(value, ["operation", "runId"]) &&
|
|
203
211
|
typeof value.runId === "string" &&
|
|
204
212
|
IDENTIFIER.test(value.runId)
|
|
@@ -508,6 +516,8 @@ export class DesignController {
|
|
|
508
516
|
return this.#journal.recordDecision(request);
|
|
509
517
|
case "approve-gate":
|
|
510
518
|
return this.#journal.approveGate(request);
|
|
519
|
+
case "validate-plan-draft":
|
|
520
|
+
return this.#validatePlanDraft(request);
|
|
511
521
|
case "compile-plan":
|
|
512
522
|
return this.#compilePlan(request);
|
|
513
523
|
case "finalize-delivery":
|
|
@@ -539,7 +549,7 @@ export class DesignController {
|
|
|
539
549
|
const canApproveGate =
|
|
540
550
|
!design.gates.gateA.current ||
|
|
541
551
|
(planReadyForGateB && !design.gates.gateB.current);
|
|
542
|
-
const
|
|
552
|
+
const legalOperations = terminal
|
|
543
553
|
? ["status"]
|
|
544
554
|
: [
|
|
545
555
|
"status",
|
|
@@ -549,7 +559,12 @@ export class DesignController {
|
|
|
549
559
|
? ["bind-change"]
|
|
550
560
|
: []),
|
|
551
561
|
...(design.gates.gateA.current && design.change
|
|
552
|
-
? [
|
|
562
|
+
? [
|
|
563
|
+
"write-artifact",
|
|
564
|
+
"delete-artifact",
|
|
565
|
+
"validate-plan-draft",
|
|
566
|
+
"compile-plan",
|
|
567
|
+
]
|
|
553
568
|
: []),
|
|
554
569
|
...(design.change &&
|
|
555
570
|
design.plan &&
|
|
@@ -557,7 +572,6 @@ export class DesignController {
|
|
|
557
572
|
design.gates.gateB.current
|
|
558
573
|
? ["finalize-delivery"]
|
|
559
574
|
: []),
|
|
560
|
-
"finish",
|
|
561
575
|
];
|
|
562
576
|
return {
|
|
563
577
|
runId: run.runId,
|
|
@@ -566,7 +580,8 @@ export class DesignController {
|
|
|
566
580
|
state: run.state,
|
|
567
581
|
completed: run.state === "completed",
|
|
568
582
|
...(run.pauseCode ? { pause: { code: run.pauseCode } } : {}),
|
|
569
|
-
|
|
583
|
+
legalOperations,
|
|
584
|
+
packetActions: terminal ? [] : ["finish"],
|
|
570
585
|
design,
|
|
571
586
|
};
|
|
572
587
|
}
|
|
@@ -578,7 +593,7 @@ export class DesignController {
|
|
|
578
593
|
...(fromRequirement
|
|
579
594
|
? {
|
|
580
595
|
provisionalKey: transientHash(
|
|
581
|
-
"abel-design-requirement
|
|
596
|
+
"abel-design-requirement",
|
|
582
597
|
request.requirement,
|
|
583
598
|
),
|
|
584
599
|
}
|
|
@@ -772,6 +787,51 @@ export class DesignController {
|
|
|
772
787
|
}
|
|
773
788
|
}
|
|
774
789
|
|
|
790
|
+
#readCompiledDraft(runId: string) {
|
|
791
|
+
const status = this.#journal.status(runId);
|
|
792
|
+
if (!status.change) throw new Error("design-change-required");
|
|
793
|
+
if (!status.gates.gateA.current) throw new Error("design-gate-a-required");
|
|
794
|
+
const draftPath = safeRelative(status.change, "plan-draft.json");
|
|
795
|
+
const draftBytes = readSafeFile(this.consumerRoot, draftPath);
|
|
796
|
+
let draft: unknown;
|
|
797
|
+
try {
|
|
798
|
+
draft = JSON.parse(draftBytes.toString("utf8"));
|
|
799
|
+
} catch {
|
|
800
|
+
throw new DesignPlanValidationError("design-plan-draft-invalid", [
|
|
801
|
+
{ code: "design-plan-draft-invalid", field: "plan-draft.json" },
|
|
802
|
+
]);
|
|
803
|
+
}
|
|
804
|
+
const compiled = compileImplementPlan(draft, {
|
|
805
|
+
consumerRoot: this.consumerRoot,
|
|
806
|
+
});
|
|
807
|
+
if (compiled.plan.changeId !== status.change) {
|
|
808
|
+
throw new DesignPlanValidationError("design-plan-change-mismatch", [
|
|
809
|
+
{ code: "design-plan-change-mismatch", field: "changeId" },
|
|
810
|
+
]);
|
|
811
|
+
}
|
|
812
|
+
return { status, compiled };
|
|
813
|
+
}
|
|
814
|
+
|
|
815
|
+
#validatePlanDraft(
|
|
816
|
+
request: Extract<
|
|
817
|
+
DesignControlRequest,
|
|
818
|
+
{ operation: "validate-plan-draft" }
|
|
819
|
+
>,
|
|
820
|
+
) {
|
|
821
|
+
const { compiled } = this.#readCompiledDraft(request.runId);
|
|
822
|
+
return {
|
|
823
|
+
operation: request.operation,
|
|
824
|
+
runId: request.runId,
|
|
825
|
+
valid: true,
|
|
826
|
+
plan: {
|
|
827
|
+
taskCount: compiled.plan.tasks.length,
|
|
828
|
+
outputCount: compiled.plan.outputs.length,
|
|
829
|
+
rawSha256: compiled.rawSha256,
|
|
830
|
+
canonicalHash: compiled.planHash,
|
|
831
|
+
},
|
|
832
|
+
};
|
|
833
|
+
}
|
|
834
|
+
|
|
775
835
|
#compilePlan(
|
|
776
836
|
request: Extract<DesignControlRequest, { operation: "compile-plan" }>,
|
|
777
837
|
) {
|
|
@@ -787,32 +847,17 @@ export class DesignController {
|
|
|
787
847
|
});
|
|
788
848
|
try {
|
|
789
849
|
this.#journal.assertNoPendingArtifactOperations(request.runId);
|
|
790
|
-
const status = this.#
|
|
791
|
-
|
|
792
|
-
if (!
|
|
793
|
-
|
|
794
|
-
const
|
|
795
|
-
const gateAPath = safeRelative(status.change, "gate-a.yaml");
|
|
850
|
+
const { status, compiled } = this.#readCompiledDraft(request.runId);
|
|
851
|
+
const change = status.change;
|
|
852
|
+
if (!change) throw new Error("design-change-required");
|
|
853
|
+
const readyPath = safeRelative(change, "ready.yaml");
|
|
854
|
+
const gateAPath = safeRelative(change, "gate-a.yaml");
|
|
796
855
|
removeSafeFile(this.consumerRoot, readyPath);
|
|
797
856
|
removeSafeFile(this.consumerRoot, gateAPath);
|
|
798
|
-
const draftPath = safeRelative(status.change, "plan-draft.json");
|
|
799
|
-
const draftBytes = readSafeFile(this.consumerRoot, draftPath);
|
|
800
|
-
let draft: unknown;
|
|
801
|
-
try {
|
|
802
|
-
draft = JSON.parse(draftBytes.toString("utf8"));
|
|
803
|
-
} catch {
|
|
804
|
-
throw new Error("design-plan-draft-invalid");
|
|
805
|
-
}
|
|
806
|
-
const compiled = compileImplementPlan(draft as never, {
|
|
807
|
-
consumerRoot: this.consumerRoot,
|
|
808
|
-
});
|
|
809
|
-
if (compiled.plan.changeId !== status.change) {
|
|
810
|
-
throw new Error("design-plan-change-mismatch");
|
|
811
|
-
}
|
|
812
857
|
this.#journal.assertFinalizationLease(lease);
|
|
813
858
|
atomicWrite(
|
|
814
859
|
this.consumerRoot,
|
|
815
|
-
safeRelative(
|
|
860
|
+
safeRelative(change, "implement-plan.json"),
|
|
816
861
|
compiled.bytes,
|
|
817
862
|
);
|
|
818
863
|
return this.#journal.recordCompiledPlan({
|
package/src/design-journal.ts
CHANGED
|
@@ -899,7 +899,7 @@ export class DesignJournal {
|
|
|
899
899
|
}): Record<string, unknown> {
|
|
900
900
|
requireIdentifier(input.decisionId, "design-decision-id");
|
|
901
901
|
const decisionContractHash = contractHash(
|
|
902
|
-
"abel-design-decision
|
|
902
|
+
"abel-design-decision",
|
|
903
903
|
input.contract,
|
|
904
904
|
);
|
|
905
905
|
if (input.category !== "behavior" && input.category !== "technical") {
|
|
@@ -1024,7 +1024,7 @@ export class DesignJournal {
|
|
|
1024
1024
|
}
|
|
1025
1025
|
const gateAContractHash =
|
|
1026
1026
|
input.gate === "gate-a"
|
|
1027
|
-
? contractHash("abel-design-gate-a
|
|
1027
|
+
? contractHash("abel-design-gate-a", input.contract)
|
|
1028
1028
|
: undefined;
|
|
1029
1029
|
return this.#transaction(() => {
|
|
1030
1030
|
this.#run(input.runId, true);
|
package/src/file-snapshot.ts
CHANGED
|
@@ -56,7 +56,7 @@ function updateManifest(
|
|
|
56
56
|
|
|
57
57
|
function recursiveDirectoryManifest(abs: string): string {
|
|
58
58
|
const hash = createHash("sha256");
|
|
59
|
-
updateManifest(hash, "cadence-directory-manifest
|
|
59
|
+
updateManifest(hash, "cadence-directory-manifest");
|
|
60
60
|
const visit = (directory: string, prefix: string): void => {
|
|
61
61
|
const names = readdirSync(directory).sort();
|
|
62
62
|
for (const name of names) {
|