@vaudience/aigentflow-flow-validator 0.24.0 → 0.26.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/PARITY.md +60 -0
- package/dist/cli.js +215 -11
- package/dist/index.cjs +213 -11
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +213 -11
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -459,6 +459,7 @@ var aigentflow_spec_default = {
|
|
|
459
459
|
"ai",
|
|
460
460
|
"aiv",
|
|
461
461
|
"async",
|
|
462
|
+
"atlas",
|
|
462
463
|
"browser",
|
|
463
464
|
"chart",
|
|
464
465
|
"db",
|
|
@@ -988,6 +989,85 @@ var aigentflow_spec_default = {
|
|
|
988
989
|
"utils/parse-date"
|
|
989
990
|
]
|
|
990
991
|
},
|
|
992
|
+
atlasExecutor: {
|
|
993
|
+
scheme: "atlas",
|
|
994
|
+
providerAgent: "agent",
|
|
995
|
+
providerCapability: "capability",
|
|
996
|
+
agentResource: "run",
|
|
997
|
+
capabilityRefPattern: "^[A-Za-z0-9][A-Za-z0-9_-]{0,127}$",
|
|
998
|
+
operationUnknown: {
|
|
999
|
+
code: "atlas_operation_unknown",
|
|
1000
|
+
messageFormat: "step %s uses %s, which is not an Atlas operation. The providers are agent (resource run) and capability (resource: a capability reference).",
|
|
1001
|
+
suggestion: "Use atlas://agent/run or atlas://capability/<capability-ref>."
|
|
1002
|
+
},
|
|
1003
|
+
agentMissing: {
|
|
1004
|
+
code: "atlas_agent_missing",
|
|
1005
|
+
messageFormat: "step %s runs an Atlas agent but query.agent is missing, empty or not a string.",
|
|
1006
|
+
suggestion: "Set query.agent to the agent to run, written out as a literal such as @acme/reporter."
|
|
1007
|
+
},
|
|
1008
|
+
agentNotLiteral: {
|
|
1009
|
+
code: "atlas_agent_not_literal",
|
|
1010
|
+
messageFormat: "step %s computes query.agent from a template. The agent must be a fixed literal, never derived from input.",
|
|
1011
|
+
suggestion: "Write the agent out as a literal such as @acme/reporter. Data may go into the prompt or the inputs instead."
|
|
1012
|
+
},
|
|
1013
|
+
capabilitiesNotLiteral: {
|
|
1014
|
+
code: "atlas_capabilities_not_literal",
|
|
1015
|
+
messageFormat: "step %s computes an entry of query.capabilities from a template. Capabilities must be fixed literals, never derived from input.",
|
|
1016
|
+
suggestion: "Write each capability out as a literal. Data may go into the prompt or the inputs instead."
|
|
1017
|
+
},
|
|
1018
|
+
promptMissing: {
|
|
1019
|
+
code: "atlas_prompt_missing",
|
|
1020
|
+
messageFormat: "step %s runs an Atlas agent with neither query.prompt nor query.prompt_template.",
|
|
1021
|
+
suggestion: "Set exactly one of query.prompt or query.prompt_template."
|
|
1022
|
+
},
|
|
1023
|
+
promptBoth: {
|
|
1024
|
+
code: "atlas_prompt_both",
|
|
1025
|
+
messageFormat: "step %s sets both query.prompt and query.prompt_template.",
|
|
1026
|
+
suggestion: "Keep exactly one of query.prompt or query.prompt_template."
|
|
1027
|
+
},
|
|
1028
|
+
capabilityRefInvalid: {
|
|
1029
|
+
code: "atlas_capability_ref_invalid",
|
|
1030
|
+
messageFormat: "step %s uses atlas://capability/%s, which is not a valid capability reference.",
|
|
1031
|
+
suggestion: "A capability reference starts with a letter or digit and continues with letters, digits, _ and - up to 128 characters in all."
|
|
1032
|
+
},
|
|
1033
|
+
modelNotLiteral: {
|
|
1034
|
+
code: "atlas_model_not_literal",
|
|
1035
|
+
messageFormat: "step %s computes a value of query.model from a template. The provider, model and reasoning_effort must be fixed literals, never derived from input.",
|
|
1036
|
+
suggestion: "Write the model choice out as literals. Data may go into the prompt or the inputs instead."
|
|
1037
|
+
},
|
|
1038
|
+
paramRefused: {
|
|
1039
|
+
code: "atlas_param_refused",
|
|
1040
|
+
messageFormat: "step %s sets %s under query. Atlas decides these itself, so a step may not set them.",
|
|
1041
|
+
suggestion: "Remove these keys from the query.",
|
|
1042
|
+
agentKeys: [
|
|
1043
|
+
"api_key",
|
|
1044
|
+
"attribution",
|
|
1045
|
+
"base_url",
|
|
1046
|
+
"host",
|
|
1047
|
+
"idempotency_key",
|
|
1048
|
+
"org_id",
|
|
1049
|
+
"person",
|
|
1050
|
+
"untrusted_input",
|
|
1051
|
+
"untrusted_input_override",
|
|
1052
|
+
"url",
|
|
1053
|
+
"user_id"
|
|
1054
|
+
],
|
|
1055
|
+
capabilityKeys: [
|
|
1056
|
+
"attribution",
|
|
1057
|
+
"idempotency_key",
|
|
1058
|
+
"untrusted_input",
|
|
1059
|
+
"untrusted_input_override"
|
|
1060
|
+
]
|
|
1061
|
+
}
|
|
1062
|
+
},
|
|
1063
|
+
reservedInputNames: {
|
|
1064
|
+
prefix: "__",
|
|
1065
|
+
code: "reserved_input_name",
|
|
1066
|
+
messageFormat: "the input %s starts with two underscores. That namespace belongs to the platform (the acting person, the credential manifest, the untrusted-input marker): a flow cannot declare an input there, and a value or default written under such a name is never delivered.",
|
|
1067
|
+
suggestion: 'Rename the input so it does not start with "__".',
|
|
1068
|
+
queryFieldFormat: "query.%s",
|
|
1069
|
+
schemaFieldFormat: "input_schema.fields.%s"
|
|
1070
|
+
},
|
|
991
1071
|
flowDataReservedKeys: {
|
|
992
1072
|
code: "flow_data_key_reserved",
|
|
993
1073
|
fieldFormat: "data.%s",
|
|
@@ -2030,6 +2110,37 @@ var FUNCTION_OPERATIONS = {
|
|
|
2030
2110
|
operations: new Set(aigentflow_spec_default.functionOperations.operations),
|
|
2031
2111
|
sorted: aigentflow_spec_default.functionOperations.operations
|
|
2032
2112
|
};
|
|
2113
|
+
var atlas = aigentflow_spec_default.atlasExecutor;
|
|
2114
|
+
var ATLAS_EXECUTOR = {
|
|
2115
|
+
scheme: atlas.scheme,
|
|
2116
|
+
providerAgent: atlas.providerAgent,
|
|
2117
|
+
providerCapability: atlas.providerCapability,
|
|
2118
|
+
agentResource: atlas.agentResource,
|
|
2119
|
+
capabilityRefPattern: new RegExp(atlas.capabilityRefPattern),
|
|
2120
|
+
operationUnknown: atlas.operationUnknown,
|
|
2121
|
+
agentMissing: atlas.agentMissing,
|
|
2122
|
+
agentNotLiteral: atlas.agentNotLiteral,
|
|
2123
|
+
capabilitiesNotLiteral: atlas.capabilitiesNotLiteral,
|
|
2124
|
+
promptMissing: atlas.promptMissing,
|
|
2125
|
+
promptBoth: atlas.promptBoth,
|
|
2126
|
+
capabilityRefInvalid: atlas.capabilityRefInvalid,
|
|
2127
|
+
modelNotLiteral: atlas.modelNotLiteral,
|
|
2128
|
+
paramRefused: {
|
|
2129
|
+
code: atlas.paramRefused.code,
|
|
2130
|
+
messageFormat: atlas.paramRefused.messageFormat,
|
|
2131
|
+
suggestion: atlas.paramRefused.suggestion,
|
|
2132
|
+
agentKeys: atlas.paramRefused.agentKeys,
|
|
2133
|
+
capabilityKeys: atlas.paramRefused.capabilityKeys
|
|
2134
|
+
}
|
|
2135
|
+
};
|
|
2136
|
+
var RESERVED_INPUT_NAMES = {
|
|
2137
|
+
prefix: aigentflow_spec_default.reservedInputNames.prefix,
|
|
2138
|
+
code: aigentflow_spec_default.reservedInputNames.code,
|
|
2139
|
+
messageFormat: aigentflow_spec_default.reservedInputNames.messageFormat,
|
|
2140
|
+
suggestion: aigentflow_spec_default.reservedInputNames.suggestion,
|
|
2141
|
+
queryFieldFormat: aigentflow_spec_default.reservedInputNames.queryFieldFormat,
|
|
2142
|
+
schemaFieldFormat: aigentflow_spec_default.reservedInputNames.schemaFieldFormat
|
|
2143
|
+
};
|
|
2033
2144
|
|
|
2034
2145
|
// src/validators/executors.ts
|
|
2035
2146
|
var SCHEME_SEPARATOR = "://";
|
|
@@ -2093,6 +2204,63 @@ function checkExecutor(executor, field, stepID, issues) {
|
|
|
2093
2204
|
}
|
|
2094
2205
|
checkFunctionOperation(executor, field, stepID, templated, issues);
|
|
2095
2206
|
}
|
|
2207
|
+
function checkAtlasStep(executor, query, stepField, stepID, issues) {
|
|
2208
|
+
if (executor.includes(TEMPLATE_ACTION_OPEN)) return;
|
|
2209
|
+
const prefix = `${ATLAS_EXECUTOR.scheme}://`;
|
|
2210
|
+
if (!executor.startsWith(prefix)) return;
|
|
2211
|
+
const rest = executor.slice(prefix.length);
|
|
2212
|
+
const slash = rest.indexOf("/");
|
|
2213
|
+
const provider = slash < 0 ? rest : rest.slice(0, slash);
|
|
2214
|
+
const resource = slash < 0 ? "" : rest.slice(slash + 1);
|
|
2215
|
+
const quoted = JSON.stringify(stepID);
|
|
2216
|
+
const report = (rule, ...args) => {
|
|
2217
|
+
let message = rule.messageFormat.replace("%s", () => quoted);
|
|
2218
|
+
for (const a of args) message = message.replace("%s", () => a);
|
|
2219
|
+
issues.error({
|
|
2220
|
+
field: stepField,
|
|
2221
|
+
message,
|
|
2222
|
+
code: rule.code,
|
|
2223
|
+
stepId: stepID,
|
|
2224
|
+
suggestion: rule.suggestion
|
|
2225
|
+
});
|
|
2226
|
+
};
|
|
2227
|
+
const q2 = isRecord(query) ? query : {};
|
|
2228
|
+
let refusedKeys = ATLAS_EXECUTOR.paramRefused.capabilityKeys;
|
|
2229
|
+
if (provider === ATLAS_EXECUTOR.providerCapability) {
|
|
2230
|
+
if (!ATLAS_EXECUTOR.capabilityRefPattern.test(resource)) {
|
|
2231
|
+
report(ATLAS_EXECUTOR.capabilityRefInvalid, resource);
|
|
2232
|
+
}
|
|
2233
|
+
} else if (provider === ATLAS_EXECUTOR.providerAgent && resource === ATLAS_EXECUTOR.agentResource) {
|
|
2234
|
+
refusedKeys = ATLAS_EXECUTOR.paramRefused.agentKeys;
|
|
2235
|
+
const agent = q2.agent;
|
|
2236
|
+
if (typeof agent !== "string" || agent.trim() === "") {
|
|
2237
|
+
report(ATLAS_EXECUTOR.agentMissing);
|
|
2238
|
+
} else if (agent.includes(TEMPLATE_ACTION_OPEN)) {
|
|
2239
|
+
report(ATLAS_EXECUTOR.agentNotLiteral);
|
|
2240
|
+
}
|
|
2241
|
+
const hasPrompt = atlasTextPresent(q2.prompt);
|
|
2242
|
+
const hasTemplate = atlasTextPresent(q2.prompt_template);
|
|
2243
|
+
if (!hasPrompt && !hasTemplate) report(ATLAS_EXECUTOR.promptMissing);
|
|
2244
|
+
else if (hasPrompt && hasTemplate) report(ATLAS_EXECUTOR.promptBoth);
|
|
2245
|
+
if (anyTemplate(q2.model)) report(ATLAS_EXECUTOR.modelNotLiteral);
|
|
2246
|
+
} else {
|
|
2247
|
+
report(ATLAS_EXECUTOR.operationUnknown, executor);
|
|
2248
|
+
return;
|
|
2249
|
+
}
|
|
2250
|
+
if (anyTemplate(q2.capabilities)) report(ATLAS_EXECUTOR.capabilitiesNotLiteral);
|
|
2251
|
+
const refused = refusedKeys.filter((key) => Object.prototype.hasOwnProperty.call(q2, key)).sort();
|
|
2252
|
+
if (refused.length > 0) report(ATLAS_EXECUTOR.paramRefused, refused.join(", "));
|
|
2253
|
+
}
|
|
2254
|
+
function anyTemplate(v) {
|
|
2255
|
+
if (typeof v === "string") return v.includes(TEMPLATE_ACTION_OPEN);
|
|
2256
|
+
if (Array.isArray(v)) return v.some(anyTemplate);
|
|
2257
|
+
if (isRecord(v)) return Object.values(v).some(anyTemplate);
|
|
2258
|
+
return false;
|
|
2259
|
+
}
|
|
2260
|
+
function atlasTextPresent(v) {
|
|
2261
|
+
if (v === void 0 || v === null) return false;
|
|
2262
|
+
return typeof v !== "string" || v.trim() !== "";
|
|
2263
|
+
}
|
|
2096
2264
|
function checkFunctionOperation(executor, field, stepID, templated, issues) {
|
|
2097
2265
|
if (templated) return;
|
|
2098
2266
|
const m = EXECUTOR_URL_PATTERN.exec(executor);
|
|
@@ -2117,6 +2285,7 @@ function validateExecutors(flow, issues) {
|
|
|
2117
2285
|
const executor = issues.stringOf(step, "executor", `steps.${stepID}`);
|
|
2118
2286
|
if (executor !== null && executor !== "") {
|
|
2119
2287
|
checkExecutor(executor, `steps.${stepID}.executor`, stepID, issues);
|
|
2288
|
+
checkAtlasStep(executor, step.query, `steps.${stepID}`, stepID, issues);
|
|
2120
2289
|
}
|
|
2121
2290
|
const loop = step.loop;
|
|
2122
2291
|
if (isRecord(loop) && Array.isArray(loop.steps)) {
|
|
@@ -2133,6 +2302,7 @@ function validateExecutors(flow, issues) {
|
|
|
2133
2302
|
`${stepID}.${subID}`,
|
|
2134
2303
|
issues
|
|
2135
2304
|
);
|
|
2305
|
+
checkAtlasStep(subExecutor, subStep.query, subPath, `${stepID}.${subID}`, issues);
|
|
2136
2306
|
}
|
|
2137
2307
|
});
|
|
2138
2308
|
}
|
|
@@ -3775,6 +3945,37 @@ function validateInputSchema(flow, issues) {
|
|
|
3775
3945
|
validateSchemaDefinition(flow.input_schema, "input_schema", issues);
|
|
3776
3946
|
}
|
|
3777
3947
|
|
|
3948
|
+
// src/validators/reservedInputs.ts
|
|
3949
|
+
function formatField(format, name) {
|
|
3950
|
+
return format.replace("%s", () => name);
|
|
3951
|
+
}
|
|
3952
|
+
function validateReservedInputNames(flow, issues) {
|
|
3953
|
+
const rule = RESERVED_INPUT_NAMES;
|
|
3954
|
+
const report = (name, fieldFormat) => {
|
|
3955
|
+
issues.error({
|
|
3956
|
+
field: formatField(fieldFormat, name),
|
|
3957
|
+
message: rule.messageFormat.replace("%s", () => JSON.stringify(name)),
|
|
3958
|
+
code: rule.code,
|
|
3959
|
+
suggestion: rule.suggestion
|
|
3960
|
+
});
|
|
3961
|
+
};
|
|
3962
|
+
const query = flow.query;
|
|
3963
|
+
if (isRecord(query)) {
|
|
3964
|
+
for (const name of Object.keys(query).sort()) {
|
|
3965
|
+
if (name.startsWith(rule.prefix)) report(name, rule.queryFieldFormat);
|
|
3966
|
+
}
|
|
3967
|
+
}
|
|
3968
|
+
const schema = flow.input_schema;
|
|
3969
|
+
const fields = isRecord(schema) ? schema.fields : void 0;
|
|
3970
|
+
if (!Array.isArray(fields)) return;
|
|
3971
|
+
for (const f of fields) {
|
|
3972
|
+
if (!isRecord(f)) continue;
|
|
3973
|
+
if (typeof f.name === "string" && f.name.startsWith(rule.prefix)) {
|
|
3974
|
+
report(f.name, rule.schemaFieldFormat);
|
|
3975
|
+
}
|
|
3976
|
+
}
|
|
3977
|
+
}
|
|
3978
|
+
|
|
3778
3979
|
// src/validators/outputSchema.ts
|
|
3779
3980
|
function validateOutputSchemas(flow, issues) {
|
|
3780
3981
|
const steps = flow.steps;
|
|
@@ -4889,7 +5090,7 @@ var CODE2 = "server_owned_query_key";
|
|
|
4889
5090
|
var KEY_QUERY = "query";
|
|
4890
5091
|
var KEY_ID = "id";
|
|
4891
5092
|
var SERVER_OWNED = new Set(SERVER_OWNED_QUERY_KEYS.keys);
|
|
4892
|
-
function
|
|
5093
|
+
function formatField2(format, ...args) {
|
|
4893
5094
|
let i = 0;
|
|
4894
5095
|
return format.replace(/%s/g, () => args[i++] ?? "");
|
|
4895
5096
|
}
|
|
@@ -4907,7 +5108,7 @@ function validateServerOwnedQueryKeys(flow, issues) {
|
|
|
4907
5108
|
issues,
|
|
4908
5109
|
stepID,
|
|
4909
5110
|
key,
|
|
4910
|
-
|
|
5111
|
+
formatField2(SERVER_OWNED_QUERY_KEYS.stepFieldFormat, stepID, key)
|
|
4911
5112
|
);
|
|
4912
5113
|
}
|
|
4913
5114
|
}
|
|
@@ -4921,7 +5122,7 @@ function validateServerOwnedQueryKeys(flow, issues) {
|
|
|
4921
5122
|
issues,
|
|
4922
5123
|
stepID,
|
|
4923
5124
|
key,
|
|
4924
|
-
|
|
5125
|
+
formatField2(SERVER_OWNED_QUERY_KEYS.loopStepFieldFormat, stepID, subID, key)
|
|
4925
5126
|
);
|
|
4926
5127
|
}
|
|
4927
5128
|
}
|
|
@@ -5188,7 +5389,7 @@ function own(m, key) {
|
|
|
5188
5389
|
if (!isRecord(m) || !Object.prototype.hasOwnProperty.call(m, key)) return void 0;
|
|
5189
5390
|
return m[key];
|
|
5190
5391
|
}
|
|
5191
|
-
function
|
|
5392
|
+
function formatField3(format, ...args) {
|
|
5192
5393
|
let i = 0;
|
|
5193
5394
|
return format.replace(/%s/g, () => args[i++] ?? "");
|
|
5194
5395
|
}
|
|
@@ -5210,14 +5411,14 @@ function credentialEndpointSteps(flow, issues) {
|
|
|
5210
5411
|
out.push({
|
|
5211
5412
|
executor: issues.stringOf(step, KEY_EXECUTOR, `steps.${stepId}`) ?? "",
|
|
5212
5413
|
query: own(step, KEY_QUERY2),
|
|
5213
|
-
field: (key) =>
|
|
5414
|
+
field: (key) => formatField3(CREDENTIAL_ENDPOINT_PAIRING.stepFieldFormat, stepId, key)
|
|
5214
5415
|
});
|
|
5215
5416
|
for (const sub of loopSubStepsOfStep(stepId, step)) {
|
|
5216
5417
|
const subId = issues.stringOf(sub.raw, KEY_ID2, sub.basePath) ?? "";
|
|
5217
5418
|
out.push({
|
|
5218
5419
|
executor: issues.stringOf(sub.raw, KEY_EXECUTOR, sub.basePath) ?? "",
|
|
5219
5420
|
query: own(sub.raw, KEY_QUERY2),
|
|
5220
|
-
field: (key) =>
|
|
5421
|
+
field: (key) => formatField3(CREDENTIAL_ENDPOINT_PAIRING.loopStepFieldFormat, stepId, subId, key)
|
|
5221
5422
|
});
|
|
5222
5423
|
}
|
|
5223
5424
|
}
|
|
@@ -5281,7 +5482,7 @@ function validateAI(flow, steps, issues) {
|
|
|
5281
5482
|
if ((stepsUsing.get(provider) ?? 0) > 0 && (stepsWithoutOwnKey.get(provider) ?? 0) === 0) {
|
|
5282
5483
|
continue;
|
|
5283
5484
|
}
|
|
5284
|
-
warnStoredShape(issues,
|
|
5485
|
+
warnStoredShape(issues, formatField3(CREDENTIAL_ENDPOINT_PAIRING.executorConfigBaseUrlFieldFormat, provider), provider);
|
|
5285
5486
|
}
|
|
5286
5487
|
}
|
|
5287
5488
|
function warnStoredShape(issues, field, provider) {
|
|
@@ -5328,7 +5529,7 @@ function familySecret(flow, family, step, issues) {
|
|
|
5328
5529
|
if (apiKey !== "" && listHas(family.secretParams, family.configApiKeyParam)) {
|
|
5329
5530
|
return {
|
|
5330
5531
|
envName: serverEnvRef(family, apiKey),
|
|
5331
|
-
field:
|
|
5532
|
+
field: formatField3(
|
|
5332
5533
|
CREDENTIAL_ENDPOINT_PAIRING.executorConfigKeyFieldFormat,
|
|
5333
5534
|
configKey,
|
|
5334
5535
|
CREDENTIAL_ENDPOINT_PAIRING.executorConfigApiKeyField
|
|
@@ -5341,7 +5542,7 @@ function familySecret(flow, family, step, issues) {
|
|
|
5341
5542
|
if (v !== null) {
|
|
5342
5543
|
return {
|
|
5343
5544
|
envName: serverEnvRef(family, v),
|
|
5344
|
-
field:
|
|
5545
|
+
field: formatField3(CREDENTIAL_ENDPOINT_PAIRING.executorConfigExtraFieldFormat, configKey, key)
|
|
5345
5546
|
};
|
|
5346
5547
|
}
|
|
5347
5548
|
}
|
|
@@ -5367,13 +5568,13 @@ function familyAuthorEndpoint(flow, family, step, issues) {
|
|
|
5367
5568
|
if (inst === null) continue;
|
|
5368
5569
|
const baseUrl = configStringField(inst, configKey, CREDENTIAL_ENDPOINT_PAIRING.executorConfigBaseUrlField, issues);
|
|
5369
5570
|
if (baseUrl !== "" && listHas(family.endpointParams, family.configBaseUrlParam)) {
|
|
5370
|
-
return decide(baseUrl,
|
|
5571
|
+
return decide(baseUrl, formatField3(CREDENTIAL_ENDPOINT_PAIRING.executorConfigBaseUrlFieldFormat, configKey));
|
|
5371
5572
|
}
|
|
5372
5573
|
const extra = own(inst, EXECUTOR_CONFIG_ENV_SCOPES.extraKey);
|
|
5373
5574
|
for (const key of family.endpointParams) {
|
|
5374
5575
|
const v = nonEmptyEndpoint(extra, key);
|
|
5375
5576
|
if (v !== null)
|
|
5376
|
-
return decide(v,
|
|
5577
|
+
return decide(v, formatField3(CREDENTIAL_ENDPOINT_PAIRING.executorConfigExtraFieldFormat, configKey, key));
|
|
5377
5578
|
}
|
|
5378
5579
|
}
|
|
5379
5580
|
return null;
|
|
@@ -7084,6 +7285,7 @@ function validateParsed(flow, opts, sources) {
|
|
|
7084
7285
|
validateOrchestratorCampaign(f, issues, opts);
|
|
7085
7286
|
validateCredentialBindings(f, issues);
|
|
7086
7287
|
validateInputSchema(f, issues);
|
|
7288
|
+
validateReservedInputNames(f, issues);
|
|
7087
7289
|
validateOutputSchemas(f, issues);
|
|
7088
7290
|
validateQualityGates(f, issues);
|
|
7089
7291
|
validateProcessingOperations(f, issues);
|