intentdna 1.2.2 → 1.3.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.
- package/.claude-plugin/hooks/hooks.json +12 -0
- package/.claude-plugin/plugin.json +5 -0
- package/dist/audit/index.d.ts +0 -1
- package/dist/audit/index.js +0 -1
- package/dist/cli/commands/compile.d.ts +0 -1
- package/dist/cli/commands/compile.js +0 -1
- package/dist/cli/commands/epigenetic.d.ts +0 -1
- package/dist/cli/commands/epigenetic.js +0 -1
- package/dist/cli/commands/evolve.d.ts +0 -1
- package/dist/cli/commands/evolve.js +0 -1
- package/dist/cli/commands/guard.d.ts +0 -1
- package/dist/cli/commands/guard.js +0 -3
- package/dist/cli/commands/import.d.ts +0 -1
- package/dist/cli/commands/import.js +0 -1
- package/dist/cli/commands/init.d.ts +0 -1
- package/dist/cli/commands/init.js +0 -1
- package/dist/cli/commands/run.d.ts +0 -1
- package/dist/cli/commands/run.js +4 -27
- package/dist/cli/commands/setup.d.ts +9 -0
- package/dist/cli/commands/setup.js +42 -0
- package/dist/cli/commands/show.d.ts +0 -1
- package/dist/cli/commands/show.js +0 -1
- package/dist/cli/commands/sync.d.ts +13 -1
- package/dist/cli/commands/sync.js +158 -33
- package/dist/cli/commands/validate.d.ts +0 -1
- package/dist/cli/commands/validate.js +0 -1
- package/dist/cli/commands/verify.d.ts +0 -1
- package/dist/cli/commands/verify.js +0 -1
- package/dist/cli/index.d.ts +0 -1
- package/dist/cli/index.js +9 -1
- package/dist/cli/util/format.d.ts +0 -1
- package/dist/cli/util/format.js +0 -1
- package/dist/cli/util/prompt.d.ts +0 -1
- package/dist/cli/util/prompt.js +0 -1
- package/dist/compiler/activate.d.ts +0 -1
- package/dist/compiler/activate.js +0 -1
- package/dist/compiler/cascade.d.ts +1 -3
- package/dist/compiler/cascade.js +1 -10
- package/dist/compiler/compile.d.ts +0 -1
- package/dist/compiler/compile.js +33 -17
- package/dist/compiler/index.d.ts +0 -1
- package/dist/compiler/index.js +0 -1
- package/dist/compiler/workflow.d.ts +0 -1
- package/dist/compiler/workflow.js +0 -2
- package/dist/evolution/collector.d.ts +0 -1
- package/dist/evolution/collector.js +0 -1
- package/dist/evolution/fitness.d.ts +0 -1
- package/dist/evolution/fitness.js +0 -1
- package/dist/evolution/index.d.ts +0 -1
- package/dist/evolution/index.js +0 -1
- package/dist/evolution/marker-gen.d.ts +0 -1
- package/dist/evolution/marker-gen.js +0 -1
- package/dist/evolution/store.d.ts +0 -1
- package/dist/evolution/store.js +0 -1
- package/dist/evolution/types.d.ts +0 -1
- package/dist/evolution/types.js +0 -1
- package/dist/hooks/cli.d.ts +17 -0
- package/dist/hooks/cli.js +156 -0
- package/dist/hooks/enforce.d.ts +106 -0
- package/dist/hooks/enforce.js +431 -0
- package/dist/hooks/index.d.ts +9 -0
- package/dist/hooks/index.js +12 -0
- package/dist/hooks/protocol.d.ts +73 -0
- package/dist/hooks/protocol.js +91 -0
- package/dist/hooks/state.d.ts +53 -0
- package/dist/hooks/state.js +93 -0
- package/dist/index.d.ts +0 -1
- package/dist/index.js +0 -1
- package/dist/log/logger.d.ts +0 -1
- package/dist/log/logger.js +0 -1
- package/dist/runtime/agent-md.d.ts +0 -1
- package/dist/runtime/agent-md.js +95 -105
- package/dist/runtime/claude-sdk.d.ts +0 -1
- package/dist/runtime/claude-sdk.js +0 -1
- package/dist/runtime/index.d.ts +3 -3
- package/dist/runtime/index.js +2 -2
- package/dist/runtime/markdown.d.ts +0 -1
- package/dist/runtime/markdown.js +0 -1
- package/dist/runtime/plugin-adapter.d.ts +42 -0
- package/dist/runtime/plugin-adapter.js +77 -0
- package/dist/runtime/settings-adapter.d.ts +8 -9
- package/dist/runtime/settings-adapter.js +57 -46
- package/dist/runtime/skill-adapter.d.ts +0 -1
- package/dist/runtime/skill-adapter.js +94 -71
- package/dist/runtime/workflow-runner.d.ts +0 -1
- package/dist/runtime/workflow-runner.js +0 -14
- package/dist/schema/index.d.ts +0 -1
- package/dist/schema/index.js +0 -1
- package/dist/schema/types.d.ts +33 -20
- package/dist/schema/types.js +0 -1
- package/dist/schema/validate.d.ts +0 -1
- package/dist/schema/validate.js +32 -19
- package/dist/schema/yaml-parser.d.ts +0 -1
- package/dist/schema/yaml-parser.js +0 -1
- package/dist/templates/code-review-pipeline.dna.yaml +0 -11
- package/dist/templates/flutter-behavior-lock.dna.yaml +0 -16
- package/dist/templates/flutter-refactoring-rescue.dna.yaml +0 -12
- package/dist/templates/flutter-rewrite.dna.yaml +0 -27
- package/dist/templates/full-pipeline.dna.yaml +0 -25
- package/dist/templates/multi-perspective-review.dna.yaml +0 -12
- package/dist/templates/subagent-parallel.dna.yaml +0 -16
- package/package.json +4 -2
- package/dist/audit/index.d.ts.map +0 -1
- package/dist/audit/index.js.map +0 -1
- package/dist/cli/commands/compile.d.ts.map +0 -1
- package/dist/cli/commands/compile.js.map +0 -1
- package/dist/cli/commands/epigenetic.d.ts.map +0 -1
- package/dist/cli/commands/epigenetic.js.map +0 -1
- package/dist/cli/commands/evolve.d.ts.map +0 -1
- package/dist/cli/commands/evolve.js.map +0 -1
- package/dist/cli/commands/guard.d.ts.map +0 -1
- package/dist/cli/commands/guard.js.map +0 -1
- package/dist/cli/commands/import.d.ts.map +0 -1
- package/dist/cli/commands/import.js.map +0 -1
- package/dist/cli/commands/init.d.ts.map +0 -1
- package/dist/cli/commands/init.js.map +0 -1
- package/dist/cli/commands/run.d.ts.map +0 -1
- package/dist/cli/commands/run.js.map +0 -1
- package/dist/cli/commands/show.d.ts.map +0 -1
- package/dist/cli/commands/show.js.map +0 -1
- package/dist/cli/commands/sync.d.ts.map +0 -1
- package/dist/cli/commands/sync.js.map +0 -1
- package/dist/cli/commands/validate.d.ts.map +0 -1
- package/dist/cli/commands/validate.js.map +0 -1
- package/dist/cli/commands/verify.d.ts.map +0 -1
- package/dist/cli/commands/verify.js.map +0 -1
- package/dist/cli/index.d.ts.map +0 -1
- package/dist/cli/index.js.map +0 -1
- package/dist/cli/util/format.d.ts.map +0 -1
- package/dist/cli/util/format.js.map +0 -1
- package/dist/cli/util/prompt.d.ts.map +0 -1
- package/dist/cli/util/prompt.js.map +0 -1
- package/dist/compiler/activate.d.ts.map +0 -1
- package/dist/compiler/activate.js.map +0 -1
- package/dist/compiler/cascade.d.ts.map +0 -1
- package/dist/compiler/cascade.js.map +0 -1
- package/dist/compiler/compile.d.ts.map +0 -1
- package/dist/compiler/compile.js.map +0 -1
- package/dist/compiler/index.d.ts.map +0 -1
- package/dist/compiler/index.js.map +0 -1
- package/dist/compiler/workflow.d.ts.map +0 -1
- package/dist/compiler/workflow.js.map +0 -1
- package/dist/evolution/collector.d.ts.map +0 -1
- package/dist/evolution/collector.js.map +0 -1
- package/dist/evolution/fitness.d.ts.map +0 -1
- package/dist/evolution/fitness.js.map +0 -1
- package/dist/evolution/index.d.ts.map +0 -1
- package/dist/evolution/index.js.map +0 -1
- package/dist/evolution/marker-gen.d.ts.map +0 -1
- package/dist/evolution/marker-gen.js.map +0 -1
- package/dist/evolution/store.d.ts.map +0 -1
- package/dist/evolution/store.js.map +0 -1
- package/dist/evolution/types.d.ts.map +0 -1
- package/dist/evolution/types.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/log/logger.d.ts.map +0 -1
- package/dist/log/logger.js.map +0 -1
- package/dist/runtime/agent-md.d.ts.map +0 -1
- package/dist/runtime/agent-md.js.map +0 -1
- package/dist/runtime/claude-sdk.d.ts.map +0 -1
- package/dist/runtime/claude-sdk.js.map +0 -1
- package/dist/runtime/hooks.d.ts +0 -67
- package/dist/runtime/hooks.d.ts.map +0 -1
- package/dist/runtime/hooks.js +0 -785
- package/dist/runtime/hooks.js.map +0 -1
- package/dist/runtime/index.d.ts.map +0 -1
- package/dist/runtime/index.js.map +0 -1
- package/dist/runtime/markdown.d.ts.map +0 -1
- package/dist/runtime/markdown.js.map +0 -1
- package/dist/runtime/settings-adapter.d.ts.map +0 -1
- package/dist/runtime/settings-adapter.js.map +0 -1
- package/dist/runtime/skill-adapter.d.ts.map +0 -1
- package/dist/runtime/skill-adapter.js.map +0 -1
- package/dist/runtime/workflow-runner.d.ts.map +0 -1
- package/dist/runtime/workflow-runner.js.map +0 -1
- package/dist/schema/index.d.ts.map +0 -1
- package/dist/schema/index.js.map +0 -1
- package/dist/schema/types.d.ts.map +0 -1
- package/dist/schema/types.js.map +0 -1
- package/dist/schema/validate.d.ts.map +0 -1
- package/dist/schema/validate.js.map +0 -1
- package/dist/schema/yaml-parser.d.ts.map +0 -1
- package/dist/schema/yaml-parser.js.map +0 -1
|
@@ -1,23 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Intent DNA — Settings Adapter
|
|
3
3
|
*
|
|
4
|
-
* Compiles DNA hook
|
|
5
|
-
* hook configurations for
|
|
4
|
+
* Compiles DNA hook events into Claude Code settings.json
|
|
5
|
+
* hook configurations for the dna-hook binary.
|
|
6
6
|
*
|
|
7
7
|
* See docs/references/cc-source-analysis.md §2 for the full hook event catalog.
|
|
8
8
|
*/
|
|
9
9
|
import { readFile, writeFile } from "node:fs/promises";
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
const HOOK_FILE_MAP = [
|
|
13
|
-
["preToolUse", "dna-pre-tool-use.sh"],
|
|
14
|
-
["postToolUse", "dna-post-tool-use.sh"],
|
|
15
|
-
["userPromptSubmit", "dna-user-prompt-submit.sh"],
|
|
16
|
-
["subagentStop", "dna-subagent-stop.sh"],
|
|
17
|
-
["preCompact", "dna-pre-compact.sh"],
|
|
18
|
-
["notification", "dna-notification.sh"],
|
|
19
|
-
];
|
|
20
|
-
// HookScripts key → Claude Code settings event name
|
|
10
|
+
// ── Plugin Mode (Node.js hooks via dna-hook binary) ───────
|
|
11
|
+
/** Hook event key → Claude Code settings event name */
|
|
21
12
|
const HOOK_EVENT_MAP = {
|
|
22
13
|
preToolUse: "PreToolUse",
|
|
23
14
|
postToolUse: "PostToolUse",
|
|
@@ -26,44 +17,59 @@ const HOOK_EVENT_MAP = {
|
|
|
26
17
|
preCompact: "PreCompact",
|
|
27
18
|
notification: "Notification",
|
|
28
19
|
};
|
|
29
|
-
// ── Compile ────────────────────────────────────────────────
|
|
30
20
|
/**
|
|
31
|
-
* Compile
|
|
32
|
-
*
|
|
21
|
+
* Compile settings.json hook configuration for dna-hook binary.
|
|
22
|
+
* Uses `dna-hook <event>` commands.
|
|
33
23
|
*/
|
|
34
|
-
export function
|
|
24
|
+
export function compilePluginSettings(enabledEvents, timeout = 10) {
|
|
35
25
|
const settings = { hooks: {} };
|
|
36
|
-
for (const
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
26
|
+
for (const key of enabledEvents) {
|
|
27
|
+
const eventName = HOOK_EVENT_MAP[key];
|
|
28
|
+
if (!eventName)
|
|
29
|
+
continue;
|
|
30
|
+
settings.hooks[eventName] = [
|
|
31
|
+
{
|
|
32
|
+
matcher: "",
|
|
33
|
+
hooks: [
|
|
34
|
+
{
|
|
35
|
+
type: "command",
|
|
36
|
+
command: `dna-hook ${eventName}`,
|
|
37
|
+
...(timeout > 0 ? { timeout } : {}),
|
|
38
|
+
},
|
|
39
|
+
],
|
|
40
|
+
},
|
|
41
|
+
];
|
|
51
42
|
}
|
|
52
43
|
return settings;
|
|
53
44
|
}
|
|
54
45
|
/**
|
|
55
|
-
*
|
|
46
|
+
* Determine which hook events are needed based on IR content.
|
|
56
47
|
*/
|
|
57
|
-
export function
|
|
58
|
-
const
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
}
|
|
66
|
-
|
|
48
|
+
export function detectEnabledEvents(ir) {
|
|
49
|
+
const events = [];
|
|
50
|
+
const hasGates = ir.pre_execution_gates.length > 0;
|
|
51
|
+
const hasFilters = ir.tool_filters.length > 0;
|
|
52
|
+
const hasRoleScope = ir.roles_scope_map && ir.roles_scope_map.length > 0;
|
|
53
|
+
const hasCheckpoints = ir.step_checkpoints && ir.step_checkpoints.length > 0;
|
|
54
|
+
if (hasGates || hasFilters || hasRoleScope || hasCheckpoints) {
|
|
55
|
+
events.push("preToolUse");
|
|
56
|
+
}
|
|
57
|
+
if (ir.post_execution_validators.length > 0) {
|
|
58
|
+
events.push("postToolUse");
|
|
59
|
+
}
|
|
60
|
+
if (ir.prompt_directives.some(d => d.priority === "high")) {
|
|
61
|
+
events.push("userPromptSubmit");
|
|
62
|
+
}
|
|
63
|
+
if (hasRoleScope) {
|
|
64
|
+
events.push("subagentStop");
|
|
65
|
+
}
|
|
66
|
+
if (ir.prompt_directives.length > 0) {
|
|
67
|
+
events.push("preCompact");
|
|
68
|
+
}
|
|
69
|
+
if (hasGates || hasFilters) {
|
|
70
|
+
events.push("notification");
|
|
71
|
+
}
|
|
72
|
+
return events;
|
|
67
73
|
}
|
|
68
74
|
// ── File Operations ────────────────────────────────────────
|
|
69
75
|
/**
|
|
@@ -85,14 +91,20 @@ export async function mergeSettingsFile(dnaSettings, settingsPath) {
|
|
|
85
91
|
for (const [eventName, entries] of Object.entries(dnaSettings.hooks)) {
|
|
86
92
|
const existingEntries = (mergedHooks[eventName] ?? []);
|
|
87
93
|
// Remove existing DNA hooks, keep user hooks
|
|
88
|
-
const nonDNA = existingEntries.filter((h) =>
|
|
94
|
+
const nonDNA = existingEntries.filter((h) => {
|
|
95
|
+
const s = JSON.stringify(h);
|
|
96
|
+
return !s.includes("dna-") && !s.includes("dna-hook");
|
|
97
|
+
});
|
|
89
98
|
mergedHooks[eventName] = [...nonDNA, ...entries];
|
|
90
99
|
}
|
|
91
100
|
// Remove DNA hook events that are no longer generated
|
|
92
101
|
for (const eventName of Object.values(HOOK_EVENT_MAP)) {
|
|
93
102
|
if (!dnaSettings.hooks[eventName] && mergedHooks[eventName]) {
|
|
94
103
|
const entries = mergedHooks[eventName];
|
|
95
|
-
const nonDNA = entries.filter((h) =>
|
|
104
|
+
const nonDNA = entries.filter((h) => {
|
|
105
|
+
const s = JSON.stringify(h);
|
|
106
|
+
return !s.includes("dna-") && !s.includes("dna-hook");
|
|
107
|
+
});
|
|
96
108
|
if (nonDNA.length > 0) {
|
|
97
109
|
mergedHooks[eventName] = nonDNA;
|
|
98
110
|
}
|
|
@@ -104,4 +116,3 @@ export async function mergeSettingsFile(dnaSettings, settingsPath) {
|
|
|
104
116
|
existing.hooks = mergedHooks;
|
|
105
117
|
await writeFile(settingsPath, JSON.stringify(existing, null, 2) + "\n", "utf-8");
|
|
106
118
|
}
|
|
107
|
-
//# sourceMappingURL=settings-adapter.js.map
|
|
@@ -20,4 +20,3 @@ export interface SkillResult {
|
|
|
20
20
|
export declare function compileWorkflowToSkill(plan: WorkflowPlan, roles: Record<string, RoleDef>, ir?: ConstraintIR, variables?: Record<string, string>): SkillResult;
|
|
21
21
|
export declare function writeSkillFiles(results: SkillResult[], outputDir: string): Promise<string[]>;
|
|
22
22
|
export declare function removeSkillFiles(outputDir: string): Promise<number>;
|
|
23
|
-
//# sourceMappingURL=skill-adapter.d.ts.map
|
|
@@ -17,11 +17,15 @@ const SENTINEL = "<!-- intentdna:managed — do not edit manually -->";
|
|
|
17
17
|
*/
|
|
18
18
|
export function compileWorkflowToSkill(plan, roles, ir, variables) {
|
|
19
19
|
const lines = [];
|
|
20
|
+
const skillName = `dna-${toKebabCase(plan.name)}`;
|
|
20
21
|
// Frontmatter
|
|
21
22
|
lines.push("---");
|
|
22
|
-
lines.push(`name: ${
|
|
23
|
-
lines.push(`description: "Use when user says /${
|
|
23
|
+
lines.push(`name: ${skillName}`);
|
|
24
|
+
lines.push(`description: "Use when user says /${skillName}. ${escapeYaml(plan.description || plan.name)}"`);
|
|
24
25
|
lines.push("user-invocable: true");
|
|
26
|
+
lines.push("triggers:");
|
|
27
|
+
lines.push(` - "${plan.name}"`);
|
|
28
|
+
lines.push(` - "run ${plan.name}"`);
|
|
25
29
|
lines.push("---");
|
|
26
30
|
lines.push("");
|
|
27
31
|
// Sentinel
|
|
@@ -29,104 +33,106 @@ export function compileWorkflowToSkill(plan, roles, ir, variables) {
|
|
|
29
33
|
lines.push(`<!-- Compiled: ${new Date().toISOString()} -->`);
|
|
30
34
|
lines.push("");
|
|
31
35
|
// Title
|
|
32
|
-
lines.push(`# /${
|
|
36
|
+
lines.push(`# /${skillName} [task-id]`);
|
|
33
37
|
lines.push("");
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
lines.push("|------|-------|-------|------|---------------|");
|
|
41
|
-
const usedRoles = new Set(plan.steps.map((s) => s.role));
|
|
42
|
-
for (const roleName of usedRoles) {
|
|
43
|
-
const role = roles[roleName];
|
|
44
|
-
if (!role)
|
|
45
|
-
continue;
|
|
46
|
-
const agent = `dna-${toKebabCase(roleName)}`;
|
|
47
|
-
const tools = role.tool_permissions?.allow?.join(", ") || "all";
|
|
48
|
-
const deny = role.tool_permissions?.deny?.join(", ") || "—";
|
|
49
|
-
const scope = role.scope?.write?.join(", ") || "—";
|
|
50
|
-
lines.push(`| ${roleName} | ${agent} | ${tools} | ${deny} | ${scope} |`);
|
|
38
|
+
// Purpose
|
|
39
|
+
if (plan.description) {
|
|
40
|
+
lines.push("<Purpose>");
|
|
41
|
+
lines.push(plan.description);
|
|
42
|
+
lines.push("</Purpose>");
|
|
43
|
+
lines.push("");
|
|
51
44
|
}
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
lines.push("
|
|
55
|
-
|
|
45
|
+
// Steps
|
|
46
|
+
const usedRoles = new Set(plan.steps.map((s) => s.role));
|
|
47
|
+
lines.push("<Steps>");
|
|
48
|
+
let stepNumber = 0;
|
|
56
49
|
for (let i = 0; i < plan.parallel_groups.length; i++) {
|
|
57
50
|
const group = plan.parallel_groups[i];
|
|
58
|
-
const isParallel = group.step_ids.length > 1;
|
|
59
|
-
if (isParallel) {
|
|
60
|
-
lines.push(`### Group ${i + 1} (parallel)`);
|
|
61
|
-
}
|
|
62
51
|
for (const stepId of group.step_ids) {
|
|
52
|
+
stepNumber++;
|
|
63
53
|
const step = plan.steps.find((s) => s.id === stepId);
|
|
64
54
|
const agent = `@dna-${toKebabCase(step.role)}`;
|
|
65
55
|
const runIf = step.run_if ? ` (${step.run_if})` : "";
|
|
66
56
|
const optional = step.optional ? " (optional)" : "";
|
|
67
|
-
|
|
68
|
-
lines.push(`${i + 1}. **${step.id}** → ${agent}${runIf}${optional}${modeTag}`);
|
|
69
|
-
if (step.mode) {
|
|
70
|
-
lines.push(` Before starting: \`echo '{"active_mode":"${step.mode}","set_at":"'$(date -u +%Y-%m-%dT%H:%M:%SZ)'","set_by":"skill:${toKebabCase(plan.name)}:${step.id}"}' > .dna/mode\``);
|
|
71
|
-
}
|
|
57
|
+
lines.push(`${stepNumber}. **${step.id}** → ${agent}${runIf}${optional}`);
|
|
72
58
|
lines.push(` ${step.description}`);
|
|
59
|
+
if (step.prompt) {
|
|
60
|
+
lines.push(` Prompt: ${step.prompt}`);
|
|
61
|
+
}
|
|
73
62
|
}
|
|
74
63
|
}
|
|
64
|
+
lines.push("</Steps>");
|
|
75
65
|
lines.push("");
|
|
76
|
-
//
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
}
|
|
66
|
+
// Tool_Usage — only if roles have permissions or scope
|
|
67
|
+
const toolUsageLines = [];
|
|
68
|
+
for (const roleName of usedRoles) {
|
|
69
|
+
const role = roles[roleName];
|
|
70
|
+
if (!role)
|
|
71
|
+
continue;
|
|
72
|
+
const allowed = role.tool_permissions?.allow?.join(", ") || "all";
|
|
73
|
+
const denied = role.tool_permissions?.deny?.join(", ") || "none";
|
|
74
|
+
const writeScope = role.scope?.write?.join(", ") || "none";
|
|
75
|
+
toolUsageLines.push(`### ${roleName}`);
|
|
76
|
+
toolUsageLines.push(`- Allowed: ${allowed}`);
|
|
77
|
+
toolUsageLines.push(`- Denied: ${denied}`);
|
|
78
|
+
toolUsageLines.push(`- Write scope: ${writeScope}`);
|
|
79
|
+
}
|
|
80
|
+
if (toolUsageLines.length > 0) {
|
|
81
|
+
lines.push("<Tool_Usage>");
|
|
82
|
+
lines.push(...toolUsageLines);
|
|
83
|
+
lines.push("</Tool_Usage>");
|
|
89
84
|
lines.push("");
|
|
90
85
|
}
|
|
91
|
-
//
|
|
86
|
+
// Constraints — IR prompt_directives grouped by priority
|
|
92
87
|
if (ir && ir.prompt_directives.length > 0) {
|
|
93
|
-
lines.push("
|
|
94
|
-
lines.push("");
|
|
88
|
+
lines.push("<Constraints>");
|
|
95
89
|
const high = ir.prompt_directives.filter((d) => d.priority === "high");
|
|
96
90
|
const medium = ir.prompt_directives.filter((d) => d.priority === "medium");
|
|
91
|
+
const low = ir.prompt_directives.filter((d) => d.priority !== "high" && d.priority !== "medium");
|
|
97
92
|
if (high.length > 0) {
|
|
98
|
-
lines.push("
|
|
93
|
+
lines.push("## Critical");
|
|
99
94
|
for (const d of high) {
|
|
100
95
|
lines.push(`- **${d.text}**`);
|
|
101
96
|
}
|
|
102
|
-
lines.push("");
|
|
103
97
|
}
|
|
104
98
|
if (medium.length > 0) {
|
|
105
|
-
lines.push("
|
|
99
|
+
lines.push("## Standard");
|
|
106
100
|
for (const d of medium) {
|
|
107
101
|
lines.push(`- ${d.text}`);
|
|
108
102
|
}
|
|
109
|
-
lines.push("");
|
|
110
103
|
}
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
continue;
|
|
119
|
-
lines.push(`### ${roleName}`);
|
|
104
|
+
if (low.length > 0) {
|
|
105
|
+
lines.push("## Other");
|
|
106
|
+
for (const d of low) {
|
|
107
|
+
lines.push(`- ${d.text}`);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
lines.push("</Constraints>");
|
|
120
111
|
lines.push("");
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
112
|
+
}
|
|
113
|
+
// Checkpoints — steps that have checkpoint conditions
|
|
114
|
+
const stepsWithCheckpoints = plan.steps.filter((s) => s.checkpoints && s.checkpoints.length > 0);
|
|
115
|
+
if (stepsWithCheckpoints.length > 0) {
|
|
116
|
+
lines.push("<Checkpoints>");
|
|
117
|
+
for (const step of stepsWithCheckpoints) {
|
|
118
|
+
lines.push(`### ${step.id}`);
|
|
119
|
+
for (const cp of step.checkpoints) {
|
|
120
|
+
const action = cp.action || "block";
|
|
121
|
+
lines.push(`- ${cp.assert}: ${cp.message} (${action})`);
|
|
124
122
|
}
|
|
125
123
|
}
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
124
|
+
lines.push("</Checkpoints>");
|
|
125
|
+
lines.push("");
|
|
126
|
+
}
|
|
127
|
+
// Variables — collect {{var_name}} references from the whole plan
|
|
128
|
+
const varRefs = collectVariableRefs(plan);
|
|
129
|
+
if (varRefs.size > 0) {
|
|
130
|
+
lines.push("<Variables>");
|
|
131
|
+
for (const varName of varRefs) {
|
|
132
|
+
const value = variables?.[varName];
|
|
133
|
+
lines.push(`- \`{{${varName}}}\`: ${value ?? varName}`);
|
|
129
134
|
}
|
|
135
|
+
lines.push("</Variables>");
|
|
130
136
|
lines.push("");
|
|
131
137
|
}
|
|
132
138
|
let content = lines.join("\n") + "\n";
|
|
@@ -136,9 +142,27 @@ export function compileWorkflowToSkill(plan, roles, ir, variables) {
|
|
|
136
142
|
content = content.replaceAll(`{{${key}}}`, value);
|
|
137
143
|
}
|
|
138
144
|
}
|
|
139
|
-
const dirName =
|
|
145
|
+
const dirName = skillName;
|
|
140
146
|
const fileName = join(dirName, "SKILL.md");
|
|
141
|
-
return { name:
|
|
147
|
+
return { name: skillName, fileName, dirName, content };
|
|
148
|
+
}
|
|
149
|
+
/** Collect all {{var_name}} references from a workflow plan. */
|
|
150
|
+
function collectVariableRefs(plan) {
|
|
151
|
+
const refs = new Set();
|
|
152
|
+
const RE = /\{\{(\w+)\}\}/g;
|
|
153
|
+
const scan = (s) => {
|
|
154
|
+
if (!s)
|
|
155
|
+
return;
|
|
156
|
+
for (const m of s.matchAll(RE))
|
|
157
|
+
refs.add(m[1]);
|
|
158
|
+
};
|
|
159
|
+
scan(plan.name);
|
|
160
|
+
scan(plan.description);
|
|
161
|
+
for (const step of plan.steps) {
|
|
162
|
+
scan(step.description);
|
|
163
|
+
scan(step.prompt);
|
|
164
|
+
}
|
|
165
|
+
return refs;
|
|
142
166
|
}
|
|
143
167
|
// ── File Operations ────────────────────────────────────────
|
|
144
168
|
export async function writeSkillFiles(results, outputDir) {
|
|
@@ -179,4 +203,3 @@ export async function removeSkillFiles(outputDir) {
|
|
|
179
203
|
function escapeYaml(s) {
|
|
180
204
|
return s.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
|
|
181
205
|
}
|
|
182
|
-
//# sourceMappingURL=skill-adapter.js.map
|
|
@@ -177,9 +177,6 @@ function generateStepExecution(step, options, plan, isParallel) {
|
|
|
177
177
|
const condLabel = retrySkipGuard ? "round == 1 (retry_from skip)" : step.run_if;
|
|
178
178
|
lines.push(` # Step: ${step.id} (run_if: ${condLabel})`);
|
|
179
179
|
lines.push(` if ${effectiveCondition}; then`);
|
|
180
|
-
if (step.mode) {
|
|
181
|
-
lines.push(` echo '{"active_mode":"${step.mode}","set_at":"'$(date -u +%Y-%m-%dT%H:%M:%SZ)'","set_by":"workflow:${plan.name}:${step.id}"}' > .dna/mode`);
|
|
182
|
-
}
|
|
183
180
|
lines.push(` ${agentCall}`);
|
|
184
181
|
lines.push(" else");
|
|
185
182
|
lines.push(` echo "[$(date '+%H:%M:%S')] Skipping step: ${step.id} (run_if: ${condLabel}, current round: $ROUND)"`);
|
|
@@ -187,9 +184,6 @@ function generateStepExecution(step, options, plan, isParallel) {
|
|
|
187
184
|
}
|
|
188
185
|
else {
|
|
189
186
|
lines.push(` # Step: ${step.id}`);
|
|
190
|
-
if (step.mode) {
|
|
191
|
-
lines.push(` echo '{"active_mode":"${step.mode}","set_at":"'$(date -u +%Y-%m-%dT%H:%M:%SZ)'","set_by":"workflow:${plan.name}:${step.id}"}' > .dna/mode`);
|
|
192
|
-
}
|
|
193
187
|
if (step.optional) {
|
|
194
188
|
lines.push(` run_agent "${agent}" '${prompt}' "${step.id}" || {`);
|
|
195
189
|
lines.push(` STEP_${varId}_STATUS=1`);
|
|
@@ -376,13 +370,6 @@ export function compileWorkflowToShell(plan, options) {
|
|
|
376
370
|
lines.push('echo "All steps passed."');
|
|
377
371
|
}
|
|
378
372
|
lines.push("");
|
|
379
|
-
// Clean up mode file after workflow completes
|
|
380
|
-
const hasAnyMode = plan.steps.some((s) => s.mode !== null);
|
|
381
|
-
if (hasAnyMode) {
|
|
382
|
-
lines.push("# Clean up mode state");
|
|
383
|
-
lines.push('rm -f .dna/mode');
|
|
384
|
-
lines.push("");
|
|
385
|
-
}
|
|
386
373
|
const script = lines.join("\n") + "\n";
|
|
387
374
|
const fileName = toKebabCase(plan.name) + ".sh";
|
|
388
375
|
return { script, fileName };
|
|
@@ -430,4 +417,3 @@ export async function removeWorkflowScripts(outputDir) {
|
|
|
430
417
|
}
|
|
431
418
|
return removed;
|
|
432
419
|
}
|
|
433
|
-
//# sourceMappingURL=workflow-runner.js.map
|
package/dist/schema/index.d.ts
CHANGED
package/dist/schema/index.js
CHANGED
package/dist/schema/types.d.ts
CHANGED
|
@@ -79,12 +79,8 @@ export interface RoleDef {
|
|
|
79
79
|
suppresses_genes?: string[];
|
|
80
80
|
post_checks?: string[];
|
|
81
81
|
instructions?: string[];
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
export interface ModeDef {
|
|
85
|
-
description: string;
|
|
86
|
-
tool_permissions?: ToolPermissions;
|
|
87
|
-
scope?: ScopeDef;
|
|
82
|
+
success_criteria?: string[];
|
|
83
|
+
failure_modes?: string[];
|
|
88
84
|
}
|
|
89
85
|
/** Transition condition between workflow steps */
|
|
90
86
|
export interface TransitionDef {
|
|
@@ -121,7 +117,6 @@ export interface CompletionCheck {
|
|
|
121
117
|
export interface WorkflowStepDef {
|
|
122
118
|
id: string;
|
|
123
119
|
role: string;
|
|
124
|
-
mode?: string;
|
|
125
120
|
description?: string;
|
|
126
121
|
depends_on?: string[];
|
|
127
122
|
optional?: boolean;
|
|
@@ -171,6 +166,16 @@ export interface DNAMetadata {
|
|
|
171
166
|
gene_count: number;
|
|
172
167
|
epigenetic_marker_count: number;
|
|
173
168
|
}
|
|
169
|
+
/** MCP server dependency declaration */
|
|
170
|
+
export interface MCPServerDef {
|
|
171
|
+
description: string;
|
|
172
|
+
command?: string;
|
|
173
|
+
args?: string[];
|
|
174
|
+
env?: Record<string, string>;
|
|
175
|
+
url?: string;
|
|
176
|
+
timeout?: number;
|
|
177
|
+
optional?: boolean;
|
|
178
|
+
}
|
|
174
179
|
export interface IntentDNA {
|
|
175
180
|
$schema?: string;
|
|
176
181
|
version: string;
|
|
@@ -181,10 +186,10 @@ export interface IntentDNA {
|
|
|
181
186
|
genes: Record<string, Gene>;
|
|
182
187
|
contexts: Record<string, ContextRegion>;
|
|
183
188
|
roles?: Record<string, RoleDef>;
|
|
184
|
-
modes?: Record<string, ModeDef>;
|
|
185
189
|
workflow?: WorkflowDef;
|
|
186
190
|
workflows?: Record<string, WorkflowDef>;
|
|
187
191
|
variables?: Record<string, string | VariableDef>;
|
|
192
|
+
mcp?: Record<string, MCPServerDef>;
|
|
188
193
|
epigenetic: {
|
|
189
194
|
markers: EpigeneticMarker[];
|
|
190
195
|
};
|
|
@@ -225,19 +230,29 @@ export interface RoleScopeEntry {
|
|
|
225
230
|
scope: ScopeDef;
|
|
226
231
|
tool_permissions?: ToolPermissions;
|
|
227
232
|
}
|
|
228
|
-
/**
|
|
229
|
-
export interface ModeConstraint {
|
|
230
|
-
mode_name: string;
|
|
231
|
-
description: string;
|
|
232
|
-
tool_deny?: string[];
|
|
233
|
-
scope_write?: string[];
|
|
234
|
-
}
|
|
235
|
-
/** Step checkpoint compiled into IR — hook enforces at mode transition */
|
|
233
|
+
/** Step checkpoint compiled into IR — hook enforces at step transition */
|
|
236
234
|
export interface StepCheckpointIR {
|
|
237
|
-
|
|
235
|
+
step_role: string;
|
|
238
236
|
step_id: string;
|
|
239
237
|
checkpoints: StepCheckpoint[];
|
|
240
238
|
}
|
|
239
|
+
/** Workflow-partitioned IR — isolates constraints per workflow */
|
|
240
|
+
export interface WorkflowIR {
|
|
241
|
+
workflow_name: string;
|
|
242
|
+
namespace: string;
|
|
243
|
+
step_checkpoints: StepCheckpointIR[];
|
|
244
|
+
active_roles: string[];
|
|
245
|
+
}
|
|
246
|
+
/** Runtime workflow state written to .dna/state/workflow.json */
|
|
247
|
+
export interface WorkflowState {
|
|
248
|
+
active: boolean;
|
|
249
|
+
workflow: string;
|
|
250
|
+
current_step: string;
|
|
251
|
+
current_role: string;
|
|
252
|
+
iteration: number;
|
|
253
|
+
session_id: string;
|
|
254
|
+
started_at: string;
|
|
255
|
+
}
|
|
241
256
|
export interface ConstraintIR {
|
|
242
257
|
prompt_directives: PromptDirective[];
|
|
243
258
|
tool_filters: ToolFilter[];
|
|
@@ -251,14 +266,13 @@ export interface ConstraintIR {
|
|
|
251
266
|
role_tool_permissions?: ToolPermissions;
|
|
252
267
|
role_scope?: ScopeDef;
|
|
253
268
|
roles_scope_map?: RoleScopeEntry[];
|
|
254
|
-
mode_constraints?: ModeConstraint[];
|
|
255
269
|
step_checkpoints?: StepCheckpointIR[];
|
|
270
|
+
workflows_ir?: WorkflowIR[];
|
|
256
271
|
}
|
|
257
272
|
/** A compiled workflow step with resolved metadata */
|
|
258
273
|
export interface WorkflowStep {
|
|
259
274
|
id: string;
|
|
260
275
|
role: string;
|
|
261
|
-
mode: string | null;
|
|
262
276
|
description: string;
|
|
263
277
|
optional: boolean;
|
|
264
278
|
run_if: string | null;
|
|
@@ -313,4 +327,3 @@ export interface WorkflowPlan {
|
|
|
313
327
|
compiled_at: string;
|
|
314
328
|
source_workflow: string;
|
|
315
329
|
}
|
|
316
|
-
//# sourceMappingURL=types.d.ts.map
|
package/dist/schema/types.js
CHANGED
package/dist/schema/validate.js
CHANGED
|
@@ -186,7 +186,7 @@ function validateRole(name, role, geneNames) {
|
|
|
186
186
|
}
|
|
187
187
|
return errors;
|
|
188
188
|
}
|
|
189
|
-
function validateWorkflow(workflow, roleNames, pathPrefix
|
|
189
|
+
function validateWorkflow(workflow, roleNames, pathPrefix) {
|
|
190
190
|
const errors = [];
|
|
191
191
|
const path = pathPrefix ?? "workflow";
|
|
192
192
|
// name required
|
|
@@ -225,13 +225,6 @@ function validateWorkflow(workflow, roleNames, pathPrefix, modeNames) {
|
|
|
225
225
|
message: `step references unknown role '${step.role}'`,
|
|
226
226
|
});
|
|
227
227
|
}
|
|
228
|
-
// step.mode optional but must exist in modes if specified
|
|
229
|
-
if (step.mode && modeNames && modeNames.size > 0 && !modeNames.has(step.mode)) {
|
|
230
|
-
errors.push({
|
|
231
|
-
path: `${stepPath}.mode`,
|
|
232
|
-
message: `step references unknown mode '${step.mode}'`,
|
|
233
|
-
});
|
|
234
|
-
}
|
|
235
228
|
// depends_on: check for empty strings in first pass
|
|
236
229
|
for (const dep of step.depends_on ?? []) {
|
|
237
230
|
if (!dep) {
|
|
@@ -384,13 +377,6 @@ export function validateDNA(dna) {
|
|
|
384
377
|
for (const [name, role] of Object.entries(dna.roles ?? {})) {
|
|
385
378
|
errors.push(...validateRole(name, role, geneNames));
|
|
386
379
|
}
|
|
387
|
-
// Validate modes
|
|
388
|
-
for (const [name, mode] of Object.entries(dna.modes ?? {})) {
|
|
389
|
-
const modePath = `modes.${name}`;
|
|
390
|
-
if (!mode.description) {
|
|
391
|
-
errors.push({ path: `${modePath}.description`, message: "mode requires 'description'" });
|
|
392
|
-
}
|
|
393
|
-
}
|
|
394
380
|
// Validate workflow / workflows (mutually exclusive)
|
|
395
381
|
if (dna.workflow !== undefined && dna.workflows !== undefined) {
|
|
396
382
|
errors.push({
|
|
@@ -399,13 +385,41 @@ export function validateDNA(dna) {
|
|
|
399
385
|
});
|
|
400
386
|
}
|
|
401
387
|
const roleNamesSet = new Set(Object.keys(dna.roles ?? {}));
|
|
402
|
-
const modeNamesSet = new Set(Object.keys(dna.modes ?? {}));
|
|
403
388
|
if (dna.workflow && !dna.workflows) {
|
|
404
|
-
errors.push(...validateWorkflow(dna.workflow, roleNamesSet, "workflow"
|
|
389
|
+
errors.push(...validateWorkflow(dna.workflow, roleNamesSet, "workflow"));
|
|
405
390
|
}
|
|
406
391
|
if (dna.workflows && !dna.workflow) {
|
|
407
392
|
for (const [wfName, wfDef] of Object.entries(dna.workflows)) {
|
|
408
|
-
errors.push(...validateWorkflow(wfDef, roleNamesSet, `workflows.${wfName}
|
|
393
|
+
errors.push(...validateWorkflow(wfDef, roleNamesSet, `workflows.${wfName}`));
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
// Validate mcp
|
|
397
|
+
if (dna.mcp) {
|
|
398
|
+
for (const [name, server] of Object.entries(dna.mcp)) {
|
|
399
|
+
const mcpPath = `mcp.${name}`;
|
|
400
|
+
if (!server.description) {
|
|
401
|
+
errors.push({ path: `${mcpPath}.description`, message: "MCP server requires 'description'" });
|
|
402
|
+
}
|
|
403
|
+
// Must have either command or url
|
|
404
|
+
if (!server.command && !server.url) {
|
|
405
|
+
errors.push({ path: mcpPath, message: "MCP server requires either 'command' or 'url'" });
|
|
406
|
+
}
|
|
407
|
+
// Can't have both command and url
|
|
408
|
+
if (server.command && server.url) {
|
|
409
|
+
errors.push({ path: mcpPath, message: "MCP server cannot have both 'command' and 'url'" });
|
|
410
|
+
}
|
|
411
|
+
// timeout must be positive
|
|
412
|
+
if (server.timeout !== undefined && server.timeout <= 0) {
|
|
413
|
+
errors.push({ path: `${mcpPath}.timeout`, message: "timeout must be positive" });
|
|
414
|
+
}
|
|
415
|
+
// env values must be strings
|
|
416
|
+
if (server.env) {
|
|
417
|
+
for (const [envKey, envVal] of Object.entries(server.env)) {
|
|
418
|
+
if (typeof envVal !== "string") {
|
|
419
|
+
errors.push({ path: `${mcpPath}.env.${envKey}`, message: "env value must be a string" });
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
}
|
|
409
423
|
}
|
|
410
424
|
}
|
|
411
425
|
// Validate epigenetic markers
|
|
@@ -429,4 +443,3 @@ export function validateDNA(dna) {
|
|
|
429
443
|
}
|
|
430
444
|
return { valid: errors.length === 0, errors, warnings: warnings.length > 0 ? warnings : undefined };
|
|
431
445
|
}
|
|
432
|
-
//# sourceMappingURL=validate.js.map
|