@vaudience/aigentflow-flow-validator 0.18.0 → 0.20.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/index.cjs CHANGED
@@ -432,7 +432,7 @@ function validateBasicStructure(flow, issues) {
432
432
 
433
433
  // src/spec/aigentflow-spec.json
434
434
  var aigentflow_spec_default = {
435
- specVersion: "2.819.0",
435
+ specVersion: "2.821.0",
436
436
  inputSchemaVersion: 1,
437
437
  executorSchemes: [
438
438
  "a2a",
@@ -1257,6 +1257,34 @@ var aigentflow_spec_default = {
1257
1257
  }
1258
1258
  }
1259
1259
  },
1260
+ complianceResidency: {
1261
+ code: "compliance_residency_unenforced",
1262
+ euResidencyCodes: ["EU", "DE", "FR", "IE", "NL", "IT", "ES"],
1263
+ regionLaneProviders: [
1264
+ "bedrock",
1265
+ "google",
1266
+ "azure",
1267
+ "openai",
1268
+ "assemblyai",
1269
+ "speechmatics",
1270
+ "deepgram",
1271
+ "mistral"
1272
+ ],
1273
+ aiProtocol: "ai",
1274
+ protocolSeparator: "://",
1275
+ regionParam: "region",
1276
+ enforceRegionParam: "enforce_region",
1277
+ baseUrlParamSuffix: "_base_url",
1278
+ enforceRegionTrueStrings: ["true", "1", "yes"],
1279
+ stepFieldFormat: "steps.%s.executor",
1280
+ loopStepFieldFormat: "steps.%s.loop.steps.%s.executor",
1281
+ orchestratorField: "orchestrator.exons",
1282
+ siteStepFormat: "step %q",
1283
+ siteLoopStepFormat: "loop sub-step %q of step %q",
1284
+ siteOrchestrator: "the orchestrator",
1285
+ 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",
1286
+ 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."
1287
+ },
1260
1288
  examples: {
1261
1289
  limits: {
1262
1290
  maxPerFlow: 50,
@@ -1644,6 +1672,7 @@ var aigentflow_spec_default = {
1644
1672
  deny_tools: "list<scalar>",
1645
1673
  discoverable_tools: "list<scalar>",
1646
1674
  enable_signals: "scalar",
1675
+ enforce_region: "scalar",
1647
1676
  engram_scope: "scalar",
1648
1677
  exons: "scalar",
1649
1678
  human_question_timeout: "scalar",
@@ -1652,6 +1681,7 @@ var aigentflow_spec_default = {
1652
1681
  max_tool_turns: "scalar",
1653
1682
  max_turns: "scalar",
1654
1683
  mode: "scalar",
1684
+ region: "scalar",
1655
1685
  require_approval_for: "list<scalar>",
1656
1686
  timeout_seconds: "scalar",
1657
1687
  tool_discovery: "scalar",
@@ -1850,6 +1880,25 @@ var CREDENTIAL_ENDPOINT_PAIRING = {
1850
1880
  familyKeySeparator: aigentflow_spec_default.credentialEndpointPairing.familyKeySeparator,
1851
1881
  families: aigentflow_spec_default.credentialEndpointPairing.families
1852
1882
  };
1883
+ var COMPLIANCE_RESIDENCY = {
1884
+ code: aigentflow_spec_default.complianceResidency.code,
1885
+ euResidencyCodes: aigentflow_spec_default.complianceResidency.euResidencyCodes,
1886
+ regionLaneProviders: aigentflow_spec_default.complianceResidency.regionLaneProviders,
1887
+ aiProtocol: aigentflow_spec_default.complianceResidency.aiProtocol,
1888
+ protocolSeparator: aigentflow_spec_default.complianceResidency.protocolSeparator,
1889
+ regionParam: aigentflow_spec_default.complianceResidency.regionParam,
1890
+ enforceRegionParam: aigentflow_spec_default.complianceResidency.enforceRegionParam,
1891
+ baseUrlParamSuffix: aigentflow_spec_default.complianceResidency.baseUrlParamSuffix,
1892
+ enforceRegionTrueStrings: aigentflow_spec_default.complianceResidency.enforceRegionTrueStrings,
1893
+ stepFieldFormat: aigentflow_spec_default.complianceResidency.stepFieldFormat,
1894
+ loopStepFieldFormat: aigentflow_spec_default.complianceResidency.loopStepFieldFormat,
1895
+ orchestratorField: aigentflow_spec_default.complianceResidency.orchestratorField,
1896
+ siteStepFormat: aigentflow_spec_default.complianceResidency.siteStepFormat,
1897
+ siteLoopStepFormat: aigentflow_spec_default.complianceResidency.siteLoopStepFormat,
1898
+ siteOrchestrator: aigentflow_spec_default.complianceResidency.siteOrchestrator,
1899
+ messageFormat: aigentflow_spec_default.complianceResidency.messageFormat,
1900
+ suggestion: aigentflow_spec_default.complianceResidency.suggestion
1901
+ };
1853
1902
  var EXAMPLES = {
1854
1903
  limits: aigentflow_spec_default.examples.limits,
1855
1904
  idPattern: new RegExp(aigentflow_spec_default.examples.idPattern),
@@ -3064,6 +3113,17 @@ function validateOrchestratorCampaign(flow, issues, opts) {
3064
3113
  code: "orchestrator_owner_needs_yield"
3065
3114
  });
3066
3115
  }
3116
+ if (orch.enforce_region === true) {
3117
+ const region = issues.stringOf(orch, "region", "orchestrator");
3118
+ if (region === null || region.trim() === "") {
3119
+ issues.error({
3120
+ field: "orchestrator.enforce_region",
3121
+ message: "orchestrator: enforce_region requires region (name the region the model must run in, e.g. region: eu)",
3122
+ code: "orchestrator_enforce_region_needs_region",
3123
+ suggestion: "Add `region: eu` (or the region the model must run in), or drop enforce_region"
3124
+ });
3125
+ }
3126
+ }
3067
3127
  if (Array.isArray(orch.triggers)) {
3068
3128
  orch.triggers.forEach((rawTrigger, i) => {
3069
3129
  if (!isRecord(rawTrigger)) return;
@@ -5191,6 +5251,141 @@ function warnOrchestratorToolWithheld(flow, orch, report, issues) {
5191
5251
  }
5192
5252
  }
5193
5253
 
5254
+ // src/validators/complianceResidency.ts
5255
+ function own2(m, key) {
5256
+ if (!isRecord(m) || !Object.prototype.hasOwnProperty.call(m, key)) return void 0;
5257
+ return m[key];
5258
+ }
5259
+ function sprintf(format, ...args) {
5260
+ let i = 0;
5261
+ return format.replace(/%[sqv]/g, (verb) => {
5262
+ const arg = args[i++] ?? "";
5263
+ return verb === "%q" ? JSON.stringify(arg) : arg;
5264
+ });
5265
+ }
5266
+ function literalOrEmpty(s) {
5267
+ const t = goTrimSpace2(s);
5268
+ return t.includes(TEMPLATE_ACTION_OPEN) ? "" : t;
5269
+ }
5270
+ function euOnlyResidency(flow, issues) {
5271
+ const raw = own2(own2(flow, "compliance"), "residency");
5272
+ if (!isArray(raw)) return null;
5273
+ const codes = [];
5274
+ for (let i = 0; i < raw.length; i++) {
5275
+ if (raw[i] === null) continue;
5276
+ const code = issues.stringAt(raw[i], `compliance.residency[${i}]`);
5277
+ if (code === null) return null;
5278
+ codes.push(code);
5279
+ }
5280
+ if (codes.length === 0) return null;
5281
+ const eu = new Set(COMPLIANCE_RESIDENCY.euResidencyCodes);
5282
+ return codes.every((c) => eu.has(goTrimSpace2(c).toUpperCase())) ? codes : null;
5283
+ }
5284
+ function aiProvider(executor) {
5285
+ const prefix = COMPLIANCE_RESIDENCY.aiProtocol + COMPLIANCE_RESIDENCY.protocolSeparator;
5286
+ if (!executor.startsWith(prefix)) return "";
5287
+ const rest = executor.slice(prefix.length);
5288
+ const slash = rest.indexOf("/");
5289
+ const provider = slash > 0 ? rest.slice(0, slash) : "";
5290
+ return provider.includes(TEMPLATE_ACTION_OPEN) ? "" : provider;
5291
+ }
5292
+ function isRegionLane(provider) {
5293
+ const literal = literalOrEmpty(provider);
5294
+ return literal !== "" && COMPLIANCE_RESIDENCY.regionLaneProviders.includes(literal.toLowerCase());
5295
+ }
5296
+ function nonBlankString(m, key) {
5297
+ const v = own2(m, key);
5298
+ return typeof v === "string" && goTrimSpace2(v) !== "";
5299
+ }
5300
+ function queryEnforcesRegion(query) {
5301
+ const v = own2(query, COMPLIANCE_RESIDENCY.enforceRegionParam);
5302
+ if (typeof v === "boolean") return v;
5303
+ return typeof v === "string" && COMPLIANCE_RESIDENCY.enforceRegionTrueStrings.includes(v);
5304
+ }
5305
+ function flowDirectsEndpoint(flow, provider, issues) {
5306
+ const key = provider.toLowerCase();
5307
+ const inst = own2(own2(flow, "executor_config"), key);
5308
+ if (!isRecord(inst)) return false;
5309
+ const baseUrl = issues.stringOf(inst, "base_url", `executor_config.${key}`);
5310
+ return baseUrl !== null && goTrimSpace2(baseUrl) !== "";
5311
+ }
5312
+ function callPinsEndpoint(flow, provider, query, issues) {
5313
+ if (nonBlankString(query, COMPLIANCE_RESIDENCY.regionParam)) return true;
5314
+ if (queryEnforcesRegion(query)) return true;
5315
+ if (nonBlankString(query, provider.toLowerCase() + COMPLIANCE_RESIDENCY.baseUrlParamSuffix)) return true;
5316
+ return flowDirectsEndpoint(flow, provider, issues);
5317
+ }
5318
+ function validateResidencyEnforcement(flow, issues) {
5319
+ const residency = euOnlyResidency(flow, issues);
5320
+ if (residency === null) return;
5321
+ const warn = (site, field, stepId, provider) => {
5322
+ issues.warn({
5323
+ field,
5324
+ ...stepId === void 0 ? {} : { stepId },
5325
+ code: COMPLIANCE_RESIDENCY.code,
5326
+ message: sprintf(COMPLIANCE_RESIDENCY.messageFormat, site, provider, `[${residency.join(" ")}]`),
5327
+ suggestion: COMPLIANCE_RESIDENCY.suggestion
5328
+ });
5329
+ };
5330
+ const steps = flow.steps;
5331
+ if (isRecord(steps)) {
5332
+ for (const stepId of Object.keys(steps).sort()) {
5333
+ const step = steps[stepId];
5334
+ if (!isRecord(step)) continue;
5335
+ const calls = [
5336
+ {
5337
+ executor: issues.stringOf(step, "executor", `steps.${stepId}`) ?? "",
5338
+ query: own2(step, "query"),
5339
+ subId: null
5340
+ }
5341
+ ];
5342
+ for (const sub of loopSubStepsOfStep(stepId, step)) {
5343
+ calls.push({
5344
+ executor: issues.stringOf(sub.raw, "executor", sub.basePath) ?? "",
5345
+ query: own2(sub.raw, "query"),
5346
+ subId: issues.stringOf(sub.raw, "id", sub.basePath) ?? ""
5347
+ });
5348
+ }
5349
+ for (const call of calls) {
5350
+ const provider = aiProvider(call.executor);
5351
+ if (!isRegionLane(provider)) continue;
5352
+ if (callPinsEndpoint(flow, provider, call.query, issues)) continue;
5353
+ if (call.subId === null) {
5354
+ warn(
5355
+ sprintf(COMPLIANCE_RESIDENCY.siteStepFormat, stepId),
5356
+ sprintf(COMPLIANCE_RESIDENCY.stepFieldFormat, stepId),
5357
+ stepId,
5358
+ provider
5359
+ );
5360
+ } else {
5361
+ warn(
5362
+ sprintf(COMPLIANCE_RESIDENCY.siteLoopStepFormat, call.subId, stepId),
5363
+ sprintf(COMPLIANCE_RESIDENCY.loopStepFieldFormat, stepId, call.subId),
5364
+ stepId,
5365
+ provider
5366
+ );
5367
+ }
5368
+ }
5369
+ }
5370
+ }
5371
+ warnOrchestrator(flow, issues, warn);
5372
+ }
5373
+ function warnOrchestrator(flow, issues, warn) {
5374
+ const orch = flow.orchestrator;
5375
+ if (!isRecord(orch)) return;
5376
+ const source = issues.stringOf(orch, "exons", "orchestrator");
5377
+ if (source === null || source === "") return;
5378
+ const report = inspectExonsFrontmatter(source);
5379
+ if (report.parseError !== null || !report.specRead || !report.hasSpec) return;
5380
+ const provider = literalOrEmpty(report.provider);
5381
+ if (!isRegionLane(provider)) return;
5382
+ const region = issues.stringOf(orch, "region", "orchestrator");
5383
+ if (region !== null && goTrimSpace2(region) !== "") return;
5384
+ if (orch.enforce_region === true) return;
5385
+ if (flowDirectsEndpoint(flow, provider, issues)) return;
5386
+ warn(COMPLIANCE_RESIDENCY.siteOrchestrator, COMPLIANCE_RESIDENCY.orchestratorField, void 0, provider);
5387
+ }
5388
+
5194
5389
  // src/validators/examples.ts
5195
5390
  var KEY_EXAMPLES = "examples";
5196
5391
  var VISIBILITY_PUBLIC = "public";
@@ -5268,7 +5463,7 @@ function num(n) {
5268
5463
  function has(o, key) {
5269
5464
  return Object.prototype.hasOwnProperty.call(o, key) && o[key] !== null && o[key] !== void 0;
5270
5465
  }
5271
- function own2(o, key) {
5466
+ function own3(o, key) {
5272
5467
  return Object.prototype.hasOwnProperty.call(o, key) ? o[key] : void 0;
5273
5468
  }
5274
5469
  function setOwn(o, key, value) {
@@ -5320,7 +5515,7 @@ function mergePatch(target, patch, depth) {
5320
5515
  continue;
5321
5516
  }
5322
5517
  if (isRecord(pv)) {
5323
- const current = own2(target, k);
5518
+ const current = own3(target, k);
5324
5519
  const existing = isRecord(current) ? deepCopy(current, 0) : {};
5325
5520
  mergePatch(existing, pv, depth + 1);
5326
5521
  setOwn(target, k, existing);
@@ -5340,7 +5535,7 @@ function asFileRef(v) {
5340
5535
  if (keys.length === 0) return null;
5341
5536
  for (const k of keys) if (!FILE_REF_KEYS.has(k)) return null;
5342
5537
  const str = (k) => {
5343
- const x = own2(v, k);
5538
+ const x = own3(v, k);
5344
5539
  return typeof x === "string" ? x : "";
5345
5540
  };
5346
5541
  return {
@@ -5408,7 +5603,7 @@ var Walker = class _Walker {
5408
5603
  `the examples block is ${size} bytes; the limit is ${L.maxBlockBytes}. Move large inputs or target outputs to a file reference (https URL).`
5409
5604
  );
5410
5605
  }
5411
- const allHeld = examples.every((e) => isRecord(e) && own2(e, "hold_out") === true);
5606
+ const allHeld = examples.every((e) => isRecord(e) && own3(e, "hold_out") === true);
5412
5607
  if (allHeld) {
5413
5608
  this.warn(
5414
5609
  "examples_all_held_out",
@@ -5496,9 +5691,9 @@ var Walker = class _Walker {
5496
5691
  `example ${q(label)} notes are ${notesN} characters; the limit is ${L.maxNotesRunes}`
5497
5692
  );
5498
5693
  }
5499
- this.validateTags(path, label, own2(ex, "tags"));
5500
- this.validateWeight(`${path}.weight`, label, numberOf(own2(ex, "weight")));
5501
- const minScore = numberOf(own2(ex, "min_score"));
5694
+ this.validateTags(path, label, own3(ex, "tags"));
5695
+ this.validateWeight(`${path}.weight`, label, numberOf(own3(ex, "weight")));
5696
+ const minScore = numberOf(own3(ex, "min_score"));
5502
5697
  if (minScore !== void 0 && !scoreInRange(minScore)) {
5503
5698
  this.err(
5504
5699
  "example_min_score_range",
@@ -5514,7 +5709,7 @@ var Walker = class _Walker {
5514
5709
  `example ${q(label)} has side_effects ${q(sideEffects)}; use refuse or allow`
5515
5710
  );
5516
5711
  }
5517
- const holdOut = own2(ex, "hold_out") === true;
5712
+ const holdOut = own3(ex, "hold_out") === true;
5518
5713
  if (holdOut && this.isPublic()) {
5519
5714
  this.err(
5520
5715
  "example_holdout_in_public_flow",
@@ -5537,17 +5732,17 @@ var Walker = class _Walker {
5537
5732
  `example ${q(label)} has neither input nor input_ref; use input: {} for a flow that takes no input`
5538
5733
  );
5539
5734
  }
5540
- const rawInput = own2(ex, "input");
5735
+ const rawInput = own3(ex, "input");
5541
5736
  const baseInput = isRecord(rawInput) ? rawInput : null;
5542
5737
  if (baseInput !== null) {
5543
5738
  this.checkInput(`${path}.input`, label, baseInput, "example_input_invalid");
5544
5739
  }
5545
- const rawInputRef = own2(ex, "input_ref");
5740
+ const rawInputRef = own3(ex, "input_ref");
5546
5741
  if (isRecord(rawInputRef)) {
5547
5742
  this.validateFileRef(`${path}.input_ref`, this.fileRefOf(rawInputRef, `${path}.input_ref`));
5548
5743
  }
5549
5744
  let binaryOnly = false;
5550
- const expected = own2(ex, "expected");
5745
+ const expected = own3(ex, "expected");
5551
5746
  if (!has(ex, "expected")) {
5552
5747
  this.err(
5553
5748
  "example_expected_missing",
@@ -5566,7 +5761,7 @@ var Walker = class _Walker {
5566
5761
  "this example can be run but not scored"
5567
5762
  );
5568
5763
  }
5569
- this.validateCheckpoints(path, label, own2(ex, "checkpoints"));
5764
+ this.validateCheckpoints(path, label, own3(ex, "checkpoints"));
5570
5765
  this.validateVariants(i, path, label, ex, hasInput, baseInput);
5571
5766
  this.scanSecretLike(i, path, ex);
5572
5767
  }
@@ -5626,8 +5821,8 @@ var Walker = class _Walker {
5626
5821
  );
5627
5822
  return;
5628
5823
  }
5629
- const schema = own2(this.flow, "input_schema");
5630
- const query = own2(this.flow, "query");
5824
+ const schema = own3(this.flow, "input_schema");
5825
+ const query = own3(this.flow, "query");
5631
5826
  if (isRecord(schema)) {
5632
5827
  this.checkInputAgainstSchema(field, label, input, schema, code);
5633
5828
  } else if (isRecord(query) && Object.keys(query).length > 0) {
@@ -5695,29 +5890,29 @@ var Walker = class _Walker {
5695
5890
  }
5696
5891
  }
5697
5892
  schemaFields(schema) {
5698
- const raw = own2(schema, "fields");
5893
+ const raw = own3(schema, "fields");
5699
5894
  if (!Array.isArray(raw)) return [];
5700
5895
  const out = [];
5701
5896
  raw.forEach((f, i) => {
5702
5897
  if (!isRecord(f)) return;
5703
5898
  const base = `input_schema.fields[${i}]`;
5704
- const enumRaw = own2(f, "enum");
5899
+ const enumRaw = own3(f, "enum");
5705
5900
  const enumValues = [];
5706
5901
  if (Array.isArray(enumRaw)) {
5707
5902
  enumRaw.forEach((e, j) => {
5708
5903
  enumValues.push(e === null ? "" : this.issues.stringAt(e, `${base}.enum[${j}]`) ?? "");
5709
5904
  });
5710
5905
  }
5711
- const vw = own2(f, "visible_when");
5906
+ const vw = own3(f, "visible_when");
5712
5907
  out.push({
5713
5908
  name: this.s(f, "name", base),
5714
5909
  type: this.s(f, "type", base),
5715
- required: own2(f, "required") === true,
5910
+ required: own3(f, "required") === true,
5716
5911
  enumValues,
5717
5912
  visibleWhen: isRecord(vw) ? {
5718
5913
  field: this.s(vw, "field", `${base}.visible_when`),
5719
- equals: own2(vw, "equals"),
5720
- in: Array.isArray(own2(vw, "in")) ? own2(vw, "in") : []
5914
+ equals: own3(vw, "equals"),
5915
+ in: Array.isArray(own3(vw, "in")) ? own3(vw, "in") : []
5721
5916
  } : null
5722
5917
  });
5723
5918
  });
@@ -5728,7 +5923,7 @@ var Walker = class _Walker {
5728
5923
  const failures = [];
5729
5924
  for (const f of fields) {
5730
5925
  if (!isVisible(f, runInput)) continue;
5731
- const raw = own2(runInput, f.name);
5926
+ const raw = own3(runInput, f.name);
5732
5927
  if (raw === void 0 || raw === null) {
5733
5928
  if (f.required) {
5734
5929
  failures.push({
@@ -5839,7 +6034,7 @@ var Walker = class _Walker {
5839
6034
  /** The names `fields` / `exact` may use, and whether such a list is declared at all. */
5840
6035
  outputNamesFor(kind, stepId) {
5841
6036
  if (kind === "final") {
5842
- const out = own2(this.flow, "output");
6037
+ const out = own3(this.flow, "output");
5843
6038
  const names2 = [];
5844
6039
  if (Array.isArray(out)) {
5845
6040
  out.forEach((item, i) => {
@@ -5848,10 +6043,10 @@ var Walker = class _Walker {
5848
6043
  }
5849
6044
  return { names: names2, declared: names2.length > 0 };
5850
6045
  }
5851
- const steps = own2(this.flow, "steps");
5852
- const step = isRecord(steps) ? own2(steps, stepId) : void 0;
5853
- const schema = isRecord(step) ? own2(step, "output_schema") : void 0;
5854
- const fields = isRecord(schema) ? own2(schema, "fields") : void 0;
6046
+ const steps = own3(this.flow, "steps");
6047
+ const step = isRecord(steps) ? own3(steps, stepId) : void 0;
6048
+ const schema = isRecord(step) ? own3(step, "output_schema") : void 0;
6049
+ const fields = isRecord(schema) ? own3(schema, "fields") : void 0;
5855
6050
  if (!Array.isArray(fields) || fields.length === 0) return { names: [], declared: false };
5856
6051
  const names = [];
5857
6052
  fields.forEach((f, i) => {
@@ -5870,8 +6065,8 @@ var Walker = class _Walker {
5870
6065
  );
5871
6066
  }
5872
6067
  const noOutput = status === STATUS_FAILED || status === STATUS_PAUSED_FOR_HUMAN;
5873
- const fieldsRec = own2(e, "fields");
5874
- const exactRec = own2(e, "exact");
6068
+ const fieldsRec = own3(e, "fields");
6069
+ const exactRec = own3(e, "exact");
5875
6070
  const fieldKeys = isRecord(fieldsRec) ? sortedKeys(fieldsRec) : [];
5876
6071
  const exactKeys = isRecord(exactRec) ? sortedKeys(exactRec) : [];
5877
6072
  const hasFields = fieldKeys.length > 0;
@@ -5889,7 +6084,7 @@ var Walker = class _Walker {
5889
6084
  `a case that ends in ${status} has no output to match; remove fields and exact, or expect status completed`
5890
6085
  );
5891
6086
  }
5892
- const minScore = numberOf(own2(e, "min_score"));
6087
+ const minScore = numberOf(own3(e, "min_score"));
5893
6088
  if (minScore !== void 0 && !scoreInRange(minScore)) {
5894
6089
  this.err(
5895
6090
  "example_min_score_range",
@@ -5916,7 +6111,7 @@ var Walker = class _Walker {
5916
6111
  }
5917
6112
  }
5918
6113
  }
5919
- const reference = own2(e, "reference");
6114
+ const reference = own3(e, "reference");
5920
6115
  if (isRecord(reference)) this.validateReference(`${path}.reference`, reference);
5921
6116
  const { names, declared } = this.outputNamesFor(kind, stepId);
5922
6117
  const checkKey = (field, key) => {
@@ -5943,12 +6138,12 @@ var Walker = class _Walker {
5943
6138
  for (const key of fieldKeys) {
5944
6139
  const fpath = `${path}.fields.${key}`;
5945
6140
  checkKey(fpath, key);
5946
- const matcher = own2(fieldsRec, key);
6141
+ const matcher = own3(fieldsRec, key);
5947
6142
  if (isRecord(matcher)) this.validateFieldMatcher(fpath, matcher);
5948
6143
  }
5949
6144
  for (const key of exactKeys) checkKey(`${path}.exact.${key}`, key);
5950
- const mustNot = this.stringList(own2(e, "must_not"), `${path}.must_not`);
5951
- const mustNotContain = this.stringList(own2(e, "must_not_contain"), `${path}.must_not_contain`);
6145
+ const mustNot = this.stringList(own3(e, "must_not"), `${path}.must_not`);
6146
+ const mustNotContain = this.stringList(own3(e, "must_not_contain"), `${path}.must_not_contain`);
5952
6147
  const mustNotMsg = `must_not takes up to ${L.maxMustNot} statements of at most ${L.maxMustNotRunes} characters each, none empty`;
5953
6148
  if (mustNot.length > L.maxMustNot) {
5954
6149
  this.err("example_must_not_invalid", `${path}.must_not`, mustNotMsg);
@@ -5969,9 +6164,9 @@ var Walker = class _Walker {
5969
6164
  }
5970
6165
  });
5971
6166
  for (const key of fieldKeys) {
5972
- const matcher = own2(fieldsRec, key);
6167
+ const matcher = own3(fieldsRec, key);
5973
6168
  if (!isRecord(matcher)) continue;
5974
- const eq = own2(matcher, "equals");
6169
+ const eq = own3(matcher, "equals");
5975
6170
  if (typeof eq !== "string" || eq === "") continue;
5976
6171
  for (const banned of mustNotContain) {
5977
6172
  if (banned !== "" && equalFold(banned, eq)) {
@@ -6031,7 +6226,7 @@ var Walker = class _Walker {
6031
6226
  }
6032
6227
  return;
6033
6228
  }
6034
- const refRec = own2(r, "ref");
6229
+ const refRec = own3(r, "ref");
6035
6230
  if (!isRecord(refRec)) return;
6036
6231
  const ref = this.fileRefOf(refRec, `${path}.ref`);
6037
6232
  this.validateFileRef(`${path}.ref`, ref);
@@ -6044,22 +6239,22 @@ var Walker = class _Walker {
6044
6239
  }
6045
6240
  }
6046
6241
  expectationIsBinaryReferenceOnly(e, path) {
6047
- const reference = own2(e, "reference");
6048
- const refRec = isRecord(reference) ? own2(reference, "ref") : void 0;
6242
+ const reference = own3(e, "reference");
6243
+ const refRec = isRecord(reference) ? own3(reference, "ref") : void 0;
6049
6244
  if (!isRecord(refRec)) return false;
6050
6245
  const mediaType = this.s(refRec, "media_type", `${path}.reference.ref`);
6051
6246
  if (mediaType === "" || isTextualMediaType(mediaType)) return false;
6052
6247
  const status = this.s(e, "status", path);
6053
- const fields = own2(e, "fields");
6054
- const exact = own2(e, "exact");
6055
- 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);
6248
+ const fields = own3(e, "fields");
6249
+ const exact = own3(e, "exact");
6250
+ 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);
6056
6251
  }
6057
6252
  validateFieldMatcher(path, m) {
6058
6253
  const L = EXAMPLES.limits;
6059
6254
  const matches = this.s(m, "matches", path);
6060
- const oneOf = own2(m, "one_of");
6061
- const approx = numberOf(own2(m, "approx"));
6062
- const tolerance = numberOf(own2(m, "tolerance"));
6255
+ const oneOf = own3(m, "one_of");
6256
+ const approx = numberOf(own3(m, "approx"));
6257
+ const tolerance = numberOf(own3(m, "tolerance"));
6063
6258
  let operators = 0;
6064
6259
  if (has(m, "equals")) operators++;
6065
6260
  if (this.s(m, "contains", path) !== "") operators++;
@@ -6067,7 +6262,7 @@ var Walker = class _Walker {
6067
6262
  if (matches !== "") operators++;
6068
6263
  if (Array.isArray(oneOf) && oneOf.length > 0) operators++;
6069
6264
  if (approx !== void 0) operators++;
6070
- if (typeof own2(m, "present") === "boolean") operators++;
6265
+ if (typeof own3(m, "present") === "boolean") operators++;
6071
6266
  if (operators !== 1) {
6072
6267
  this.err(
6073
6268
  "example_field_matcher_invalid",
@@ -6094,12 +6289,12 @@ var Walker = class _Walker {
6094
6289
  // -- checkpoints ------------------------------------------------------
6095
6290
  validateCheckpoints(path, label, cps) {
6096
6291
  if (!isRecord(cps) || Object.keys(cps).length === 0) return;
6097
- const stepsRaw = own2(this.flow, "steps");
6292
+ const stepsRaw = own3(this.flow, "steps");
6098
6293
  const steps = isRecord(stepsRaw) ? stepsRaw : {};
6099
6294
  const stepIds = sortedKeys(steps);
6100
6295
  for (const id of sortedKeys(cps)) {
6101
6296
  const cpath = `${path}.checkpoints.${id}`;
6102
- const step = own2(steps, id);
6297
+ const step = own3(steps, id);
6103
6298
  if (!isRecord(step)) {
6104
6299
  this.err(
6105
6300
  "example_checkpoint_step_unknown",
@@ -6109,7 +6304,7 @@ var Walker = class _Walker {
6109
6304
  );
6110
6305
  continue;
6111
6306
  }
6112
- const next = own2(step, "next");
6307
+ const next = own3(step, "next");
6113
6308
  if (has(step, "for_each") || has(step, "loop") || isRecord(next) && has(next, "parallel")) {
6114
6309
  this.err(
6115
6310
  "example_checkpoint_step_composite",
@@ -6118,7 +6313,7 @@ var Walker = class _Walker {
6118
6313
  );
6119
6314
  continue;
6120
6315
  }
6121
- const cp = own2(cps, id);
6316
+ const cp = own3(cps, id);
6122
6317
  if (cp === null || cp === void 0) {
6123
6318
  this.validateExpectation(cpath, label, {}, "checkpoint", id);
6124
6319
  } else if (isRecord(cp)) {
@@ -6129,7 +6324,7 @@ var Walker = class _Walker {
6129
6324
  // -- variants ---------------------------------------------------------
6130
6325
  validateVariants(i, path, label, ex, hasInput, baseInput) {
6131
6326
  const L = EXAMPLES.limits;
6132
- const variants = own2(ex, "variants");
6327
+ const variants = own3(ex, "variants");
6133
6328
  if (!Array.isArray(variants) || variants.length === 0) return;
6134
6329
  if (variants.length > L.maxVariants) {
6135
6330
  this.err(
@@ -6192,8 +6387,8 @@ var Walker = class _Walker {
6192
6387
  `example ${q(both)} notes are ${provN} characters; the limit is ${L.maxProvenanceRunes}`
6193
6388
  );
6194
6389
  }
6195
- this.validateWeight(`${vpath}.weight`, both, numberOf(own2(v, "weight")));
6196
- const patch = own2(v, "input_patch");
6390
+ this.validateWeight(`${vpath}.weight`, both, numberOf(own3(v, "weight")));
6391
+ const patch = own3(v, "input_patch");
6197
6392
  const patchRec = isRecord(patch) ? patch : null;
6198
6393
  const hasPatch = patchRec !== null && Object.keys(patchRec).length > 0;
6199
6394
  const hasRef = has(v, "input_ref");
@@ -6210,7 +6405,7 @@ var Walker = class _Walker {
6210
6405
  `variant ${q(vlabel)} of example ${q(label)} changes neither the input nor the expectation`
6211
6406
  );
6212
6407
  }
6213
- const refRec = own2(v, "input_ref");
6408
+ const refRec = own3(v, "input_ref");
6214
6409
  if (isRecord(refRec)) {
6215
6410
  this.validateFileRef(`${vpath}.input_ref`, this.fileRefOf(refRec, `${vpath}.input_ref`));
6216
6411
  }
@@ -6225,7 +6420,7 @@ var Walker = class _Walker {
6225
6420
  this.checkVariantPatch(vpath, label, vlabel, baseInput, patchRec);
6226
6421
  }
6227
6422
  }
6228
- const expected = own2(v, "expected");
6423
+ const expected = own3(v, "expected");
6229
6424
  if (isRecord(expected)) {
6230
6425
  this.validateExpectation(`${vpath}.expected`, both, expected, "final", "");
6231
6426
  }
@@ -6236,11 +6431,11 @@ var Walker = class _Walker {
6236
6431
  * itself supplies. A null patch value deleting a secret is fine.
6237
6432
  */
6238
6433
  checkVariantPatch(vpath, label, vlabel, base, patch) {
6239
- const schema = own2(this.flow, "input_schema");
6434
+ const schema = own3(this.flow, "input_schema");
6240
6435
  if (isRecord(schema)) {
6241
6436
  for (const f of this.schemaFields(schema)) {
6242
6437
  if (f.type !== TYPE_SECRET) continue;
6243
- const val = own2(patch, f.name);
6438
+ const val = own3(patch, f.name);
6244
6439
  if (val !== void 0 && val !== null) {
6245
6440
  this.err(
6246
6441
  "example_secret_value",
@@ -6280,18 +6475,18 @@ var Walker = class _Walker {
6280
6475
  emit(`${path}.title`, this.s(ex, "title", path));
6281
6476
  emit(`${path}.guidance`, this.s(ex, "guidance", path));
6282
6477
  emit(`${path}.notes`, this.s(ex, "notes", path));
6283
- const input = own2(ex, "input");
6478
+ const input = own3(ex, "input");
6284
6479
  if (isRecord(input)) scanLeaves(`${path}.input`, input, 0, emit);
6285
- const expected = own2(ex, "expected");
6480
+ const expected = own3(ex, "expected");
6286
6481
  if (isRecord(expected)) this.scanExpectationLeaves(`${path}.expected`, expected, emit);
6287
- const cps = own2(ex, "checkpoints");
6482
+ const cps = own3(ex, "checkpoints");
6288
6483
  if (isRecord(cps)) {
6289
6484
  for (const id of sortedKeys(cps)) {
6290
- const cp = own2(cps, id);
6485
+ const cp = own3(cps, id);
6291
6486
  if (isRecord(cp)) this.scanExpectationLeaves(`${path}.checkpoints.${id}`, cp, emit);
6292
6487
  }
6293
6488
  }
6294
- const variants = own2(ex, "variants");
6489
+ const variants = own3(ex, "variants");
6295
6490
  if (Array.isArray(variants)) {
6296
6491
  variants.forEach((v, j) => {
6297
6492
  if (!isRecord(v)) return;
@@ -6299,34 +6494,34 @@ var Walker = class _Walker {
6299
6494
  emit(`${vpath}.title`, this.s(v, "title", vpath));
6300
6495
  emit(`${vpath}.guidance`, this.s(v, "guidance", vpath));
6301
6496
  emit(`${vpath}.provenance`, this.s(v, "provenance", vpath));
6302
- scanLeaves(`${vpath}.input_patch`, own2(v, "input_patch"), 0, emit);
6303
- const vexp = own2(v, "expected");
6497
+ scanLeaves(`${vpath}.input_patch`, own3(v, "input_patch"), 0, emit);
6498
+ const vexp = own3(v, "expected");
6304
6499
  if (isRecord(vexp)) this.scanExpectationLeaves(`${vpath}.expected`, vexp, emit);
6305
6500
  });
6306
6501
  }
6307
6502
  }
6308
6503
  scanExpectationLeaves(path, e, emit) {
6309
6504
  emit(`${path}.rubric`, this.s(e, "rubric", path));
6310
- const reference = own2(e, "reference");
6505
+ const reference = own3(e, "reference");
6311
6506
  if (isRecord(reference)) {
6312
6507
  emit(`${path}.reference.text`, this.s(reference, "text", `${path}.reference`));
6313
6508
  }
6314
- this.stringList(own2(e, "must_not"), `${path}.must_not`).forEach(
6509
+ this.stringList(own3(e, "must_not"), `${path}.must_not`).forEach(
6315
6510
  (s, j) => emit(`${path}.must_not[${j}]`, s)
6316
6511
  );
6317
- this.stringList(own2(e, "must_not_contain"), `${path}.must_not_contain`).forEach(
6512
+ this.stringList(own3(e, "must_not_contain"), `${path}.must_not_contain`).forEach(
6318
6513
  (s, j) => emit(`${path}.must_not_contain[${j}]`, s)
6319
6514
  );
6320
- const fields = own2(e, "fields");
6515
+ const fields = own3(e, "fields");
6321
6516
  if (isRecord(fields)) {
6322
6517
  for (const key of sortedKeys(fields)) {
6323
- const m = own2(fields, key);
6518
+ const m = own3(fields, key);
6324
6519
  if (!isRecord(m)) continue;
6325
6520
  const fpath = `${path}.fields.${key}`;
6326
- scanLeaves(`${fpath}.equals`, own2(m, "equals"), 0, emit);
6521
+ scanLeaves(`${fpath}.equals`, own3(m, "equals"), 0, emit);
6327
6522
  emit(`${fpath}.contains`, this.s(m, "contains", fpath));
6328
6523
  emit(`${fpath}.not_contains`, this.s(m, "not_contains", fpath));
6329
- const oneOf = own2(m, "one_of");
6524
+ const oneOf = own3(m, "one_of");
6330
6525
  if (Array.isArray(oneOf)) {
6331
6526
  oneOf.forEach(
6332
6527
  (one, j) => scanLeaves(`${fpath}.one_of[${j}]`, one, 0, emit)
@@ -6334,7 +6529,7 @@ var Walker = class _Walker {
6334
6529
  }
6335
6530
  }
6336
6531
  }
6337
- scanLeaves(`${path}.exact`, own2(e, "exact"), 0, emit);
6532
+ scanLeaves(`${path}.exact`, own3(e, "exact"), 0, emit);
6338
6533
  }
6339
6534
  };
6340
6535
  function scoreInRange(v) {
@@ -6450,7 +6645,7 @@ function inputValueFailures(f, raw) {
6450
6645
  case TYPE_FILE2: {
6451
6646
  if (typeof raw === "string") return raw === "" ? [mismatch(f, TYPE_FILE2)] : [];
6452
6647
  if (isRecord(raw)) {
6453
- const ref = own2(raw, FILE_REF_KEY);
6648
+ const ref = own3(raw, FILE_REF_KEY);
6454
6649
  return typeof ref === "string" && ref !== "" ? [] : [mismatch(f, TYPE_FILE2)];
6455
6650
  }
6456
6651
  return [mismatch(f, TYPE_FILE2)];
@@ -6533,6 +6728,7 @@ function validateParsed(flow, opts, sources) {
6533
6728
  validateCredentialEndpointPairing(f, issues);
6534
6729
  validateExamples(f, issues);
6535
6730
  validateOrchestratorExons(f, issues);
6731
+ validateResidencyEnforcement(f, issues);
6536
6732
  validateUnknownKeys(f, issues);
6537
6733
  const templateStats = validateTemplates(f, issues, opts);
6538
6734
  const totalSteps = f.steps && typeof f.steps === "object" && !Array.isArray(f.steps) ? Object.keys(f.steps).length : 0;