@vaudience/aigentflow-flow-validator 0.19.0 → 0.21.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/dist/cli.js CHANGED
@@ -307,6 +307,17 @@ function isValidGoDuration(input) {
307
307
  var RESERVED_STEP_ID_CHAR = ".";
308
308
  var RESERVED_STEP_ID_ORCHESTRATOR = "orchestrator";
309
309
  var DISPLAY_NAME_MAX_LEN = 80;
310
+ var YAML11_BOOL_WORDS = new Set(
311
+ ["y", "yes", "on", "n", "no", "off"].flatMap((w) => [
312
+ w,
313
+ w.toUpperCase(),
314
+ w[0].toUpperCase() + w.slice(1)
315
+ ])
316
+ );
317
+ function isBoolLike(v) {
318
+ if (v === null || typeof v === "boolean") return true;
319
+ return typeof v === "string" && YAML11_BOOL_WORDS.has(v);
320
+ }
310
321
  function validateBasicStructure(flow, issues) {
311
322
  if (!issues.nonEmptyStringOf(flow, "aigentflow_version", "")) {
312
323
  issues.error({
@@ -336,6 +347,14 @@ function validateBasicStructure(flow, issues) {
336
347
  });
337
348
  }
338
349
  }
350
+ if (flow.strict_templates !== void 0 && !isBoolLike(flow.strict_templates)) {
351
+ issues.error({
352
+ field: "strict_templates",
353
+ message: "strict_templates must be a boolean (true or false)",
354
+ code: "invalid_type",
355
+ suggestion: "Write 'strict_templates: true' or remove the key"
356
+ });
357
+ }
339
358
  const start = issues.stringOf(flow, "start", "");
340
359
  if (start === null || start === "") {
341
360
  issues.error({
@@ -436,7 +455,7 @@ function validateBasicStructure(flow, issues) {
436
455
  // src/spec/aigentflow-spec.json
437
456
  var aigentflow_spec_default = {
438
457
  $comment: "Vendored enum surface mirrored from the AIgentFlow Go reference implementation. Regenerate / review on every flow-YAML schema change. See PARITY.md. Values here are public protocol/type names only.",
439
- specVersion: "2.820.0",
458
+ specVersion: "2.827.0",
440
459
  inputSchemaVersion: 1,
441
460
  executorSchemes: [
442
461
  "a2a",
@@ -460,6 +479,7 @@ var aigentflow_spec_default = {
460
479
  "geocoding",
461
480
  "geovisualize",
462
481
  "getmd",
482
+ "here",
463
483
  "homeassistant",
464
484
  "hosting",
465
485
  "http",
@@ -1275,6 +1295,42 @@ var aigentflow_spec_default = {
1275
1295
  }
1276
1296
  }
1277
1297
  },
1298
+ templateDefaultPiped: {
1299
+ $comment: "template_default_piped (ERROR at the top level, WARNING inside a loop body, like template_syntax_error). The template function `default` takes the value FIRST; a pipeline that passes a value into it as a non-first command hands the piped value as the LAST argument, so the fallback is always the result. Flagged: any pipeline (in any action, including if / else if / range / with / template / block conditions, parenthesised sub-pipelines and variable declarations) in which a command whose first word is the bare identifier `default` is not the FIRST command. Never flagged: a field, a variable, a string literal, a comment, `default` as the first command. The message fills %s with the pipeline.",
1300
+ code: "template_default_piped",
1301
+ function: "default",
1302
+ messageFormat: "`default` takes the value FIRST, and a pipe passes the piped value LAST: `%s` is `default <fallback> <value>`, so the fallback is always the result",
1303
+ suggestion: 'write the value first and the fallback second, as a call: `{{ default .x "fallback" }}`'
1304
+ },
1305
+ complianceResidency: {
1306
+ $comment: "compliance_residency_unenforced (WARNING, never an error; needs no catalogue). When compliance.residency is non-empty and every code (trimmed, upper-cased) is in euResidencyCodes, each top-level step and loop sub-step whose executor starts with aiProtocol+protocolSeparator, then the orchestrator (provider = its exons execution.provider), warns when its provider (literal, lower-cased; skipped when empty or containing templateActionOpen) is in regionLaneProviders and the call is not pinned. Pinned = query region (orchestrator.region) a non-empty string after trimming; OR enforce_region true (query: bool true or the strings in enforceRegionTrueStrings; orchestrator: bool true); OR the author named the endpoint: query <provider>+baseUrlParamSuffix a non-empty string after trimming, or executor_config.<provider>.base_url non-empty after trimming. The provider segment of ai://<provider>/<operation> exists only when a slash follows it. regionLaneProviders is the set of providers whose adapter routes on `region`; a provider outside it has no region lane and is never warned. Message, suggestion and site formats fill %s and %q (a Go-quoted string) in order; the message's last placeholder is the residency list as written, printed [A B]. Reference: validateResidencyEnforcement (validation.residency.go).",
1307
+ code: "compliance_residency_unenforced",
1308
+ euResidencyCodes: ["EU", "DE", "FR", "IE", "NL", "IT", "ES"],
1309
+ regionLaneProviders: [
1310
+ "bedrock",
1311
+ "google",
1312
+ "azure",
1313
+ "openai",
1314
+ "assemblyai",
1315
+ "speechmatics",
1316
+ "deepgram",
1317
+ "mistral"
1318
+ ],
1319
+ aiProtocol: "ai",
1320
+ protocolSeparator: "://",
1321
+ regionParam: "region",
1322
+ enforceRegionParam: "enforce_region",
1323
+ baseUrlParamSuffix: "_base_url",
1324
+ enforceRegionTrueStrings: ["true", "1", "yes"],
1325
+ stepFieldFormat: "steps.%s.executor",
1326
+ loopStepFieldFormat: "steps.%s.loop.steps.%s.executor",
1327
+ orchestratorField: "orchestrator.exons",
1328
+ siteStepFormat: "step %q",
1329
+ siteLoopStepFormat: "loop sub-step %q of step %q",
1330
+ siteOrchestrator: "the orchestrator",
1331
+ messageFormat: "%s calls provider %q, whose default endpoint commits to no jurisdiction, but sets neither region nor enforce_region, so nothing pins it to the declared residency %v. compliance.residency is a catalogue eligibility check, not endpoint evidence",
1332
+ suggestion: "Add `region: eu` and `enforce_region: true` to the call (an orchestrator: the same two keys on the orchestrator block). Prove it afterwards: the step record's diagnostics.region is stamped from the host actually dialled."
1333
+ },
1278
1334
  examples: {
1279
1335
  $comment: "The examples: block. Derived from the reference's constants, never hand-typed: limits, vocabularies, the credential-shaped-literal pattern set and each code's severity. example_ref_blocked_host is listed for completeness but is raised by the reference implementation only; the ports never raise it. See PARITY.md, 'The examples block'.",
1280
1336
  limits: {
@@ -1609,6 +1665,7 @@ var aigentflow_spec_default = {
1609
1665
  rate_limit: "FlowRateLimitConfig",
1610
1666
  start: "scalar",
1611
1667
  steps: "map<StepDefinition>",
1668
+ strict_templates: "scalar",
1612
1669
  tags: "list<scalar>",
1613
1670
  template: "FlowTemplateMetadata",
1614
1671
  tool_discovery: "scalar",
@@ -1943,6 +2000,25 @@ var CREDENTIAL_ENDPOINT_PAIRING = {
1943
2000
  familyKeySeparator: aigentflow_spec_default.credentialEndpointPairing.familyKeySeparator,
1944
2001
  families: aigentflow_spec_default.credentialEndpointPairing.families
1945
2002
  };
2003
+ var COMPLIANCE_RESIDENCY = {
2004
+ code: aigentflow_spec_default.complianceResidency.code,
2005
+ euResidencyCodes: aigentflow_spec_default.complianceResidency.euResidencyCodes,
2006
+ regionLaneProviders: aigentflow_spec_default.complianceResidency.regionLaneProviders,
2007
+ aiProtocol: aigentflow_spec_default.complianceResidency.aiProtocol,
2008
+ protocolSeparator: aigentflow_spec_default.complianceResidency.protocolSeparator,
2009
+ regionParam: aigentflow_spec_default.complianceResidency.regionParam,
2010
+ enforceRegionParam: aigentflow_spec_default.complianceResidency.enforceRegionParam,
2011
+ baseUrlParamSuffix: aigentflow_spec_default.complianceResidency.baseUrlParamSuffix,
2012
+ enforceRegionTrueStrings: aigentflow_spec_default.complianceResidency.enforceRegionTrueStrings,
2013
+ stepFieldFormat: aigentflow_spec_default.complianceResidency.stepFieldFormat,
2014
+ loopStepFieldFormat: aigentflow_spec_default.complianceResidency.loopStepFieldFormat,
2015
+ orchestratorField: aigentflow_spec_default.complianceResidency.orchestratorField,
2016
+ siteStepFormat: aigentflow_spec_default.complianceResidency.siteStepFormat,
2017
+ siteLoopStepFormat: aigentflow_spec_default.complianceResidency.siteLoopStepFormat,
2018
+ siteOrchestrator: aigentflow_spec_default.complianceResidency.siteOrchestrator,
2019
+ messageFormat: aigentflow_spec_default.complianceResidency.messageFormat,
2020
+ suggestion: aigentflow_spec_default.complianceResidency.suggestion
2021
+ };
1946
2022
  var EXAMPLES = {
1947
2023
  limits: aigentflow_spec_default.examples.limits,
1948
2024
  idPattern: new RegExp(aigentflow_spec_default.examples.idPattern),
@@ -1962,6 +2038,12 @@ var EXAMPLES = {
1962
2038
  })),
1963
2039
  codes: aigentflow_spec_default.examples.codes
1964
2040
  };
2041
+ var TEMPLATE_DEFAULT_PIPED = {
2042
+ code: aigentflow_spec_default.templateDefaultPiped.code,
2043
+ function: aigentflow_spec_default.templateDefaultPiped.function,
2044
+ messageFormat: aigentflow_spec_default.templateDefaultPiped.messageFormat,
2045
+ suggestion: aigentflow_spec_default.templateDefaultPiped.suggestion
2046
+ };
1965
2047
 
1966
2048
  // src/validators/executors.ts
1967
2049
  var SCHEME_SEPARATOR = "://";
@@ -3925,6 +4007,117 @@ function splitPipeline(body) {
3925
4007
  return stages;
3926
4008
  }
3927
4009
 
4010
+ // src/template/gotmpl-default.ts
4011
+ var FUNCTION_NAME = "default";
4012
+ var PIPE = "|";
4013
+ var OPEN_PAREN = "(";
4014
+ var CLOSE_PAREN = ")";
4015
+ var MAX_NESTING_DEPTH = 100;
4016
+ var PIPELINE_KEYWORDS = /^(?:else\s+if|else\s+with|if|range|with|template|block)(?![\w$.])/;
4017
+ var NO_PIPELINE = /^(?:define|else|end|break|continue)(?![\w$.])/;
4018
+ var DECLARATION = /^\$\w*(?:\s*,\s*\$\w*)*\s*:?=/;
4019
+ function pipedDefaultPipelines(src) {
4020
+ const { actions, fatal } = lexActions(src);
4021
+ if (fatal) return [];
4022
+ const found = /* @__PURE__ */ new Set();
4023
+ try {
4024
+ for (const action of actions) {
4025
+ if (action.isComment || action.body === "") continue;
4026
+ scanAction(action.body, found);
4027
+ }
4028
+ } catch (err) {
4029
+ if (!(err instanceof RangeError)) throw err;
4030
+ return [];
4031
+ }
4032
+ return [...found].sort();
4033
+ }
4034
+ function scanAction(body, found) {
4035
+ let rest = body;
4036
+ const kw = PIPELINE_KEYWORDS.exec(rest);
4037
+ if (!kw && NO_PIPELINE.test(rest)) return;
4038
+ if (kw) {
4039
+ rest = rest.slice(kw[0].length).trimStart();
4040
+ const keyword = kw[0].replace(/\s+/g, " ");
4041
+ if (keyword === "template" || keyword === "block") {
4042
+ const q2 = rest[0];
4043
+ if (q2 === '"' || q2 === "`") {
4044
+ const end = scanString(rest, 0, q2);
4045
+ if (end === -1) return;
4046
+ rest = rest.slice(end + 1).trimStart();
4047
+ }
4048
+ }
4049
+ }
4050
+ if (rest === "") return;
4051
+ parsePipeline(rest, 0, false, found, 0);
4052
+ }
4053
+ function parsePipeline(src, start, nested, found, depth) {
4054
+ if (depth > MAX_NESTING_DEPTH) return { text: src.slice(start), end: src.length };
4055
+ let i = start;
4056
+ const n = src.length;
4057
+ let decl = "";
4058
+ const decMatch = DECLARATION.exec(src.slice(i));
4059
+ if (decMatch) {
4060
+ decl = decMatch[0].replace(/\s+/g, " ") + " ";
4061
+ i += decMatch[0].length;
4062
+ }
4063
+ const commands = [];
4064
+ let current = [];
4065
+ let firstWords = [];
4066
+ let pipedDefault = false;
4067
+ const pushCommand = () => {
4068
+ if (current.length > 0) {
4069
+ commands.push(current);
4070
+ firstWords.push(current[0]);
4071
+ }
4072
+ current = [];
4073
+ };
4074
+ while (i < n) {
4075
+ const c = src[i];
4076
+ if (c === " " || c === " " || c === "\n" || c === "\r") {
4077
+ i += 1;
4078
+ continue;
4079
+ }
4080
+ if (c === '"' || c === "`" || c === "'") {
4081
+ const end = scanString(src, i, c);
4082
+ const stop = end === -1 ? n - 1 : end;
4083
+ current.push(src.slice(i, stop + 1));
4084
+ i = stop + 1;
4085
+ continue;
4086
+ }
4087
+ if (c === OPEN_PAREN) {
4088
+ const inner = parsePipeline(src, i + 1, true, found, depth + 1);
4089
+ current.push(`(${inner.text})`);
4090
+ i = inner.end;
4091
+ continue;
4092
+ }
4093
+ if (c === CLOSE_PAREN) {
4094
+ if (nested) {
4095
+ i += 1;
4096
+ break;
4097
+ }
4098
+ i += 1;
4099
+ continue;
4100
+ }
4101
+ if (c === PIPE) {
4102
+ pushCommand();
4103
+ i += 1;
4104
+ continue;
4105
+ }
4106
+ let j = i;
4107
+ while (j < n && !/[\s|()"`']/.test(src[j])) j += 1;
4108
+ if (j === i) j = i + 1;
4109
+ current.push(src.slice(i, j));
4110
+ i = j;
4111
+ }
4112
+ pushCommand();
4113
+ firstWords.forEach((word, idx) => {
4114
+ if (idx > 0 && word === FUNCTION_NAME) pipedDefault = true;
4115
+ });
4116
+ const text = decl + commands.map((cmd) => cmd.join(" ")).join(` ${PIPE} `);
4117
+ if (pipedDefault) found.add(text);
4118
+ return { text, end: i };
4119
+ }
4120
+
3928
4121
  // src/validators/processingOperations.ts
3929
4122
  var PROCESSING_OP_GUARD_KEY = PROCESSING_OPERATIONS.guardKey;
3930
4123
  var PROCESSING_PHASES = ["pre_processing", "post_processing"];
@@ -4071,6 +4264,17 @@ function checkTemplateString(value, field, stepID, issues, stats, opts, demote =
4071
4264
  });
4072
4265
  }
4073
4266
  }
4267
+ if (errors.length > 0) return;
4268
+ for (const pipe of pipedDefaultPipelines(value)) {
4269
+ report({
4270
+ field,
4271
+ message: TEMPLATE_DEFAULT_PIPED.messageFormat.replace("%s", () => pipe),
4272
+ code: TEMPLATE_DEFAULT_PIPED.code,
4273
+ stepId: stepID,
4274
+ context: `Template: ${value}`,
4275
+ suggestion: TEMPLATE_DEFAULT_PIPED.suggestion
4276
+ });
4277
+ }
4074
4278
  }
4075
4279
  function walkStrings2(basePath, value, stepID, issues, stats, opts, check, demote = false) {
4076
4280
  if (isString(value)) {
@@ -5302,6 +5506,141 @@ function warnOrchestratorToolWithheld(flow, orch, report, issues) {
5302
5506
  }
5303
5507
  }
5304
5508
 
5509
+ // src/validators/complianceResidency.ts
5510
+ function own2(m, key) {
5511
+ if (!isRecord(m) || !Object.prototype.hasOwnProperty.call(m, key)) return void 0;
5512
+ return m[key];
5513
+ }
5514
+ function sprintf(format, ...args) {
5515
+ let i = 0;
5516
+ return format.replace(/%[sqv]/g, (verb) => {
5517
+ const arg = args[i++] ?? "";
5518
+ return verb === "%q" ? JSON.stringify(arg) : arg;
5519
+ });
5520
+ }
5521
+ function literalOrEmpty(s) {
5522
+ const t = goTrimSpace2(s);
5523
+ return t.includes(TEMPLATE_ACTION_OPEN) ? "" : t;
5524
+ }
5525
+ function euOnlyResidency(flow, issues) {
5526
+ const raw = own2(own2(flow, "compliance"), "residency");
5527
+ if (!isArray(raw)) return null;
5528
+ const codes = [];
5529
+ for (let i = 0; i < raw.length; i++) {
5530
+ if (raw[i] === null) continue;
5531
+ const code = issues.stringAt(raw[i], `compliance.residency[${i}]`);
5532
+ if (code === null) return null;
5533
+ codes.push(code);
5534
+ }
5535
+ if (codes.length === 0) return null;
5536
+ const eu = new Set(COMPLIANCE_RESIDENCY.euResidencyCodes);
5537
+ return codes.every((c) => eu.has(goTrimSpace2(c).toUpperCase())) ? codes : null;
5538
+ }
5539
+ function aiProvider(executor) {
5540
+ const prefix = COMPLIANCE_RESIDENCY.aiProtocol + COMPLIANCE_RESIDENCY.protocolSeparator;
5541
+ if (!executor.startsWith(prefix)) return "";
5542
+ const rest = executor.slice(prefix.length);
5543
+ const slash = rest.indexOf("/");
5544
+ const provider = slash > 0 ? rest.slice(0, slash) : "";
5545
+ return provider.includes(TEMPLATE_ACTION_OPEN) ? "" : provider;
5546
+ }
5547
+ function isRegionLane(provider) {
5548
+ const literal = literalOrEmpty(provider);
5549
+ return literal !== "" && COMPLIANCE_RESIDENCY.regionLaneProviders.includes(literal.toLowerCase());
5550
+ }
5551
+ function nonBlankString(m, key) {
5552
+ const v = own2(m, key);
5553
+ return typeof v === "string" && goTrimSpace2(v) !== "";
5554
+ }
5555
+ function queryEnforcesRegion(query) {
5556
+ const v = own2(query, COMPLIANCE_RESIDENCY.enforceRegionParam);
5557
+ if (typeof v === "boolean") return v;
5558
+ return typeof v === "string" && COMPLIANCE_RESIDENCY.enforceRegionTrueStrings.includes(v);
5559
+ }
5560
+ function flowDirectsEndpoint(flow, provider, issues) {
5561
+ const key = provider.toLowerCase();
5562
+ const inst = own2(own2(flow, "executor_config"), key);
5563
+ if (!isRecord(inst)) return false;
5564
+ const baseUrl = issues.stringOf(inst, "base_url", `executor_config.${key}`);
5565
+ return baseUrl !== null && goTrimSpace2(baseUrl) !== "";
5566
+ }
5567
+ function callPinsEndpoint(flow, provider, query, issues) {
5568
+ if (nonBlankString(query, COMPLIANCE_RESIDENCY.regionParam)) return true;
5569
+ if (queryEnforcesRegion(query)) return true;
5570
+ if (nonBlankString(query, provider.toLowerCase() + COMPLIANCE_RESIDENCY.baseUrlParamSuffix)) return true;
5571
+ return flowDirectsEndpoint(flow, provider, issues);
5572
+ }
5573
+ function validateResidencyEnforcement(flow, issues) {
5574
+ const residency = euOnlyResidency(flow, issues);
5575
+ if (residency === null) return;
5576
+ const warn = (site, field, stepId, provider) => {
5577
+ issues.warn({
5578
+ field,
5579
+ ...stepId === void 0 ? {} : { stepId },
5580
+ code: COMPLIANCE_RESIDENCY.code,
5581
+ message: sprintf(COMPLIANCE_RESIDENCY.messageFormat, site, provider, `[${residency.join(" ")}]`),
5582
+ suggestion: COMPLIANCE_RESIDENCY.suggestion
5583
+ });
5584
+ };
5585
+ const steps = flow.steps;
5586
+ if (isRecord(steps)) {
5587
+ for (const stepId of Object.keys(steps).sort()) {
5588
+ const step = steps[stepId];
5589
+ if (!isRecord(step)) continue;
5590
+ const calls = [
5591
+ {
5592
+ executor: issues.stringOf(step, "executor", `steps.${stepId}`) ?? "",
5593
+ query: own2(step, "query"),
5594
+ subId: null
5595
+ }
5596
+ ];
5597
+ for (const sub of loopSubStepsOfStep(stepId, step)) {
5598
+ calls.push({
5599
+ executor: issues.stringOf(sub.raw, "executor", sub.basePath) ?? "",
5600
+ query: own2(sub.raw, "query"),
5601
+ subId: issues.stringOf(sub.raw, "id", sub.basePath) ?? ""
5602
+ });
5603
+ }
5604
+ for (const call of calls) {
5605
+ const provider = aiProvider(call.executor);
5606
+ if (!isRegionLane(provider)) continue;
5607
+ if (callPinsEndpoint(flow, provider, call.query, issues)) continue;
5608
+ if (call.subId === null) {
5609
+ warn(
5610
+ sprintf(COMPLIANCE_RESIDENCY.siteStepFormat, stepId),
5611
+ sprintf(COMPLIANCE_RESIDENCY.stepFieldFormat, stepId),
5612
+ stepId,
5613
+ provider
5614
+ );
5615
+ } else {
5616
+ warn(
5617
+ sprintf(COMPLIANCE_RESIDENCY.siteLoopStepFormat, call.subId, stepId),
5618
+ sprintf(COMPLIANCE_RESIDENCY.loopStepFieldFormat, stepId, call.subId),
5619
+ stepId,
5620
+ provider
5621
+ );
5622
+ }
5623
+ }
5624
+ }
5625
+ }
5626
+ warnOrchestrator(flow, issues, warn);
5627
+ }
5628
+ function warnOrchestrator(flow, issues, warn) {
5629
+ const orch = flow.orchestrator;
5630
+ if (!isRecord(orch)) return;
5631
+ const source = issues.stringOf(orch, "exons", "orchestrator");
5632
+ if (source === null || source === "") return;
5633
+ const report = inspectExonsFrontmatter(source);
5634
+ if (report.parseError !== null || !report.specRead || !report.hasSpec) return;
5635
+ const provider = literalOrEmpty(report.provider);
5636
+ if (!isRegionLane(provider)) return;
5637
+ const region = issues.stringOf(orch, "region", "orchestrator");
5638
+ if (region !== null && goTrimSpace2(region) !== "") return;
5639
+ if (orch.enforce_region === true) return;
5640
+ if (flowDirectsEndpoint(flow, provider, issues)) return;
5641
+ warn(COMPLIANCE_RESIDENCY.siteOrchestrator, COMPLIANCE_RESIDENCY.orchestratorField, void 0, provider);
5642
+ }
5643
+
5305
5644
  // src/validators/examples.ts
5306
5645
  var KEY_EXAMPLES = "examples";
5307
5646
  var VISIBILITY_PUBLIC = "public";
@@ -5379,7 +5718,7 @@ function num(n) {
5379
5718
  function has(o, key) {
5380
5719
  return Object.prototype.hasOwnProperty.call(o, key) && o[key] !== null && o[key] !== void 0;
5381
5720
  }
5382
- function own2(o, key) {
5721
+ function own3(o, key) {
5383
5722
  return Object.prototype.hasOwnProperty.call(o, key) ? o[key] : void 0;
5384
5723
  }
5385
5724
  function setOwn(o, key, value) {
@@ -5431,7 +5770,7 @@ function mergePatch(target, patch, depth) {
5431
5770
  continue;
5432
5771
  }
5433
5772
  if (isRecord(pv)) {
5434
- const current = own2(target, k);
5773
+ const current = own3(target, k);
5435
5774
  const existing = isRecord(current) ? deepCopy(current, 0) : {};
5436
5775
  mergePatch(existing, pv, depth + 1);
5437
5776
  setOwn(target, k, existing);
@@ -5451,7 +5790,7 @@ function asFileRef(v) {
5451
5790
  if (keys.length === 0) return null;
5452
5791
  for (const k of keys) if (!FILE_REF_KEYS.has(k)) return null;
5453
5792
  const str = (k) => {
5454
- const x = own2(v, k);
5793
+ const x = own3(v, k);
5455
5794
  return typeof x === "string" ? x : "";
5456
5795
  };
5457
5796
  return {
@@ -5519,7 +5858,7 @@ var Walker = class _Walker {
5519
5858
  `the examples block is ${size} bytes; the limit is ${L.maxBlockBytes}. Move large inputs or target outputs to a file reference (https URL).`
5520
5859
  );
5521
5860
  }
5522
- const allHeld = examples.every((e) => isRecord(e) && own2(e, "hold_out") === true);
5861
+ const allHeld = examples.every((e) => isRecord(e) && own3(e, "hold_out") === true);
5523
5862
  if (allHeld) {
5524
5863
  this.warn(
5525
5864
  "examples_all_held_out",
@@ -5607,9 +5946,9 @@ var Walker = class _Walker {
5607
5946
  `example ${q(label)} notes are ${notesN} characters; the limit is ${L.maxNotesRunes}`
5608
5947
  );
5609
5948
  }
5610
- this.validateTags(path, label, own2(ex, "tags"));
5611
- this.validateWeight(`${path}.weight`, label, numberOf(own2(ex, "weight")));
5612
- const minScore = numberOf(own2(ex, "min_score"));
5949
+ this.validateTags(path, label, own3(ex, "tags"));
5950
+ this.validateWeight(`${path}.weight`, label, numberOf(own3(ex, "weight")));
5951
+ const minScore = numberOf(own3(ex, "min_score"));
5613
5952
  if (minScore !== void 0 && !scoreInRange(minScore)) {
5614
5953
  this.err(
5615
5954
  "example_min_score_range",
@@ -5625,7 +5964,7 @@ var Walker = class _Walker {
5625
5964
  `example ${q(label)} has side_effects ${q(sideEffects)}; use refuse or allow`
5626
5965
  );
5627
5966
  }
5628
- const holdOut = own2(ex, "hold_out") === true;
5967
+ const holdOut = own3(ex, "hold_out") === true;
5629
5968
  if (holdOut && this.isPublic()) {
5630
5969
  this.err(
5631
5970
  "example_holdout_in_public_flow",
@@ -5648,17 +5987,17 @@ var Walker = class _Walker {
5648
5987
  `example ${q(label)} has neither input nor input_ref; use input: {} for a flow that takes no input`
5649
5988
  );
5650
5989
  }
5651
- const rawInput = own2(ex, "input");
5990
+ const rawInput = own3(ex, "input");
5652
5991
  const baseInput = isRecord(rawInput) ? rawInput : null;
5653
5992
  if (baseInput !== null) {
5654
5993
  this.checkInput(`${path}.input`, label, baseInput, "example_input_invalid");
5655
5994
  }
5656
- const rawInputRef = own2(ex, "input_ref");
5995
+ const rawInputRef = own3(ex, "input_ref");
5657
5996
  if (isRecord(rawInputRef)) {
5658
5997
  this.validateFileRef(`${path}.input_ref`, this.fileRefOf(rawInputRef, `${path}.input_ref`));
5659
5998
  }
5660
5999
  let binaryOnly = false;
5661
- const expected = own2(ex, "expected");
6000
+ const expected = own3(ex, "expected");
5662
6001
  if (!has(ex, "expected")) {
5663
6002
  this.err(
5664
6003
  "example_expected_missing",
@@ -5677,7 +6016,7 @@ var Walker = class _Walker {
5677
6016
  "this example can be run but not scored"
5678
6017
  );
5679
6018
  }
5680
- this.validateCheckpoints(path, label, own2(ex, "checkpoints"));
6019
+ this.validateCheckpoints(path, label, own3(ex, "checkpoints"));
5681
6020
  this.validateVariants(i, path, label, ex, hasInput, baseInput);
5682
6021
  this.scanSecretLike(i, path, ex);
5683
6022
  }
@@ -5737,8 +6076,8 @@ var Walker = class _Walker {
5737
6076
  );
5738
6077
  return;
5739
6078
  }
5740
- const schema = own2(this.flow, "input_schema");
5741
- const query = own2(this.flow, "query");
6079
+ const schema = own3(this.flow, "input_schema");
6080
+ const query = own3(this.flow, "query");
5742
6081
  if (isRecord(schema)) {
5743
6082
  this.checkInputAgainstSchema(field, label, input, schema, code);
5744
6083
  } else if (isRecord(query) && Object.keys(query).length > 0) {
@@ -5806,29 +6145,29 @@ var Walker = class _Walker {
5806
6145
  }
5807
6146
  }
5808
6147
  schemaFields(schema) {
5809
- const raw = own2(schema, "fields");
6148
+ const raw = own3(schema, "fields");
5810
6149
  if (!Array.isArray(raw)) return [];
5811
6150
  const out = [];
5812
6151
  raw.forEach((f, i) => {
5813
6152
  if (!isRecord(f)) return;
5814
6153
  const base = `input_schema.fields[${i}]`;
5815
- const enumRaw = own2(f, "enum");
6154
+ const enumRaw = own3(f, "enum");
5816
6155
  const enumValues = [];
5817
6156
  if (Array.isArray(enumRaw)) {
5818
6157
  enumRaw.forEach((e, j) => {
5819
6158
  enumValues.push(e === null ? "" : this.issues.stringAt(e, `${base}.enum[${j}]`) ?? "");
5820
6159
  });
5821
6160
  }
5822
- const vw = own2(f, "visible_when");
6161
+ const vw = own3(f, "visible_when");
5823
6162
  out.push({
5824
6163
  name: this.s(f, "name", base),
5825
6164
  type: this.s(f, "type", base),
5826
- required: own2(f, "required") === true,
6165
+ required: own3(f, "required") === true,
5827
6166
  enumValues,
5828
6167
  visibleWhen: isRecord(vw) ? {
5829
6168
  field: this.s(vw, "field", `${base}.visible_when`),
5830
- equals: own2(vw, "equals"),
5831
- in: Array.isArray(own2(vw, "in")) ? own2(vw, "in") : []
6169
+ equals: own3(vw, "equals"),
6170
+ in: Array.isArray(own3(vw, "in")) ? own3(vw, "in") : []
5832
6171
  } : null
5833
6172
  });
5834
6173
  });
@@ -5839,7 +6178,7 @@ var Walker = class _Walker {
5839
6178
  const failures = [];
5840
6179
  for (const f of fields) {
5841
6180
  if (!isVisible(f, runInput)) continue;
5842
- const raw = own2(runInput, f.name);
6181
+ const raw = own3(runInput, f.name);
5843
6182
  if (raw === void 0 || raw === null) {
5844
6183
  if (f.required) {
5845
6184
  failures.push({
@@ -5950,7 +6289,7 @@ var Walker = class _Walker {
5950
6289
  /** The names `fields` / `exact` may use, and whether such a list is declared at all. */
5951
6290
  outputNamesFor(kind, stepId) {
5952
6291
  if (kind === "final") {
5953
- const out = own2(this.flow, "output");
6292
+ const out = own3(this.flow, "output");
5954
6293
  const names2 = [];
5955
6294
  if (Array.isArray(out)) {
5956
6295
  out.forEach((item, i) => {
@@ -5959,10 +6298,10 @@ var Walker = class _Walker {
5959
6298
  }
5960
6299
  return { names: names2, declared: names2.length > 0 };
5961
6300
  }
5962
- const steps = own2(this.flow, "steps");
5963
- const step = isRecord(steps) ? own2(steps, stepId) : void 0;
5964
- const schema = isRecord(step) ? own2(step, "output_schema") : void 0;
5965
- const fields = isRecord(schema) ? own2(schema, "fields") : void 0;
6301
+ const steps = own3(this.flow, "steps");
6302
+ const step = isRecord(steps) ? own3(steps, stepId) : void 0;
6303
+ const schema = isRecord(step) ? own3(step, "output_schema") : void 0;
6304
+ const fields = isRecord(schema) ? own3(schema, "fields") : void 0;
5966
6305
  if (!Array.isArray(fields) || fields.length === 0) return { names: [], declared: false };
5967
6306
  const names = [];
5968
6307
  fields.forEach((f, i) => {
@@ -5981,8 +6320,8 @@ var Walker = class _Walker {
5981
6320
  );
5982
6321
  }
5983
6322
  const noOutput = status === STATUS_FAILED || status === STATUS_PAUSED_FOR_HUMAN;
5984
- const fieldsRec = own2(e, "fields");
5985
- const exactRec = own2(e, "exact");
6323
+ const fieldsRec = own3(e, "fields");
6324
+ const exactRec = own3(e, "exact");
5986
6325
  const fieldKeys = isRecord(fieldsRec) ? sortedKeys(fieldsRec) : [];
5987
6326
  const exactKeys = isRecord(exactRec) ? sortedKeys(exactRec) : [];
5988
6327
  const hasFields = fieldKeys.length > 0;
@@ -6000,7 +6339,7 @@ var Walker = class _Walker {
6000
6339
  `a case that ends in ${status} has no output to match; remove fields and exact, or expect status completed`
6001
6340
  );
6002
6341
  }
6003
- const minScore = numberOf(own2(e, "min_score"));
6342
+ const minScore = numberOf(own3(e, "min_score"));
6004
6343
  if (minScore !== void 0 && !scoreInRange(minScore)) {
6005
6344
  this.err(
6006
6345
  "example_min_score_range",
@@ -6027,7 +6366,7 @@ var Walker = class _Walker {
6027
6366
  }
6028
6367
  }
6029
6368
  }
6030
- const reference = own2(e, "reference");
6369
+ const reference = own3(e, "reference");
6031
6370
  if (isRecord(reference)) this.validateReference(`${path}.reference`, reference);
6032
6371
  const { names, declared } = this.outputNamesFor(kind, stepId);
6033
6372
  const checkKey = (field, key) => {
@@ -6054,12 +6393,12 @@ var Walker = class _Walker {
6054
6393
  for (const key of fieldKeys) {
6055
6394
  const fpath = `${path}.fields.${key}`;
6056
6395
  checkKey(fpath, key);
6057
- const matcher = own2(fieldsRec, key);
6396
+ const matcher = own3(fieldsRec, key);
6058
6397
  if (isRecord(matcher)) this.validateFieldMatcher(fpath, matcher);
6059
6398
  }
6060
6399
  for (const key of exactKeys) checkKey(`${path}.exact.${key}`, key);
6061
- const mustNot = this.stringList(own2(e, "must_not"), `${path}.must_not`);
6062
- const mustNotContain = this.stringList(own2(e, "must_not_contain"), `${path}.must_not_contain`);
6400
+ const mustNot = this.stringList(own3(e, "must_not"), `${path}.must_not`);
6401
+ const mustNotContain = this.stringList(own3(e, "must_not_contain"), `${path}.must_not_contain`);
6063
6402
  const mustNotMsg = `must_not takes up to ${L.maxMustNot} statements of at most ${L.maxMustNotRunes} characters each, none empty`;
6064
6403
  if (mustNot.length > L.maxMustNot) {
6065
6404
  this.err("example_must_not_invalid", `${path}.must_not`, mustNotMsg);
@@ -6080,9 +6419,9 @@ var Walker = class _Walker {
6080
6419
  }
6081
6420
  });
6082
6421
  for (const key of fieldKeys) {
6083
- const matcher = own2(fieldsRec, key);
6422
+ const matcher = own3(fieldsRec, key);
6084
6423
  if (!isRecord(matcher)) continue;
6085
- const eq = own2(matcher, "equals");
6424
+ const eq = own3(matcher, "equals");
6086
6425
  if (typeof eq !== "string" || eq === "") continue;
6087
6426
  for (const banned of mustNotContain) {
6088
6427
  if (banned !== "" && equalFold(banned, eq)) {
@@ -6142,7 +6481,7 @@ var Walker = class _Walker {
6142
6481
  }
6143
6482
  return;
6144
6483
  }
6145
- const refRec = own2(r, "ref");
6484
+ const refRec = own3(r, "ref");
6146
6485
  if (!isRecord(refRec)) return;
6147
6486
  const ref = this.fileRefOf(refRec, `${path}.ref`);
6148
6487
  this.validateFileRef(`${path}.ref`, ref);
@@ -6155,22 +6494,22 @@ var Walker = class _Walker {
6155
6494
  }
6156
6495
  }
6157
6496
  expectationIsBinaryReferenceOnly(e, path) {
6158
- const reference = own2(e, "reference");
6159
- const refRec = isRecord(reference) ? own2(reference, "ref") : void 0;
6497
+ const reference = own3(e, "reference");
6498
+ const refRec = isRecord(reference) ? own3(reference, "ref") : void 0;
6160
6499
  if (!isRecord(refRec)) return false;
6161
6500
  const mediaType = this.s(refRec, "media_type", `${path}.reference.ref`);
6162
6501
  if (mediaType === "" || isTextualMediaType(mediaType)) return false;
6163
6502
  const status = this.s(e, "status", path);
6164
- const fields = own2(e, "fields");
6165
- const exact = own2(e, "exact");
6166
- return this.s(e, "rubric", path) === "" && !(isRecord(fields) && Object.keys(fields).length > 0) && !(isRecord(exact) && Object.keys(exact).length > 0) && this.stringList(own2(e, "must_not"), `${path}.must_not`).length === 0 && this.stringList(own2(e, "must_not_contain"), `${path}.must_not_contain`).length === 0 && (status === "" || status === STATUS_COMPLETED);
6503
+ const fields = own3(e, "fields");
6504
+ const exact = own3(e, "exact");
6505
+ return this.s(e, "rubric", path) === "" && !(isRecord(fields) && Object.keys(fields).length > 0) && !(isRecord(exact) && Object.keys(exact).length > 0) && this.stringList(own3(e, "must_not"), `${path}.must_not`).length === 0 && this.stringList(own3(e, "must_not_contain"), `${path}.must_not_contain`).length === 0 && (status === "" || status === STATUS_COMPLETED);
6167
6506
  }
6168
6507
  validateFieldMatcher(path, m) {
6169
6508
  const L = EXAMPLES.limits;
6170
6509
  const matches = this.s(m, "matches", path);
6171
- const oneOf = own2(m, "one_of");
6172
- const approx = numberOf(own2(m, "approx"));
6173
- const tolerance = numberOf(own2(m, "tolerance"));
6510
+ const oneOf = own3(m, "one_of");
6511
+ const approx = numberOf(own3(m, "approx"));
6512
+ const tolerance = numberOf(own3(m, "tolerance"));
6174
6513
  let operators = 0;
6175
6514
  if (has(m, "equals")) operators++;
6176
6515
  if (this.s(m, "contains", path) !== "") operators++;
@@ -6178,7 +6517,7 @@ var Walker = class _Walker {
6178
6517
  if (matches !== "") operators++;
6179
6518
  if (Array.isArray(oneOf) && oneOf.length > 0) operators++;
6180
6519
  if (approx !== void 0) operators++;
6181
- if (typeof own2(m, "present") === "boolean") operators++;
6520
+ if (typeof own3(m, "present") === "boolean") operators++;
6182
6521
  if (operators !== 1) {
6183
6522
  this.err(
6184
6523
  "example_field_matcher_invalid",
@@ -6205,12 +6544,12 @@ var Walker = class _Walker {
6205
6544
  // -- checkpoints ------------------------------------------------------
6206
6545
  validateCheckpoints(path, label, cps) {
6207
6546
  if (!isRecord(cps) || Object.keys(cps).length === 0) return;
6208
- const stepsRaw = own2(this.flow, "steps");
6547
+ const stepsRaw = own3(this.flow, "steps");
6209
6548
  const steps = isRecord(stepsRaw) ? stepsRaw : {};
6210
6549
  const stepIds = sortedKeys(steps);
6211
6550
  for (const id of sortedKeys(cps)) {
6212
6551
  const cpath = `${path}.checkpoints.${id}`;
6213
- const step = own2(steps, id);
6552
+ const step = own3(steps, id);
6214
6553
  if (!isRecord(step)) {
6215
6554
  this.err(
6216
6555
  "example_checkpoint_step_unknown",
@@ -6220,7 +6559,7 @@ var Walker = class _Walker {
6220
6559
  );
6221
6560
  continue;
6222
6561
  }
6223
- const next = own2(step, "next");
6562
+ const next = own3(step, "next");
6224
6563
  if (has(step, "for_each") || has(step, "loop") || isRecord(next) && has(next, "parallel")) {
6225
6564
  this.err(
6226
6565
  "example_checkpoint_step_composite",
@@ -6229,7 +6568,7 @@ var Walker = class _Walker {
6229
6568
  );
6230
6569
  continue;
6231
6570
  }
6232
- const cp = own2(cps, id);
6571
+ const cp = own3(cps, id);
6233
6572
  if (cp === null || cp === void 0) {
6234
6573
  this.validateExpectation(cpath, label, {}, "checkpoint", id);
6235
6574
  } else if (isRecord(cp)) {
@@ -6240,7 +6579,7 @@ var Walker = class _Walker {
6240
6579
  // -- variants ---------------------------------------------------------
6241
6580
  validateVariants(i, path, label, ex, hasInput, baseInput) {
6242
6581
  const L = EXAMPLES.limits;
6243
- const variants = own2(ex, "variants");
6582
+ const variants = own3(ex, "variants");
6244
6583
  if (!Array.isArray(variants) || variants.length === 0) return;
6245
6584
  if (variants.length > L.maxVariants) {
6246
6585
  this.err(
@@ -6303,8 +6642,8 @@ var Walker = class _Walker {
6303
6642
  `example ${q(both)} notes are ${provN} characters; the limit is ${L.maxProvenanceRunes}`
6304
6643
  );
6305
6644
  }
6306
- this.validateWeight(`${vpath}.weight`, both, numberOf(own2(v, "weight")));
6307
- const patch = own2(v, "input_patch");
6645
+ this.validateWeight(`${vpath}.weight`, both, numberOf(own3(v, "weight")));
6646
+ const patch = own3(v, "input_patch");
6308
6647
  const patchRec = isRecord(patch) ? patch : null;
6309
6648
  const hasPatch = patchRec !== null && Object.keys(patchRec).length > 0;
6310
6649
  const hasRef = has(v, "input_ref");
@@ -6321,7 +6660,7 @@ var Walker = class _Walker {
6321
6660
  `variant ${q(vlabel)} of example ${q(label)} changes neither the input nor the expectation`
6322
6661
  );
6323
6662
  }
6324
- const refRec = own2(v, "input_ref");
6663
+ const refRec = own3(v, "input_ref");
6325
6664
  if (isRecord(refRec)) {
6326
6665
  this.validateFileRef(`${vpath}.input_ref`, this.fileRefOf(refRec, `${vpath}.input_ref`));
6327
6666
  }
@@ -6336,7 +6675,7 @@ var Walker = class _Walker {
6336
6675
  this.checkVariantPatch(vpath, label, vlabel, baseInput, patchRec);
6337
6676
  }
6338
6677
  }
6339
- const expected = own2(v, "expected");
6678
+ const expected = own3(v, "expected");
6340
6679
  if (isRecord(expected)) {
6341
6680
  this.validateExpectation(`${vpath}.expected`, both, expected, "final", "");
6342
6681
  }
@@ -6347,11 +6686,11 @@ var Walker = class _Walker {
6347
6686
  * itself supplies. A null patch value deleting a secret is fine.
6348
6687
  */
6349
6688
  checkVariantPatch(vpath, label, vlabel, base, patch) {
6350
- const schema = own2(this.flow, "input_schema");
6689
+ const schema = own3(this.flow, "input_schema");
6351
6690
  if (isRecord(schema)) {
6352
6691
  for (const f of this.schemaFields(schema)) {
6353
6692
  if (f.type !== TYPE_SECRET) continue;
6354
- const val = own2(patch, f.name);
6693
+ const val = own3(patch, f.name);
6355
6694
  if (val !== void 0 && val !== null) {
6356
6695
  this.err(
6357
6696
  "example_secret_value",
@@ -6391,18 +6730,18 @@ var Walker = class _Walker {
6391
6730
  emit(`${path}.title`, this.s(ex, "title", path));
6392
6731
  emit(`${path}.guidance`, this.s(ex, "guidance", path));
6393
6732
  emit(`${path}.notes`, this.s(ex, "notes", path));
6394
- const input = own2(ex, "input");
6733
+ const input = own3(ex, "input");
6395
6734
  if (isRecord(input)) scanLeaves(`${path}.input`, input, 0, emit);
6396
- const expected = own2(ex, "expected");
6735
+ const expected = own3(ex, "expected");
6397
6736
  if (isRecord(expected)) this.scanExpectationLeaves(`${path}.expected`, expected, emit);
6398
- const cps = own2(ex, "checkpoints");
6737
+ const cps = own3(ex, "checkpoints");
6399
6738
  if (isRecord(cps)) {
6400
6739
  for (const id of sortedKeys(cps)) {
6401
- const cp = own2(cps, id);
6740
+ const cp = own3(cps, id);
6402
6741
  if (isRecord(cp)) this.scanExpectationLeaves(`${path}.checkpoints.${id}`, cp, emit);
6403
6742
  }
6404
6743
  }
6405
- const variants = own2(ex, "variants");
6744
+ const variants = own3(ex, "variants");
6406
6745
  if (Array.isArray(variants)) {
6407
6746
  variants.forEach((v, j) => {
6408
6747
  if (!isRecord(v)) return;
@@ -6410,34 +6749,34 @@ var Walker = class _Walker {
6410
6749
  emit(`${vpath}.title`, this.s(v, "title", vpath));
6411
6750
  emit(`${vpath}.guidance`, this.s(v, "guidance", vpath));
6412
6751
  emit(`${vpath}.provenance`, this.s(v, "provenance", vpath));
6413
- scanLeaves(`${vpath}.input_patch`, own2(v, "input_patch"), 0, emit);
6414
- const vexp = own2(v, "expected");
6752
+ scanLeaves(`${vpath}.input_patch`, own3(v, "input_patch"), 0, emit);
6753
+ const vexp = own3(v, "expected");
6415
6754
  if (isRecord(vexp)) this.scanExpectationLeaves(`${vpath}.expected`, vexp, emit);
6416
6755
  });
6417
6756
  }
6418
6757
  }
6419
6758
  scanExpectationLeaves(path, e, emit) {
6420
6759
  emit(`${path}.rubric`, this.s(e, "rubric", path));
6421
- const reference = own2(e, "reference");
6760
+ const reference = own3(e, "reference");
6422
6761
  if (isRecord(reference)) {
6423
6762
  emit(`${path}.reference.text`, this.s(reference, "text", `${path}.reference`));
6424
6763
  }
6425
- this.stringList(own2(e, "must_not"), `${path}.must_not`).forEach(
6764
+ this.stringList(own3(e, "must_not"), `${path}.must_not`).forEach(
6426
6765
  (s, j) => emit(`${path}.must_not[${j}]`, s)
6427
6766
  );
6428
- this.stringList(own2(e, "must_not_contain"), `${path}.must_not_contain`).forEach(
6767
+ this.stringList(own3(e, "must_not_contain"), `${path}.must_not_contain`).forEach(
6429
6768
  (s, j) => emit(`${path}.must_not_contain[${j}]`, s)
6430
6769
  );
6431
- const fields = own2(e, "fields");
6770
+ const fields = own3(e, "fields");
6432
6771
  if (isRecord(fields)) {
6433
6772
  for (const key of sortedKeys(fields)) {
6434
- const m = own2(fields, key);
6773
+ const m = own3(fields, key);
6435
6774
  if (!isRecord(m)) continue;
6436
6775
  const fpath = `${path}.fields.${key}`;
6437
- scanLeaves(`${fpath}.equals`, own2(m, "equals"), 0, emit);
6776
+ scanLeaves(`${fpath}.equals`, own3(m, "equals"), 0, emit);
6438
6777
  emit(`${fpath}.contains`, this.s(m, "contains", fpath));
6439
6778
  emit(`${fpath}.not_contains`, this.s(m, "not_contains", fpath));
6440
- const oneOf = own2(m, "one_of");
6779
+ const oneOf = own3(m, "one_of");
6441
6780
  if (Array.isArray(oneOf)) {
6442
6781
  oneOf.forEach(
6443
6782
  (one, j) => scanLeaves(`${fpath}.one_of[${j}]`, one, 0, emit)
@@ -6445,7 +6784,7 @@ var Walker = class _Walker {
6445
6784
  }
6446
6785
  }
6447
6786
  }
6448
- scanLeaves(`${path}.exact`, own2(e, "exact"), 0, emit);
6787
+ scanLeaves(`${path}.exact`, own3(e, "exact"), 0, emit);
6449
6788
  }
6450
6789
  };
6451
6790
  function scoreInRange(v) {
@@ -6561,7 +6900,7 @@ function inputValueFailures(f, raw) {
6561
6900
  case TYPE_FILE2: {
6562
6901
  if (typeof raw === "string") return raw === "" ? [mismatch(f, TYPE_FILE2)] : [];
6563
6902
  if (isRecord(raw)) {
6564
- const ref = own2(raw, FILE_REF_KEY);
6903
+ const ref = own3(raw, FILE_REF_KEY);
6565
6904
  return typeof ref === "string" && ref !== "" ? [] : [mismatch(f, TYPE_FILE2)];
6566
6905
  }
6567
6906
  return [mismatch(f, TYPE_FILE2)];
@@ -6641,6 +6980,7 @@ function validateParsed(flow, opts, sources) {
6641
6980
  validateCredentialEndpointPairing(f, issues);
6642
6981
  validateExamples(f, issues);
6643
6982
  validateOrchestratorExons(f, issues);
6983
+ validateResidencyEnforcement(f, issues);
6644
6984
  validateUnknownKeys(f, issues);
6645
6985
  const templateStats = validateTemplates(f, issues, opts);
6646
6986
  const totalSteps = f.steps && typeof f.steps === "object" && !Array.isArray(f.steps) ? Object.keys(f.steps).length : 0;