intentdna 1.2.3 → 1.4.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/marketplace.json +12 -0
- package/.claude-plugin/plugin.json +5 -0
- package/dist/cli/commands/setup.d.ts +21 -0
- package/dist/cli/commands/setup.js +192 -0
- package/dist/cli/commands/sync.d.ts +12 -0
- package/dist/cli/commands/sync.js +115 -15
- package/dist/cli/commands/verify.d.ts +1 -0
- package/dist/cli/commands/verify.js +69 -0
- package/dist/cli/index.js +26 -0
- package/dist/compiler/compile.js +40 -0
- package/dist/compiler/workflow.js +1 -0
- package/dist/hooks/cli.js +70 -4
- package/dist/hooks/enforce.d.ts +56 -1
- package/dist/hooks/enforce.js +160 -0
- package/dist/hooks/index.d.ts +2 -2
- package/dist/hooks/index.js +1 -1
- package/dist/hooks/protocol.d.ts +4 -1
- package/dist/hooks/state.d.ts +40 -1
- package/dist/hooks/state.js +137 -2
- package/dist/runtime/skill-adapter.js +21 -0
- package/dist/schema/types.d.ts +54 -0
- package/dist/schema/validate.js +29 -0
- package/dist/templates/code-review-pipeline.dna.yaml +12 -0
- package/dist/templates/flutter-refactoring-rescue.dna.yaml +20 -0
- package/dist/templates/flutter-rewrite.dna.yaml +39 -0
- package/dist/templates/full-pipeline.dna.yaml +29 -0
- package/package.json +2 -1
package/dist/schema/types.d.ts
CHANGED
|
@@ -82,6 +82,20 @@ export interface RoleDef {
|
|
|
82
82
|
success_criteria?: string[];
|
|
83
83
|
failure_modes?: string[];
|
|
84
84
|
}
|
|
85
|
+
/** Handoff artifact type — what kind of artifact is passed between steps */
|
|
86
|
+
export type HandoffType = "file" | "directory" | "test_result" | "git_commit" | "summary" | "state";
|
|
87
|
+
/** A single artifact consumed or produced by a workflow step */
|
|
88
|
+
export interface HandoffArtifact {
|
|
89
|
+
type: HandoffType;
|
|
90
|
+
path?: string;
|
|
91
|
+
from?: string;
|
|
92
|
+
description: string;
|
|
93
|
+
}
|
|
94
|
+
/** Handoff declaration for a workflow step */
|
|
95
|
+
export interface StepHandoff {
|
|
96
|
+
consumes?: HandoffArtifact[];
|
|
97
|
+
produces?: HandoffArtifact[];
|
|
98
|
+
}
|
|
85
99
|
/** Transition condition between workflow steps */
|
|
86
100
|
export interface TransitionDef {
|
|
87
101
|
from: string;
|
|
@@ -124,6 +138,7 @@ export interface WorkflowStepDef {
|
|
|
124
138
|
prompt?: string;
|
|
125
139
|
completion?: CompletionCheck[];
|
|
126
140
|
checkpoints?: StepCheckpoint[];
|
|
141
|
+
handoff?: StepHandoff;
|
|
127
142
|
}
|
|
128
143
|
/** Top-level workflow definition */
|
|
129
144
|
export interface WorkflowDef {
|
|
@@ -133,6 +148,8 @@ export interface WorkflowDef {
|
|
|
133
148
|
transitions?: TransitionDef[];
|
|
134
149
|
retry_policy?: RetryPolicy;
|
|
135
150
|
max_rounds?: number;
|
|
151
|
+
produces?: HandoffArtifact[];
|
|
152
|
+
consumes?: HandoffArtifact[];
|
|
136
153
|
}
|
|
137
154
|
export interface EpigeneticEffect {
|
|
138
155
|
gene?: string;
|
|
@@ -166,6 +183,16 @@ export interface DNAMetadata {
|
|
|
166
183
|
gene_count: number;
|
|
167
184
|
epigenetic_marker_count: number;
|
|
168
185
|
}
|
|
186
|
+
/** MCP server dependency declaration */
|
|
187
|
+
export interface MCPServerDef {
|
|
188
|
+
description: string;
|
|
189
|
+
command?: string;
|
|
190
|
+
args?: string[];
|
|
191
|
+
env?: Record<string, string>;
|
|
192
|
+
url?: string;
|
|
193
|
+
timeout?: number;
|
|
194
|
+
optional?: boolean;
|
|
195
|
+
}
|
|
169
196
|
export interface IntentDNA {
|
|
170
197
|
$schema?: string;
|
|
171
198
|
version: string;
|
|
@@ -179,6 +206,7 @@ export interface IntentDNA {
|
|
|
179
206
|
workflow?: WorkflowDef;
|
|
180
207
|
workflows?: Record<string, WorkflowDef>;
|
|
181
208
|
variables?: Record<string, string | VariableDef>;
|
|
209
|
+
mcp?: Record<string, MCPServerDef>;
|
|
182
210
|
epigenetic: {
|
|
183
211
|
markers: EpigeneticMarker[];
|
|
184
212
|
};
|
|
@@ -225,6 +253,29 @@ export interface StepCheckpointIR {
|
|
|
225
253
|
step_id: string;
|
|
226
254
|
checkpoints: StepCheckpoint[];
|
|
227
255
|
}
|
|
256
|
+
/** Handoff chain entry — tracks what each step consumes/produces */
|
|
257
|
+
export interface HandoffChainEntry {
|
|
258
|
+
step_id: string;
|
|
259
|
+
produces?: HandoffArtifact[];
|
|
260
|
+
consumes?: HandoffArtifact[];
|
|
261
|
+
}
|
|
262
|
+
/** Workflow-partitioned IR — isolates constraints per workflow */
|
|
263
|
+
export interface WorkflowIR {
|
|
264
|
+
workflow_name: string;
|
|
265
|
+
namespace: string;
|
|
266
|
+
step_checkpoints: StepCheckpointIR[];
|
|
267
|
+
active_roles: string[];
|
|
268
|
+
handoff_chain: HandoffChainEntry[];
|
|
269
|
+
}
|
|
270
|
+
/** Record of artifacts completed by a step — used for cross-session resume */
|
|
271
|
+
export interface CompletedArtifactEntry {
|
|
272
|
+
step_id: string;
|
|
273
|
+
artifacts: {
|
|
274
|
+
type: string;
|
|
275
|
+
path: string;
|
|
276
|
+
verified_at: string;
|
|
277
|
+
}[];
|
|
278
|
+
}
|
|
228
279
|
/** Runtime workflow state written to .dna/state/workflow.json */
|
|
229
280
|
export interface WorkflowState {
|
|
230
281
|
active: boolean;
|
|
@@ -234,6 +285,7 @@ export interface WorkflowState {
|
|
|
234
285
|
iteration: number;
|
|
235
286
|
session_id: string;
|
|
236
287
|
started_at: string;
|
|
288
|
+
completed_artifacts?: CompletedArtifactEntry[];
|
|
237
289
|
}
|
|
238
290
|
export interface ConstraintIR {
|
|
239
291
|
prompt_directives: PromptDirective[];
|
|
@@ -249,6 +301,7 @@ export interface ConstraintIR {
|
|
|
249
301
|
role_scope?: ScopeDef;
|
|
250
302
|
roles_scope_map?: RoleScopeEntry[];
|
|
251
303
|
step_checkpoints?: StepCheckpointIR[];
|
|
304
|
+
workflows_ir?: WorkflowIR[];
|
|
252
305
|
}
|
|
253
306
|
/** A compiled workflow step with resolved metadata */
|
|
254
307
|
export interface WorkflowStep {
|
|
@@ -261,6 +314,7 @@ export interface WorkflowStep {
|
|
|
261
314
|
prompt: string | null;
|
|
262
315
|
completion: CompletionCheck[] | null;
|
|
263
316
|
checkpoints: StepCheckpoint[] | null;
|
|
317
|
+
handoff: StepHandoff | null;
|
|
264
318
|
}
|
|
265
319
|
/** A group of steps that can execute in parallel */
|
|
266
320
|
export interface ParallelGroup {
|
package/dist/schema/validate.js
CHANGED
|
@@ -393,6 +393,35 @@ export function validateDNA(dna) {
|
|
|
393
393
|
errors.push(...validateWorkflow(wfDef, roleNamesSet, `workflows.${wfName}`));
|
|
394
394
|
}
|
|
395
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
|
+
}
|
|
423
|
+
}
|
|
424
|
+
}
|
|
396
425
|
// Validate epigenetic markers
|
|
397
426
|
for (let i = 0; i < (dna.epigenetic?.markers?.length ?? 0); i++) {
|
|
398
427
|
const marker = dna.epigenetic.markers[i];
|
|
@@ -80,10 +80,22 @@ workflow:
|
|
|
80
80
|
role: implementer
|
|
81
81
|
description: Implement the feature
|
|
82
82
|
prompt: "Implement task {{task_id}} according to the design document."
|
|
83
|
+
handoff:
|
|
84
|
+
produces:
|
|
85
|
+
- type: git_commit
|
|
86
|
+
description: "Implementation commit"
|
|
83
87
|
- id: review
|
|
84
88
|
role: reviewer
|
|
85
89
|
description: Review the implementation
|
|
86
90
|
prompt: "Review all changes for task {{task_id}}. Output PASS or FAIL."
|
|
91
|
+
handoff:
|
|
92
|
+
consumes:
|
|
93
|
+
- type: git_commit
|
|
94
|
+
from: implement
|
|
95
|
+
description: "Implementation to review"
|
|
96
|
+
produces:
|
|
97
|
+
- type: summary
|
|
98
|
+
description: "Review verdict (PASS/FAIL)"
|
|
87
99
|
transitions:
|
|
88
100
|
- from: review
|
|
89
101
|
to: implement
|
|
@@ -130,13 +130,33 @@ workflows:
|
|
|
130
130
|
role: investigator
|
|
131
131
|
description: Trace the broken chain in v1 and v2, identify first breakpoint
|
|
132
132
|
prompt: "Trace the call chain for '{{feature}}' in v1 ({{v1_path}}) and v2 ({{v2_path}}). Find where v2 breaks."
|
|
133
|
+
handoff:
|
|
134
|
+
produces:
|
|
135
|
+
- type: summary
|
|
136
|
+
description: "Breakpoint analysis with file paths and line numbers"
|
|
133
137
|
- id: fix
|
|
134
138
|
role: surgeon
|
|
135
139
|
depends_on: [trace]
|
|
136
140
|
description: Fix the identified breakpoint
|
|
137
141
|
prompt: "Fix the breakpoint identified by investigator. Copy logic from v1, change one file only."
|
|
142
|
+
handoff:
|
|
143
|
+
consumes:
|
|
144
|
+
- type: summary
|
|
145
|
+
from: trace
|
|
146
|
+
description: "Breakpoint analysis from investigator"
|
|
147
|
+
produces:
|
|
148
|
+
- type: git_commit
|
|
149
|
+
description: "Single-file fix commit"
|
|
138
150
|
- id: verify
|
|
139
151
|
role: investigator
|
|
140
152
|
depends_on: [fix]
|
|
141
153
|
description: Verify the fix with adb
|
|
142
154
|
prompt: "Run the feature on device. adb screencap + logcat. Compare with v1 behavior."
|
|
155
|
+
handoff:
|
|
156
|
+
consumes:
|
|
157
|
+
- type: git_commit
|
|
158
|
+
from: fix
|
|
159
|
+
description: "Fix commit to verify"
|
|
160
|
+
produces:
|
|
161
|
+
- type: summary
|
|
162
|
+
description: "Verification result with screenshots"
|
|
@@ -190,11 +190,27 @@ workflows:
|
|
|
190
190
|
role: scanner
|
|
191
191
|
description: "Scan v1 module in {{v1_path}}/. Output behavior doc to {{behavior_docs}}/$ARGUMENTS.md. List all user actions with call chains."
|
|
192
192
|
prompt: "Scan module '$ARGUMENTS' in {{v1_path}}/. For each page, list: action → function() → return value. Output to {{behavior_docs}}/$ARGUMENTS.md. Then immediately proceed to write_tests."
|
|
193
|
+
handoff:
|
|
194
|
+
produces:
|
|
195
|
+
- type: file
|
|
196
|
+
path: "{{behavior_docs}}/$ARGUMENTS.md"
|
|
197
|
+
description: "Behavior document for module"
|
|
193
198
|
- id: write_tests
|
|
194
199
|
role: test_writer
|
|
195
200
|
depends_on: [scan]
|
|
196
201
|
description: "Read {{behavior_docs}}/$ARGUMENTS.md, write tests in {{test_path}}/$ARGUMENTS/, run baseline, commit."
|
|
197
202
|
prompt: "Read {{behavior_docs}}/$ARGUMENTS.md. Write tests in {{test_path}}/$ARGUMENTS/. Test ALL layers: logic, widget, navigation. Run tests, record red/green baseline. Append baseline to behavior doc. Git commit: behavior-lock($ARGUMENTS): X tests (Y red, Z skipped)"
|
|
203
|
+
handoff:
|
|
204
|
+
consumes:
|
|
205
|
+
- type: file
|
|
206
|
+
path: "{{behavior_docs}}/$ARGUMENTS.md"
|
|
207
|
+
description: "Behavior document from scan step"
|
|
208
|
+
produces:
|
|
209
|
+
- type: directory
|
|
210
|
+
path: "{{test_path}}/$ARGUMENTS/"
|
|
211
|
+
description: "Test files for module"
|
|
212
|
+
- type: git_commit
|
|
213
|
+
description: "Behavior lock commit"
|
|
198
214
|
|
|
199
215
|
rescue:
|
|
200
216
|
name: Rescue
|
|
@@ -204,6 +220,13 @@ workflows:
|
|
|
204
220
|
role: investigator
|
|
205
221
|
description: "Run tests, assess current state, pick next targets."
|
|
206
222
|
prompt: "Run tests in {{test_path}}/$ARGUMENTS/. Categorize all non-passing tests: 1) RED (failing) — highest priority, fix first. 2) SKIPPED-logic — state/notifier/service tests, fix second. 3) SKIPPED-widget — widget/UI/navigation tests, fix after logic is done. For the highest priority category, pick a batch of related tests. Trace: what does v1 do vs what does v2 do? Find the breakpoints. Report findings and the plan for this round."
|
|
223
|
+
handoff:
|
|
224
|
+
produces:
|
|
225
|
+
- type: summary
|
|
226
|
+
description: "Investigation findings and breakpoint analysis"
|
|
227
|
+
- type: test_result
|
|
228
|
+
path: "{{test_path}}/$ARGUMENTS/"
|
|
229
|
+
description: "Current test state assessment"
|
|
207
230
|
- id: fix
|
|
208
231
|
role: surgeon
|
|
209
232
|
depends_on: [investigate]
|
|
@@ -212,11 +235,27 @@ workflows:
|
|
|
212
235
|
- assert: clean_working_tree
|
|
213
236
|
message: "Commit all changes before proceeding to report step"
|
|
214
237
|
prompt: "Fix the identified breakpoints. Read v1 in {{v1_path}}/. Rewrite in v2 style in {{v2_path}}/. Logic tests: implement notifier/state/service code. Widget tests: copy widget from v1, change bindings (Obx→Consumer, Get.to→context.go), set up widget test infra (ProviderScope, mock providers, GoRouter) if needed. Run tests after each fix. Red→green or Skipped→green = done. Still failing = revert and re-analyze. Maximize test coverage per round. When done, commit all changes: rescue($ARGUMENTS): round N — X passed (+Y)"
|
|
238
|
+
handoff:
|
|
239
|
+
consumes:
|
|
240
|
+
- type: summary
|
|
241
|
+
from: investigate
|
|
242
|
+
description: "Investigation findings from investigate step"
|
|
243
|
+
produces:
|
|
244
|
+
- type: git_commit
|
|
245
|
+
description: "Rescue round commit"
|
|
215
246
|
- id: report
|
|
216
247
|
role: investigator
|
|
217
248
|
depends_on: [fix]
|
|
218
249
|
description: "Summarize round, guide next steps."
|
|
219
250
|
prompt: "Run full test suite in {{test_path}}/$ARGUMENTS/. Report: 1) passed/skipped/failed delta vs last round. 2) List remaining skipped tests by category (logic vs widget vs platform). 3) If skipped tests remain, end with: Run /rescue $ARGUMENTS to continue. 4) If all tests pass, end with: Module $ARGUMENTS rescue complete."
|
|
251
|
+
handoff:
|
|
252
|
+
consumes:
|
|
253
|
+
- type: git_commit
|
|
254
|
+
from: fix
|
|
255
|
+
description: "Committed fix from surgeon"
|
|
256
|
+
produces:
|
|
257
|
+
- type: summary
|
|
258
|
+
description: "Round summary with test delta"
|
|
220
259
|
|
|
221
260
|
core-align:
|
|
222
261
|
name: Core Align
|
|
@@ -110,18 +110,47 @@ workflow:
|
|
|
110
110
|
description: Read task and produce design document
|
|
111
111
|
run_if: "round == 1"
|
|
112
112
|
prompt: "Read task {{task_id}} from BOARD.md. Produce a design document."
|
|
113
|
+
handoff:
|
|
114
|
+
produces:
|
|
115
|
+
- type: file
|
|
116
|
+
path: "docs/tasks/{{task_id}}.md"
|
|
117
|
+
description: "Design document for task"
|
|
113
118
|
- id: implement
|
|
114
119
|
role: implementer
|
|
115
120
|
description: Implement according to design
|
|
116
121
|
prompt: "Implement task {{task_id}} following the design document."
|
|
122
|
+
handoff:
|
|
123
|
+
consumes:
|
|
124
|
+
- type: file
|
|
125
|
+
path: "docs/tasks/{{task_id}}.md"
|
|
126
|
+
description: "Design document from planner"
|
|
127
|
+
produces:
|
|
128
|
+
- type: git_commit
|
|
129
|
+
description: "Implementation commit"
|
|
117
130
|
- id: test
|
|
118
131
|
role: tester
|
|
119
132
|
description: Run tests and fix failures
|
|
120
133
|
prompt: "Run tests. Fix failures. Add missing tests for {{task_id}}."
|
|
134
|
+
handoff:
|
|
135
|
+
consumes:
|
|
136
|
+
- type: git_commit
|
|
137
|
+
from: implement
|
|
138
|
+
description: "Implementation to test"
|
|
139
|
+
produces:
|
|
140
|
+
- type: test_result
|
|
141
|
+
description: "Test results after fixes"
|
|
121
142
|
- id: review
|
|
122
143
|
role: reviewer
|
|
123
144
|
description: Review and output verdict
|
|
124
145
|
prompt: "Review changes for {{task_id}}. Output PASS or FAIL."
|
|
146
|
+
handoff:
|
|
147
|
+
consumes:
|
|
148
|
+
- type: test_result
|
|
149
|
+
from: test
|
|
150
|
+
description: "Test results to review"
|
|
151
|
+
produces:
|
|
152
|
+
- type: summary
|
|
153
|
+
description: "Review verdict (PASS/FAIL)"
|
|
125
154
|
transitions:
|
|
126
155
|
- from: review
|
|
127
156
|
to: implement
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "intentdna",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"description": "Intent DNA — Declarative policy layer for AI agent behavior",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -33,6 +33,7 @@
|
|
|
33
33
|
],
|
|
34
34
|
"files": [
|
|
35
35
|
"dist",
|
|
36
|
+
".claude-plugin",
|
|
36
37
|
"README.md",
|
|
37
38
|
"LICENSE"
|
|
38
39
|
],
|