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.
@@ -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 {
@@ -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.2.3",
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
  ],