@vaudience/aigentflow-flow-validator 0.19.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/cli.js CHANGED
@@ -436,7 +436,7 @@ function validateBasicStructure(flow, issues) {
436
436
  // src/spec/aigentflow-spec.json
437
437
  var aigentflow_spec_default = {
438
438
  $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",
439
+ specVersion: "2.821.0",
440
440
  inputSchemaVersion: 1,
441
441
  executorSchemes: [
442
442
  "a2a",
@@ -1275,6 +1275,35 @@ var aigentflow_spec_default = {
1275
1275
  }
1276
1276
  }
1277
1277
  },
1278
+ complianceResidency: {
1279
+ $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).",
1280
+ code: "compliance_residency_unenforced",
1281
+ euResidencyCodes: ["EU", "DE", "FR", "IE", "NL", "IT", "ES"],
1282
+ regionLaneProviders: [
1283
+ "bedrock",
1284
+ "google",
1285
+ "azure",
1286
+ "openai",
1287
+ "assemblyai",
1288
+ "speechmatics",
1289
+ "deepgram",
1290
+ "mistral"
1291
+ ],
1292
+ aiProtocol: "ai",
1293
+ protocolSeparator: "://",
1294
+ regionParam: "region",
1295
+ enforceRegionParam: "enforce_region",
1296
+ baseUrlParamSuffix: "_base_url",
1297
+ enforceRegionTrueStrings: ["true", "1", "yes"],
1298
+ stepFieldFormat: "steps.%s.executor",
1299
+ loopStepFieldFormat: "steps.%s.loop.steps.%s.executor",
1300
+ orchestratorField: "orchestrator.exons",
1301
+ siteStepFormat: "step %q",
1302
+ siteLoopStepFormat: "loop sub-step %q of step %q",
1303
+ siteOrchestrator: "the orchestrator",
1304
+ 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",
1305
+ 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."
1306
+ },
1278
1307
  examples: {
1279
1308
  $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
1309
  limits: {
@@ -1943,6 +1972,25 @@ var CREDENTIAL_ENDPOINT_PAIRING = {
1943
1972
  familyKeySeparator: aigentflow_spec_default.credentialEndpointPairing.familyKeySeparator,
1944
1973
  families: aigentflow_spec_default.credentialEndpointPairing.families
1945
1974
  };
1975
+ var COMPLIANCE_RESIDENCY = {
1976
+ code: aigentflow_spec_default.complianceResidency.code,
1977
+ euResidencyCodes: aigentflow_spec_default.complianceResidency.euResidencyCodes,
1978
+ regionLaneProviders: aigentflow_spec_default.complianceResidency.regionLaneProviders,
1979
+ aiProtocol: aigentflow_spec_default.complianceResidency.aiProtocol,
1980
+ protocolSeparator: aigentflow_spec_default.complianceResidency.protocolSeparator,
1981
+ regionParam: aigentflow_spec_default.complianceResidency.regionParam,
1982
+ enforceRegionParam: aigentflow_spec_default.complianceResidency.enforceRegionParam,
1983
+ baseUrlParamSuffix: aigentflow_spec_default.complianceResidency.baseUrlParamSuffix,
1984
+ enforceRegionTrueStrings: aigentflow_spec_default.complianceResidency.enforceRegionTrueStrings,
1985
+ stepFieldFormat: aigentflow_spec_default.complianceResidency.stepFieldFormat,
1986
+ loopStepFieldFormat: aigentflow_spec_default.complianceResidency.loopStepFieldFormat,
1987
+ orchestratorField: aigentflow_spec_default.complianceResidency.orchestratorField,
1988
+ siteStepFormat: aigentflow_spec_default.complianceResidency.siteStepFormat,
1989
+ siteLoopStepFormat: aigentflow_spec_default.complianceResidency.siteLoopStepFormat,
1990
+ siteOrchestrator: aigentflow_spec_default.complianceResidency.siteOrchestrator,
1991
+ messageFormat: aigentflow_spec_default.complianceResidency.messageFormat,
1992
+ suggestion: aigentflow_spec_default.complianceResidency.suggestion
1993
+ };
1946
1994
  var EXAMPLES = {
1947
1995
  limits: aigentflow_spec_default.examples.limits,
1948
1996
  idPattern: new RegExp(aigentflow_spec_default.examples.idPattern),
@@ -5302,6 +5350,141 @@ function warnOrchestratorToolWithheld(flow, orch, report, issues) {
5302
5350
  }
5303
5351
  }
5304
5352
 
5353
+ // src/validators/complianceResidency.ts
5354
+ function own2(m, key) {
5355
+ if (!isRecord(m) || !Object.prototype.hasOwnProperty.call(m, key)) return void 0;
5356
+ return m[key];
5357
+ }
5358
+ function sprintf(format, ...args) {
5359
+ let i = 0;
5360
+ return format.replace(/%[sqv]/g, (verb) => {
5361
+ const arg = args[i++] ?? "";
5362
+ return verb === "%q" ? JSON.stringify(arg) : arg;
5363
+ });
5364
+ }
5365
+ function literalOrEmpty(s) {
5366
+ const t = goTrimSpace2(s);
5367
+ return t.includes(TEMPLATE_ACTION_OPEN) ? "" : t;
5368
+ }
5369
+ function euOnlyResidency(flow, issues) {
5370
+ const raw = own2(own2(flow, "compliance"), "residency");
5371
+ if (!isArray(raw)) return null;
5372
+ const codes = [];
5373
+ for (let i = 0; i < raw.length; i++) {
5374
+ if (raw[i] === null) continue;
5375
+ const code = issues.stringAt(raw[i], `compliance.residency[${i}]`);
5376
+ if (code === null) return null;
5377
+ codes.push(code);
5378
+ }
5379
+ if (codes.length === 0) return null;
5380
+ const eu = new Set(COMPLIANCE_RESIDENCY.euResidencyCodes);
5381
+ return codes.every((c) => eu.has(goTrimSpace2(c).toUpperCase())) ? codes : null;
5382
+ }
5383
+ function aiProvider(executor) {
5384
+ const prefix = COMPLIANCE_RESIDENCY.aiProtocol + COMPLIANCE_RESIDENCY.protocolSeparator;
5385
+ if (!executor.startsWith(prefix)) return "";
5386
+ const rest = executor.slice(prefix.length);
5387
+ const slash = rest.indexOf("/");
5388
+ const provider = slash > 0 ? rest.slice(0, slash) : "";
5389
+ return provider.includes(TEMPLATE_ACTION_OPEN) ? "" : provider;
5390
+ }
5391
+ function isRegionLane(provider) {
5392
+ const literal = literalOrEmpty(provider);
5393
+ return literal !== "" && COMPLIANCE_RESIDENCY.regionLaneProviders.includes(literal.toLowerCase());
5394
+ }
5395
+ function nonBlankString(m, key) {
5396
+ const v = own2(m, key);
5397
+ return typeof v === "string" && goTrimSpace2(v) !== "";
5398
+ }
5399
+ function queryEnforcesRegion(query) {
5400
+ const v = own2(query, COMPLIANCE_RESIDENCY.enforceRegionParam);
5401
+ if (typeof v === "boolean") return v;
5402
+ return typeof v === "string" && COMPLIANCE_RESIDENCY.enforceRegionTrueStrings.includes(v);
5403
+ }
5404
+ function flowDirectsEndpoint(flow, provider, issues) {
5405
+ const key = provider.toLowerCase();
5406
+ const inst = own2(own2(flow, "executor_config"), key);
5407
+ if (!isRecord(inst)) return false;
5408
+ const baseUrl = issues.stringOf(inst, "base_url", `executor_config.${key}`);
5409
+ return baseUrl !== null && goTrimSpace2(baseUrl) !== "";
5410
+ }
5411
+ function callPinsEndpoint(flow, provider, query, issues) {
5412
+ if (nonBlankString(query, COMPLIANCE_RESIDENCY.regionParam)) return true;
5413
+ if (queryEnforcesRegion(query)) return true;
5414
+ if (nonBlankString(query, provider.toLowerCase() + COMPLIANCE_RESIDENCY.baseUrlParamSuffix)) return true;
5415
+ return flowDirectsEndpoint(flow, provider, issues);
5416
+ }
5417
+ function validateResidencyEnforcement(flow, issues) {
5418
+ const residency = euOnlyResidency(flow, issues);
5419
+ if (residency === null) return;
5420
+ const warn = (site, field, stepId, provider) => {
5421
+ issues.warn({
5422
+ field,
5423
+ ...stepId === void 0 ? {} : { stepId },
5424
+ code: COMPLIANCE_RESIDENCY.code,
5425
+ message: sprintf(COMPLIANCE_RESIDENCY.messageFormat, site, provider, `[${residency.join(" ")}]`),
5426
+ suggestion: COMPLIANCE_RESIDENCY.suggestion
5427
+ });
5428
+ };
5429
+ const steps = flow.steps;
5430
+ if (isRecord(steps)) {
5431
+ for (const stepId of Object.keys(steps).sort()) {
5432
+ const step = steps[stepId];
5433
+ if (!isRecord(step)) continue;
5434
+ const calls = [
5435
+ {
5436
+ executor: issues.stringOf(step, "executor", `steps.${stepId}`) ?? "",
5437
+ query: own2(step, "query"),
5438
+ subId: null
5439
+ }
5440
+ ];
5441
+ for (const sub of loopSubStepsOfStep(stepId, step)) {
5442
+ calls.push({
5443
+ executor: issues.stringOf(sub.raw, "executor", sub.basePath) ?? "",
5444
+ query: own2(sub.raw, "query"),
5445
+ subId: issues.stringOf(sub.raw, "id", sub.basePath) ?? ""
5446
+ });
5447
+ }
5448
+ for (const call of calls) {
5449
+ const provider = aiProvider(call.executor);
5450
+ if (!isRegionLane(provider)) continue;
5451
+ if (callPinsEndpoint(flow, provider, call.query, issues)) continue;
5452
+ if (call.subId === null) {
5453
+ warn(
5454
+ sprintf(COMPLIANCE_RESIDENCY.siteStepFormat, stepId),
5455
+ sprintf(COMPLIANCE_RESIDENCY.stepFieldFormat, stepId),
5456
+ stepId,
5457
+ provider
5458
+ );
5459
+ } else {
5460
+ warn(
5461
+ sprintf(COMPLIANCE_RESIDENCY.siteLoopStepFormat, call.subId, stepId),
5462
+ sprintf(COMPLIANCE_RESIDENCY.loopStepFieldFormat, stepId, call.subId),
5463
+ stepId,
5464
+ provider
5465
+ );
5466
+ }
5467
+ }
5468
+ }
5469
+ }
5470
+ warnOrchestrator(flow, issues, warn);
5471
+ }
5472
+ function warnOrchestrator(flow, issues, warn) {
5473
+ const orch = flow.orchestrator;
5474
+ if (!isRecord(orch)) return;
5475
+ const source = issues.stringOf(orch, "exons", "orchestrator");
5476
+ if (source === null || source === "") return;
5477
+ const report = inspectExonsFrontmatter(source);
5478
+ if (report.parseError !== null || !report.specRead || !report.hasSpec) return;
5479
+ const provider = literalOrEmpty(report.provider);
5480
+ if (!isRegionLane(provider)) return;
5481
+ const region = issues.stringOf(orch, "region", "orchestrator");
5482
+ if (region !== null && goTrimSpace2(region) !== "") return;
5483
+ if (orch.enforce_region === true) return;
5484
+ if (flowDirectsEndpoint(flow, provider, issues)) return;
5485
+ warn(COMPLIANCE_RESIDENCY.siteOrchestrator, COMPLIANCE_RESIDENCY.orchestratorField, void 0, provider);
5486
+ }
5487
+
5305
5488
  // src/validators/examples.ts
5306
5489
  var KEY_EXAMPLES = "examples";
5307
5490
  var VISIBILITY_PUBLIC = "public";
@@ -5379,7 +5562,7 @@ function num(n) {
5379
5562
  function has(o, key) {
5380
5563
  return Object.prototype.hasOwnProperty.call(o, key) && o[key] !== null && o[key] !== void 0;
5381
5564
  }
5382
- function own2(o, key) {
5565
+ function own3(o, key) {
5383
5566
  return Object.prototype.hasOwnProperty.call(o, key) ? o[key] : void 0;
5384
5567
  }
5385
5568
  function setOwn(o, key, value) {
@@ -5431,7 +5614,7 @@ function mergePatch(target, patch, depth) {
5431
5614
  continue;
5432
5615
  }
5433
5616
  if (isRecord(pv)) {
5434
- const current = own2(target, k);
5617
+ const current = own3(target, k);
5435
5618
  const existing = isRecord(current) ? deepCopy(current, 0) : {};
5436
5619
  mergePatch(existing, pv, depth + 1);
5437
5620
  setOwn(target, k, existing);
@@ -5451,7 +5634,7 @@ function asFileRef(v) {
5451
5634
  if (keys.length === 0) return null;
5452
5635
  for (const k of keys) if (!FILE_REF_KEYS.has(k)) return null;
5453
5636
  const str = (k) => {
5454
- const x = own2(v, k);
5637
+ const x = own3(v, k);
5455
5638
  return typeof x === "string" ? x : "";
5456
5639
  };
5457
5640
  return {
@@ -5519,7 +5702,7 @@ var Walker = class _Walker {
5519
5702
  `the examples block is ${size} bytes; the limit is ${L.maxBlockBytes}. Move large inputs or target outputs to a file reference (https URL).`
5520
5703
  );
5521
5704
  }
5522
- const allHeld = examples.every((e) => isRecord(e) && own2(e, "hold_out") === true);
5705
+ const allHeld = examples.every((e) => isRecord(e) && own3(e, "hold_out") === true);
5523
5706
  if (allHeld) {
5524
5707
  this.warn(
5525
5708
  "examples_all_held_out",
@@ -5607,9 +5790,9 @@ var Walker = class _Walker {
5607
5790
  `example ${q(label)} notes are ${notesN} characters; the limit is ${L.maxNotesRunes}`
5608
5791
  );
5609
5792
  }
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"));
5793
+ this.validateTags(path, label, own3(ex, "tags"));
5794
+ this.validateWeight(`${path}.weight`, label, numberOf(own3(ex, "weight")));
5795
+ const minScore = numberOf(own3(ex, "min_score"));
5613
5796
  if (minScore !== void 0 && !scoreInRange(minScore)) {
5614
5797
  this.err(
5615
5798
  "example_min_score_range",
@@ -5625,7 +5808,7 @@ var Walker = class _Walker {
5625
5808
  `example ${q(label)} has side_effects ${q(sideEffects)}; use refuse or allow`
5626
5809
  );
5627
5810
  }
5628
- const holdOut = own2(ex, "hold_out") === true;
5811
+ const holdOut = own3(ex, "hold_out") === true;
5629
5812
  if (holdOut && this.isPublic()) {
5630
5813
  this.err(
5631
5814
  "example_holdout_in_public_flow",
@@ -5648,17 +5831,17 @@ var Walker = class _Walker {
5648
5831
  `example ${q(label)} has neither input nor input_ref; use input: {} for a flow that takes no input`
5649
5832
  );
5650
5833
  }
5651
- const rawInput = own2(ex, "input");
5834
+ const rawInput = own3(ex, "input");
5652
5835
  const baseInput = isRecord(rawInput) ? rawInput : null;
5653
5836
  if (baseInput !== null) {
5654
5837
  this.checkInput(`${path}.input`, label, baseInput, "example_input_invalid");
5655
5838
  }
5656
- const rawInputRef = own2(ex, "input_ref");
5839
+ const rawInputRef = own3(ex, "input_ref");
5657
5840
  if (isRecord(rawInputRef)) {
5658
5841
  this.validateFileRef(`${path}.input_ref`, this.fileRefOf(rawInputRef, `${path}.input_ref`));
5659
5842
  }
5660
5843
  let binaryOnly = false;
5661
- const expected = own2(ex, "expected");
5844
+ const expected = own3(ex, "expected");
5662
5845
  if (!has(ex, "expected")) {
5663
5846
  this.err(
5664
5847
  "example_expected_missing",
@@ -5677,7 +5860,7 @@ var Walker = class _Walker {
5677
5860
  "this example can be run but not scored"
5678
5861
  );
5679
5862
  }
5680
- this.validateCheckpoints(path, label, own2(ex, "checkpoints"));
5863
+ this.validateCheckpoints(path, label, own3(ex, "checkpoints"));
5681
5864
  this.validateVariants(i, path, label, ex, hasInput, baseInput);
5682
5865
  this.scanSecretLike(i, path, ex);
5683
5866
  }
@@ -5737,8 +5920,8 @@ var Walker = class _Walker {
5737
5920
  );
5738
5921
  return;
5739
5922
  }
5740
- const schema = own2(this.flow, "input_schema");
5741
- const query = own2(this.flow, "query");
5923
+ const schema = own3(this.flow, "input_schema");
5924
+ const query = own3(this.flow, "query");
5742
5925
  if (isRecord(schema)) {
5743
5926
  this.checkInputAgainstSchema(field, label, input, schema, code);
5744
5927
  } else if (isRecord(query) && Object.keys(query).length > 0) {
@@ -5806,29 +5989,29 @@ var Walker = class _Walker {
5806
5989
  }
5807
5990
  }
5808
5991
  schemaFields(schema) {
5809
- const raw = own2(schema, "fields");
5992
+ const raw = own3(schema, "fields");
5810
5993
  if (!Array.isArray(raw)) return [];
5811
5994
  const out = [];
5812
5995
  raw.forEach((f, i) => {
5813
5996
  if (!isRecord(f)) return;
5814
5997
  const base = `input_schema.fields[${i}]`;
5815
- const enumRaw = own2(f, "enum");
5998
+ const enumRaw = own3(f, "enum");
5816
5999
  const enumValues = [];
5817
6000
  if (Array.isArray(enumRaw)) {
5818
6001
  enumRaw.forEach((e, j) => {
5819
6002
  enumValues.push(e === null ? "" : this.issues.stringAt(e, `${base}.enum[${j}]`) ?? "");
5820
6003
  });
5821
6004
  }
5822
- const vw = own2(f, "visible_when");
6005
+ const vw = own3(f, "visible_when");
5823
6006
  out.push({
5824
6007
  name: this.s(f, "name", base),
5825
6008
  type: this.s(f, "type", base),
5826
- required: own2(f, "required") === true,
6009
+ required: own3(f, "required") === true,
5827
6010
  enumValues,
5828
6011
  visibleWhen: isRecord(vw) ? {
5829
6012
  field: this.s(vw, "field", `${base}.visible_when`),
5830
- equals: own2(vw, "equals"),
5831
- in: Array.isArray(own2(vw, "in")) ? own2(vw, "in") : []
6013
+ equals: own3(vw, "equals"),
6014
+ in: Array.isArray(own3(vw, "in")) ? own3(vw, "in") : []
5832
6015
  } : null
5833
6016
  });
5834
6017
  });
@@ -5839,7 +6022,7 @@ var Walker = class _Walker {
5839
6022
  const failures = [];
5840
6023
  for (const f of fields) {
5841
6024
  if (!isVisible(f, runInput)) continue;
5842
- const raw = own2(runInput, f.name);
6025
+ const raw = own3(runInput, f.name);
5843
6026
  if (raw === void 0 || raw === null) {
5844
6027
  if (f.required) {
5845
6028
  failures.push({
@@ -5950,7 +6133,7 @@ var Walker = class _Walker {
5950
6133
  /** The names `fields` / `exact` may use, and whether such a list is declared at all. */
5951
6134
  outputNamesFor(kind, stepId) {
5952
6135
  if (kind === "final") {
5953
- const out = own2(this.flow, "output");
6136
+ const out = own3(this.flow, "output");
5954
6137
  const names2 = [];
5955
6138
  if (Array.isArray(out)) {
5956
6139
  out.forEach((item, i) => {
@@ -5959,10 +6142,10 @@ var Walker = class _Walker {
5959
6142
  }
5960
6143
  return { names: names2, declared: names2.length > 0 };
5961
6144
  }
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;
6145
+ const steps = own3(this.flow, "steps");
6146
+ const step = isRecord(steps) ? own3(steps, stepId) : void 0;
6147
+ const schema = isRecord(step) ? own3(step, "output_schema") : void 0;
6148
+ const fields = isRecord(schema) ? own3(schema, "fields") : void 0;
5966
6149
  if (!Array.isArray(fields) || fields.length === 0) return { names: [], declared: false };
5967
6150
  const names = [];
5968
6151
  fields.forEach((f, i) => {
@@ -5981,8 +6164,8 @@ var Walker = class _Walker {
5981
6164
  );
5982
6165
  }
5983
6166
  const noOutput = status === STATUS_FAILED || status === STATUS_PAUSED_FOR_HUMAN;
5984
- const fieldsRec = own2(e, "fields");
5985
- const exactRec = own2(e, "exact");
6167
+ const fieldsRec = own3(e, "fields");
6168
+ const exactRec = own3(e, "exact");
5986
6169
  const fieldKeys = isRecord(fieldsRec) ? sortedKeys(fieldsRec) : [];
5987
6170
  const exactKeys = isRecord(exactRec) ? sortedKeys(exactRec) : [];
5988
6171
  const hasFields = fieldKeys.length > 0;
@@ -6000,7 +6183,7 @@ var Walker = class _Walker {
6000
6183
  `a case that ends in ${status} has no output to match; remove fields and exact, or expect status completed`
6001
6184
  );
6002
6185
  }
6003
- const minScore = numberOf(own2(e, "min_score"));
6186
+ const minScore = numberOf(own3(e, "min_score"));
6004
6187
  if (minScore !== void 0 && !scoreInRange(minScore)) {
6005
6188
  this.err(
6006
6189
  "example_min_score_range",
@@ -6027,7 +6210,7 @@ var Walker = class _Walker {
6027
6210
  }
6028
6211
  }
6029
6212
  }
6030
- const reference = own2(e, "reference");
6213
+ const reference = own3(e, "reference");
6031
6214
  if (isRecord(reference)) this.validateReference(`${path}.reference`, reference);
6032
6215
  const { names, declared } = this.outputNamesFor(kind, stepId);
6033
6216
  const checkKey = (field, key) => {
@@ -6054,12 +6237,12 @@ var Walker = class _Walker {
6054
6237
  for (const key of fieldKeys) {
6055
6238
  const fpath = `${path}.fields.${key}`;
6056
6239
  checkKey(fpath, key);
6057
- const matcher = own2(fieldsRec, key);
6240
+ const matcher = own3(fieldsRec, key);
6058
6241
  if (isRecord(matcher)) this.validateFieldMatcher(fpath, matcher);
6059
6242
  }
6060
6243
  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`);
6244
+ const mustNot = this.stringList(own3(e, "must_not"), `${path}.must_not`);
6245
+ const mustNotContain = this.stringList(own3(e, "must_not_contain"), `${path}.must_not_contain`);
6063
6246
  const mustNotMsg = `must_not takes up to ${L.maxMustNot} statements of at most ${L.maxMustNotRunes} characters each, none empty`;
6064
6247
  if (mustNot.length > L.maxMustNot) {
6065
6248
  this.err("example_must_not_invalid", `${path}.must_not`, mustNotMsg);
@@ -6080,9 +6263,9 @@ var Walker = class _Walker {
6080
6263
  }
6081
6264
  });
6082
6265
  for (const key of fieldKeys) {
6083
- const matcher = own2(fieldsRec, key);
6266
+ const matcher = own3(fieldsRec, key);
6084
6267
  if (!isRecord(matcher)) continue;
6085
- const eq = own2(matcher, "equals");
6268
+ const eq = own3(matcher, "equals");
6086
6269
  if (typeof eq !== "string" || eq === "") continue;
6087
6270
  for (const banned of mustNotContain) {
6088
6271
  if (banned !== "" && equalFold(banned, eq)) {
@@ -6142,7 +6325,7 @@ var Walker = class _Walker {
6142
6325
  }
6143
6326
  return;
6144
6327
  }
6145
- const refRec = own2(r, "ref");
6328
+ const refRec = own3(r, "ref");
6146
6329
  if (!isRecord(refRec)) return;
6147
6330
  const ref = this.fileRefOf(refRec, `${path}.ref`);
6148
6331
  this.validateFileRef(`${path}.ref`, ref);
@@ -6155,22 +6338,22 @@ var Walker = class _Walker {
6155
6338
  }
6156
6339
  }
6157
6340
  expectationIsBinaryReferenceOnly(e, path) {
6158
- const reference = own2(e, "reference");
6159
- const refRec = isRecord(reference) ? own2(reference, "ref") : void 0;
6341
+ const reference = own3(e, "reference");
6342
+ const refRec = isRecord(reference) ? own3(reference, "ref") : void 0;
6160
6343
  if (!isRecord(refRec)) return false;
6161
6344
  const mediaType = this.s(refRec, "media_type", `${path}.reference.ref`);
6162
6345
  if (mediaType === "" || isTextualMediaType(mediaType)) return false;
6163
6346
  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);
6347
+ const fields = own3(e, "fields");
6348
+ const exact = own3(e, "exact");
6349
+ 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
6350
  }
6168
6351
  validateFieldMatcher(path, m) {
6169
6352
  const L = EXAMPLES.limits;
6170
6353
  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"));
6354
+ const oneOf = own3(m, "one_of");
6355
+ const approx = numberOf(own3(m, "approx"));
6356
+ const tolerance = numberOf(own3(m, "tolerance"));
6174
6357
  let operators = 0;
6175
6358
  if (has(m, "equals")) operators++;
6176
6359
  if (this.s(m, "contains", path) !== "") operators++;
@@ -6178,7 +6361,7 @@ var Walker = class _Walker {
6178
6361
  if (matches !== "") operators++;
6179
6362
  if (Array.isArray(oneOf) && oneOf.length > 0) operators++;
6180
6363
  if (approx !== void 0) operators++;
6181
- if (typeof own2(m, "present") === "boolean") operators++;
6364
+ if (typeof own3(m, "present") === "boolean") operators++;
6182
6365
  if (operators !== 1) {
6183
6366
  this.err(
6184
6367
  "example_field_matcher_invalid",
@@ -6205,12 +6388,12 @@ var Walker = class _Walker {
6205
6388
  // -- checkpoints ------------------------------------------------------
6206
6389
  validateCheckpoints(path, label, cps) {
6207
6390
  if (!isRecord(cps) || Object.keys(cps).length === 0) return;
6208
- const stepsRaw = own2(this.flow, "steps");
6391
+ const stepsRaw = own3(this.flow, "steps");
6209
6392
  const steps = isRecord(stepsRaw) ? stepsRaw : {};
6210
6393
  const stepIds = sortedKeys(steps);
6211
6394
  for (const id of sortedKeys(cps)) {
6212
6395
  const cpath = `${path}.checkpoints.${id}`;
6213
- const step = own2(steps, id);
6396
+ const step = own3(steps, id);
6214
6397
  if (!isRecord(step)) {
6215
6398
  this.err(
6216
6399
  "example_checkpoint_step_unknown",
@@ -6220,7 +6403,7 @@ var Walker = class _Walker {
6220
6403
  );
6221
6404
  continue;
6222
6405
  }
6223
- const next = own2(step, "next");
6406
+ const next = own3(step, "next");
6224
6407
  if (has(step, "for_each") || has(step, "loop") || isRecord(next) && has(next, "parallel")) {
6225
6408
  this.err(
6226
6409
  "example_checkpoint_step_composite",
@@ -6229,7 +6412,7 @@ var Walker = class _Walker {
6229
6412
  );
6230
6413
  continue;
6231
6414
  }
6232
- const cp = own2(cps, id);
6415
+ const cp = own3(cps, id);
6233
6416
  if (cp === null || cp === void 0) {
6234
6417
  this.validateExpectation(cpath, label, {}, "checkpoint", id);
6235
6418
  } else if (isRecord(cp)) {
@@ -6240,7 +6423,7 @@ var Walker = class _Walker {
6240
6423
  // -- variants ---------------------------------------------------------
6241
6424
  validateVariants(i, path, label, ex, hasInput, baseInput) {
6242
6425
  const L = EXAMPLES.limits;
6243
- const variants = own2(ex, "variants");
6426
+ const variants = own3(ex, "variants");
6244
6427
  if (!Array.isArray(variants) || variants.length === 0) return;
6245
6428
  if (variants.length > L.maxVariants) {
6246
6429
  this.err(
@@ -6303,8 +6486,8 @@ var Walker = class _Walker {
6303
6486
  `example ${q(both)} notes are ${provN} characters; the limit is ${L.maxProvenanceRunes}`
6304
6487
  );
6305
6488
  }
6306
- this.validateWeight(`${vpath}.weight`, both, numberOf(own2(v, "weight")));
6307
- const patch = own2(v, "input_patch");
6489
+ this.validateWeight(`${vpath}.weight`, both, numberOf(own3(v, "weight")));
6490
+ const patch = own3(v, "input_patch");
6308
6491
  const patchRec = isRecord(patch) ? patch : null;
6309
6492
  const hasPatch = patchRec !== null && Object.keys(patchRec).length > 0;
6310
6493
  const hasRef = has(v, "input_ref");
@@ -6321,7 +6504,7 @@ var Walker = class _Walker {
6321
6504
  `variant ${q(vlabel)} of example ${q(label)} changes neither the input nor the expectation`
6322
6505
  );
6323
6506
  }
6324
- const refRec = own2(v, "input_ref");
6507
+ const refRec = own3(v, "input_ref");
6325
6508
  if (isRecord(refRec)) {
6326
6509
  this.validateFileRef(`${vpath}.input_ref`, this.fileRefOf(refRec, `${vpath}.input_ref`));
6327
6510
  }
@@ -6336,7 +6519,7 @@ var Walker = class _Walker {
6336
6519
  this.checkVariantPatch(vpath, label, vlabel, baseInput, patchRec);
6337
6520
  }
6338
6521
  }
6339
- const expected = own2(v, "expected");
6522
+ const expected = own3(v, "expected");
6340
6523
  if (isRecord(expected)) {
6341
6524
  this.validateExpectation(`${vpath}.expected`, both, expected, "final", "");
6342
6525
  }
@@ -6347,11 +6530,11 @@ var Walker = class _Walker {
6347
6530
  * itself supplies. A null patch value deleting a secret is fine.
6348
6531
  */
6349
6532
  checkVariantPatch(vpath, label, vlabel, base, patch) {
6350
- const schema = own2(this.flow, "input_schema");
6533
+ const schema = own3(this.flow, "input_schema");
6351
6534
  if (isRecord(schema)) {
6352
6535
  for (const f of this.schemaFields(schema)) {
6353
6536
  if (f.type !== TYPE_SECRET) continue;
6354
- const val = own2(patch, f.name);
6537
+ const val = own3(patch, f.name);
6355
6538
  if (val !== void 0 && val !== null) {
6356
6539
  this.err(
6357
6540
  "example_secret_value",
@@ -6391,18 +6574,18 @@ var Walker = class _Walker {
6391
6574
  emit(`${path}.title`, this.s(ex, "title", path));
6392
6575
  emit(`${path}.guidance`, this.s(ex, "guidance", path));
6393
6576
  emit(`${path}.notes`, this.s(ex, "notes", path));
6394
- const input = own2(ex, "input");
6577
+ const input = own3(ex, "input");
6395
6578
  if (isRecord(input)) scanLeaves(`${path}.input`, input, 0, emit);
6396
- const expected = own2(ex, "expected");
6579
+ const expected = own3(ex, "expected");
6397
6580
  if (isRecord(expected)) this.scanExpectationLeaves(`${path}.expected`, expected, emit);
6398
- const cps = own2(ex, "checkpoints");
6581
+ const cps = own3(ex, "checkpoints");
6399
6582
  if (isRecord(cps)) {
6400
6583
  for (const id of sortedKeys(cps)) {
6401
- const cp = own2(cps, id);
6584
+ const cp = own3(cps, id);
6402
6585
  if (isRecord(cp)) this.scanExpectationLeaves(`${path}.checkpoints.${id}`, cp, emit);
6403
6586
  }
6404
6587
  }
6405
- const variants = own2(ex, "variants");
6588
+ const variants = own3(ex, "variants");
6406
6589
  if (Array.isArray(variants)) {
6407
6590
  variants.forEach((v, j) => {
6408
6591
  if (!isRecord(v)) return;
@@ -6410,34 +6593,34 @@ var Walker = class _Walker {
6410
6593
  emit(`${vpath}.title`, this.s(v, "title", vpath));
6411
6594
  emit(`${vpath}.guidance`, this.s(v, "guidance", vpath));
6412
6595
  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");
6596
+ scanLeaves(`${vpath}.input_patch`, own3(v, "input_patch"), 0, emit);
6597
+ const vexp = own3(v, "expected");
6415
6598
  if (isRecord(vexp)) this.scanExpectationLeaves(`${vpath}.expected`, vexp, emit);
6416
6599
  });
6417
6600
  }
6418
6601
  }
6419
6602
  scanExpectationLeaves(path, e, emit) {
6420
6603
  emit(`${path}.rubric`, this.s(e, "rubric", path));
6421
- const reference = own2(e, "reference");
6604
+ const reference = own3(e, "reference");
6422
6605
  if (isRecord(reference)) {
6423
6606
  emit(`${path}.reference.text`, this.s(reference, "text", `${path}.reference`));
6424
6607
  }
6425
- this.stringList(own2(e, "must_not"), `${path}.must_not`).forEach(
6608
+ this.stringList(own3(e, "must_not"), `${path}.must_not`).forEach(
6426
6609
  (s, j) => emit(`${path}.must_not[${j}]`, s)
6427
6610
  );
6428
- this.stringList(own2(e, "must_not_contain"), `${path}.must_not_contain`).forEach(
6611
+ this.stringList(own3(e, "must_not_contain"), `${path}.must_not_contain`).forEach(
6429
6612
  (s, j) => emit(`${path}.must_not_contain[${j}]`, s)
6430
6613
  );
6431
- const fields = own2(e, "fields");
6614
+ const fields = own3(e, "fields");
6432
6615
  if (isRecord(fields)) {
6433
6616
  for (const key of sortedKeys(fields)) {
6434
- const m = own2(fields, key);
6617
+ const m = own3(fields, key);
6435
6618
  if (!isRecord(m)) continue;
6436
6619
  const fpath = `${path}.fields.${key}`;
6437
- scanLeaves(`${fpath}.equals`, own2(m, "equals"), 0, emit);
6620
+ scanLeaves(`${fpath}.equals`, own3(m, "equals"), 0, emit);
6438
6621
  emit(`${fpath}.contains`, this.s(m, "contains", fpath));
6439
6622
  emit(`${fpath}.not_contains`, this.s(m, "not_contains", fpath));
6440
- const oneOf = own2(m, "one_of");
6623
+ const oneOf = own3(m, "one_of");
6441
6624
  if (Array.isArray(oneOf)) {
6442
6625
  oneOf.forEach(
6443
6626
  (one, j) => scanLeaves(`${fpath}.one_of[${j}]`, one, 0, emit)
@@ -6445,7 +6628,7 @@ var Walker = class _Walker {
6445
6628
  }
6446
6629
  }
6447
6630
  }
6448
- scanLeaves(`${path}.exact`, own2(e, "exact"), 0, emit);
6631
+ scanLeaves(`${path}.exact`, own3(e, "exact"), 0, emit);
6449
6632
  }
6450
6633
  };
6451
6634
  function scoreInRange(v) {
@@ -6561,7 +6744,7 @@ function inputValueFailures(f, raw) {
6561
6744
  case TYPE_FILE2: {
6562
6745
  if (typeof raw === "string") return raw === "" ? [mismatch(f, TYPE_FILE2)] : [];
6563
6746
  if (isRecord(raw)) {
6564
- const ref = own2(raw, FILE_REF_KEY);
6747
+ const ref = own3(raw, FILE_REF_KEY);
6565
6748
  return typeof ref === "string" && ref !== "" ? [] : [mismatch(f, TYPE_FILE2)];
6566
6749
  }
6567
6750
  return [mismatch(f, TYPE_FILE2)];
@@ -6641,6 +6824,7 @@ function validateParsed(flow, opts, sources) {
6641
6824
  validateCredentialEndpointPairing(f, issues);
6642
6825
  validateExamples(f, issues);
6643
6826
  validateOrchestratorExons(f, issues);
6827
+ validateResidencyEnforcement(f, issues);
6644
6828
  validateUnknownKeys(f, issues);
6645
6829
  const templateStats = validateTemplates(f, issues, opts);
6646
6830
  const totalSteps = f.steps && typeof f.steps === "object" && !Array.isArray(f.steps) ? Object.keys(f.steps).length : 0;