intentdna 1.9.0 → 1.9.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.
Files changed (131) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/README.md +227 -87
  4. package/dist/cli/commands/run-lifecycle.d.ts +61 -11
  5. package/dist/cli/commands/run-lifecycle.js +184 -50
  6. package/dist/cli/commands/run-observer.d.ts +15 -0
  7. package/dist/cli/commands/run-observer.js +210 -0
  8. package/dist/cli/commands/run.d.ts +16 -20
  9. package/dist/cli/commands/run.js +461 -659
  10. package/dist/cli/commands/sync.js +16 -12
  11. package/dist/cli/index.js +14 -5
  12. package/dist/compiler/compile.d.ts +1 -0
  13. package/dist/compiler/compile.js +1 -1
  14. package/dist/compiler/controller.d.ts +16 -0
  15. package/dist/compiler/controller.js +693 -0
  16. package/dist/compiler/input-resolver.d.ts +2 -0
  17. package/dist/compiler/input-resolver.js +22 -6
  18. package/dist/hooks/cli.d.ts +45 -0
  19. package/dist/hooks/cli.js +263 -31
  20. package/dist/hooks/host-event.d.ts +57 -0
  21. package/dist/hooks/host-event.js +187 -0
  22. package/dist/hooks/index.d.ts +1 -0
  23. package/dist/hooks/index.js +1 -0
  24. package/dist/hooks/protocol.d.ts +7 -0
  25. package/dist/hooks/schema.d.ts +1 -0
  26. package/dist/hooks/schema.js +89 -1
  27. package/dist/hooks/state.d.ts +23 -1
  28. package/dist/hooks/state.js +9 -0
  29. package/dist/index.d.ts +1 -0
  30. package/dist/index.js +1 -0
  31. package/dist/mcp/index.js +2 -0
  32. package/dist/mcp/tools-run.d.ts +4 -0
  33. package/dist/mcp/tools-run.js +419 -0
  34. package/dist/mcp/tools-state.d.ts +1 -1
  35. package/dist/mcp/tools-state.js +13 -241
  36. package/dist/runtime/artifact-store.d.ts +146 -0
  37. package/dist/runtime/artifact-store.js +1436 -0
  38. package/dist/runtime/canonical-attempt-outcome.d.ts +12 -0
  39. package/dist/runtime/canonical-attempt-outcome.js +195 -0
  40. package/dist/runtime/canonical-json.d.ts +10 -0
  41. package/dist/runtime/canonical-json.js +105 -0
  42. package/dist/runtime/canonical-run-application.d.ts +93 -0
  43. package/dist/runtime/canonical-run-application.js +229 -0
  44. package/dist/runtime/canonical-run-service.d.ts +454 -0
  45. package/dist/runtime/canonical-run-service.js +4760 -0
  46. package/dist/runtime/canonical-runtime-composition.d.ts +22 -0
  47. package/dist/runtime/canonical-runtime-composition.js +34 -0
  48. package/dist/runtime/canonical-runtime-projection.d.ts +3 -0
  49. package/dist/runtime/canonical-runtime-projection.js +4 -0
  50. package/dist/runtime/canonical-target-compiler.d.ts +46 -0
  51. package/dist/runtime/canonical-target-compiler.js +514 -0
  52. package/dist/runtime/claude-agent-identity.d.ts +2 -0
  53. package/dist/runtime/claude-agent-identity.js +21 -0
  54. package/dist/runtime/executable-run-plan.d.ts +328 -0
  55. package/dist/runtime/executable-run-plan.js +1485 -0
  56. package/dist/runtime/execution-authority.d.ts +83 -0
  57. package/dist/runtime/execution-authority.js +98 -0
  58. package/dist/runtime/handoff-resolver.js +4 -1
  59. package/dist/runtime/harness-pull-adapter.d.ts +146 -0
  60. package/dist/runtime/harness-pull-adapter.js +315 -0
  61. package/dist/runtime/index.d.ts +39 -14
  62. package/dist/runtime/index.js +29 -7
  63. package/dist/runtime/local-execution-authority.d.ts +194 -0
  64. package/dist/runtime/local-execution-authority.js +2897 -0
  65. package/dist/runtime/local-execution-reconciliation.d.ts +20 -0
  66. package/dist/runtime/local-execution-reconciliation.js +107 -0
  67. package/dist/runtime/local-execution-supervisor-script.d.ts +7 -0
  68. package/dist/runtime/local-execution-supervisor-script.js +793 -0
  69. package/dist/runtime/local-provider-sandbox.d.ts +42 -0
  70. package/dist/runtime/local-provider-sandbox.js +154 -0
  71. package/dist/runtime/local-verifier-execution.d.ts +24 -0
  72. package/dist/runtime/local-verifier-execution.js +290 -0
  73. package/dist/runtime/local-windows-execution-supervisor-script.d.ts +6 -0
  74. package/dist/runtime/local-windows-execution-supervisor-script.js +788 -0
  75. package/dist/runtime/plan-store.d.ts +30 -0
  76. package/dist/runtime/plan-store.js +231 -0
  77. package/dist/runtime/process-tree.d.ts +9 -0
  78. package/dist/runtime/process-tree.js +97 -24
  79. package/dist/runtime/providers/codex.js +2 -2
  80. package/dist/runtime/push-driver.d.ts +184 -0
  81. package/dist/runtime/push-driver.js +1002 -0
  82. package/dist/runtime/result-store.d.ts +34 -3
  83. package/dist/runtime/result-store.js +1073 -2
  84. package/dist/runtime/run-binding.d.ts +68 -0
  85. package/dist/runtime/run-binding.js +278 -0
  86. package/dist/runtime/run-contracts.d.ts +575 -0
  87. package/dist/runtime/run-contracts.js +58 -7
  88. package/dist/runtime/run-controller.d.ts +1 -6
  89. package/dist/runtime/run-controller.js +0 -41
  90. package/dist/runtime/run-store.d.ts +85 -7
  91. package/dist/runtime/run-store.js +2528 -186
  92. package/dist/runtime/skill-adapter.d.ts +18 -7
  93. package/dist/runtime/skill-adapter.js +100 -742
  94. package/dist/runtime/structured-output-validator.d.ts +44 -0
  95. package/dist/runtime/structured-output-validator.js +171 -0
  96. package/dist/runtime/verifier-command-binding.d.ts +22 -0
  97. package/dist/runtime/verifier-command-binding.js +162 -0
  98. package/dist/runtime/verifier.d.ts +46 -6
  99. package/dist/runtime/verifier.js +355 -53
  100. package/dist/runtime/windows-job-keeper.d.ts +47 -0
  101. package/dist/runtime/windows-job-keeper.js +231 -0
  102. package/dist/runtime/worker-executor.d.ts +17 -1
  103. package/dist/runtime/worker-executor.js +26 -5
  104. package/dist/runtime/workflow-plan-adapter.d.ts +19 -0
  105. package/dist/runtime/workflow-plan-adapter.js +502 -6
  106. package/dist/runtime/workflow-runtime-manifest.d.ts +1 -0
  107. package/dist/runtime/workflow-runtime-manifest.js +5 -0
  108. package/dist/runtime/workspace-isolation.d.ts +29 -2
  109. package/dist/runtime/workspace-isolation.js +488 -11
  110. package/dist/runtime/workspace-observation.d.ts +44 -0
  111. package/dist/runtime/workspace-observation.js +216 -0
  112. package/dist/schema/controller-registry.d.ts +0 -7
  113. package/dist/schema/controller-registry.js +0 -8
  114. package/dist/schema/types.d.ts +84 -10
  115. package/dist/schema/types.js +2 -0
  116. package/dist/schema/validate.js +151 -1
  117. package/dist/schema/validators/controllers.d.ts +1 -1
  118. package/dist/schema/validators/controllers.js +126 -41
  119. package/dist/schema/workflow-authoring-contract.js +2 -0
  120. package/dist/schema/yaml-parser.js +1 -1
  121. package/dist/templates/flutter-rewrite-new.dna.yaml +1 -0
  122. package/dist/templates/flutter-rewrite.dna.yaml +87 -60
  123. package/dist/templates/safe-refactoring.dna.yaml +1 -0
  124. package/native/windows-job-keeper/README.md +80 -0
  125. package/native/windows-job-keeper/bin/aarch64/intentdna-windows-job-keeper.exe +0 -0
  126. package/native/windows-job-keeper/bin/x86_64/intentdna-windows-job-keeper.exe +0 -0
  127. package/native/windows-job-keeper/keeper.c +979 -0
  128. package/native/windows-job-keeper/manifest.json +33 -0
  129. package/package.json +6 -2
  130. package/scripts/build-windows-job-keeper.mjs +172 -0
  131. package/scripts/verify-windows-job-keeper.mjs +184 -0
@@ -0,0 +1,22 @@
1
+ import { ArtifactStore } from "./artifact-store.js";
2
+ import { CanonicalRunService, type CanonicalRunServiceOptions } from "./canonical-run-service.js";
3
+ import { DurablePlanStore } from "./plan-store.js";
4
+ import { ImmutableCanonicalResultStore } from "./result-store.js";
5
+ import { DurableRunStore } from "./run-store.js";
6
+ export interface CanonicalRuntimeStores {
7
+ readonly root_directory: string;
8
+ readonly plan_store: DurablePlanStore;
9
+ readonly run_store: DurableRunStore;
10
+ readonly artifact_store: ArtifactStore;
11
+ readonly result_store: ImmutableCanonicalResultStore;
12
+ }
13
+ export interface CanonicalRuntimeComposition extends CanonicalRuntimeStores {
14
+ readonly service: CanonicalRunService;
15
+ }
16
+ export interface CreateCanonicalRuntimeCompositionOptions extends Omit<CanonicalRunServiceOptions, "plan_store" | "run_store" | "artifact_store" | "result_store" | "handoff_root_directory"> {
17
+ readonly project_directory: string;
18
+ readonly run_store?: DurableRunStore;
19
+ }
20
+ export declare function canonicalRuntimeRoot(projectDirectory: string): string;
21
+ export declare function createCanonicalRuntimeStores(projectDirectory: string, runStore?: DurableRunStore): CanonicalRuntimeStores;
22
+ export declare function createCanonicalRuntimeComposition(options: CreateCanonicalRuntimeCompositionOptions): CanonicalRuntimeComposition;
@@ -0,0 +1,34 @@
1
+ import { join, resolve } from "node:path";
2
+ import { ArtifactStore } from "./artifact-store.js";
3
+ import { CanonicalRunService, } from "./canonical-run-service.js";
4
+ import { DurablePlanStore } from "./plan-store.js";
5
+ import { ImmutableCanonicalResultStore } from "./result-store.js";
6
+ import { DurableRunStore } from "./run-store.js";
7
+ export function canonicalRuntimeRoot(projectDirectory) {
8
+ return join(resolve(projectDirectory), ".dna", "runtime");
9
+ }
10
+ export function createCanonicalRuntimeStores(projectDirectory, runStore) {
11
+ const rootDirectory = canonicalRuntimeRoot(projectDirectory);
12
+ return {
13
+ root_directory: rootDirectory,
14
+ plan_store: new DurablePlanStore({ root_directory: rootDirectory }),
15
+ run_store: runStore ?? new DurableRunStore({ root_directory: rootDirectory }),
16
+ artifact_store: new ArtifactStore({ root_directory: rootDirectory }),
17
+ result_store: new ImmutableCanonicalResultStore({ root_directory: rootDirectory }),
18
+ };
19
+ }
20
+ export function createCanonicalRuntimeComposition(options) {
21
+ const { project_directory, run_store, ...serviceOptions } = options;
22
+ const stores = createCanonicalRuntimeStores(project_directory, run_store);
23
+ return {
24
+ ...stores,
25
+ service: new CanonicalRunService({
26
+ ...serviceOptions,
27
+ plan_store: stores.plan_store,
28
+ run_store: stores.run_store,
29
+ artifact_store: stores.artifact_store,
30
+ result_store: stores.result_store,
31
+ handoff_root_directory: join(stores.root_directory, "handoffs"),
32
+ }),
33
+ };
34
+ }
@@ -0,0 +1,3 @@
1
+ import type { CanonicalRuntimeProjection } from "./canonical-target-compiler.js";
2
+ import { type CompiledIRFile } from "./plugin-adapter.js";
3
+ export declare function durableCanonicalRuntimeProjection(projection: CanonicalRuntimeProjection): CompiledIRFile;
@@ -0,0 +1,4 @@
1
+ import { createCompiledIR, } from "./plugin-adapter.js";
2
+ export function durableCanonicalRuntimeProjection(projection) {
3
+ return JSON.parse(JSON.stringify(createCompiledIR(projection.constraint_ir, { ...projection.roles }, projection.workflow_manifest)));
4
+ }
@@ -0,0 +1,46 @@
1
+ import type { ConstraintIR, IntentDNA, RoleDef, WorkflowPlan } from "../schema/types.js";
2
+ import { type ExecutableRunPlanPayload, type Sha256Digest } from "./executable-run-plan.js";
3
+ import { type WorkflowRuntimeManifest } from "./workflow-runtime-manifest.js";
4
+ export declare const CANONICAL_TARGET_COMPILER_NAME = "intentdna";
5
+ export declare const CANONICAL_TARGET_COMPILER_VERSION = "1";
6
+ export interface CanonicalTarget {
7
+ readonly kind: "workflow" | "controller";
8
+ readonly key: string;
9
+ }
10
+ export interface CanonicalDnaSource {
11
+ readonly dna: IntentDNA;
12
+ readonly source_id: string;
13
+ readonly relative_ref: string;
14
+ readonly content_digest: Sha256Digest;
15
+ readonly snapshot_bytes: Uint8Array;
16
+ }
17
+ export interface CompileCanonicalTargetRequest {
18
+ readonly dna_sources: readonly (IntentDNA | CanonicalDnaSource)[];
19
+ readonly target: CanonicalTarget;
20
+ readonly context?: string | null;
21
+ readonly attempt_policy?: {
22
+ readonly timeout_ms: number | null;
23
+ readonly cancellation_grace_ms: number;
24
+ };
25
+ }
26
+ export interface CanonicalRuntimeProjection {
27
+ readonly roles: Readonly<Record<string, RoleDef>>;
28
+ readonly constraint_ir: ConstraintIR;
29
+ readonly workflow_manifest: WorkflowRuntimeManifest;
30
+ readonly workflow_plan: WorkflowPlan;
31
+ readonly workflow_asset: string | null;
32
+ }
33
+ export interface CanonicalTargetCompilation {
34
+ readonly plan: ExecutableRunPlanPayload;
35
+ readonly projection: CanonicalRuntimeProjection;
36
+ }
37
+ export type CanonicalTargetCompilerErrorCode = "invalid_sources" | "invalid_target" | "target_not_found" | "unsupported_target_kind" | "controller_compilation_failed" | "workflow_compilation_failed" | "workflow_adaptation_failed";
38
+ export declare class CanonicalTargetCompilerError extends Error {
39
+ readonly code: CanonicalTargetCompilerErrorCode;
40
+ constructor(code: CanonicalTargetCompilerErrorCode, message: string, options?: ErrorOptions);
41
+ }
42
+ export declare class CanonicalTargetCompiler {
43
+ compile(request: CompileCanonicalTargetRequest): ExecutableRunPlanPayload;
44
+ compileCascade(request: CompileCanonicalTargetRequest): CanonicalTargetCompilation;
45
+ }
46
+ export declare function compileCanonicalTarget(request: CompileCanonicalTargetRequest): ExecutableRunPlanPayload;
@@ -0,0 +1,514 @@
1
+ import { createHash } from "node:crypto";
2
+ import { TextDecoder } from "node:util";
3
+ import { cascadeDNA } from "../compiler/cascade.js";
4
+ import { activateDNA } from "../compiler/activate.js";
5
+ import { compileDNA } from "../compiler/compile.js";
6
+ import { attachProvenance } from "../compiler/provenance.js";
7
+ import { compileWorkflow } from "../compiler/workflow.js";
8
+ import { compileControllerPlan, ControllerPlanCompilerError, } from "../compiler/controller.js";
9
+ import { validateDNA } from "../schema/validate.js";
10
+ import { parseYAML } from "../schema/yaml-parser.js";
11
+ import { canonicalizeJson } from "./canonical-json.js";
12
+ import { createWorkflowRuntimeManifest, } from "./workflow-runtime-manifest.js";
13
+ import { defaultResolvedVariableScopes, indexWorkflowVariableScopes, resolvedVariablesForNamespace, } from "./workflow-variable-scopes.js";
14
+ import { adaptWorkflowPlanToExecutableRunPlan, } from "./workflow-plan-adapter.js";
15
+ export const CANONICAL_TARGET_COMPILER_NAME = "intentdna";
16
+ export const CANONICAL_TARGET_COMPILER_VERSION = "1";
17
+ export class CanonicalTargetCompilerError extends Error {
18
+ code;
19
+ constructor(code, message, options) {
20
+ super(message, options);
21
+ this.name = "CanonicalTargetCompilerError";
22
+ this.code = code;
23
+ }
24
+ }
25
+ function digestBytes(value) {
26
+ return `sha256:${createHash("sha256").update(value).digest("hex")}`;
27
+ }
28
+ function hasStableArtifactIdentity(artifact) {
29
+ return artifact.artifact_id !== undefined
30
+ || artifact.name !== undefined
31
+ || artifact.path !== undefined
32
+ || artifact.type === "git_commit";
33
+ }
34
+ function authoredArtifactIdentity(artifact) {
35
+ return artifact.artifact_id
36
+ ?? artifact.name
37
+ ?? artifact.path
38
+ ?? (artifact.type === "git_commit" ? "git_commit" : null);
39
+ }
40
+ function containsRuntimeIdentityTemplate(value) {
41
+ return value.includes("$ARGUMENTS") || /\{\{[^}]+\}\}/u.test(value);
42
+ }
43
+ function controllerArtifactId(stepId, direction, index) {
44
+ return `${stepId}-${direction}-${index}`;
45
+ }
46
+ function canonicalControllerHandoffIdentities(plan) {
47
+ const outputIds = new Map();
48
+ const stepsWithOutputs = plan.steps.map((step) => {
49
+ if (step.handoff === null)
50
+ return step;
51
+ const produces = (step.handoff.produces ?? []).flatMap((artifact, index) => {
52
+ const identity = authoredArtifactIdentity(artifact);
53
+ if (identity === null)
54
+ return artifact.required === false ? [] : [artifact];
55
+ if (!containsRuntimeIdentityTemplate(identity))
56
+ return [artifact];
57
+ const artifactId = controllerArtifactId(step.id, "output", index);
58
+ outputIds.set(`${step.id}\u0000${identity}`, artifactId);
59
+ return [{ ...artifact, artifact_id: artifactId }];
60
+ });
61
+ return { ...step, handoff: { ...step.handoff, produces } };
62
+ });
63
+ return {
64
+ ...plan,
65
+ steps: stepsWithOutputs.map((step) => {
66
+ if (step.handoff === null)
67
+ return step;
68
+ const consumes = (step.handoff.consumes ?? []).map((artifact, index) => {
69
+ const identity = authoredArtifactIdentity(artifact);
70
+ if (identity === null || !containsRuntimeIdentityTemplate(identity))
71
+ return artifact;
72
+ const sourceArtifactId = artifact.from === undefined
73
+ ? undefined
74
+ : outputIds.get(`${artifact.from}\u0000${identity}`);
75
+ return {
76
+ ...artifact,
77
+ artifact_id: sourceArtifactId
78
+ ?? controllerArtifactId(step.id, "input", index),
79
+ };
80
+ });
81
+ return { ...step, handoff: { ...step.handoff, consumes } };
82
+ }),
83
+ };
84
+ }
85
+ function logicalSourceRef(dna, index) {
86
+ const segment = dna.id.replace(/[^A-Za-z0-9._-]/gu, "_") || `source-${index}`;
87
+ return `sources/${segment}.dna.json`;
88
+ }
89
+ function isCanonicalDnaSource(source) {
90
+ return Object.prototype.hasOwnProperty.call(source, "dna");
91
+ }
92
+ function normalizeSources(sources) {
93
+ if (sources.length === 0) {
94
+ throw new CanonicalTargetCompilerError("invalid_sources", "dna_sources must contain at least one source");
95
+ }
96
+ return sources.map((source, index) => {
97
+ try {
98
+ const candidate = isCanonicalDnaSource(source)
99
+ ? source
100
+ : (() => {
101
+ const bytes = Buffer.from(canonicalizeJson(source), "utf8");
102
+ return {
103
+ dna: source,
104
+ source_id: source.id,
105
+ relative_ref: logicalSourceRef(source, index),
106
+ content_digest: digestBytes(bytes),
107
+ snapshot_bytes: bytes,
108
+ };
109
+ })();
110
+ if (!(candidate.snapshot_bytes instanceof Uint8Array)) {
111
+ throw new TypeError("snapshot_bytes must be a Uint8Array");
112
+ }
113
+ const snapshotBytes = Uint8Array.from(candidate.snapshot_bytes);
114
+ const actualDigest = digestBytes(snapshotBytes);
115
+ if (candidate.content_digest !== actualDigest) {
116
+ throw new TypeError(`content_digest does not match snapshot bytes (${actualDigest})`);
117
+ }
118
+ const raw = new TextDecoder("utf-8", { fatal: true }).decode(snapshotBytes);
119
+ let snapshotDna;
120
+ try {
121
+ snapshotDna = JSON.parse(raw);
122
+ }
123
+ catch {
124
+ snapshotDna = parseYAML(raw);
125
+ }
126
+ const validation = validateDNA(snapshotDna);
127
+ if (!validation.valid) {
128
+ throw new TypeError(validation.errors
129
+ .map((error) => `${error.path}: ${error.message}`)
130
+ .join("; "));
131
+ }
132
+ if (candidate.source_id !== snapshotDna.id || candidate.source_id !== candidate.dna.id) {
133
+ throw new TypeError("source_id must match the snapshot DNA id");
134
+ }
135
+ if (canonicalizeJson(candidate.dna) !== canonicalizeJson(snapshotDna)) {
136
+ throw new TypeError("parsed DNA must match snapshot bytes");
137
+ }
138
+ return {
139
+ ...candidate,
140
+ dna: snapshotDna,
141
+ content_digest: actualDigest,
142
+ snapshot_bytes: snapshotBytes,
143
+ };
144
+ }
145
+ catch (error) {
146
+ throw new CanonicalTargetCompilerError("invalid_sources", `DNA source at index ${index} is not bound to a valid immutable snapshot`, { cause: error });
147
+ }
148
+ });
149
+ }
150
+ function collectTemplateInputNames(value, names) {
151
+ if (typeof value === "string") {
152
+ for (const match of value.matchAll(/\{\{(\w+)\}\}/gu))
153
+ names.add(match[1]);
154
+ if (/(^|[^\\])\$ARGUMENTS/u.test(value))
155
+ names.add("ARGUMENTS");
156
+ return;
157
+ }
158
+ if (Array.isArray(value)) {
159
+ for (const item of value)
160
+ collectTemplateInputNames(item, names);
161
+ return;
162
+ }
163
+ if (value !== null && typeof value === "object") {
164
+ for (const item of Object.values(value)) {
165
+ collectTemplateInputNames(item, names);
166
+ }
167
+ }
168
+ }
169
+ function variableDefinition(name, value) {
170
+ if (value === undefined) {
171
+ return {
172
+ name,
173
+ type: "string",
174
+ required: true,
175
+ sensitive: false,
176
+ description: `Runtime value for template input '${name}'`,
177
+ };
178
+ }
179
+ return {
180
+ name,
181
+ type: typeof value === "string"
182
+ ? "string"
183
+ : value.runtime_type ?? "string",
184
+ required: false,
185
+ sensitive: false,
186
+ description: typeof value === "string"
187
+ ? `Runtime value for declared input '${name}'`
188
+ : value.description,
189
+ default_value: typeof value === "string" ? value : value.default,
190
+ };
191
+ }
192
+ function inputContract(dnas, targetKey, workflow, roles) {
193
+ const variableIndex = indexWorkflowVariableScopes([...dnas]);
194
+ const namespace = variableIndex.workflowNamespaces.get(targetKey) ?? "";
195
+ const declared = {
196
+ ...(namespace ? variableIndex.rawByNamespace.get("") : {}),
197
+ ...(variableIndex.rawByNamespace.get(namespace) ?? {}),
198
+ };
199
+ const names = new Set(Object.keys(declared));
200
+ collectTemplateInputNames(workflow, names);
201
+ for (const roleName of new Set(workflow.steps.map((step) => step.role))) {
202
+ const role = roles[roleName];
203
+ if (role)
204
+ collectTemplateInputNames(role, names);
205
+ }
206
+ return {
207
+ inputs: [...names]
208
+ .sort()
209
+ .map((name) => variableDefinition(name, declared[name])),
210
+ allow_unknown_inputs: false,
211
+ };
212
+ }
213
+ function sourceProvenance(sources) {
214
+ return {
215
+ compiler: {
216
+ name: CANONICAL_TARGET_COMPILER_NAME,
217
+ version: CANONICAL_TARGET_COMPILER_VERSION,
218
+ },
219
+ sources: sources.map((source) => ({
220
+ source_id: source.source_id,
221
+ relative_ref: source.relative_ref,
222
+ content_digest: source.content_digest,
223
+ })),
224
+ };
225
+ }
226
+ function canonicalCompletion(completion) {
227
+ return JSON.parse(canonicalizeJson(completion));
228
+ }
229
+ function canonicalRuntimeWorkflowPlan(workflow, plan) {
230
+ const definitions = new Map(workflow.steps.map((step) => [step.id, step]));
231
+ const steps = plan.steps.map((step) => {
232
+ const definition = definitions.get(step.id);
233
+ const runtime = definition?.canonical_runtime;
234
+ if (definition === undefined || runtime === undefined)
235
+ return step;
236
+ const sourceByArtifactId = runtime.handoff_sources ?? {};
237
+ const authoredConsumes = step.handoff?.consumes ?? [];
238
+ for (const [artifactId, sourceStepId] of Object.entries(sourceByArtifactId)) {
239
+ const matches = authoredConsumes.filter((artifact) => artifact.artifact_id === artifactId);
240
+ if (matches.length !== 1) {
241
+ throw new Error(`step '${step.id}' canonical source '${artifactId}' must identify one consumed artifact`);
242
+ }
243
+ if (matches[0].from !== undefined && matches[0].from !== sourceStepId) {
244
+ throw new Error(`step '${step.id}' canonical source '${artifactId}' conflicts with authored source '${matches[0].from}'`);
245
+ }
246
+ }
247
+ const canonicalConsumes = authoredConsumes.map((artifact) => {
248
+ const sourceStepId = artifact.artifact_id === undefined
249
+ ? undefined
250
+ : sourceByArtifactId[artifact.artifact_id];
251
+ return sourceStepId === undefined ? artifact : { ...artifact, from: sourceStepId };
252
+ });
253
+ let prompt = step.prompt;
254
+ const pathBindings = {};
255
+ for (const artifactId of runtime.prompt_handoff_bindings ?? []) {
256
+ const matches = canonicalConsumes.filter((artifact) => (artifact.artifact_id === artifactId));
257
+ if (matches.length !== 1 || !matches[0].from || !matches[0].path) {
258
+ throw new Error(`step '${step.id}' canonical binding '${artifactId}' must identify one path handoff with a source step`);
259
+ }
260
+ if (prompt === null || !prompt.includes(matches[0].path)) {
261
+ throw new Error(`step '${step.id}' canonical binding '${artifactId}' is not referenced by the authored prompt`);
262
+ }
263
+ const replacement = `{{handoff.${step.id}:${artifactId}.materialized_path}}`;
264
+ prompt = prompt.replaceAll(matches[0].path, replacement);
265
+ pathBindings[matches[0].path] = replacement;
266
+ }
267
+ if (runtime.prompt_suffix !== undefined) {
268
+ prompt = `${prompt ?? step.description}\n\n${runtime.prompt_suffix}`;
269
+ }
270
+ const canonicalOutputs = runtime.outputs ?? [];
271
+ return {
272
+ ...step,
273
+ prompt,
274
+ handoff: step.handoff === null
275
+ ? (canonicalOutputs.length === 0 ? null : { produces: canonicalOutputs })
276
+ : {
277
+ ...step.handoff,
278
+ consumes: canonicalConsumes,
279
+ produces: [...(step.handoff.produces ?? []), ...canonicalOutputs],
280
+ },
281
+ completion: runtime.completion === undefined
282
+ ? step.completion
283
+ : runtime.completion.map(canonicalCompletion),
284
+ canonical_handoff_path_bindings: pathBindings,
285
+ canonical_requires_attested_independent_submit: runtime.require_attested_independent_submit === true,
286
+ };
287
+ });
288
+ return { ...plan, steps };
289
+ }
290
+ function compilerProvenance(sources) {
291
+ return sources.map((source) => ({
292
+ source_id: source.source_id,
293
+ source_ref: source.relative_ref,
294
+ resolved_path: source.relative_ref,
295
+ fingerprint: source.content_digest,
296
+ type: source.dna.type,
297
+ cascade_priority: source.dna.cascade.priority,
298
+ version: source.dna.version,
299
+ trust: "input",
300
+ genes: Object.keys(source.dna.genes ?? {}).sort(),
301
+ }));
302
+ }
303
+ export class CanonicalTargetCompiler {
304
+ compile(request) {
305
+ return this.compileCascade(request).plan;
306
+ }
307
+ compileCascade(request) {
308
+ if (request.target.kind !== "workflow"
309
+ && request.target.kind !== "controller") {
310
+ throw new CanonicalTargetCompilerError("invalid_target", `target kind must be 'workflow' or 'controller', received '${String(request.target.kind)}'`);
311
+ }
312
+ if (!request.target.key.trim()) {
313
+ throw new CanonicalTargetCompilerError("invalid_target", "target key must be non-empty");
314
+ }
315
+ const sources = normalizeSources(request.dna_sources);
316
+ const dnas = sources.map((source) => source.dna);
317
+ const cascaded = cascadeDNA(dnas);
318
+ const activated = activateDNA(cascaded, request.context ?? null, null);
319
+ const constraintIr = attachProvenance(compileDNA(activated, cascaded), compilerProvenance(sources));
320
+ if (request.target.kind === "controller") {
321
+ const controller = cascaded.controllers[request.target.key];
322
+ if (!controller) {
323
+ throw new CanonicalTargetCompilerError("target_not_found", `controller '${request.target.key}' not found; available: ${Object.keys(cascaded.controllers).sort().join(", ") || "(none)"}`);
324
+ }
325
+ if (!controller.runtime_program) {
326
+ throw new CanonicalTargetCompilerError("controller_compilation_failed", `controller '${request.target.key}' has no typed runtime_program`);
327
+ }
328
+ const diagnosisKey = controller.diagnosis_workflow;
329
+ const fixKey = controller.fix_workflow;
330
+ if (!diagnosisKey || !fixKey) {
331
+ throw new CanonicalTargetCompilerError("controller_compilation_failed", `controller '${request.target.key}' must reference diagnosis_workflow and fix_workflow`);
332
+ }
333
+ const compileComponent = (workflowKey) => {
334
+ const definition = cascaded.workflows[workflowKey];
335
+ if (!definition) {
336
+ throw new CanonicalTargetCompilerError("controller_compilation_failed", `controller '${request.target.key}' references missing workflow '${workflowKey}'`);
337
+ }
338
+ const result = compileWorkflow(definition, {
339
+ workflow_key: workflowKey,
340
+ roles: cascaded.roles,
341
+ });
342
+ if (!result.ok || !result.plan) {
343
+ throw new CanonicalTargetCompilerError("workflow_compilation_failed", `workflow '${workflowKey}' compilation failed:\n${result.errors
344
+ .map((error) => ` ${error.path}: ${error.message}`)
345
+ .join("\n")}`);
346
+ }
347
+ const workflowPlan = canonicalRuntimeWorkflowPlan(definition, result.plan);
348
+ const controllerPlan = canonicalControllerHandoffIdentities({
349
+ ...workflowPlan,
350
+ steps: workflowPlan.steps.map((step) => ({
351
+ ...step,
352
+ handoff: step.handoff === null
353
+ ? null
354
+ : {
355
+ ...step.handoff,
356
+ produces: step.handoff.produces?.filter((artifact) => (artifact.required !== false || hasStableArtifactIdentity(artifact))),
357
+ },
358
+ blocked_items_path: undefined,
359
+ handoff_to: undefined,
360
+ max_handoffs: undefined,
361
+ on_handoff_exhausted: undefined,
362
+ on_fail: step.on_fail === "retry_with_feedback"
363
+ ? step.on_fail
364
+ : undefined,
365
+ })),
366
+ });
367
+ return {
368
+ definition,
369
+ workflow_plan: workflowPlan,
370
+ executable_plan: adaptWorkflowPlanToExecutableRunPlan(controllerPlan, {
371
+ roles: cascaded.roles,
372
+ target_key: workflowKey,
373
+ input_contract: inputContract(dnas, workflowKey, definition, cascaded.roles),
374
+ source_provenance: sourceProvenance(sources),
375
+ global_constraints: constraintIr.prompt_directives.map((directive) => directive.text),
376
+ timeout_ms: request.attempt_policy?.timeout_ms,
377
+ cancellation_grace_ms: request.attempt_policy?.cancellation_grace_ms,
378
+ }),
379
+ };
380
+ };
381
+ try {
382
+ const diagnosis = compileComponent(diagnosisKey);
383
+ const fix = compileComponent(fixKey);
384
+ const plan = compileControllerPlan({
385
+ controller_key: request.target.key,
386
+ controller,
387
+ diagnosis_plan: diagnosis.executable_plan,
388
+ fix_plan: fix.executable_plan,
389
+ source_provenance: sourceProvenance(sources),
390
+ });
391
+ if (!constraintIr.compiled_ir_hash) {
392
+ throw new Error("compiled IR hash is required for runtime projection");
393
+ }
394
+ const variableIndex = indexWorkflowVariableScopes(dnas);
395
+ const defaultVariables = defaultResolvedVariableScopes(variableIndex);
396
+ const runtimePlans = Object.entries(cascaded.workflows).map(([workflowKey, definition]) => {
397
+ const result = compileWorkflow(definition, {
398
+ workflow_key: workflowKey,
399
+ roles: cascaded.roles,
400
+ });
401
+ if (!result.ok || !result.plan) {
402
+ throw new CanonicalTargetCompilerError("workflow_compilation_failed", `workflow '${workflowKey}' compilation failed:\n${result.errors
403
+ .map((error) => ` ${error.path}: ${error.message}`)
404
+ .join("\n")}`);
405
+ }
406
+ const runtimePlan = canonicalRuntimeWorkflowPlan(definition, result.plan);
407
+ const namespace = variableIndex.workflowNamespaces.get(workflowKey) ?? "";
408
+ return {
409
+ plan: runtimePlan,
410
+ resolvedVariables: resolvedVariablesForNamespace(defaultVariables, namespace),
411
+ runtimeInputRefs: inputContract(dnas, workflowKey, definition, cascaded.roles).inputs.map((input) => input.name),
412
+ workflowAsset: variableIndex.workflowAssets.get(workflowKey),
413
+ additionalRuntimeValues: constraintIr.verifier_specs?.filter((spec) => spec.workflow_name === workflowKey) ?? [],
414
+ };
415
+ });
416
+ return {
417
+ plan,
418
+ projection: {
419
+ roles: cascaded.roles,
420
+ constraint_ir: constraintIr,
421
+ workflow_manifest: createWorkflowRuntimeManifest({
422
+ plans: runtimePlans,
423
+ compiledAt: constraintIr.compiled_at,
424
+ compiledIrHash: constraintIr.compiled_ir_hash,
425
+ sourceDnaIds: constraintIr.source_dna_ids,
426
+ }),
427
+ workflow_plan: fix.workflow_plan,
428
+ workflow_asset: variableIndex.workflowAssets.get(fixKey) ?? null,
429
+ },
430
+ };
431
+ }
432
+ catch (error) {
433
+ if (error instanceof CanonicalTargetCompilerError)
434
+ throw error;
435
+ throw new CanonicalTargetCompilerError("controller_compilation_failed", `controller '${request.target.key}' could not be adapted to an executable plan`, { cause: error instanceof ControllerPlanCompilerError ? error : error });
436
+ }
437
+ }
438
+ const workflow = cascaded.workflows[request.target.key];
439
+ if (!workflow) {
440
+ throw new CanonicalTargetCompilerError("target_not_found", `workflow '${request.target.key}' not found; available: ${Object.keys(cascaded.workflows).sort().join(", ") || "(none)"}`);
441
+ }
442
+ const compiled = compileWorkflow(workflow, {
443
+ workflow_key: request.target.key,
444
+ roles: cascaded.roles,
445
+ });
446
+ if (!compiled.ok || !compiled.plan) {
447
+ throw new CanonicalTargetCompilerError("workflow_compilation_failed", `workflow '${request.target.key}' compilation failed:\n${compiled.errors
448
+ .map((error) => ` ${error.path}: ${error.message}`)
449
+ .join("\n")}`);
450
+ }
451
+ try {
452
+ const canonicalPlan = canonicalRuntimeWorkflowPlan(workflow, compiled.plan);
453
+ const plan = adaptWorkflowPlanToExecutableRunPlan(canonicalPlan, {
454
+ roles: cascaded.roles,
455
+ target_key: request.target.key,
456
+ input_contract: inputContract(dnas, request.target.key, workflow, cascaded.roles),
457
+ source_provenance: sourceProvenance(sources),
458
+ global_constraints: constraintIr.prompt_directives.map((directive) => directive.text),
459
+ timeout_ms: request.attempt_policy?.timeout_ms,
460
+ cancellation_grace_ms: request.attempt_policy?.cancellation_grace_ms,
461
+ });
462
+ if (!constraintIr.compiled_ir_hash) {
463
+ throw new Error("compiled IR hash is required for runtime projection");
464
+ }
465
+ const variableIndex = indexWorkflowVariableScopes(dnas);
466
+ const defaultVariables = defaultResolvedVariableScopes(variableIndex);
467
+ const runtimePlans = Object.entries(cascaded.workflows).map(([workflowKey, definition]) => {
468
+ const result = workflowKey === request.target.key
469
+ ? compiled
470
+ : compileWorkflow(definition, {
471
+ workflow_key: workflowKey,
472
+ roles: cascaded.roles,
473
+ });
474
+ if (!result.ok || !result.plan) {
475
+ throw new CanonicalTargetCompilerError("workflow_compilation_failed", `workflow '${workflowKey}' compilation failed:\n${result.errors
476
+ .map((error) => ` ${error.path}: ${error.message}`)
477
+ .join("\n")}`);
478
+ }
479
+ const runtimePlan = canonicalRuntimeWorkflowPlan(definition, result.plan);
480
+ const namespace = variableIndex.workflowNamespaces.get(workflowKey) ?? "";
481
+ return {
482
+ plan: runtimePlan,
483
+ resolvedVariables: resolvedVariablesForNamespace(defaultVariables, namespace),
484
+ runtimeInputRefs: inputContract(dnas, workflowKey, definition, cascaded.roles).inputs.map((input) => input.name),
485
+ workflowAsset: variableIndex.workflowAssets.get(workflowKey),
486
+ additionalRuntimeValues: constraintIr.verifier_specs?.filter((spec) => spec.workflow_name === workflowKey) ?? [],
487
+ };
488
+ });
489
+ return {
490
+ plan,
491
+ projection: {
492
+ roles: cascaded.roles,
493
+ constraint_ir: constraintIr,
494
+ workflow_manifest: createWorkflowRuntimeManifest({
495
+ plans: runtimePlans,
496
+ compiledAt: constraintIr.compiled_at,
497
+ compiledIrHash: constraintIr.compiled_ir_hash,
498
+ sourceDnaIds: constraintIr.source_dna_ids,
499
+ }),
500
+ workflow_plan: canonicalPlan,
501
+ workflow_asset: variableIndex.workflowAssets.get(request.target.key) ?? null,
502
+ },
503
+ };
504
+ }
505
+ catch (error) {
506
+ if (error instanceof CanonicalTargetCompilerError)
507
+ throw error;
508
+ throw new CanonicalTargetCompilerError("workflow_adaptation_failed", `workflow '${request.target.key}' could not be adapted to an executable plan`, { cause: error });
509
+ }
510
+ }
511
+ }
512
+ export function compileCanonicalTarget(request) {
513
+ return new CanonicalTargetCompiler().compile(request);
514
+ }
@@ -0,0 +1,2 @@
1
+ export declare function canonicalClaudeAgentName(role: string, workerSessionId: string): string;
2
+ export declare function legacyClaudeAgentName(role: string): string;
@@ -0,0 +1,21 @@
1
+ import { createHash } from "node:crypto";
2
+ export function canonicalClaudeAgentName(role, workerSessionId) {
3
+ if (role.length === 0)
4
+ throw new TypeError("role must not be empty");
5
+ if (workerSessionId.length === 0) {
6
+ throw new TypeError("workerSessionId must not be empty");
7
+ }
8
+ const identity = createHash("sha256")
9
+ .update(role, "utf8")
10
+ .update("\0", "utf8")
11
+ .update(workerSessionId, "utf8")
12
+ .digest("hex")
13
+ .slice(0, 32);
14
+ return `dna-attempt-${identity}`;
15
+ }
16
+ export function legacyClaudeAgentName(role) {
17
+ return `dna-${role
18
+ .replace(/([a-z0-9])([A-Z])/gu, "$1-$2")
19
+ .replace(/[_\s]+/gu, "-")
20
+ .toLowerCase()}`;
21
+ }