intentdna 1.8.7 → 1.9.0-rc.2
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/.claude-plugin/marketplace.json +2 -2
- package/.claude-plugin/plugin.json +1 -1
- package/dist/cli/commands/candidate-promotion.d.ts +15 -0
- package/dist/cli/commands/candidate-promotion.js +197 -0
- package/dist/cli/commands/run-lifecycle.js +1 -0
- package/dist/cli/commands/run.js +76 -42
- package/dist/cli/commands/setup.d.ts +10 -0
- package/dist/cli/commands/setup.js +129 -36
- package/dist/cli/commands/source-assets.d.ts +32 -0
- package/dist/cli/commands/source-assets.js +154 -0
- package/dist/cli/commands/sync.js +52 -12
- package/dist/cli/commands/templates.js +59 -37
- package/dist/cli/index.js +161 -5
- package/dist/compiler/cascade.js +1 -1
- package/dist/hooks/cli.d.ts +6 -0
- package/dist/hooks/cli.js +118 -10
- package/dist/hooks/enforcement-boundary.d.ts +1 -1
- package/dist/hooks/protocol.d.ts +1 -1
- package/dist/hooks/state.d.ts +5 -0
- package/dist/hooks/state.js +21 -6
- package/dist/mcp/tools-state.js +251 -15
- package/dist/runtime/claude-sync-target.d.ts +2 -0
- package/dist/runtime/claude-sync-target.js +1 -1
- package/dist/runtime/evaluator.d.ts +13 -0
- package/dist/runtime/evaluator.js +46 -0
- package/dist/runtime/index.d.ts +8 -4
- package/dist/runtime/index.js +4 -2
- package/dist/runtime/plugin-adapter.d.ts +14 -1
- package/dist/runtime/plugin-adapter.js +23 -9
- package/dist/runtime/run-contracts.d.ts +5 -3
- package/dist/runtime/run-contracts.js +11 -1
- package/dist/runtime/run-controller.d.ts +15 -1
- package/dist/runtime/run-controller.js +235 -94
- package/dist/runtime/skill-adapter.js +24 -53
- package/dist/runtime/verifier.js +101 -2
- package/dist/runtime/workflow-plan-adapter.d.ts +2 -1
- package/dist/runtime/workflow-plan-adapter.js +78 -11
- package/dist/runtime/workflow-runtime-manifest.d.ts +48 -0
- package/dist/runtime/workflow-runtime-manifest.js +196 -0
- package/dist/runtime/workflow-variable-scopes.d.ts +12 -0
- package/dist/runtime/workflow-variable-scopes.js +55 -0
- package/dist/schema/types.d.ts +9 -0
- package/dist/schema/validate.js +29 -1
- package/dist/sources/authoring-packet.d.ts +8 -0
- package/dist/sources/authoring-packet.js +85 -0
- package/dist/sources/discovery.d.ts +7 -0
- package/dist/sources/discovery.js +150 -0
- package/dist/sources/license.d.ts +5 -0
- package/dist/sources/license.js +94 -0
- package/dist/sources/manifest.d.ts +11 -0
- package/dist/sources/manifest.js +84 -0
- package/dist/sources/skill-markdown.d.ts +6 -0
- package/dist/sources/skill-markdown.js +174 -0
- package/dist/sources/types.d.ts +125 -0
- package/dist/sources/types.js +1 -0
- package/dist/templates/asset-refinery.dna.yaml +192 -0
- package/dist/templates/flutter-behavior-lock.dna.yaml +17 -0
- package/dist/templates/flutter-refactoring-rescue.dna.yaml +11 -0
- package/dist/templates/flutter-rewrite.dna.yaml +154 -28
- package/dist/templates/metadata.js +2 -0
- package/dist/templates/multi-agent-handoff-coordination.dna.yaml +102 -37
- package/dist/templates/persistent-executor.dna.yaml +61 -3
- package/dist/templates/research-improvement.dna.yaml +295 -0
- package/dist/templates/subagent-parallel.dna.yaml +90 -17
- package/dist/templates/workflow-evidence-review.dna.yaml +8 -0
- package/dist/workflow/candidate-projection.d.ts +33 -0
- package/dist/workflow/candidate-projection.js +70 -0
- package/package.json +3 -1
- package/scripts/sync-release-plugin.cjs +87 -0
package/dist/hooks/cli.js
CHANGED
|
@@ -24,7 +24,7 @@ import { readStdinResult, writeOutput, silentOutput, allowOutput, blockOutput, s
|
|
|
24
24
|
import { validateHookInput } from "./schema.js";
|
|
25
25
|
import { hookFailureOutput } from "./enforcement-boundary.js";
|
|
26
26
|
import { enforcePreToolUse, enforcePostToolUse, enforceUserPromptSubmit, enforceSubagentStop, enforcePreCompact, enforceNotification, enforceSessionStart, enforceStop, extractBashWritePaths, checkReflectionLimit, checkContextReadiness, checkWorkflowBoundary, } from "./enforce.js";
|
|
27
|
-
import { appendAudit, readWorkflowState, appendTrace, appendRuntimeDecisionEvent, appendEvidenceCaptureEvent, rotateTraces, readTraces, cleanStaleState, readSurgeonAttempts, updateSurgeonAttempts, appendSessionRead, readSessionReads, appendVerifierResult, readVerifierResults, appendCompletedArtifact, artifactIdentity, buildArtifactKey, readArtifactManifest, resolveArtifactTemplate, safePathComponent, writeArtifactManifest, EVIDENCE_CAPTURE_SCHEMA_VERSION } from "./state.js";
|
|
27
|
+
import { appendAudit, readWorkflowState, appendTrace, appendRuntimeDecisionEvent, appendEvidenceCaptureEvent, rotateTraces, readTraces, cleanStaleState, readSurgeonAttempts, updateSurgeonAttempts, appendSessionRead, readSessionReads, appendVerifierResult, readVerifierResults, appendCompletedArtifact, artifactIdentity, buildArtifactKey, readArtifactManifest, resolveArtifactTemplate, safePathComponent, workflowTemplateVariables, writeArtifactManifest, EVIDENCE_CAPTURE_SCHEMA_VERSION } from "./state.js";
|
|
28
28
|
import { hookEventsForSurface } from "./event-registry.js";
|
|
29
29
|
import { writeAuditEvent } from "../audit/index.js";
|
|
30
30
|
import { RUNTIME_DECISION_EVENT_SCHEMA_VERSION, trustedEvidenceCaptureAttribution } from "../governance/index.js";
|
|
@@ -33,6 +33,90 @@ import { runCheckpointVerifier as runSharedCheckpointVerifier, runCompletionVeri
|
|
|
33
33
|
// ── Constants ──────────────────────────────────────────────
|
|
34
34
|
const DEFAULT_IR_PATH = ".dna/compiled/ir.json";
|
|
35
35
|
const VALID_EVENTS = new Set(hookEventsForSurface("cli"));
|
|
36
|
+
function workflowRuntimeRevisionMismatch(ir, state) {
|
|
37
|
+
if (!state?.active || state.resolved_variables_source !== "compiled_manifest")
|
|
38
|
+
return null;
|
|
39
|
+
const pinnedHash = state.workflow_runtime_compiled_ir_hash;
|
|
40
|
+
if (!pinnedHash)
|
|
41
|
+
return "Active workflow is missing its pinned compiled IR hash; restart it after running dna sync.";
|
|
42
|
+
if (!ir.compiled_ir_hash)
|
|
43
|
+
return "Current compiled IR is missing its hash; run dna sync and restart the active workflow.";
|
|
44
|
+
if (pinnedHash !== ir.compiled_ir_hash) {
|
|
45
|
+
return "Compiled IR changed during the active workflow; restart it before executing more tools.";
|
|
46
|
+
}
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
function isTerminalWorkflowDeactivation(event, rawInput, state) {
|
|
50
|
+
if (event !== "PreToolUse" || !state?.active)
|
|
51
|
+
return false;
|
|
52
|
+
const toolName = typeof rawInput.tool_name === "string" ? rawInput.tool_name : "";
|
|
53
|
+
const toolInput = rawInput.tool_input;
|
|
54
|
+
if (!toolName.endsWith("dna_workflow_write") || !toolInput || typeof toolInput !== "object")
|
|
55
|
+
return false;
|
|
56
|
+
const args = toolInput;
|
|
57
|
+
return args.active === false && args.workflow === state.workflow;
|
|
58
|
+
}
|
|
59
|
+
async function hookProjectBoundaryExists(projectDir) {
|
|
60
|
+
for (const marker of [".dna", ".git"]) {
|
|
61
|
+
try {
|
|
62
|
+
await stat(resolve(projectDir, marker));
|
|
63
|
+
return true;
|
|
64
|
+
}
|
|
65
|
+
catch (error) {
|
|
66
|
+
const code = error instanceof Error && "code" in error
|
|
67
|
+
? error.code
|
|
68
|
+
: undefined;
|
|
69
|
+
if (code !== "ENOENT" && code !== "ENOTDIR")
|
|
70
|
+
return true;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return false;
|
|
74
|
+
}
|
|
75
|
+
async function resolveHookRuntimePaths(cwd, irPath = DEFAULT_IR_PATH, explicitIRPath = false) {
|
|
76
|
+
const initialDir = resolve(cwd);
|
|
77
|
+
if (explicitIRPath) {
|
|
78
|
+
return {
|
|
79
|
+
projectDir: initialDir,
|
|
80
|
+
irPath: resolve(initialDir, irPath),
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
let candidateDir = initialDir;
|
|
84
|
+
while (true) {
|
|
85
|
+
const candidateIRPath = resolve(candidateDir, DEFAULT_IR_PATH);
|
|
86
|
+
try {
|
|
87
|
+
await stat(candidateIRPath);
|
|
88
|
+
return {
|
|
89
|
+
projectDir: candidateDir,
|
|
90
|
+
irPath: candidateIRPath,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
catch (error) {
|
|
94
|
+
const code = error instanceof Error && "code" in error
|
|
95
|
+
? error.code
|
|
96
|
+
: undefined;
|
|
97
|
+
if (code !== "ENOENT" && code !== "ENOTDIR") {
|
|
98
|
+
return {
|
|
99
|
+
projectDir: candidateDir,
|
|
100
|
+
irPath: candidateIRPath,
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
if (await hookProjectBoundaryExists(candidateDir)) {
|
|
105
|
+
return {
|
|
106
|
+
projectDir: candidateDir,
|
|
107
|
+
irPath: candidateIRPath,
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
const parentDir = dirname(candidateDir);
|
|
111
|
+
if (parentDir === candidateDir) {
|
|
112
|
+
return {
|
|
113
|
+
projectDir: initialDir,
|
|
114
|
+
irPath: resolve(initialDir, DEFAULT_IR_PATH),
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
candidateDir = parentDir;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
36
120
|
// ── Runtime Decision Evidence ────────────────────────────
|
|
37
121
|
function normalizeDecision(output) {
|
|
38
122
|
if (output.continue === false)
|
|
@@ -150,7 +234,12 @@ function buildRuntimeDecisionEvent(params) {
|
|
|
150
234
|
tool_name: typeof params.rawInput.tool_name === "string" ? params.rawInput.tool_name : "unknown",
|
|
151
235
|
action_kind: actionKind(params.rawInput),
|
|
152
236
|
resource_ref: resourceRef(params.rawInput),
|
|
153
|
-
evidence_refs: [
|
|
237
|
+
evidence_refs: [
|
|
238
|
+
{ type: "trace", ref: params.traceId },
|
|
239
|
+
...(params.wfState?.workflow_runtime_manifest_hash
|
|
240
|
+
? [{ type: "artifact", ref: params.wfState.workflow_runtime_manifest_hash }]
|
|
241
|
+
: []),
|
|
242
|
+
],
|
|
154
243
|
};
|
|
155
244
|
}
|
|
156
245
|
function captureResultForHook(rawInput, decision) {
|
|
@@ -277,9 +366,11 @@ async function main() {
|
|
|
277
366
|
return;
|
|
278
367
|
}
|
|
279
368
|
let irPath = DEFAULT_IR_PATH;
|
|
369
|
+
let explicitIRPath = false;
|
|
280
370
|
const irFlagIdx = args.indexOf("--ir");
|
|
281
371
|
if (irFlagIdx !== -1 && args[irFlagIdx + 1]) {
|
|
282
372
|
irPath = args[irFlagIdx + 1];
|
|
373
|
+
explicitIRPath = true;
|
|
283
374
|
}
|
|
284
375
|
// Read stdin
|
|
285
376
|
const stdin = await readStdinResult(5000);
|
|
@@ -297,10 +388,12 @@ async function main() {
|
|
|
297
388
|
}
|
|
298
389
|
const rawInput = validation.normalized;
|
|
299
390
|
// Resolve project directory from input or cwd
|
|
300
|
-
const
|
|
391
|
+
const cwd = typeof rawInput.cwd === "string" ? rawInput.cwd : process.cwd();
|
|
392
|
+
const runtimePaths = await resolveHookRuntimePaths(cwd, irPath, explicitIRPath);
|
|
393
|
+
const { projectDir } = runtimePaths;
|
|
301
394
|
const sessionId = typeof rawInput.sessionId === "string" ? rawInput.sessionId : undefined;
|
|
302
395
|
// Load compiled IR
|
|
303
|
-
const resolvedIRPath =
|
|
396
|
+
const resolvedIRPath = runtimePaths.irPath;
|
|
304
397
|
const ir = await loadIR(resolvedIRPath);
|
|
305
398
|
if (!ir) {
|
|
306
399
|
writeOutput(hookFailureOutput(event, "missing_ir", `Compiled IR is missing, unreadable, invalid, or version-incompatible at ${resolvedIRPath}.`));
|
|
@@ -361,6 +454,12 @@ export async function runHookEvent(options) {
|
|
|
361
454
|
return finish(workflowState.output);
|
|
362
455
|
}
|
|
363
456
|
wfStateRaw = workflowState.state;
|
|
457
|
+
const revisionMismatch = workflowRuntimeRevisionMismatch(ir, wfStateRaw);
|
|
458
|
+
if (revisionMismatch && !isTerminalWorkflowDeactivation(event, rawInput, wfStateRaw)) {
|
|
459
|
+
const mismatch = hookFailureOutput(event, "runtime_revision_mismatch", revisionMismatch);
|
|
460
|
+
await writeRuntimeDecision(mismatch, { output: mismatch, trace: { matched_rule: "workflow_runtime_revision", step_id: wfStateRaw?.current_step } }, wfStateRaw);
|
|
461
|
+
return finish(mismatch);
|
|
462
|
+
}
|
|
364
463
|
if (wfStateRaw?.active
|
|
365
464
|
&& typeof rawInput.agent_type === "string"
|
|
366
465
|
&& !subagentMatchesWorkflowRole(rawInput, wfStateRaw)) {
|
|
@@ -463,6 +562,12 @@ export async function runHookEvent(options) {
|
|
|
463
562
|
return finish(workflowState.output);
|
|
464
563
|
}
|
|
465
564
|
const wfState = workflowState.state;
|
|
565
|
+
const revisionMismatch = workflowRuntimeRevisionMismatch(ir, wfState);
|
|
566
|
+
if (revisionMismatch) {
|
|
567
|
+
const mismatch = hookFailureOutput(event, "runtime_revision_mismatch", revisionMismatch);
|
|
568
|
+
await writeRuntimeDecision(mismatch, { output: mismatch, trace: { matched_rule: "workflow_runtime_revision", step_id: wfState?.current_step } }, wfState);
|
|
569
|
+
return finish(mismatch);
|
|
570
|
+
}
|
|
466
571
|
let stopArtifactFacts = [];
|
|
467
572
|
if (wfState?.active) {
|
|
468
573
|
const artifactFacts = await finalizeAndResolveArtifactsForHook(projectDir, ir, wfState, event, sessionId);
|
|
@@ -759,11 +864,13 @@ async function runCodexHookCli(args) {
|
|
|
759
864
|
return;
|
|
760
865
|
}
|
|
761
866
|
const rawInput = stdin.data;
|
|
762
|
-
const
|
|
763
|
-
const
|
|
764
|
-
const
|
|
867
|
+
const cwd = typeof rawInput.cwd === "string" ? rawInput.cwd : process.cwd();
|
|
868
|
+
const explicitIRPath = argValue(args, "--ir");
|
|
869
|
+
const runtimePaths = await resolveHookRuntimePaths(cwd, explicitIRPath ?? DEFAULT_IR_PATH, explicitIRPath !== undefined);
|
|
870
|
+
const { projectDir, irPath } = runtimePaths;
|
|
871
|
+
const ir = await loadIR(irPath);
|
|
765
872
|
if (!ir) {
|
|
766
|
-
writeOutput(hookFailureOutput(policyEvent, "missing_ir", `Compiled IR is missing, unreadable, invalid, or version-incompatible at ${
|
|
873
|
+
writeOutput(hookFailureOutput(policyEvent, "missing_ir", `Compiled IR is missing, unreadable, invalid, or version-incompatible at ${irPath}.`));
|
|
767
874
|
return;
|
|
768
875
|
}
|
|
769
876
|
const result = await runCodexHookWithLoadedIr(rawInput, projectDir, args, ir);
|
|
@@ -1014,6 +1121,7 @@ export const recordProducedArtifactsForTest = recordProducedArtifacts;
|
|
|
1014
1121
|
export const resolveWorkflowArtifactFactsForTest = resolveWorkflowArtifactFacts;
|
|
1015
1122
|
export const readWorkflowStateForHookTest = readWorkflowStateForHook;
|
|
1016
1123
|
export const runCodexHookWithLoadedIrForTest = runCodexHookWithLoadedIr;
|
|
1124
|
+
export const resolveHookRuntimePathsForTest = resolveHookRuntimePaths;
|
|
1017
1125
|
export const inferWorkflowAssetFromIrForTest = inferWorkflowAssetFromIr;
|
|
1018
1126
|
export const resolveWorkflowArtifactFactsForHookTest = resolveWorkflowArtifactFactsForHook;
|
|
1019
1127
|
export const finalizeAndResolveArtifactsForHookTest = finalizeAndResolveArtifactsForHook;
|
|
@@ -1137,7 +1245,7 @@ async function runVerifierSpec(projectDir, ir, spec, workflowState, sessionId, o
|
|
|
1137
1245
|
if (spec.kind === "checkpoint" && spec.checkpoint) {
|
|
1138
1246
|
const checkpointResult = await runSharedCheckpointVerifier(spec.checkpoint, ir, {
|
|
1139
1247
|
projectDir,
|
|
1140
|
-
variables:
|
|
1248
|
+
variables: workflowTemplateVariables(workflowState),
|
|
1141
1249
|
commandTimeoutMs: options?.commandTimeoutMs,
|
|
1142
1250
|
});
|
|
1143
1251
|
passed = checkpointResult.passed;
|
|
@@ -1157,7 +1265,7 @@ async function runVerifierSpec(projectDir, ir, spec, workflowState, sessionId, o
|
|
|
1157
1265
|
else {
|
|
1158
1266
|
const completionResult = await runCompletionVerifier(completion, ir, {
|
|
1159
1267
|
projectDir,
|
|
1160
|
-
variables:
|
|
1268
|
+
variables: workflowTemplateVariables(workflowState),
|
|
1161
1269
|
commandTimeoutMs: options?.commandTimeoutMs,
|
|
1162
1270
|
});
|
|
1163
1271
|
passed = completionResult.passed;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { HookEvent } from "./event-registry.js";
|
|
2
2
|
import { type HookOutput } from "./protocol.js";
|
|
3
|
-
export type HookFailureKind = "malformed_input" | "missing_ir" | "role_mismatch" | "gate_evaluation" | "bash_write_scope";
|
|
3
|
+
export type HookFailureKind = "malformed_input" | "missing_ir" | "runtime_revision_mismatch" | "role_mismatch" | "gate_evaluation" | "bash_write_scope";
|
|
4
4
|
export type HookFailureDisposition = "advisory" | "blocking";
|
|
5
5
|
/**
|
|
6
6
|
* Foundation Hook failure policy.
|
package/dist/hooks/protocol.d.ts
CHANGED
|
@@ -59,7 +59,7 @@ export interface HookOutput {
|
|
|
59
59
|
permissionDecision?: "ask" | "allow" | "deny";
|
|
60
60
|
};
|
|
61
61
|
}
|
|
62
|
-
export type MatchedRule = "scope" | "filter" | "gate" | "schema" | "validator" | "handoff" | "step_rule" | "output_schema" | "context_gate" | "reflection_gate" | "workflow_boundary";
|
|
62
|
+
export type MatchedRule = "scope" | "filter" | "gate" | "schema" | "validator" | "handoff" | "step_rule" | "output_schema" | "context_gate" | "reflection_gate" | "workflow_runtime_revision" | "workflow_boundary";
|
|
63
63
|
export interface TraceMetadata {
|
|
64
64
|
matched_rule: MatchedRule;
|
|
65
65
|
gene_id?: string;
|
package/dist/hooks/state.d.ts
CHANGED
|
@@ -30,6 +30,10 @@ export interface DNAWorkflowState {
|
|
|
30
30
|
started_at: string;
|
|
31
31
|
inputs?: Record<string, string>;
|
|
32
32
|
resolved_variables?: Record<string, string>;
|
|
33
|
+
resolved_variables_source?: "compiled_manifest" | "legacy_skill";
|
|
34
|
+
workflow_runtime_manifest_hash?: string;
|
|
35
|
+
workflow_runtime_compiled_ir_hash?: string;
|
|
36
|
+
workflow_inputs_pinned?: boolean;
|
|
33
37
|
completed_artifacts?: CompletedArtifactEntry[];
|
|
34
38
|
}
|
|
35
39
|
/** Audit log entry (one per line in JSON Lines format) */
|
|
@@ -117,6 +121,7 @@ export declare function buildArtifactKey(params: {
|
|
|
117
121
|
}): ArtifactKey;
|
|
118
122
|
export declare function artifactManifestPath(projectDir: string, key: ArtifactKey): string;
|
|
119
123
|
export declare function resolveArtifactTemplate(template: string, state?: Pick<DNAWorkflowState, "inputs" | "resolved_variables">): string | null;
|
|
124
|
+
export declare function workflowTemplateVariables(state?: Pick<DNAWorkflowState, "inputs" | "resolved_variables">): Record<string, string>;
|
|
120
125
|
export declare function writeArtifactManifest(projectDir: string, manifest: Omit<ArtifactManifest, "id" | "recorded_at" | "resolver_version">): Promise<ArtifactFact>;
|
|
121
126
|
export declare function readArtifactManifest(projectDir: string, key: ArtifactKey): Promise<ArtifactFact | null>;
|
|
122
127
|
/**
|
package/dist/hooks/state.js
CHANGED
|
@@ -78,16 +78,19 @@ export function resolveArtifactTemplate(template, state) {
|
|
|
78
78
|
const resolvedVariables = state?.resolved_variables ?? {};
|
|
79
79
|
resolved = resolved.replace(/\{\{(\w+)\}\}/g, (_match, name) => {
|
|
80
80
|
const inputValue = inputs[name];
|
|
81
|
-
|
|
81
|
+
const resolvedValue = resolvedVariables[name];
|
|
82
|
+
if (USER_ARTIFACT_PATH_ARGUMENTS.has(name) && inputValue !== undefined) {
|
|
82
83
|
return safeUserArtifactPathArgument(inputValue, name) ?? `{{${name}}}`;
|
|
83
84
|
}
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
if (USER_ARTIFACT_PATH_ARGUMENTS.has(name)) {
|
|
85
|
+
if (resolvedValue !== undefined) {
|
|
86
|
+
if (!USER_ARTIFACT_PATH_ARGUMENTS.has(name))
|
|
87
|
+
return resolvedValue;
|
|
88
88
|
return safeUserArtifactPathArgument(resolvedValue, name) ?? `{{${name}}}`;
|
|
89
89
|
}
|
|
90
|
-
|
|
90
|
+
if (inputValue !== undefined) {
|
|
91
|
+
return safeUserArtifactPathArgument(inputValue, name) ?? `{{${name}}}`;
|
|
92
|
+
}
|
|
93
|
+
return `{{${name}}}`;
|
|
91
94
|
});
|
|
92
95
|
const args = inputs.ARGUMENTS ?? inputs.arguments ?? inputs.task_id ?? resolvedVariables.ARGUMENTS ?? resolvedVariables.arguments ?? resolvedVariables.task_id;
|
|
93
96
|
if (resolved.includes("$ARGUMENTS")) {
|
|
@@ -102,6 +105,18 @@ export function resolveArtifactTemplate(template, state) {
|
|
|
102
105
|
return null;
|
|
103
106
|
return resolved;
|
|
104
107
|
}
|
|
108
|
+
export function workflowTemplateVariables(state) {
|
|
109
|
+
const variables = { ...(state?.inputs ?? {}) };
|
|
110
|
+
const argumentsValue = variables.ARGUMENTS ?? variables.arguments ?? variables.task_id;
|
|
111
|
+
for (const [name, value] of Object.entries(state?.resolved_variables ?? {})) {
|
|
112
|
+
if (!USER_ARTIFACT_PATH_ARGUMENTS.has(name) || variables[name] === undefined) {
|
|
113
|
+
variables[name] = argumentsValue === undefined
|
|
114
|
+
? value
|
|
115
|
+
: value.replace(/(^|[^\\])\$ARGUMENTS/g, (_match, prefix) => `${prefix}${argumentsValue}`);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
return variables;
|
|
119
|
+
}
|
|
105
120
|
export async function writeArtifactManifest(projectDir, manifest) {
|
|
106
121
|
const id = artifactHash(manifest.key);
|
|
107
122
|
const full = {
|
package/dist/mcp/tools-state.js
CHANGED
|
@@ -10,12 +10,111 @@
|
|
|
10
10
|
import { resolve } from "node:path";
|
|
11
11
|
import { readWorkflowState, writeWorkflowState, readRuntimeDecisionEvents, readTraces, listSessions } from "../hooks/state.js";
|
|
12
12
|
import { validateRuntimeDecisionEvent } from "../governance/index.js";
|
|
13
|
-
import { loadCompiledIR } from "../runtime/plugin-adapter.js";
|
|
14
|
-
import {
|
|
13
|
+
import { loadCompiledIR, loadCompiledIRResult } from "../runtime/plugin-adapter.js";
|
|
14
|
+
import { validateWorkflowRuntimeManifest } from "../runtime/workflow-runtime-manifest.js";
|
|
15
|
+
import { errorResult, textResult } from "./server.js";
|
|
15
16
|
function isStringRecord(value) {
|
|
16
|
-
return typeof value === "object" && value !== null &&
|
|
17
|
+
return typeof value === "object" && value !== null && !Array.isArray(value) &&
|
|
17
18
|
Object.values(value).every(v => typeof v === "string");
|
|
18
19
|
}
|
|
20
|
+
function sameStringRecord(a, b) {
|
|
21
|
+
const aKeys = Object.keys(a).sort();
|
|
22
|
+
const bKeys = Object.keys(b).sort();
|
|
23
|
+
return aKeys.length === bKeys.length && aKeys.every((key, index) => key === bKeys[index] && a[key] === b[key]);
|
|
24
|
+
}
|
|
25
|
+
const RUNTIME_ARGUMENT_NAMES = ["ARGUMENTS", "arguments", "task_id"];
|
|
26
|
+
function compatibleManifestInputCandidate(binding, candidate) {
|
|
27
|
+
if (!candidate)
|
|
28
|
+
return { ignored: [] };
|
|
29
|
+
const allowed = new Set([...binding.runtime_input_refs, ...RUNTIME_ARGUMENT_NAMES]);
|
|
30
|
+
const entries = Object.entries(candidate);
|
|
31
|
+
return {
|
|
32
|
+
candidate: Object.fromEntries(entries.filter(([name]) => allowed.has(name))),
|
|
33
|
+
ignored: entries.filter(([name]) => !allowed.has(name)).map(([name]) => name).sort(),
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
async function lookupRuntimeBinding(projectDir, workflow) {
|
|
37
|
+
const result = await loadCompiledIRResult(resolve(projectDir, ".dna", "compiled", "ir.json"));
|
|
38
|
+
if (result.status === "missing") {
|
|
39
|
+
return { status: "error", kind: "invalid_ir", message: "No compiled IR found. Run `dna sync` before starting or continuing this workflow." };
|
|
40
|
+
}
|
|
41
|
+
if (result.status === "invalid") {
|
|
42
|
+
return { status: "error", kind: "invalid_ir", message: `Invalid compiled IR: ${result.reason}. Run \`dna sync\` before starting or continuing this workflow.` };
|
|
43
|
+
}
|
|
44
|
+
const compiled = result.compiled;
|
|
45
|
+
if (!Object.prototype.hasOwnProperty.call(compiled, "workflow_runtime")) {
|
|
46
|
+
return { status: "legacy", compiledIrHash: compiled.compiled_ir_hash };
|
|
47
|
+
}
|
|
48
|
+
if (typeof compiled.compiled_ir_hash !== "string" ||
|
|
49
|
+
typeof compiled.ir.compiled_ir_hash !== "string" ||
|
|
50
|
+
compiled.compiled_ir_hash !== compiled.ir.compiled_ir_hash) {
|
|
51
|
+
return {
|
|
52
|
+
status: "error",
|
|
53
|
+
kind: "invalid_ir",
|
|
54
|
+
message: "Invalid compiled IR: workflow runtime bindings require matching wrapper and IR hashes. Run `dna sync` before starting or continuing this workflow.",
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
const validation = validateWorkflowRuntimeManifest(compiled.workflow_runtime, compiled.compiled_ir_hash);
|
|
58
|
+
if (!validation.valid) {
|
|
59
|
+
return {
|
|
60
|
+
status: "error",
|
|
61
|
+
kind: "invalid_manifest",
|
|
62
|
+
compiledIrHash: compiled.compiled_ir_hash,
|
|
63
|
+
message: `Invalid compiled workflow runtime manifest: ${validation.reason}. Run \`dna sync\` before starting or continuing this workflow.`,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
if (!Object.prototype.hasOwnProperty.call(validation.manifest.workflows, workflow)) {
|
|
67
|
+
return {
|
|
68
|
+
status: "error",
|
|
69
|
+
kind: "workflow_missing",
|
|
70
|
+
compiledIrHash: validation.manifest.compiled_ir_hash,
|
|
71
|
+
message: `Workflow ${workflow} is not present in the compiled workflow runtime manifest. Run \`dna sync\` to refresh generated runtime artifacts.`,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
const binding = validation.manifest.workflows[workflow];
|
|
75
|
+
return {
|
|
76
|
+
status: "found",
|
|
77
|
+
binding,
|
|
78
|
+
manifestHash: validation.manifest.manifest_hash,
|
|
79
|
+
compiledIrHash: validation.manifest.compiled_ir_hash,
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
function normalizeManifestInputs(binding, candidate) {
|
|
83
|
+
const rawInputs = { ...(candidate ?? {}) };
|
|
84
|
+
const allowed = new Set([...binding.runtime_input_refs, ...RUNTIME_ARGUMENT_NAMES]);
|
|
85
|
+
const unexpected = Object.keys(rawInputs).filter((name) => !allowed.has(name));
|
|
86
|
+
if (unexpected.length > 0) {
|
|
87
|
+
return { valid: false, message: `Workflow inputs are not declared by the compiled runtime binding: ${unexpected.join(", ")}` };
|
|
88
|
+
}
|
|
89
|
+
const argumentValues = RUNTIME_ARGUMENT_NAMES
|
|
90
|
+
.map((name) => rawInputs[name])
|
|
91
|
+
.filter((value) => value !== undefined);
|
|
92
|
+
const distinctArgumentValues = [...new Set(argumentValues)];
|
|
93
|
+
if (distinctArgumentValues.length > 1) {
|
|
94
|
+
return { valid: false, message: "ARGUMENTS, arguments, and task_id must identify the same runtime input." };
|
|
95
|
+
}
|
|
96
|
+
const argumentValue = distinctArgumentValues[0];
|
|
97
|
+
if (!binding.requires_arguments && argumentValue !== undefined) {
|
|
98
|
+
return { valid: true, note: "Ignored legacy argument input for an argument-free workflow." };
|
|
99
|
+
}
|
|
100
|
+
if (binding.requires_arguments && (!argumentValue || argumentValue.trim() === "")) {
|
|
101
|
+
return { valid: false, message: "This workflow requires a non-empty ARGUMENTS input." };
|
|
102
|
+
}
|
|
103
|
+
const inputs = {};
|
|
104
|
+
for (const name of binding.runtime_input_refs) {
|
|
105
|
+
if (RUNTIME_ARGUMENT_NAMES.includes(name)) {
|
|
106
|
+
if (argumentValue !== undefined)
|
|
107
|
+
inputs[name] = argumentValue;
|
|
108
|
+
}
|
|
109
|
+
else if (rawInputs[name] !== undefined) {
|
|
110
|
+
inputs[name] = rawInputs[name];
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
return { valid: false, message: `This workflow requires runtime input ${name}.` };
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
return { valid: true, inputs: Object.keys(inputs).length > 0 ? inputs : undefined };
|
|
117
|
+
}
|
|
19
118
|
export function createStateTools(projectDir) {
|
|
20
119
|
return [
|
|
21
120
|
// ── dna_status ────────────────────────────────────────
|
|
@@ -39,6 +138,15 @@ export function createStateTools(projectDir) {
|
|
|
39
138
|
if (ir.workflows_ir?.length) {
|
|
40
139
|
lines.push(` Workflows: ${ir.workflows_ir.map(w => w.workflow_name).join(", ")}`);
|
|
41
140
|
}
|
|
141
|
+
if (!Object.prototype.hasOwnProperty.call(compiled, "workflow_runtime")) {
|
|
142
|
+
lines.push(" Workflow runtime: legacy; workflow starts are blocked until `dna sync` regenerates deterministic bindings");
|
|
143
|
+
}
|
|
144
|
+
else {
|
|
145
|
+
const runtimeValidation = validateWorkflowRuntimeManifest(compiled.workflow_runtime, compiled.compiled_ir_hash);
|
|
146
|
+
lines.push(runtimeValidation.valid
|
|
147
|
+
? ` Workflow runtime: ${runtimeValidation.manifest.schema_version}`
|
|
148
|
+
: ` Workflow runtime: invalid (${runtimeValidation.reason}); run \`dna sync\``);
|
|
149
|
+
}
|
|
42
150
|
}
|
|
43
151
|
else {
|
|
44
152
|
lines.push("IR: not found (run `dna sync` to compile)");
|
|
@@ -99,40 +207,168 @@ export function createStateTools(projectDir) {
|
|
|
99
207
|
// ── dna_workflow_write ────────────────────────────────
|
|
100
208
|
{
|
|
101
209
|
name: "dna_workflow_write",
|
|
102
|
-
description: "Update workflow state
|
|
210
|
+
description: "Update workflow state. Template variables and workflow asset identity are initialized from the compiled runtime manifest.",
|
|
103
211
|
inputSchema: {
|
|
104
212
|
type: "object",
|
|
105
213
|
properties: {
|
|
106
214
|
workflow: { type: "string", description: "Workflow name" },
|
|
107
|
-
workflow_asset: { type: "string", description: "
|
|
215
|
+
workflow_asset: { type: "string", description: "Deprecated Skill input; ignored because the compiled runtime manifest owns workflow attribution" },
|
|
108
216
|
current_step: { type: "string", description: "Current step ID" },
|
|
109
217
|
current_role: { type: "string", description: "Current role name" },
|
|
110
218
|
iteration: { type: "number", description: "Current iteration number" },
|
|
111
219
|
active: { type: "boolean", description: "Whether workflow is active (false to deactivate)" },
|
|
112
220
|
session_id: { type: "string", description: "Session ID for isolation" },
|
|
113
221
|
inputs: { type: "object", description: "Workflow runtime inputs such as ARGUMENTS" },
|
|
114
|
-
resolved_variables: { type: "object", description: "
|
|
222
|
+
resolved_variables: { type: "object", description: "Deprecated Skill input; ignored when a manifest exists and never accepted as compiled configuration" },
|
|
115
223
|
},
|
|
116
224
|
required: ["workflow", "current_step", "current_role"],
|
|
117
225
|
},
|
|
118
226
|
handler: async (args) => {
|
|
119
227
|
const sessionId = typeof args.session_id === "string" ? args.session_id : undefined;
|
|
120
228
|
const existing = await readWorkflowState(projectDir, sessionId, 0);
|
|
229
|
+
const workflow = String(args.workflow);
|
|
230
|
+
if (existing?.active && existing.workflow !== workflow) {
|
|
231
|
+
return errorResult(`Workflow ${existing.workflow} is already active. Deactivate it before starting or writing state for ${workflow}.`);
|
|
232
|
+
}
|
|
233
|
+
const sameActiveWorkflow = existing?.active === true && existing.workflow === workflow;
|
|
234
|
+
const closingWorkflow = args.active === false;
|
|
235
|
+
if (sameActiveWorkflow && closingWorkflow) {
|
|
236
|
+
const state = {
|
|
237
|
+
...existing,
|
|
238
|
+
active: false,
|
|
239
|
+
current_step: String(args.current_step),
|
|
240
|
+
current_role: String(args.current_role),
|
|
241
|
+
iteration: typeof args.iteration === "number" ? args.iteration : existing.iteration,
|
|
242
|
+
};
|
|
243
|
+
await writeWorkflowState(projectDir, state, sessionId);
|
|
244
|
+
return textResult(`Workflow state updated: ${state.workflow} step=${state.current_step} role=${state.current_role} iteration=${state.iteration}\n`
|
|
245
|
+
+ "Terminal deactivation preserved the run's pinned state and ignored replacement runtime bindings.");
|
|
246
|
+
}
|
|
247
|
+
const runtimeBinding = await lookupRuntimeBinding(projectDir, workflow);
|
|
248
|
+
const hasPinnedRuntimeBinding = sameActiveWorkflow &&
|
|
249
|
+
existing?.resolved_variables_source === "compiled_manifest" &&
|
|
250
|
+
typeof existing.workflow_runtime_manifest_hash === "string" &&
|
|
251
|
+
typeof existing.workflow_runtime_compiled_ir_hash === "string";
|
|
252
|
+
if (runtimeBinding.status === "error" && !hasPinnedRuntimeBinding) {
|
|
253
|
+
return errorResult(runtimeBinding.message);
|
|
254
|
+
}
|
|
255
|
+
const currentCompiledIrHash = runtimeBinding.compiledIrHash;
|
|
256
|
+
if (hasPinnedRuntimeBinding &&
|
|
257
|
+
currentCompiledIrHash !== existing.workflow_runtime_compiled_ir_hash &&
|
|
258
|
+
!closingWorkflow) {
|
|
259
|
+
return errorResult("The compiled IR changed during this active workflow. Restart the workflow so one run cannot execute against multiple policy revisions.");
|
|
260
|
+
}
|
|
261
|
+
if (args.inputs !== undefined && !isStringRecord(args.inputs)) {
|
|
262
|
+
return errorResult("Workflow inputs must be an object whose values are strings.");
|
|
263
|
+
}
|
|
264
|
+
const providedInputs = isStringRecord(args.inputs) ? args.inputs : undefined;
|
|
265
|
+
let inputs;
|
|
266
|
+
let workflowInputsPinned = sameActiveWorkflow ? existing?.workflow_inputs_pinned : undefined;
|
|
267
|
+
let workflowAsset;
|
|
268
|
+
let resolvedVariables;
|
|
269
|
+
let resolvedVariablesSource;
|
|
270
|
+
let workflowRuntimeManifestHash;
|
|
271
|
+
let workflowRuntimeCompiledIrHash;
|
|
272
|
+
const notes = [];
|
|
273
|
+
if (hasPinnedRuntimeBinding) {
|
|
274
|
+
workflowAsset = existing.workflow_asset;
|
|
275
|
+
resolvedVariables = existing.resolved_variables;
|
|
276
|
+
resolvedVariablesSource = "compiled_manifest";
|
|
277
|
+
workflowRuntimeManifestHash = existing.workflow_runtime_manifest_hash;
|
|
278
|
+
workflowRuntimeCompiledIrHash = existing.workflow_runtime_compiled_ir_hash;
|
|
279
|
+
workflowInputsPinned = true;
|
|
280
|
+
if (providedInputs) {
|
|
281
|
+
const normalized = runtimeBinding.status === "found"
|
|
282
|
+
? normalizeManifestInputs(runtimeBinding.binding, providedInputs)
|
|
283
|
+
: { valid: true, inputs: providedInputs };
|
|
284
|
+
if (!normalized.valid)
|
|
285
|
+
return errorResult(normalized.message);
|
|
286
|
+
if (!sameStringRecord(existing.inputs ?? {}, normalized.inputs ?? {})) {
|
|
287
|
+
return errorResult("Workflow inputs are pinned for an active run and cannot be changed. Finish or restart the workflow to use different inputs.");
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
inputs = existing.inputs;
|
|
291
|
+
if (args.resolved_variables !== undefined) {
|
|
292
|
+
notes.push("Deprecated resolved_variables input ignored; active workflow bindings are pinned.");
|
|
293
|
+
}
|
|
294
|
+
if (runtimeBinding.status === "found" && runtimeBinding.manifestHash !== workflowRuntimeManifestHash) {
|
|
295
|
+
notes.push("A newer compiled workflow runtime manifest exists; this active workflow remains pinned to its start-time bindings.");
|
|
296
|
+
}
|
|
297
|
+
else if (runtimeBinding.status === "error") {
|
|
298
|
+
notes.push("The compiled workflow manifest is invalid or unavailable; this run remains pinned to the same compiled IR revision. Run `dna sync` before the next workflow.");
|
|
299
|
+
}
|
|
300
|
+
else if (runtimeBinding.status === "legacy") {
|
|
301
|
+
notes.push("The compiled runtime manifest is unavailable; this active workflow remains pinned, but `dna sync` is required before the next workflow.");
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
else if (runtimeBinding.status === "found") {
|
|
305
|
+
let candidateInputs = providedInputs ?? (sameActiveWorkflow ? existing?.inputs : undefined);
|
|
306
|
+
if (sameActiveWorkflow && existing?.resolved_variables_source !== "compiled_manifest") {
|
|
307
|
+
const existingCandidate = compatibleManifestInputCandidate(runtimeBinding.binding, existing.inputs);
|
|
308
|
+
const providedCandidate = compatibleManifestInputCandidate(runtimeBinding.binding, providedInputs);
|
|
309
|
+
const normalizedExisting = normalizeManifestInputs(runtimeBinding.binding, existingCandidate.candidate);
|
|
310
|
+
const normalizedProvided = providedInputs
|
|
311
|
+
? normalizeManifestInputs(runtimeBinding.binding, providedCandidate.candidate)
|
|
312
|
+
: null;
|
|
313
|
+
if (normalizedExisting.valid && normalizedExisting.inputs) {
|
|
314
|
+
if (normalizedProvided?.valid && normalizedProvided.inputs &&
|
|
315
|
+
!sameStringRecord(normalizedExisting.inputs, normalizedProvided.inputs)) {
|
|
316
|
+
return errorResult("Workflow inputs are pinned for an active legacy run and cannot be changed during migration.");
|
|
317
|
+
}
|
|
318
|
+
candidateInputs = existingCandidate.candidate;
|
|
319
|
+
}
|
|
320
|
+
else {
|
|
321
|
+
candidateInputs = { ...existingCandidate.candidate, ...providedCandidate.candidate };
|
|
322
|
+
}
|
|
323
|
+
const ignored = [...new Set([...existingCandidate.ignored, ...providedCandidate.ignored])];
|
|
324
|
+
if (ignored.length > 0) {
|
|
325
|
+
notes.push(`Ignored legacy workflow input metadata during migration: ${ignored.join(", ")}.`);
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
const normalizedInputs = normalizeManifestInputs(runtimeBinding.binding, candidateInputs);
|
|
329
|
+
if (!normalizedInputs.valid)
|
|
330
|
+
return errorResult(normalizedInputs.message);
|
|
331
|
+
inputs = normalizedInputs.inputs;
|
|
332
|
+
workflowInputsPinned = true;
|
|
333
|
+
workflowAsset = runtimeBinding.binding.workflow_asset;
|
|
334
|
+
resolvedVariables = runtimeBinding.binding.resolved_variables;
|
|
335
|
+
resolvedVariablesSource = "compiled_manifest";
|
|
336
|
+
workflowRuntimeManifestHash = runtimeBinding.manifestHash;
|
|
337
|
+
workflowRuntimeCompiledIrHash = runtimeBinding.compiledIrHash;
|
|
338
|
+
if (normalizedInputs.note)
|
|
339
|
+
notes.push(normalizedInputs.note);
|
|
340
|
+
if (args.resolved_variables !== undefined) {
|
|
341
|
+
notes.push("Deprecated resolved_variables input ignored; compiled workflow runtime manifest is authoritative.");
|
|
342
|
+
}
|
|
343
|
+
if (sameActiveWorkflow && existing?.resolved_variables_source !== "compiled_manifest") {
|
|
344
|
+
notes.push("Legacy workflow state upgraded to compiled workflow runtime bindings.");
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
else {
|
|
348
|
+
return errorResult("This project has a legacy compiled IR without deterministic workflow runtime bindings. Run `dna sync` with the upgraded IntentDNA CLI, then retry the workflow. Model-supplied workflow_asset and resolved_variables are not trusted.");
|
|
349
|
+
}
|
|
121
350
|
const state = {
|
|
122
351
|
active: typeof args.active === "boolean" ? args.active : true,
|
|
123
|
-
workflow_asset:
|
|
124
|
-
workflow
|
|
352
|
+
workflow_asset: workflowAsset,
|
|
353
|
+
workflow,
|
|
125
354
|
current_step: String(args.current_step),
|
|
126
355
|
current_role: String(args.current_role),
|
|
127
|
-
iteration: typeof args.iteration === "number" ? args.iteration : (existing?.iteration ?? 1),
|
|
128
|
-
session_id: sessionId ?? existing?.session_id ?? "",
|
|
129
|
-
started_at: existing
|
|
130
|
-
inputs
|
|
131
|
-
resolved_variables:
|
|
132
|
-
|
|
356
|
+
iteration: typeof args.iteration === "number" ? args.iteration : (sameActiveWorkflow ? existing?.iteration ?? 1 : 1),
|
|
357
|
+
session_id: sessionId ?? (sameActiveWorkflow ? existing?.session_id : undefined) ?? "",
|
|
358
|
+
started_at: sameActiveWorkflow ? existing.started_at : new Date().toISOString(),
|
|
359
|
+
inputs,
|
|
360
|
+
resolved_variables: resolvedVariables,
|
|
361
|
+
resolved_variables_source: resolvedVariablesSource,
|
|
362
|
+
workflow_runtime_manifest_hash: workflowRuntimeManifestHash,
|
|
363
|
+
workflow_runtime_compiled_ir_hash: workflowRuntimeCompiledIrHash,
|
|
364
|
+
workflow_inputs_pinned: workflowInputsPinned,
|
|
365
|
+
completed_artifacts: sameActiveWorkflow ? existing?.completed_artifacts : undefined,
|
|
133
366
|
};
|
|
134
367
|
await writeWorkflowState(projectDir, state, sessionId);
|
|
135
|
-
return textResult(
|
|
368
|
+
return textResult([
|
|
369
|
+
`Workflow state updated: ${state.workflow} step=${state.current_step} role=${state.current_role} iteration=${state.iteration}`,
|
|
370
|
+
...notes,
|
|
371
|
+
].join("\n"));
|
|
136
372
|
},
|
|
137
373
|
},
|
|
138
374
|
// ── dna_trace_query ──────────────────────────────────
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { ConstraintIR, RoleDef } from "../schema/types.js";
|
|
2
2
|
import type { SyncOutputArtifactId } from "./output-artifact-registry.js";
|
|
3
3
|
import { type CompiledIRFile } from "./plugin-adapter.js";
|
|
4
|
+
import type { WorkflowRuntimeManifest } from "./workflow-runtime-manifest.js";
|
|
4
5
|
import { type DNASettings, type HookEventKey, type IntentDNASettingsHookCleanupResult } from "./settings-adapter.js";
|
|
5
6
|
import type { AdapterCapabilityReport, CapabilityReportEntry, PlannedArtifact, SyncTargetPlan } from "./sync-target-plan.js";
|
|
6
7
|
export type ClaudeSyncMode = "plugin" | "bin";
|
|
@@ -21,6 +22,7 @@ export interface ClaudeCoreSyncTargetPlanOptions {
|
|
|
21
22
|
projectDir: string;
|
|
22
23
|
ir: ConstraintIR;
|
|
23
24
|
roles?: Record<string, RoleDef>;
|
|
25
|
+
workflowRuntime?: WorkflowRuntimeManifest;
|
|
24
26
|
mode: ClaudeSyncMode;
|
|
25
27
|
settingsPath?: string;
|
|
26
28
|
}
|
|
@@ -43,7 +43,7 @@ function createSettingsHookRegistration(ir, mode, settingsPath) {
|
|
|
43
43
|
};
|
|
44
44
|
}
|
|
45
45
|
export function createClaudeCoreSyncTargetPlan(options) {
|
|
46
|
-
const compiledIR = createCompiledIR(options.ir, options.roles);
|
|
46
|
+
const compiledIR = createCompiledIR(options.ir, options.roles, options.workflowRuntime);
|
|
47
47
|
const compiledIRPath = resolve(options.projectDir, ".dna", "compiled", "ir.json");
|
|
48
48
|
const legacyHooksDir = resolve(options.projectDir, ".claude", "hooks");
|
|
49
49
|
const mcpConfigPath = resolve(options.projectDir, ".mcp.json");
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export declare const MAX_EVALUATOR_RESULT_BYTES = 65536;
|
|
2
|
+
export interface EvaluatorResult {
|
|
3
|
+
readonly pass: boolean;
|
|
4
|
+
readonly score?: number;
|
|
5
|
+
}
|
|
6
|
+
export interface ParseEvaluatorResultOptions {
|
|
7
|
+
readonly require_score?: boolean;
|
|
8
|
+
readonly max_bytes?: number;
|
|
9
|
+
}
|
|
10
|
+
export declare class EvaluatorResultError extends Error {
|
|
11
|
+
constructor(message: string);
|
|
12
|
+
}
|
|
13
|
+
export declare function parseEvaluatorResult(raw: string, options?: ParseEvaluatorResultOptions): EvaluatorResult;
|