@farmslot/recipe-harness 0.7.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 (115) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/README.md +83 -182
  3. package/dist/adapters/app-lifecycle.d.ts.map +1 -1
  4. package/dist/adapters/app-lifecycle.js +5 -0
  5. package/dist/adapters/app-lifecycle.js.map +1 -1
  6. package/dist/adapters/core.d.ts.map +1 -1
  7. package/dist/adapters/core.js +25 -46
  8. package/dist/adapters/core.js.map +1 -1
  9. package/dist/adapters/ui.d.ts +0 -2
  10. package/dist/adapters/ui.d.ts.map +1 -1
  11. package/dist/adapters/ui.js +5 -2
  12. package/dist/adapters/ui.js.map +1 -1
  13. package/dist/cli/index.d.ts.map +1 -1
  14. package/dist/cli/index.js +0 -2
  15. package/dist/cli/index.js.map +1 -1
  16. package/dist/cli/run-command.d.ts.map +1 -1
  17. package/dist/cli/run-command.js +197 -32
  18. package/dist/cli/run-command.js.map +1 -1
  19. package/dist/cli/support.d.ts +5 -2
  20. package/dist/cli/support.d.ts.map +1 -1
  21. package/dist/cli/support.js +131 -25
  22. package/dist/cli/support.js.map +1 -1
  23. package/dist/cli/validate-command.d.ts.map +1 -1
  24. package/dist/cli/validate-command.js +4 -1
  25. package/dist/cli/validate-command.js.map +1 -1
  26. package/dist/core/compose.d.ts +21 -31
  27. package/dist/core/compose.d.ts.map +1 -1
  28. package/dist/core/compose.js +93 -125
  29. package/dist/core/compose.js.map +1 -1
  30. package/dist/core/execution.d.ts +40 -0
  31. package/dist/core/execution.d.ts.map +1 -0
  32. package/dist/core/execution.js +263 -0
  33. package/dist/core/execution.js.map +1 -0
  34. package/dist/core/graph.d.ts +4 -5
  35. package/dist/core/graph.d.ts.map +1 -1
  36. package/dist/core/graph.js +51 -103
  37. package/dist/core/graph.js.map +1 -1
  38. package/dist/core/hud.d.ts.map +1 -1
  39. package/dist/core/hud.js +2 -6
  40. package/dist/core/hud.js.map +1 -1
  41. package/dist/core/library.d.ts +17 -51
  42. package/dist/core/library.d.ts.map +1 -1
  43. package/dist/core/library.js +144 -155
  44. package/dist/core/library.js.map +1 -1
  45. package/dist/core/parameters.d.ts +5 -0
  46. package/dist/core/parameters.d.ts.map +1 -0
  47. package/dist/core/parameters.js +57 -0
  48. package/dist/core/parameters.js.map +1 -0
  49. package/dist/core/passive-observations.d.ts +2 -5
  50. package/dist/core/passive-observations.d.ts.map +1 -1
  51. package/dist/core/passive-observations.js +6 -40
  52. package/dist/core/passive-observations.js.map +1 -1
  53. package/dist/core/path.d.ts +6 -0
  54. package/dist/core/path.d.ts.map +1 -0
  55. package/dist/core/path.js +126 -0
  56. package/dist/core/path.js.map +1 -0
  57. package/dist/core/recording-cleanup.d.ts +1 -0
  58. package/dist/core/recording-cleanup.d.ts.map +1 -1
  59. package/dist/core/recording-cleanup.js +8 -0
  60. package/dist/core/recording-cleanup.js.map +1 -1
  61. package/dist/core/resolution-error.d.ts +7 -0
  62. package/dist/core/resolution-error.d.ts.map +1 -0
  63. package/dist/core/resolution-error.js +9 -0
  64. package/dist/core/resolution-error.js.map +1 -0
  65. package/dist/core/runner.d.ts.map +1 -1
  66. package/dist/core/runner.js +178 -373
  67. package/dist/core/runner.js.map +1 -1
  68. package/dist/core/trace.d.ts +3 -4
  69. package/dist/core/trace.d.ts.map +1 -1
  70. package/dist/core/trace.js +3 -4
  71. package/dist/core/trace.js.map +1 -1
  72. package/dist/core/trust-error.d.ts +9 -0
  73. package/dist/core/trust-error.d.ts.map +1 -0
  74. package/dist/core/trust-error.js +18 -0
  75. package/dist/core/trust-error.js.map +1 -0
  76. package/dist/core/trust-input.d.ts +20 -0
  77. package/dist/core/trust-input.d.ts.map +1 -0
  78. package/dist/core/trust-input.js +68 -0
  79. package/dist/core/trust-input.js.map +1 -0
  80. package/dist/core/trust.d.ts +20 -0
  81. package/dist/core/trust.d.ts.map +1 -0
  82. package/dist/core/trust.js +231 -0
  83. package/dist/core/trust.js.map +1 -0
  84. package/dist/core/types.d.ts +41 -47
  85. package/dist/core/types.d.ts.map +1 -1
  86. package/dist/index.d.ts +8 -5
  87. package/dist/index.d.ts.map +1 -1
  88. package/dist/index.js +6 -3
  89. package/dist/index.js.map +1 -1
  90. package/dist/node/writers.d.ts +3 -8
  91. package/dist/node/writers.d.ts.map +1 -1
  92. package/dist/node/writers.js +27 -26
  93. package/dist/node/writers.js.map +1 -1
  94. package/dist/recording/cdp-video-recorder.js +2 -3
  95. package/dist/recording/cdp-video-recorder.js.map +1 -1
  96. package/dist/runtime/cdp.d.ts.map +1 -1
  97. package/dist/runtime/cdp.js +3 -7
  98. package/dist/runtime/cdp.js.map +1 -1
  99. package/package.json +2 -2
  100. package/dist/cli/flows-command.d.ts +0 -3
  101. package/dist/cli/flows-command.d.ts.map +0 -1
  102. package/dist/cli/flows-command.js +0 -313
  103. package/dist/cli/flows-command.js.map +0 -1
  104. package/dist/core/flows.d.ts +0 -45
  105. package/dist/core/flows.d.ts.map +0 -1
  106. package/dist/core/flows.js +0 -359
  107. package/dist/core/flows.js.map +0 -1
  108. package/dist/core/predicates.d.ts +0 -7
  109. package/dist/core/predicates.d.ts.map +0 -1
  110. package/dist/core/predicates.js +0 -102
  111. package/dist/core/predicates.js.map +0 -1
  112. package/dist/core/promote.d.ts +0 -41
  113. package/dist/core/promote.d.ts.map +0 -1
  114. package/dist/core/promote.js +0 -249
  115. package/dist/core/promote.js.map +0 -1
@@ -1,7 +1,10 @@
1
1
  import { readdir, readFile } from 'node:fs/promises';
2
2
  import path from 'node:path';
3
- import { isRecord, mergeRecipeValidationResults, validateArtifactManifestDocument, validateRecipeArtifactPackage, validateRecipeDocument, validateRecipeWithManifest, } from '@farmslot/protocol';
3
+ import { applyRecipeParamDefaults, digestRecipeDocument, isRecord, mergeRecipeValidationResults, resolvedRecipeArtifactPath, validateArtifactManifestDocument, validateRecipeArtifactPackage, validateRecipeDocument, validateRecipeParams, validateRecipeWithManifest, } from '@farmslot/protocol';
4
+ import { resolveRecipeDependencies, rootResolutionRef, validateRecipeDependencyParams, } from '../core/compose.js';
4
5
  import { loadRecipeLibraries } from '../core/library.js';
6
+ import { readFileWithinRoot } from '../core/path.js';
7
+ import { RecipeResolutionError } from '../core/resolution-error.js';
5
8
  export function recipeCliBaseDir() {
6
9
  return process.env.INIT_CWD ?? process.cwd();
7
10
  }
@@ -15,6 +18,36 @@ export function parsePositiveInteger(value) {
15
18
  }
16
19
  return parsed;
17
20
  }
21
+ export function parseRecipeParamAssignments(values) {
22
+ const params = {};
23
+ for (const value of values) {
24
+ const separator = value.indexOf('=');
25
+ if (separator <= 0) {
26
+ throw new Error(`Recipe parameter ${JSON.stringify(value)} must use key=value.`);
27
+ }
28
+ const key = value.slice(0, separator).trim();
29
+ if (!key || Object.hasOwn(params, key)) {
30
+ throw new Error(Object.hasOwn(params, key)
31
+ ? `Recipe parameter ${key} was provided more than once.`
32
+ : `Recipe parameter ${JSON.stringify(value)} has an empty key.`);
33
+ }
34
+ const raw = value.slice(separator + 1);
35
+ let parsed;
36
+ try {
37
+ parsed = JSON.parse(raw);
38
+ }
39
+ catch {
40
+ parsed = raw;
41
+ }
42
+ Object.defineProperty(params, key, {
43
+ value: parsed,
44
+ enumerable: true,
45
+ configurable: true,
46
+ writable: true,
47
+ });
48
+ }
49
+ return params;
50
+ }
18
51
  export function parseRecordingTarget(options) {
19
52
  if (options.recordPid)
20
53
  return { kind: 'pid', pid: parsePositiveInteger(options.recordPid) };
@@ -44,19 +77,26 @@ export async function readRecipeCliJsonFile(filePath, baseDir = recipeCliBaseDir
44
77
  }
45
78
  return parseRecipeCliJsonText(filePath, text);
46
79
  }
47
- async function readOptionalRecipeCliJsonFile(filePath, baseDir = recipeCliBaseDir()) {
48
- const resolvedPath = resolveRecipeCliPath(filePath, baseDir);
80
+ export async function readRecipeCliJsonFileWithinRoot(root, relativePath) {
49
81
  let text;
50
82
  try {
51
- text = await readFile(resolvedPath, 'utf-8');
83
+ text = (await readFileWithinRoot(root, relativePath)).toString('utf-8');
52
84
  }
53
85
  catch (error) {
54
- if (error?.code === 'ENOENT')
55
- return undefined;
56
86
  const message = error instanceof Error ? error.message : String(error);
57
- throw new Error(`Failed to read JSON from ${filePath}: ${message}`);
87
+ throw new Error(`Failed to read JSON from ${relativePath}: ${message}`, { cause: error });
88
+ }
89
+ return parseRecipeCliJsonText(relativePath, text);
90
+ }
91
+ async function readOptionalRecipeCliJsonFileWithinRoot(root, relativePath) {
92
+ try {
93
+ return await readRecipeCliJsonFileWithinRoot(root, relativePath);
94
+ }
95
+ catch (error) {
96
+ if (error?.cause?.code === 'ENOENT')
97
+ return undefined;
98
+ throw error;
58
99
  }
59
- return parseRecipeCliJsonText(filePath, text);
60
100
  }
61
101
  function parseRecipeCliJsonText(filePath, text) {
62
102
  try {
@@ -67,12 +107,44 @@ function parseRecipeCliJsonText(filePath, text) {
67
107
  throw new Error(`Failed to parse JSON from ${filePath}: ${message}`);
68
108
  }
69
109
  }
70
- export async function validateRecipeCliInput({ recipePath, actionManifestPath, artifactManifestPath, artifactDir, baseDir = recipeCliBaseDir(), librarySources, }) {
110
+ export async function validateRecipeCliInput({ recipePath, actionManifestPath, artifactManifestPath, artifactDir, baseDir = recipeCliBaseDir(), librarySources, params = {}, }) {
71
111
  const recipe = await readRecipeCliJsonFile(recipePath, baseDir);
72
112
  const results = [];
73
- const validationOptions = librarySources && librarySources.length > 0
74
- ? { externalFlowIds: new Set((await loadRecipeLibraries(librarySources)).flows.keys()) }
113
+ const effectiveParams = isRecord(recipe)
114
+ ? applyRecipeParamDefaults(params, recipe.paramsSchema)
115
+ : params;
116
+ if (isRecord(recipe))
117
+ results.push(validateRecipeParams(effectiveParams, recipe.paramsSchema));
118
+ const artifactRoot = artifactDir ? resolveRecipeCliPath(artifactDir, baseDir) : undefined;
119
+ const artifactPaths = artifactRoot ? await listRelativeRecipeCliFiles(artifactRoot) : undefined;
120
+ const recipeResolution = artifactRoot
121
+ ? await readOptionalRecipeCliJsonFileWithinRoot(artifactRoot, 'recipe-resolution.json')
75
122
  : undefined;
123
+ const resolvedRecipes = {};
124
+ if (artifactRoot && isRecord(recipeResolution) && Array.isArray(recipeResolution.dependencies)) {
125
+ for (const dependency of recipeResolution.dependencies) {
126
+ if (!isRecord(dependency))
127
+ continue;
128
+ const artifact = resolvedRecipeArtifactPath(dependency.digest);
129
+ if (!artifact)
130
+ continue;
131
+ const document = await readOptionalRecipeCliJsonFileWithinRoot(artifactRoot, artifact);
132
+ if (document !== undefined)
133
+ resolvedRecipes[String(dependency.digest)] = document;
134
+ }
135
+ }
136
+ const libraryResolution = librarySources && librarySources.length > 0
137
+ ? await loadRecipeLibraries(librarySources)
138
+ : undefined;
139
+ const externalRecipeIds = new Set(libraryResolution?.recipes.keys() ?? []);
140
+ if (isRecord(recipeResolution) && Array.isArray(recipeResolution.dependencies)) {
141
+ for (const dependency of recipeResolution.dependencies) {
142
+ if (isRecord(dependency) && typeof dependency.ref === 'string') {
143
+ externalRecipeIds.add(dependency.ref);
144
+ }
145
+ }
146
+ }
147
+ const validationOptions = externalRecipeIds.size > 0 ? { externalRecipeIds } : undefined;
76
148
  if (actionManifestPath) {
77
149
  const actionManifest = await readRecipeCliJsonFile(actionManifestPath, baseDir);
78
150
  results.push(validateRecipeWithManifest(recipe, actionManifest, validationOptions));
@@ -80,16 +152,57 @@ export async function validateRecipeCliInput({ recipePath, actionManifestPath, a
80
152
  else {
81
153
  results.push(validateRecipeDocument(recipe, validationOptions));
82
154
  }
83
- const artifactPaths = artifactDir
84
- ? await listRelativeRecipeCliFiles(resolveRecipeCliPath(artifactDir, baseDir))
85
- : undefined;
155
+ if (!artifactDir &&
156
+ libraryResolution &&
157
+ isRecord(recipe) &&
158
+ results.every((result) => result.status === 'valid')) {
159
+ try {
160
+ const rootDigest = digestRecipeDocument(recipe);
161
+ resolveRecipeDependencies({
162
+ rootRef: rootResolutionRef(rootDigest),
163
+ root: recipe,
164
+ rootSource: {
165
+ kind: 'operator',
166
+ trust: 'unknown',
167
+ path: resolveRecipeCliPath(recipePath, baseDir),
168
+ digest: rootDigest,
169
+ },
170
+ recipes: libraryResolution.recipes,
171
+ });
172
+ validateRecipeDependencyParams({
173
+ root: recipe,
174
+ params: effectiveParams,
175
+ recipes: libraryResolution.recipes,
176
+ });
177
+ }
178
+ catch (error) {
179
+ results.push({
180
+ status: 'invalid',
181
+ findings: [
182
+ {
183
+ severity: 'error',
184
+ code: error instanceof RecipeResolutionError
185
+ ? error.code.toLowerCase()
186
+ : 'recipe.unresolved_dependency_graph',
187
+ path: 'workflow',
188
+ message: error instanceof RecipeResolutionError
189
+ ? `${error.message} Next: ${error.userAction}.`
190
+ : error instanceof Error
191
+ ? error.message
192
+ : String(error),
193
+ },
194
+ ],
195
+ summary: { errors: 1, warnings: 0 },
196
+ });
197
+ }
198
+ }
86
199
  const manifestPath = artifactManifestPath ??
87
200
  (artifactDir ? path.join(artifactDir, 'artifact-manifest.json') : undefined);
88
201
  let manifest;
89
202
  if (manifestPath) {
90
203
  manifest = artifactManifestPath
91
204
  ? await readRecipeCliJsonFile(manifestPath, baseDir)
92
- : await readOptionalRecipeCliJsonFile(manifestPath, baseDir);
205
+ : await readOptionalRecipeCliJsonFileWithinRoot(artifactRoot, 'artifact-manifest.json');
93
206
  if (manifest !== undefined && !artifactDir) {
94
207
  results.push(validateArtifactManifestDocument(manifest, {
95
208
  recipe,
@@ -98,19 +211,12 @@ export async function validateRecipeCliInput({ recipePath, actionManifestPath, a
98
211
  }
99
212
  }
100
213
  if (artifactDir) {
101
- // Flow-call resolution already ran above via validateRecipeWithManifest with the
102
- // configured library. Always read resolved-recipe.json so a present-but-malformed
103
- // file throws (never silently skipped); the validator then checks the composition
104
- // in full only for a passing run (runPassed) — matching the runner/gateway.
105
- const resolvedRecipe = await readOptionalRecipeCliJsonFile(path.join(artifactDir, 'resolved-recipe.json'), baseDir);
106
214
  results.push(validateRecipeArtifactPackage({
107
215
  recipe,
108
216
  manifest,
109
217
  artifactPaths,
110
- ...(resolvedRecipe !== undefined ? { resolvedRecipe } : {}),
111
- // Only a confirmed failure relaxes composition enforcement; unknown/missing
112
- // status still requires the composition to be proven.
113
- runPassed: !(isRecord(manifest) && manifest.runStatus === 'fail'),
218
+ resolvedRecipes,
219
+ recipeResolution,
114
220
  }));
115
221
  }
116
222
  return mergeRecipeValidationResults(results);
@@ -124,7 +230,7 @@ async function listRelativeRecipeCliFiles(root) {
124
230
  if (entry.isDirectory()) {
125
231
  await visit(relativePath);
126
232
  }
127
- else if (entry.isFile()) {
233
+ else if (entry.isFile() || entry.isSymbolicLink()) {
128
234
  output.push(relativePath.split(path.sep).join('/'));
129
235
  }
130
236
  }
@@ -1 +1 @@
1
- {"version":3,"file":"support.js","sourceRoot":"","sources":["../../src/cli/support.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"support.js","sourceRoot":"","sources":["../../src/cli/support.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"validate-command.d.ts","sourceRoot":"","sources":["../../src/cli/validate-command.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,WAAW,CAAC;AAczC,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAoC9D"}
1
+ {"version":3,"file":"validate-command.d.ts","sourceRoot":"","sources":["../../src/cli/validate-command.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,WAAW,CAAC;AAczC,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAuC9D"}
@@ -11,7 +11,10 @@ export function registerValidateCommand(program) {
11
11
  .option('--library <entry>', 'Recipe library source as name=path or path (repeatable; order is precedence, first wins). Defaults to RECIPE_LIBRARY_PATH, then the personal library under the farmslot home — same resolution as run.', collectRepeatable, [])
12
12
  .option('--json', 'Print validation result as JSON')
13
13
  .action(async (recipePath, options) => {
14
- const librarySources = await resolveRecipeLibrarySources({ cliEntries: options.library });
14
+ const librarySources = await resolveRecipeLibrarySources({
15
+ cliEntries: options.library,
16
+ recipePath,
17
+ });
15
18
  const result = await validateRecipeCliInput({
16
19
  recipePath,
17
20
  actionManifestPath: options.actionManifest,
@@ -1 +1 @@
1
- {"version":3,"file":"validate-command.js","sourceRoot":"","sources":["../../src/cli/validate-command.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,2BAA2B,EAAE,MAAM,oBAAoB,CAAC;AAEjE,OAAO,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC;AAUtD,MAAM,UAAU,uBAAuB,CAAC,OAAgB;IACtD,OAAO;SACJ,OAAO,CAAC,UAAU,CAAC;SACnB,WAAW,CAAC,oDAAoD,CAAC;SACjE,QAAQ,CAAC,UAAU,EAAE,qBAAqB,CAAC;SAC3C,MAAM,CAAC,8BAA8B,EAAE,6BAA6B,CAAC;SACrE,MAAM,CAAC,gCAAgC,EAAE,wBAAwB,CAAC;SAClE,MAAM,CAAC,sBAAsB,EAAE,4BAA4B,CAAC;SAC5D,MAAM,CACL,mBAAmB,EACnB,wMAAwM,EACxM,iBAAiB,EACjB,EAAc,CACf;SACA,MAAM,CAAC,QAAQ,EAAE,iCAAiC,CAAC;SACnD,MAAM,CAAC,KAAK,EAAE,UAAkB,EAAE,OAA+B,EAAE,EAAE;QACpE,MAAM,cAAc,GAAG,MAAM,2BAA2B,CAAC,EAAE,UAAU,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;QAC1F,MAAM,MAAM,GAAG,MAAM,sBAAsB,CAAC;YAC1C,UAAU;YACV,kBAAkB,EAAE,OAAO,CAAC,cAAc;YAC1C,oBAAoB,EAAE,OAAO,CAAC,gBAAgB;YAC9C,WAAW,EAAE,OAAO,CAAC,WAAW;YAChC,GAAG,CAAC,cAAc,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACzD,CAAC,CAAC;QACH,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;YACjB,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAC/C,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,GAAG,CACT,sBAAsB,MAAM,CAAC,MAAM,KAAK,MAAM,CAAC,OAAO,CAAC,MAAM,YAAY,MAAM,CAAC,OAAO,CAAC,QAAQ,YAAY,CAC7G,CAAC;YACF,KAAK,MAAM,OAAO,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;gBACtC,OAAO,CAAC,GAAG,CAAC,KAAK,OAAO,CAAC,QAAQ,IAAI,OAAO,CAAC,IAAI,IAAI,OAAO,CAAC,IAAI,KAAK,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;YAC3F,CAAC;QACH,CAAC;QACD,IAAI,MAAM,CAAC,MAAM,KAAK,SAAS;YAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACnD,CAAC,CAAC,CAAC;AACP,CAAC;AAED,SAAS,iBAAiB,CAAC,KAAa,EAAE,QAAkB;IAC1D,OAAO,CAAC,GAAG,QAAQ,EAAE,KAAK,CAAC,CAAC;AAC9B,CAAC"}
1
+ {"version":3,"file":"validate-command.js","sourceRoot":"","sources":["../../src/cli/validate-command.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,2BAA2B,EAAE,MAAM,oBAAoB,CAAC;AAEjE,OAAO,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC;AAUtD,MAAM,UAAU,uBAAuB,CAAC,OAAgB;IACtD,OAAO;SACJ,OAAO,CAAC,UAAU,CAAC;SACnB,WAAW,CAAC,oDAAoD,CAAC;SACjE,QAAQ,CAAC,UAAU,EAAE,qBAAqB,CAAC;SAC3C,MAAM,CAAC,8BAA8B,EAAE,6BAA6B,CAAC;SACrE,MAAM,CAAC,gCAAgC,EAAE,wBAAwB,CAAC;SAClE,MAAM,CAAC,sBAAsB,EAAE,4BAA4B,CAAC;SAC5D,MAAM,CACL,mBAAmB,EACnB,wMAAwM,EACxM,iBAAiB,EACjB,EAAc,CACf;SACA,MAAM,CAAC,QAAQ,EAAE,iCAAiC,CAAC;SACnD,MAAM,CAAC,KAAK,EAAE,UAAkB,EAAE,OAA+B,EAAE,EAAE;QACpE,MAAM,cAAc,GAAG,MAAM,2BAA2B,CAAC;YACvD,UAAU,EAAE,OAAO,CAAC,OAAO;YAC3B,UAAU;SACX,CAAC,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,sBAAsB,CAAC;YAC1C,UAAU;YACV,kBAAkB,EAAE,OAAO,CAAC,cAAc;YAC1C,oBAAoB,EAAE,OAAO,CAAC,gBAAgB;YAC9C,WAAW,EAAE,OAAO,CAAC,WAAW;YAChC,GAAG,CAAC,cAAc,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACzD,CAAC,CAAC;QACH,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;YACjB,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAC/C,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,GAAG,CACT,sBAAsB,MAAM,CAAC,MAAM,KAAK,MAAM,CAAC,OAAO,CAAC,MAAM,YAAY,MAAM,CAAC,OAAO,CAAC,QAAQ,YAAY,CAC7G,CAAC;YACF,KAAK,MAAM,OAAO,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;gBACtC,OAAO,CAAC,GAAG,CAAC,KAAK,OAAO,CAAC,QAAQ,IAAI,OAAO,CAAC,IAAI,IAAI,OAAO,CAAC,IAAI,KAAK,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;YAC3F,CAAC;QACH,CAAC;QACD,IAAI,MAAM,CAAC,MAAM,KAAK,SAAS;YAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACnD,CAAC,CAAC,CAAC;AACP,CAAC;AAED,SAAS,iBAAiB,CAAC,KAAa,EAAE,QAAkB;IAC1D,OAAO,CAAC,GAAG,QAAQ,EAAE,KAAK,CAAC,CAAC;AAC9B,CAAC"}
@@ -1,33 +1,23 @@
1
- import { type InlineFlow } from './flows.js';
2
- import type { RecipeLibrarySource, RecipeLogger } from './types.js';
3
- /**
4
- * Inlines the flows the recipe requires into `flows`, yielding a self-contained
5
- * recipe whose `call.ref`s resolve without the recipe library. Only referenced
6
- * flows are inlined (not the whole catalog, and not unreferenced authored inline
7
- * flows), and `uses` is dropped so `validateFlowCalls` verifies every ref is
8
- * present inline rather than short-circuiting on the external catalog. Returns the
9
- * recipe unchanged (same reference) when nothing external was composed — recipe.json
10
- * is already the full composition.
11
- */
12
- export declare function buildResolvedRecipe(recipe: unknown, flowCatalog: ReadonlyMap<string, InlineFlow>): unknown;
13
- export interface ComposeRecipeOptions {
14
- projectRoot: string;
15
- recipeDir: string;
16
- /** Library sources whose flows count as resolvable, mirroring run resolution. */
17
- librarySources?: RecipeLibrarySource[];
18
- logger?: RecipeLogger;
1
+ import { type RecipeResolutionDocument, type RecipeResolutionEdge, type RecipeSourceProvenance } from '@farmslot/protocol';
2
+ import type { ResolvedLibraryRecipe } from './library.js';
3
+ export interface ResolvedRecipeDependencies {
4
+ recipes: ReadonlyMap<string, ResolvedLibraryRecipe>;
5
+ edges: RecipeResolutionEdge[];
6
+ document: RecipeResolutionDocument;
19
7
  }
20
- export interface ComposeRecipeResult {
21
- /** The self-contained recipe with every reachable flow inlined under `flows`. */
22
- resolved: unknown;
23
- /** Flows inlined into the resolved recipe; 0 means nothing external was composed. */
24
- flowCount: number;
25
- }
26
- /**
27
- * Resolves a recipe's full flow composition — inline `flows`, `uses` catalogs,
28
- * and configured library sources, transitively — and returns the fully-composed,
29
- * self-contained recipe. Shared by the runner (executed path) and the CLI/CI
30
- * static resolve-check so both derive the same `resolved-recipe.json`.
31
- */
32
- export declare function composeRecipe(recipe: unknown, options: ComposeRecipeOptions): Promise<ComposeRecipeResult>;
8
+ export declare function rootResolutionRef(digest: string): string;
9
+ /** Validate every static call boundary after parent defaults and parameters are applied. */
10
+ export declare function validateRecipeDependencyParams(options: {
11
+ root: Record<string, unknown>;
12
+ params: Record<string, unknown>;
13
+ recipes: ReadonlyMap<string, ResolvedLibraryRecipe>;
14
+ }): void;
15
+ /** Resolve the exact static recipe call DAG before any side effect. */
16
+ export declare function resolveRecipeDependencies(options: {
17
+ rootRef: string;
18
+ root: Record<string, unknown>;
19
+ rootSource: RecipeSourceProvenance;
20
+ recipes: ReadonlyMap<string, ResolvedLibraryRecipe>;
21
+ maxDepth?: number;
22
+ }): ResolvedRecipeDependencies;
33
23
  //# sourceMappingURL=compose.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"compose.d.ts","sourceRoot":"","sources":["../../src/core/compose.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,KAAK,UAAU,EAAE,MAAM,YAAY,CAAC;AAO3D,OAAO,KAAK,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAwFpE;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,OAAO,EACf,WAAW,EAAE,WAAW,CAAC,MAAM,EAAE,UAAU,CAAC,GAC3C,OAAO,CAsBT;AAED,MAAM,WAAW,oBAAoB;IACnC,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,iFAAiF;IACjF,cAAc,CAAC,EAAE,mBAAmB,EAAE,CAAC;IACvC,MAAM,CAAC,EAAE,YAAY,CAAC;CACvB;AAED,MAAM,WAAW,mBAAmB;IAClC,iFAAiF;IACjF,QAAQ,EAAE,OAAO,CAAC;IAClB,qFAAqF;IACrF,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;;GAKG;AACH,wBAAsB,aAAa,CACjC,MAAM,EAAE,OAAO,EACf,OAAO,EAAE,oBAAoB,GAC5B,OAAO,CAAC,mBAAmB,CAAC,CAsB9B"}
1
+ {"version":3,"file":"compose.d.ts","sourceRoot":"","sources":["../../src/core/compose.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,wBAAwB,EAC7B,KAAK,oBAAoB,EACzB,KAAK,sBAAsB,EAE5B,MAAM,oBAAoB,CAAC;AAK5B,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;AAI1D,MAAM,WAAW,0BAA0B;IACzC,OAAO,EAAE,WAAW,CAAC,MAAM,EAAE,qBAAqB,CAAC,CAAC;IACpD,KAAK,EAAE,oBAAoB,EAAE,CAAC;IAC9B,QAAQ,EAAE,wBAAwB,CAAC;CACpC;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAExD;AAED,4FAA4F;AAC5F,wBAAgB,8BAA8B,CAAC,OAAO,EAAE;IACtD,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,OAAO,EAAE,WAAW,CAAC,MAAM,EAAE,qBAAqB,CAAC,CAAC;CACrD,GAAG,IAAI,CAkBP;AAED,uEAAuE;AACvE,wBAAgB,yBAAyB,CAAC,OAAO,EAAE;IACjD,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9B,UAAU,EAAE,sBAAsB,CAAC;IACnC,OAAO,EAAE,WAAW,CAAC,MAAM,EAAE,qBAAqB,CAAC,CAAC;IACpD,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,GAAG,0BAA0B,CAuF7B"}
@@ -1,136 +1,104 @@
1
- import { collectFlows } from './flows.js';
1
+ import { normalizeRecipeRef, resolvedRecipeArtifactPath, } from '@farmslot/protocol';
2
+ import { DEFAULT_MAX_RECIPE_CALL_DEPTH } from './execution.js';
3
+ import { extractWorkflowGraph } from './graph.js';
2
4
  import { isRecord } from './json.js';
3
- import { createEffectiveFlowCatalog, loadRecipeLibraries, } from './library.js';
4
- /** Locate a flow definition's node map, tolerating both `{entry,nodes}` and `{workflow:{...}}`. */
5
- function flowNodes(flow) {
6
- if (!isRecord(flow))
7
- return undefined;
8
- const workflow = isRecord(flow.workflow) ? flow.workflow : flow;
9
- return isRecord(workflow.nodes) ? workflow.nodes : undefined;
5
+ import { resolveRecipeParams, resolveRecipeValue } from './parameters.js';
6
+ import { RecipeResolutionError } from './resolution-error.js';
7
+ export function rootResolutionRef(digest) {
8
+ return `$root:${digest}`;
10
9
  }
11
- /**
12
- * Every `call.ref` on any node in a node map. This mirrors `validateFlowCalls`,
13
- * which checks all nodes of every inline flow (not just graph-reachable ones), so
14
- * the resolved recipe must inline every referenced flow to be self-contained.
15
- */
16
- function callRefsInNodes(nodes) {
17
- if (!nodes)
18
- return [];
19
- const refs = [];
20
- for (const node of Object.values(nodes)) {
21
- if (isRecord(node) &&
22
- node.action === 'call' &&
23
- typeof node.ref === 'string' &&
24
- node.ref.trim()) {
25
- refs.push(node.ref);
10
+ /** Validate every static call boundary after parent defaults and parameters are applied. */
11
+ export function validateRecipeDependencyParams(options) {
12
+ const visit = (document, params) => {
13
+ for (const rawNode of Object.values(extractWorkflowGraph(document).nodes)) {
14
+ if (rawNode.action !== 'call' || typeof rawNode.ref !== 'string')
15
+ continue;
16
+ const ref = normalizeRecipeRef(rawNode.ref);
17
+ const dependency = options.recipes.get(ref);
18
+ if (!dependency)
19
+ continue;
20
+ const node = resolveRecipeValue(rawNode, params);
21
+ const childParams = resolveRecipeParams(ref, dependency.document, isRecord(node) && isRecord(node.params) ? node.params : {}, { allowTemplates: true });
22
+ visit(dependency.document, childParams);
26
23
  }
27
- }
28
- return refs;
24
+ };
25
+ visit(options.root, options.params);
29
26
  }
30
- /** Lifecycle arrays (setup/teardown) always execute, so every `call` in them counts. */
31
- function callRefsInLifecycle(list) {
32
- if (!Array.isArray(list))
33
- return [];
34
- const refs = [];
35
- for (const node of list) {
36
- if (isRecord(node) &&
37
- node.action === 'call' &&
38
- typeof node.ref === 'string' &&
39
- node.ref.trim()) {
40
- refs.push(node.ref);
27
+ /** Resolve the exact static recipe call DAG before any side effect. */
28
+ export function resolveRecipeDependencies(options) {
29
+ const maxDepth = options.maxDepth ?? DEFAULT_MAX_RECIPE_CALL_DEPTH;
30
+ const resolved = new Map();
31
+ const edges = [];
32
+ const visiting = [];
33
+ const visited = new Set();
34
+ const visit = (from, document, depth) => {
35
+ if (depth >= maxDepth) {
36
+ throw new RecipeResolutionError('RECIPE_CALL_DEPTH_EXCEEDED', `Recipe call depth exceeded maximum ${maxDepth}.`, `reduce nested recipe calls below ${maxDepth}`);
41
37
  }
42
- }
43
- return refs;
44
- }
45
- /**
46
- * Computes the flow ids the resolved recipe must inline: every flow referenced by
47
- * any node of the recipe's workflow, its setup/teardown lifecycle, or `startState`,
48
- * then transitively every flow referenced by any node of those flows. Matches
49
- * `validateFlowCalls`' all-nodes check, so the result is exactly the set required
50
- * for the resolved recipe to be self-contained — never the whole library, and never
51
- * an unreferenced authored inline flow.
52
- */
53
- function collectRequiredFlowRefs(recipe, flowCatalog) {
54
- const seeds = [];
55
- const validate = isRecord(recipe.validate) ? recipe.validate : undefined;
56
- const workflow = validate && isRecord(validate.workflow) ? validate.workflow : undefined;
57
- if (workflow) {
58
- seeds.push(...callRefsInNodes(isRecord(workflow.nodes) ? workflow.nodes : undefined));
59
- seeds.push(...callRefsInLifecycle(workflow.setup));
60
- seeds.push(...callRefsInLifecycle(workflow.teardown));
61
- }
62
- if (isRecord(recipe.startState) &&
63
- recipe.startState.action === 'call' &&
64
- typeof recipe.startState.ref === 'string') {
65
- seeds.push(recipe.startState.ref);
66
- }
67
- const required = new Set();
68
- const queue = [...seeds];
69
- while (queue.length > 0) {
70
- const ref = queue.shift();
71
- if (required.has(ref))
72
- continue;
73
- required.add(ref);
74
- for (const child of callRefsInNodes(flowNodes(flowCatalog.get(ref)))) {
75
- if (!required.has(child))
76
- queue.push(child);
38
+ for (const ref of callRefs(document)) {
39
+ edges.push({ from, to: ref });
40
+ const cycleStart = visiting.indexOf(ref);
41
+ if (cycleStart >= 0 || ref === options.rootRef) {
42
+ const cycle = [...visiting.slice(Math.max(cycleStart, 0)), ref];
43
+ throw new RecipeResolutionError('RECIPE_CALL_CYCLE', `Recipe call cycle detected: ${cycle.join(' -> ')}.`, 'remove one call edge so the recipe dependency graph is acyclic');
44
+ }
45
+ const dependency = options.recipes.get(ref);
46
+ if (!dependency) {
47
+ throw new RecipeResolutionError('RECIPE_REFERENCE_NOT_FOUND', `Recipe ${ref} is not available from configured libraries.`, `add ${ref} to a configured recipe library or correct call.ref`);
48
+ }
49
+ resolved.set(ref, dependency);
50
+ if (visited.has(ref))
51
+ continue;
52
+ visiting.push(ref);
53
+ visit(ref, dependency.document, depth + 1);
54
+ visiting.pop();
55
+ visited.add(ref);
77
56
  }
57
+ };
58
+ visiting.push(options.rootRef);
59
+ visit(options.rootRef, options.root, 0);
60
+ visiting.pop();
61
+ const rootDigest = options.rootSource.digest;
62
+ if (!rootDigest) {
63
+ throw new RecipeResolutionError('RECIPE_RESOLUTION_DIGEST_MISSING', 'Resolved root recipe source is missing its content digest.', 'reload the root recipe through the runner so its digest is computed');
78
64
  }
79
- return required;
65
+ const dependencies = [...resolved.values()]
66
+ .sort((left, right) => compareStrings(left.ref, right.ref))
67
+ .map((recipe) => {
68
+ const digest = recipe.provenance.digest;
69
+ if (!digest) {
70
+ throw new RecipeResolutionError('RECIPE_RESOLUTION_DIGEST_MISSING', `Resolved recipe ${recipe.ref} is missing its content digest.`, `reload ${recipe.ref} through the library resolver so its digest is computed`);
71
+ }
72
+ return {
73
+ ref: recipe.ref,
74
+ source: recipe.source,
75
+ file: recipe.file,
76
+ digest,
77
+ artifact: resolvedRecipeArtifactPath(digest),
78
+ ...(recipe.adapter ? { adapter: recipe.adapter } : {}),
79
+ };
80
+ });
81
+ return {
82
+ recipes: resolved,
83
+ edges,
84
+ document: {
85
+ schema_version: 1,
86
+ root: { ref: options.rootRef, digest: rootDigest },
87
+ dependencies,
88
+ edges: [...edges].sort((left, right) => compareStrings(`${left.from}:${left.to}`, `${right.from}:${right.to}`)),
89
+ },
90
+ };
80
91
  }
81
- /**
82
- * Inlines the flows the recipe requires into `flows`, yielding a self-contained
83
- * recipe whose `call.ref`s resolve without the recipe library. Only referenced
84
- * flows are inlined (not the whole catalog, and not unreferenced authored inline
85
- * flows), and `uses` is dropped so `validateFlowCalls` verifies every ref is
86
- * present inline rather than short-circuiting on the external catalog. Returns the
87
- * recipe unchanged (same reference) when nothing external was composed — recipe.json
88
- * is already the full composition.
89
- */
90
- export function buildResolvedRecipe(recipe, flowCatalog) {
91
- if (!isRecord(recipe) || flowCatalog.size === 0)
92
- return recipe;
93
- const refs = collectRequiredFlowRefs(recipe, flowCatalog);
94
- const flows = {};
95
- for (const ref of refs) {
96
- const flow = flowCatalog.get(ref);
97
- if (flow)
98
- flows[ref] = flow;
99
- }
100
- if (Object.keys(flows).length === 0)
101
- return recipe;
102
- // Emit only when `uses`/library composition contributed — either a reached flow
103
- // is not an authored inline flow, or the recipe declared `uses` (now inlined and
104
- // dropped). Otherwise recipe.json is already self-contained.
105
- const authoredFlowKeys = new Set(isRecord(recipe.flows) ? Object.keys(recipe.flows) : []);
106
- const hasUses = Array.isArray(recipe.uses) && recipe.uses.length > 0;
107
- const composedExternal = Object.keys(flows).some((ref) => !authoredFlowKeys.has(ref));
108
- if (!composedExternal && !hasUses)
109
- return recipe;
110
- const { uses: _uses, ...rest } = recipe;
111
- void _uses;
112
- return { ...rest, flows };
92
+ function compareStrings(left, right) {
93
+ return left < right ? -1 : left > right ? 1 : 0;
113
94
  }
114
- /**
115
- * Resolves a recipe's full flow composition — inline `flows`, `uses` catalogs,
116
- * and configured library sources, transitively — and returns the fully-composed,
117
- * self-contained recipe. Shared by the runner (executed path) and the CLI/CI
118
- * static resolve-check so both derive the same `resolved-recipe.json`.
119
- */
120
- export async function composeRecipe(recipe, options) {
121
- const recipeLocalFlows = await collectFlows(recipe, {
122
- projectRoot: options.projectRoot,
123
- recipeDir: options.recipeDir,
124
- });
125
- const resolution = options.librarySources && options.librarySources.length > 0
126
- ? await loadRecipeLibraries(options.librarySources, options.logger)
127
- : undefined;
128
- const usedLibraryFlows = new Map();
129
- const { catalog } = createEffectiveFlowCatalog(recipeLocalFlows, resolution, usedLibraryFlows, options.logger);
130
- const resolved = buildResolvedRecipe(recipe, catalog);
131
- const flowCount = resolved !== recipe && isRecord(resolved) && isRecord(resolved.flows)
132
- ? Object.keys(resolved.flows).length
133
- : 0;
134
- return { resolved, flowCount };
95
+ function callRefs(recipe) {
96
+ const refs = [];
97
+ for (const node of Object.values(extractWorkflowGraph(recipe).nodes)) {
98
+ if (node.action === 'call' && typeof node.ref === 'string' && node.ref.trim()) {
99
+ refs.push(normalizeRecipeRef(node.ref));
100
+ }
101
+ }
102
+ return refs;
135
103
  }
136
104
  //# sourceMappingURL=compose.js.map