@davidorex/pi-workflows 0.5.0 → 0.9.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.
Files changed (51) hide show
  1. package/README.md +1 -1
  2. package/agents/audit-finding-verifier.agent.yaml +40 -0
  3. package/agents/audit-results-router.agent.yaml +30 -0
  4. package/agents/gap-resolution-assessor.agent.yaml +40 -0
  5. package/dist/expression.d.ts.map +1 -1
  6. package/dist/expression.js +6 -0
  7. package/dist/expression.js.map +1 -1
  8. package/dist/index.d.ts.map +1 -1
  9. package/dist/index.js +5 -4
  10. package/dist/index.js.map +1 -1
  11. package/dist/step-agent.d.ts.map +1 -1
  12. package/dist/step-agent.js +13 -1
  13. package/dist/step-agent.js.map +1 -1
  14. package/dist/step-block.d.ts +18 -0
  15. package/dist/step-block.d.ts.map +1 -0
  16. package/dist/step-block.js +204 -0
  17. package/dist/step-block.js.map +1 -0
  18. package/dist/template-validation.d.ts +25 -0
  19. package/dist/template-validation.d.ts.map +1 -0
  20. package/dist/template-validation.js +341 -0
  21. package/dist/template-validation.js.map +1 -0
  22. package/dist/types.d.ts +31 -0
  23. package/dist/types.d.ts.map +1 -1
  24. package/dist/workflow-executor.d.ts.map +1 -1
  25. package/dist/workflow-executor.js +31 -5
  26. package/dist/workflow-executor.js.map +1 -1
  27. package/dist/workflow-sdk.d.ts +1 -0
  28. package/dist/workflow-sdk.d.ts.map +1 -1
  29. package/dist/workflow-sdk.js +7 -0
  30. package/dist/workflow-sdk.js.map +1 -1
  31. package/dist/workflow-spec.d.ts.map +1 -1
  32. package/dist/workflow-spec.js +106 -0
  33. package/dist/workflow-spec.js.map +1 -1
  34. package/package.json +7 -8
  35. package/schemas/audit-routing-manifest.schema.json +38 -0
  36. package/schemas/finding-verification.schema.json +34 -0
  37. package/schemas/resolution-assessment.schema.json +36 -0
  38. package/skills/pi-workflows/SKILL.md +1 -1
  39. package/skills/pi-workflows/references/bundled-resources.md +12 -3
  40. package/templates/audit-finding-verifier/task.md +59 -0
  41. package/templates/audit-results-router/task.md +37 -0
  42. package/templates/gap-resolution-assessor/task.md +48 -0
  43. package/templates/handoff-writer/task.md +16 -6
  44. package/templates/phase-author/task.md +8 -0
  45. package/workflows/create-handoff.workflow.yaml +56 -35
  46. package/workflows/create-phase.workflow.yaml +27 -32
  47. package/workflows/do-gap.workflow.yaml +48 -28
  48. package/workflows/fix-audit.workflow.yaml +89 -127
  49. package/workflows/gap-to-phase.workflow.yaml +47 -42
  50. package/workflows/parallel-analysis.workflow.yaml +20 -8
  51. package/workflows/plan-from-requirements.workflow.yaml +16 -27
@@ -0,0 +1,204 @@
1
+ /**
2
+ * Block step executor — performs validated, in-process block I/O.
3
+ * No LLM call, no subprocess — calls the block API directly.
4
+ *
5
+ * Operations:
6
+ * - read: single or multi-block read via readBlock()
7
+ * - readDir: directory enumeration for .project/ subdirectories
8
+ * - write: validated write via writeBlock()
9
+ * - append: array append via appendToBlock()
10
+ * - update: item update via updateItemInBlock()
11
+ */
12
+ import fs from "node:fs";
13
+ import path from "node:path";
14
+ import { appendToBlock, readBlock, updateItemInBlock, writeBlock } from "@davidorex/pi-project/block-api";
15
+ import { PROJECT_DIR } from "@davidorex/pi-project/project-dir";
16
+ import { validateFromFile } from "@davidorex/pi-project/schema-validator";
17
+ import { resolveExpressions } from "./expression.js";
18
+ import { persistStepOutput } from "./output.js";
19
+ import { zeroUsage } from "./step-shared.js";
20
+ /**
21
+ * Execute a block step: performs block I/O using the block API.
22
+ * All block names and values are expression-resolved before API calls.
23
+ */
24
+ export function executeBlock(blockSpec, stepName, scope, cwd, runDir, outputPath) {
25
+ const startTime = Date.now();
26
+ try {
27
+ // Resolve expressions in the block spec
28
+ const resolved = resolveExpressions(blockSpec, scope);
29
+ let output;
30
+ if ("read" in resolved) {
31
+ output = executeRead(resolved.read, resolved.optional, cwd);
32
+ }
33
+ else if ("readDir" in resolved) {
34
+ output = executeReadDir(resolved.readDir, cwd);
35
+ }
36
+ else if ("write" in resolved) {
37
+ output = executeWrite(resolved.write, cwd);
38
+ }
39
+ else if ("append" in resolved) {
40
+ output = executeAppend(resolved.append, cwd);
41
+ }
42
+ else if ("update" in resolved) {
43
+ output = executeUpdate(resolved.update, cwd);
44
+ }
45
+ else {
46
+ throw new Error("Block spec must have one of: read, readDir, write, append, update");
47
+ }
48
+ const result = {
49
+ step: stepName,
50
+ agent: "block",
51
+ status: "completed",
52
+ output,
53
+ textOutput: JSON.stringify(output, null, 2),
54
+ usage: zeroUsage(),
55
+ durationMs: Date.now() - startTime,
56
+ };
57
+ if (runDir) {
58
+ result.outputPath = persistStepOutput(runDir, stepName, output, undefined, outputPath);
59
+ }
60
+ return result;
61
+ }
62
+ catch (err) {
63
+ return {
64
+ step: stepName,
65
+ agent: "block",
66
+ status: "failed",
67
+ usage: zeroUsage(),
68
+ durationMs: Date.now() - startTime,
69
+ error: err instanceof Error ? err.message : String(err),
70
+ };
71
+ }
72
+ }
73
+ /**
74
+ * Read one or more blocks. Single string → single block content.
75
+ * Array → object keyed by block name.
76
+ */
77
+ function executeRead(read, optional, cwd) {
78
+ const optionalSet = new Set(optional ?? []);
79
+ if (typeof read === "string") {
80
+ // Single block read
81
+ try {
82
+ return readBlock(cwd, read);
83
+ }
84
+ catch (err) {
85
+ if (optionalSet.has(read))
86
+ return null;
87
+ throw err;
88
+ }
89
+ }
90
+ // Multi-block read
91
+ const result = {};
92
+ for (const name of read) {
93
+ try {
94
+ result[name] = readBlock(cwd, name);
95
+ }
96
+ catch (err) {
97
+ if (optionalSet.has(name)) {
98
+ result[name] = null;
99
+ }
100
+ else {
101
+ throw err;
102
+ }
103
+ }
104
+ }
105
+ return result;
106
+ }
107
+ /**
108
+ * Read all JSON files in a .project/ subdirectory.
109
+ * Returns sorted array of parsed contents.
110
+ * Missing directories return [] (on-demand subdirectories).
111
+ */
112
+ function executeReadDir(subdir, cwd) {
113
+ const dirPath = path.join(cwd, PROJECT_DIR, subdir);
114
+ let entries;
115
+ try {
116
+ entries = fs
117
+ .readdirSync(dirPath)
118
+ .filter((f) => f.endsWith(".json"))
119
+ .sort();
120
+ }
121
+ catch {
122
+ // Missing directory = "no items yet" for on-demand .project/ subdirectories
123
+ return [];
124
+ }
125
+ const results = [];
126
+ for (const filename of entries) {
127
+ const filePath = path.join(dirPath, filename);
128
+ let content;
129
+ try {
130
+ content = fs.readFileSync(filePath, "utf-8");
131
+ }
132
+ catch {
133
+ throw new Error(`Cannot read file: ${PROJECT_DIR}/${subdir}/${filename}`);
134
+ }
135
+ try {
136
+ results.push(JSON.parse(content));
137
+ }
138
+ catch {
139
+ throw new Error(`Invalid JSON in: ${PROJECT_DIR}/${subdir}/${filename}`);
140
+ }
141
+ }
142
+ return results;
143
+ }
144
+ /**
145
+ * Write a block via writeBlock (schema validation + atomic write).
146
+ * Supports optional path override for subdirectory writes.
147
+ */
148
+ function executeWrite(spec, cwd) {
149
+ if (spec.path) {
150
+ return executeSubdirWrite(spec.name, spec.data, spec.path, cwd);
151
+ }
152
+ writeBlock(cwd, spec.name, spec.data);
153
+ return { written: spec.name, path: `${PROJECT_DIR}/${spec.name}.json` };
154
+ }
155
+ /**
156
+ * Write to a subdirectory path (.project/{path}.json) with schema
157
+ * validation from `name`. Provides atomic writes and directory creation.
158
+ */
159
+ function executeSubdirWrite(schemaName, data, subPath, cwd) {
160
+ const filePath = path.join(cwd, PROJECT_DIR, `${subPath}.json`);
161
+ const schemaFile = path.join(cwd, PROJECT_DIR, "schemas", `${schemaName}.schema.json`);
162
+ // Validate against schema if it exists
163
+ if (fs.existsSync(schemaFile)) {
164
+ validateFromFile(schemaFile, data, `block file '${subPath}.json'`);
165
+ }
166
+ // Ensure parent directory exists
167
+ fs.mkdirSync(path.dirname(filePath), { recursive: true });
168
+ // Atomic write
169
+ const tmpPath = `${filePath}.block-step-${process.pid}.tmp`;
170
+ try {
171
+ fs.writeFileSync(tmpPath, JSON.stringify(data, null, 2), "utf-8");
172
+ fs.renameSync(tmpPath, filePath);
173
+ }
174
+ catch (err) {
175
+ try {
176
+ fs.unlinkSync(tmpPath);
177
+ }
178
+ catch {
179
+ /* cleanup best-effort */
180
+ }
181
+ const msg = err instanceof Error ? err.message : String(err);
182
+ throw new Error(`Failed to write ${PROJECT_DIR}/${subPath}.json: ${msg}`);
183
+ }
184
+ return { written: schemaName, path: `${PROJECT_DIR}/${subPath}.json` };
185
+ }
186
+ /**
187
+ * Append an item to a block array via appendToBlock.
188
+ */
189
+ function executeAppend(spec, cwd) {
190
+ appendToBlock(cwd, spec.name, spec.key, spec.item);
191
+ return { appended: spec.name, key: spec.key };
192
+ }
193
+ /**
194
+ * Update an item in a block array via updateItemInBlock.
195
+ * The `match` object is converted to a predicate.
196
+ */
197
+ function executeUpdate(spec, cwd) {
198
+ const predicate = (item) => {
199
+ return Object.entries(spec.match).every(([k, v]) => item[k] === v);
200
+ };
201
+ updateItemInBlock(cwd, spec.name, spec.key, predicate, spec.set);
202
+ return { updated: spec.name, key: spec.key, matched: spec.match };
203
+ }
204
+ //# sourceMappingURL=step-block.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"step-block.js","sourceRoot":"","sources":["../src/step-block.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ import type { WorkflowSpec } from "./types.js";
2
+ import type { ValidationIssue } from "./workflow-sdk.js";
3
+ export interface TemplateVariable {
4
+ root: string;
5
+ path: string;
6
+ guarded: boolean;
7
+ usage: "output" | "loop" | "conditional";
8
+ }
9
+ export interface SchemaFields {
10
+ properties: Record<string, {
11
+ type: string;
12
+ }>;
13
+ required: string[];
14
+ }
15
+ /**
16
+ * Extract all Nunjucks variable references from a template string.
17
+ * Returns structured entries with full dotted paths and usage context.
18
+ */
19
+ export declare function extractTemplateVariables(content: string): TemplateVariable[];
20
+ /**
21
+ * Validate template-input alignment for all agent steps in a workflow.
22
+ * Returns validation issues for field mismatches, missing inputs, and naming errors.
23
+ */
24
+ export declare function validateTemplateAlignment(spec: WorkflowSpec, cwd: string, builtinDir?: string): ValidationIssue[];
25
+ //# sourceMappingURL=template-validation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"template-validation.d.ts","sourceRoot":"","sources":["../src/template-validation.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAY,YAAY,EAAE,MAAM,YAAY,CAAC;AACzD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAKzD,MAAM,WAAW,gBAAgB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,QAAQ,GAAG,MAAM,GAAG,aAAa,CAAC;CACzC;AAED,MAAM,WAAW,YAAY;IAC5B,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC7C,QAAQ,EAAE,MAAM,EAAE,CAAC;CACnB;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,MAAM,GAAG,gBAAgB,EAAE,CAmE5E;AA4ID;;;GAGG;AACH,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,YAAY,EAAE,GAAG,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,eAAe,EAAE,CA4HjH"}
@@ -0,0 +1,341 @@
1
+ /**
2
+ * Template-input alignment validation for workflow agent steps.
3
+ *
4
+ * Traces the full chain: workflow step → input expressions → source schemas → template field references.
5
+ * Catches field name mismatches, missing inputs, and forEach variable naming errors that cause
6
+ * Nunjucks to silently render empty strings.
7
+ */
8
+ import * as fs from "node:fs";
9
+ import * as path from "node:path";
10
+ import { createAgentLoader } from "./agent-spec.js";
11
+ import { resolveSchemaPath } from "./step-shared.js";
12
+ // Variables injected by the execution engine, not from workflow inputs
13
+ const INJECTED_VARIABLES = new Set(["output_schema", "loop"]);
14
+ /**
15
+ * Extract all Nunjucks variable references from a template string.
16
+ * Returns structured entries with full dotted paths and usage context.
17
+ */
18
+ export function extractTemplateVariables(content) {
19
+ const variables = [];
20
+ const seen = new Set();
21
+ // Track which lines are inside {% if var %} guards
22
+ const guardedRoots = new Set();
23
+ const ifStack = [];
24
+ let depth = 0;
25
+ const lines = content.split("\n");
26
+ for (const line of lines) {
27
+ // Track {% if var.field %} blocks
28
+ const ifMatch = line.match(/\{%[-\s]*if\s+([\w.]+)/);
29
+ if (ifMatch) {
30
+ depth++;
31
+ const root = ifMatch[1].split(".")[0];
32
+ ifStack.push({ root, depth });
33
+ guardedRoots.add(root);
34
+ }
35
+ const endifMatch = line.match(/\{%[-\s]*endif/);
36
+ if (endifMatch) {
37
+ while (ifStack.length > 0 && ifStack[ifStack.length - 1].depth === depth) {
38
+ const popped = ifStack.pop();
39
+ if (popped)
40
+ guardedRoots.delete(popped.root);
41
+ }
42
+ depth--;
43
+ }
44
+ // Extract {{ var.field }} output expressions
45
+ const outputPattern = /\{\{\s*([\w]+(?:\.[\w]+)*)\s*(?:\|[^}]*)?\}\}/g;
46
+ let match;
47
+ match = outputPattern.exec(line);
48
+ while (match !== null) {
49
+ const fullPath = match[1];
50
+ const root = fullPath.split(".")[0];
51
+ if (!INJECTED_VARIABLES.has(root) && fullPath.includes(".") && !seen.has(fullPath)) {
52
+ seen.add(fullPath);
53
+ variables.push({
54
+ root,
55
+ path: fullPath,
56
+ guarded: guardedRoots.has(root),
57
+ usage: "output",
58
+ });
59
+ }
60
+ match = outputPattern.exec(line);
61
+ }
62
+ // Extract {% for x in var.field %} loop sources
63
+ const forPattern = /\{%[-\s]*for\s+\w+\s+in\s+([\w]+(?:\.[\w]+)*)\s*%\}/g;
64
+ match = forPattern.exec(line);
65
+ while (match !== null) {
66
+ const fullPath = match[1];
67
+ const root = fullPath.split(".")[0];
68
+ if (!INJECTED_VARIABLES.has(root) && fullPath.includes(".") && !seen.has(fullPath)) {
69
+ seen.add(fullPath);
70
+ variables.push({
71
+ root,
72
+ path: fullPath,
73
+ guarded: guardedRoots.has(root),
74
+ usage: "loop",
75
+ });
76
+ }
77
+ match = forPattern.exec(line);
78
+ }
79
+ }
80
+ return variables;
81
+ }
82
+ /**
83
+ * Given a step's input expression and the workflow spec, trace to a source schema
84
+ * and return its field definitions. Returns null if unverifiable.
85
+ */
86
+ function traceInputSchema(inputExpr, stepSpec, spec, cwd) {
87
+ // Extract the expression content from ${{ ... }}
88
+ const exprMatch = inputExpr.match(/\$\{\{\s*(.+?)\s*\}\}/);
89
+ if (!exprMatch)
90
+ return null;
91
+ const expr = exprMatch[1];
92
+ // Case 1: forEach `as` variable — trace to the forEach source array's item schema
93
+ if (stepSpec.forEach && stepSpec.as && expr === stepSpec.as) {
94
+ return traceForEachItemSchema(stepSpec.forEach, spec, cwd);
95
+ }
96
+ // Case 2: ${{ steps.X.output }} or ${{ steps.X.output.field }}
97
+ const stepsMatch = expr.match(/^steps\.([\w-]+)\.output(?:\.([\w]+))?$/);
98
+ if (stepsMatch) {
99
+ const [, stepName, subField] = stepsMatch;
100
+ const sourceStep = spec.steps[stepName];
101
+ if (!sourceStep?.output?.schema)
102
+ return null;
103
+ return loadSchemaFields(sourceStep.output.schema, spec.filePath, cwd, subField);
104
+ }
105
+ return null;
106
+ }
107
+ /**
108
+ * Trace a forEach expression to the schema of each array item.
109
+ * E.g. ${{ steps.decompose.output.specs }} → decomposition-specs schema → specs.items.properties
110
+ */
111
+ function traceForEachItemSchema(forEachExpr, spec, cwd) {
112
+ const exprMatch = forEachExpr.match(/\$\{\{\s*(.+?)\s*\}\}/);
113
+ if (!exprMatch)
114
+ return null;
115
+ const expr = exprMatch[1];
116
+ // Match steps.X.output.arrayField
117
+ const match = expr.match(/^steps\.([\w-]+)\.output\.([\w]+)$/);
118
+ if (!match)
119
+ return null;
120
+ const [, stepName, arrayField] = match;
121
+ const sourceStep = spec.steps[stepName];
122
+ if (!sourceStep?.output?.schema)
123
+ return null;
124
+ const schemaPath = resolveSchemaPath(sourceStep.output.schema, spec.filePath, cwd);
125
+ try {
126
+ const schema = JSON.parse(fs.readFileSync(schemaPath, "utf-8"));
127
+ const arrayProp = schema.properties?.[arrayField];
128
+ if (!arrayProp)
129
+ return null;
130
+ // Navigate to items schema
131
+ const itemSchema = arrayProp.items;
132
+ if (!itemSchema?.properties)
133
+ return null;
134
+ const properties = {};
135
+ for (const [key, value] of Object.entries(itemSchema.properties)) {
136
+ properties[key] = { type: value.type };
137
+ }
138
+ return {
139
+ properties,
140
+ required: itemSchema.required ?? [],
141
+ };
142
+ }
143
+ catch {
144
+ return null;
145
+ }
146
+ }
147
+ /**
148
+ * Load a schema file and return its field definitions.
149
+ * If subField is provided, navigates into that property's sub-schema.
150
+ */
151
+ function loadSchemaFields(schemaRef, specFilePath, cwd, subField) {
152
+ const schemaPath = resolveSchemaPath(schemaRef, specFilePath, cwd);
153
+ try {
154
+ const schema = JSON.parse(fs.readFileSync(schemaPath, "utf-8"));
155
+ let target = schema;
156
+ if (subField) {
157
+ target = schema.properties?.[subField];
158
+ if (!target)
159
+ return null;
160
+ }
161
+ if (!target.properties)
162
+ return null;
163
+ const properties = {};
164
+ for (const [key, value] of Object.entries(target.properties)) {
165
+ properties[key] = { type: value.type };
166
+ }
167
+ return {
168
+ properties,
169
+ required: target.required ?? [],
170
+ };
171
+ }
172
+ catch {
173
+ return null;
174
+ }
175
+ }
176
+ /**
177
+ * Find the closest matching field name from a schema for a mismatched template reference.
178
+ */
179
+ function suggestClosest(field, schemaFields) {
180
+ // Simple heuristic: check if one contains the other or shares a stem
181
+ for (const sf of schemaFields) {
182
+ if (sf.includes(field) || field.includes(sf))
183
+ return sf;
184
+ }
185
+ // Check common renames: underscore/camelCase, pluralization
186
+ const normalized = field.toLowerCase().replace(/_/g, "");
187
+ for (const sf of schemaFields) {
188
+ const sfNorm = sf.toLowerCase().replace(/_/g, "");
189
+ if (sfNorm === normalized)
190
+ return sf;
191
+ // Check if one is a prefix of the other
192
+ if (sfNorm.startsWith(normalized) || normalized.startsWith(sfNorm))
193
+ return sf;
194
+ }
195
+ return undefined;
196
+ }
197
+ /**
198
+ * Walk all agent steps in a workflow spec, including nested loop/parallel/forEach steps.
199
+ * Yields [stepName, stepSpec, parentPrefix] tuples.
200
+ */
201
+ function* walkAgentSteps(steps, prefix = "") {
202
+ for (const [name, step] of Object.entries(steps)) {
203
+ const fullName = prefix ? `${prefix}.${name}` : name;
204
+ if (step.agent) {
205
+ yield [fullName, step, fullName];
206
+ }
207
+ if (step.loop?.steps) {
208
+ yield* walkAgentSteps(step.loop.steps, `${fullName}.loop`);
209
+ }
210
+ if (step.parallel) {
211
+ yield* walkAgentSteps(step.parallel, `${fullName}.parallel`);
212
+ }
213
+ }
214
+ }
215
+ /**
216
+ * Validate template-input alignment for all agent steps in a workflow.
217
+ * Returns validation issues for field mismatches, missing inputs, and naming errors.
218
+ */
219
+ export function validateTemplateAlignment(spec, cwd, builtinDir) {
220
+ const issues = [];
221
+ let loadAgent;
222
+ try {
223
+ loadAgent = createAgentLoader(cwd, builtinDir);
224
+ }
225
+ catch {
226
+ return issues; // can't load agents — agent resolution check already handles this
227
+ }
228
+ // Template search mirrors createTemplateEnv() — project, user, builtin
229
+ const builtinTemplateDir = builtinDir
230
+ ? path.resolve(builtinDir, "..", "templates")
231
+ : path.resolve(import.meta.dirname, "..", "templates");
232
+ const templateSearchPaths = [
233
+ path.join(cwd, ".pi", "templates"),
234
+ path.join(process.env.HOME ?? "", ".pi", "agent", "templates"),
235
+ builtinTemplateDir,
236
+ ];
237
+ for (const [stepName, stepSpec] of walkAgentSteps(spec.steps)) {
238
+ if (!stepSpec.agent)
239
+ continue;
240
+ // Load agent spec
241
+ let agentSpec;
242
+ try {
243
+ agentSpec = loadAgent(stepSpec.agent);
244
+ }
245
+ catch {
246
+ continue; // agent resolution check handles this
247
+ }
248
+ if (!agentSpec.taskTemplate)
249
+ continue;
250
+ // Resolve and read template file
251
+ let templateContent = null;
252
+ for (const searchPath of templateSearchPaths) {
253
+ const fullPath = path.join(searchPath, agentSpec.taskTemplate);
254
+ try {
255
+ templateContent = fs.readFileSync(fullPath, "utf-8");
256
+ break;
257
+ }
258
+ catch {
259
+ // try next path
260
+ }
261
+ }
262
+ if (!templateContent)
263
+ continue;
264
+ const templateVars = extractTemplateVariables(templateContent);
265
+ if (templateVars.length === 0)
266
+ continue;
267
+ const inputKeys = stepSpec.input ? new Set(Object.keys(stepSpec.input)) : new Set();
268
+ // Check 1: forEach `as` variable matches template root variables
269
+ if (stepSpec.forEach && stepSpec.as) {
270
+ const forEachRoots = new Set(templateVars.map((v) => v.root));
271
+ // The `as` name should appear as a root in the template, OR a root that IS in the input
272
+ // The common bug: template uses `spec.*` but forEach says `as: plan`
273
+ if (!forEachRoots.has(stepSpec.as) && !inputKeys.has(stepSpec.as)) {
274
+ // forEach variable is never referenced — find what the template uses instead
275
+ const nonInputRoots = [...forEachRoots].filter((r) => !inputKeys.has(r) && !INJECTED_VARIABLES.has(r));
276
+ if (nonInputRoots.length > 0) {
277
+ issues.push({
278
+ severity: "error",
279
+ message: `Template '${agentSpec.taskTemplate}' uses '${nonInputRoots[0]}.*' but forEach binds as '${stepSpec.as}'. Template variables will be undefined.`,
280
+ field: `steps.${stepName}.as`,
281
+ });
282
+ }
283
+ }
284
+ }
285
+ // Check 2: Root variables exist in step inputs (or are injected)
286
+ const uniqueRoots = new Set(templateVars.map((v) => v.root));
287
+ for (const root of uniqueRoots) {
288
+ if (INJECTED_VARIABLES.has(root))
289
+ continue;
290
+ if (inputKeys.has(root))
291
+ continue;
292
+ // forEach `as` variable counts as an input
293
+ if (stepSpec.forEach && stepSpec.as === root)
294
+ continue;
295
+ // Find if any template var with this root is guarded
296
+ const allGuarded = templateVars.filter((v) => v.root === root).every((v) => v.guarded);
297
+ issues.push({
298
+ severity: allGuarded ? "warning" : "error",
299
+ message: `Template '${agentSpec.taskTemplate}' references '${root}' but step '${stepName}' does not declare it in input.${allGuarded ? " (guarded with conditional)" : ""}`,
300
+ field: `steps.${stepName}.input`,
301
+ });
302
+ }
303
+ // Check 3: Field-level alignment against source schemas
304
+ for (const tv of templateVars) {
305
+ if (INJECTED_VARIABLES.has(tv.root))
306
+ continue;
307
+ const fieldParts = tv.path.split(".");
308
+ if (fieldParts.length < 2)
309
+ continue;
310
+ const field = fieldParts[1]; // first-level field access on the root variable
311
+ // Find the input expression for this root
312
+ const inputExpr = stepSpec.input?.[tv.root];
313
+ // Also check if this is the forEach `as` variable
314
+ const isForEachVar = stepSpec.forEach && stepSpec.as === tv.root;
315
+ let exprToTrace;
316
+ if (isForEachVar) {
317
+ exprToTrace = `\${{ ${stepSpec.as} }}`;
318
+ }
319
+ else if (typeof inputExpr === "string") {
320
+ exprToTrace = inputExpr;
321
+ }
322
+ if (!exprToTrace)
323
+ continue;
324
+ const schemaFields = traceInputSchema(exprToTrace, stepSpec, spec, cwd);
325
+ if (!schemaFields)
326
+ continue; // unverifiable
327
+ if (!(field in schemaFields.properties)) {
328
+ const closest = suggestClosest(field, Object.keys(schemaFields.properties));
329
+ const suggestion = closest ? ` Did you mean '${closest}'?` : "";
330
+ const available = Object.keys(schemaFields.properties).join(", ");
331
+ issues.push({
332
+ severity: tv.guarded ? "warning" : "error",
333
+ message: `Template '${agentSpec.taskTemplate}' references '${tv.path}' but schema has no field '${field}'.${suggestion} Available: [${available}]`,
334
+ field: `steps.${stepName}.input.${tv.root}`,
335
+ });
336
+ }
337
+ }
338
+ }
339
+ return issues;
340
+ }
341
+ //# sourceMappingURL=template-validation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"template-validation.js","sourceRoot":"","sources":["../src/template-validation.ts"],"names":[],"mappings":"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"}
package/dist/types.d.ts CHANGED
@@ -39,6 +39,7 @@ export interface StepSpec {
39
39
  pause?: string | boolean;
40
40
  monitor?: string;
41
41
  command?: string;
42
+ block?: BlockSpec;
42
43
  forEach?: string;
43
44
  as?: string;
44
45
  color?: string;
@@ -63,6 +64,36 @@ export interface TransformSpec {
63
64
  */
64
65
  mapping: Record<string, unknown>;
65
66
  }
67
+ export interface BlockReadSpec {
68
+ read: string | string[];
69
+ optional?: string[];
70
+ }
71
+ export interface BlockReadDirSpec {
72
+ readDir: string;
73
+ }
74
+ export interface BlockWriteSpec {
75
+ write: {
76
+ name: string;
77
+ data: unknown;
78
+ path?: string;
79
+ };
80
+ }
81
+ export interface BlockAppendSpec {
82
+ append: {
83
+ name: string;
84
+ key: string;
85
+ item: unknown;
86
+ };
87
+ }
88
+ export interface BlockUpdateSpec {
89
+ update: {
90
+ name: string;
91
+ key: string;
92
+ match: Record<string, unknown>;
93
+ set: Record<string, unknown>;
94
+ };
95
+ }
96
+ export type BlockSpec = BlockReadSpec | BlockReadDirSpec | BlockWriteSpec | BlockAppendSpec | BlockUpdateSpec;
66
97
  export interface StepOutputSpec {
67
98
  format?: "json" | "text";
68
99
  schema?: string;