@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/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.819.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: {
@@ -1726,6 +1755,7 @@ var aigentflow_spec_default = {
1726
1755
  deny_tools: "list<scalar>",
1727
1756
  discoverable_tools: "list<scalar>",
1728
1757
  enable_signals: "scalar",
1758
+ enforce_region: "scalar",
1729
1759
  engram_scope: "scalar",
1730
1760
  exons: "scalar",
1731
1761
  human_question_timeout: "scalar",
@@ -1734,6 +1764,7 @@ var aigentflow_spec_default = {
1734
1764
  max_tool_turns: "scalar",
1735
1765
  max_turns: "scalar",
1736
1766
  mode: "scalar",
1767
+ region: "scalar",
1737
1768
  require_approval_for: "list<scalar>",
1738
1769
  timeout_seconds: "scalar",
1739
1770
  tool_discovery: "scalar",
@@ -1941,6 +1972,25 @@ var CREDENTIAL_ENDPOINT_PAIRING = {
1941
1972
  familyKeySeparator: aigentflow_spec_default.credentialEndpointPairing.familyKeySeparator,
1942
1973
  families: aigentflow_spec_default.credentialEndpointPairing.families
1943
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
+ };
1944
1994
  var EXAMPLES = {
1945
1995
  limits: aigentflow_spec_default.examples.limits,
1946
1996
  idPattern: new RegExp(aigentflow_spec_default.examples.idPattern),
@@ -3157,6 +3207,17 @@ function validateOrchestratorCampaign(flow, issues, opts) {
3157
3207
  code: "orchestrator_owner_needs_yield"
3158
3208
  });
3159
3209
  }
3210
+ if (orch.enforce_region === true) {
3211
+ const region = issues.stringOf(orch, "region", "orchestrator");
3212
+ if (region === null || region.trim() === "") {
3213
+ issues.error({
3214
+ field: "orchestrator.enforce_region",
3215
+ message: "orchestrator: enforce_region requires region (name the region the model must run in, e.g. region: eu)",
3216
+ code: "orchestrator_enforce_region_needs_region",
3217
+ suggestion: "Add `region: eu` (or the region the model must run in), or drop enforce_region"
3218
+ });
3219
+ }
3220
+ }
3160
3221
  if (Array.isArray(orch.triggers)) {
3161
3222
  orch.triggers.forEach((rawTrigger, i) => {
3162
3223
  if (!isRecord(rawTrigger)) return;
@@ -5289,6 +5350,141 @@ function warnOrchestratorToolWithheld(flow, orch, report, issues) {
5289
5350
  }
5290
5351
  }
5291
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
+
5292
5488
  // src/validators/examples.ts
5293
5489
  var KEY_EXAMPLES = "examples";
5294
5490
  var VISIBILITY_PUBLIC = "public";
@@ -5366,7 +5562,7 @@ function num(n) {
5366
5562
  function has(o, key) {
5367
5563
  return Object.prototype.hasOwnProperty.call(o, key) && o[key] !== null && o[key] !== void 0;
5368
5564
  }
5369
- function own2(o, key) {
5565
+ function own3(o, key) {
5370
5566
  return Object.prototype.hasOwnProperty.call(o, key) ? o[key] : void 0;
5371
5567
  }
5372
5568
  function setOwn(o, key, value) {
@@ -5418,7 +5614,7 @@ function mergePatch(target, patch, depth) {
5418
5614
  continue;
5419
5615
  }
5420
5616
  if (isRecord(pv)) {
5421
- const current = own2(target, k);
5617
+ const current = own3(target, k);
5422
5618
  const existing = isRecord(current) ? deepCopy(current, 0) : {};
5423
5619
  mergePatch(existing, pv, depth + 1);
5424
5620
  setOwn(target, k, existing);
@@ -5438,7 +5634,7 @@ function asFileRef(v) {
5438
5634
  if (keys.length === 0) return null;
5439
5635
  for (const k of keys) if (!FILE_REF_KEYS.has(k)) return null;
5440
5636
  const str = (k) => {
5441
- const x = own2(v, k);
5637
+ const x = own3(v, k);
5442
5638
  return typeof x === "string" ? x : "";
5443
5639
  };
5444
5640
  return {
@@ -5506,7 +5702,7 @@ var Walker = class _Walker {
5506
5702
  `the examples block is ${size} bytes; the limit is ${L.maxBlockBytes}. Move large inputs or target outputs to a file reference (https URL).`
5507
5703
  );
5508
5704
  }
5509
- 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);
5510
5706
  if (allHeld) {
5511
5707
  this.warn(
5512
5708
  "examples_all_held_out",
@@ -5594,9 +5790,9 @@ var Walker = class _Walker {
5594
5790
  `example ${q(label)} notes are ${notesN} characters; the limit is ${L.maxNotesRunes}`
5595
5791
  );
5596
5792
  }
5597
- this.validateTags(path, label, own2(ex, "tags"));
5598
- this.validateWeight(`${path}.weight`, label, numberOf(own2(ex, "weight")));
5599
- 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"));
5600
5796
  if (minScore !== void 0 && !scoreInRange(minScore)) {
5601
5797
  this.err(
5602
5798
  "example_min_score_range",
@@ -5612,7 +5808,7 @@ var Walker = class _Walker {
5612
5808
  `example ${q(label)} has side_effects ${q(sideEffects)}; use refuse or allow`
5613
5809
  );
5614
5810
  }
5615
- const holdOut = own2(ex, "hold_out") === true;
5811
+ const holdOut = own3(ex, "hold_out") === true;
5616
5812
  if (holdOut && this.isPublic()) {
5617
5813
  this.err(
5618
5814
  "example_holdout_in_public_flow",
@@ -5635,17 +5831,17 @@ var Walker = class _Walker {
5635
5831
  `example ${q(label)} has neither input nor input_ref; use input: {} for a flow that takes no input`
5636
5832
  );
5637
5833
  }
5638
- const rawInput = own2(ex, "input");
5834
+ const rawInput = own3(ex, "input");
5639
5835
  const baseInput = isRecord(rawInput) ? rawInput : null;
5640
5836
  if (baseInput !== null) {
5641
5837
  this.checkInput(`${path}.input`, label, baseInput, "example_input_invalid");
5642
5838
  }
5643
- const rawInputRef = own2(ex, "input_ref");
5839
+ const rawInputRef = own3(ex, "input_ref");
5644
5840
  if (isRecord(rawInputRef)) {
5645
5841
  this.validateFileRef(`${path}.input_ref`, this.fileRefOf(rawInputRef, `${path}.input_ref`));
5646
5842
  }
5647
5843
  let binaryOnly = false;
5648
- const expected = own2(ex, "expected");
5844
+ const expected = own3(ex, "expected");
5649
5845
  if (!has(ex, "expected")) {
5650
5846
  this.err(
5651
5847
  "example_expected_missing",
@@ -5664,7 +5860,7 @@ var Walker = class _Walker {
5664
5860
  "this example can be run but not scored"
5665
5861
  );
5666
5862
  }
5667
- this.validateCheckpoints(path, label, own2(ex, "checkpoints"));
5863
+ this.validateCheckpoints(path, label, own3(ex, "checkpoints"));
5668
5864
  this.validateVariants(i, path, label, ex, hasInput, baseInput);
5669
5865
  this.scanSecretLike(i, path, ex);
5670
5866
  }
@@ -5724,8 +5920,8 @@ var Walker = class _Walker {
5724
5920
  );
5725
5921
  return;
5726
5922
  }
5727
- const schema = own2(this.flow, "input_schema");
5728
- const query = own2(this.flow, "query");
5923
+ const schema = own3(this.flow, "input_schema");
5924
+ const query = own3(this.flow, "query");
5729
5925
  if (isRecord(schema)) {
5730
5926
  this.checkInputAgainstSchema(field, label, input, schema, code);
5731
5927
  } else if (isRecord(query) && Object.keys(query).length > 0) {
@@ -5793,29 +5989,29 @@ var Walker = class _Walker {
5793
5989
  }
5794
5990
  }
5795
5991
  schemaFields(schema) {
5796
- const raw = own2(schema, "fields");
5992
+ const raw = own3(schema, "fields");
5797
5993
  if (!Array.isArray(raw)) return [];
5798
5994
  const out = [];
5799
5995
  raw.forEach((f, i) => {
5800
5996
  if (!isRecord(f)) return;
5801
5997
  const base = `input_schema.fields[${i}]`;
5802
- const enumRaw = own2(f, "enum");
5998
+ const enumRaw = own3(f, "enum");
5803
5999
  const enumValues = [];
5804
6000
  if (Array.isArray(enumRaw)) {
5805
6001
  enumRaw.forEach((e, j) => {
5806
6002
  enumValues.push(e === null ? "" : this.issues.stringAt(e, `${base}.enum[${j}]`) ?? "");
5807
6003
  });
5808
6004
  }
5809
- const vw = own2(f, "visible_when");
6005
+ const vw = own3(f, "visible_when");
5810
6006
  out.push({
5811
6007
  name: this.s(f, "name", base),
5812
6008
  type: this.s(f, "type", base),
5813
- required: own2(f, "required") === true,
6009
+ required: own3(f, "required") === true,
5814
6010
  enumValues,
5815
6011
  visibleWhen: isRecord(vw) ? {
5816
6012
  field: this.s(vw, "field", `${base}.visible_when`),
5817
- equals: own2(vw, "equals"),
5818
- in: Array.isArray(own2(vw, "in")) ? own2(vw, "in") : []
6013
+ equals: own3(vw, "equals"),
6014
+ in: Array.isArray(own3(vw, "in")) ? own3(vw, "in") : []
5819
6015
  } : null
5820
6016
  });
5821
6017
  });
@@ -5826,7 +6022,7 @@ var Walker = class _Walker {
5826
6022
  const failures = [];
5827
6023
  for (const f of fields) {
5828
6024
  if (!isVisible(f, runInput)) continue;
5829
- const raw = own2(runInput, f.name);
6025
+ const raw = own3(runInput, f.name);
5830
6026
  if (raw === void 0 || raw === null) {
5831
6027
  if (f.required) {
5832
6028
  failures.push({
@@ -5937,7 +6133,7 @@ var Walker = class _Walker {
5937
6133
  /** The names `fields` / `exact` may use, and whether such a list is declared at all. */
5938
6134
  outputNamesFor(kind, stepId) {
5939
6135
  if (kind === "final") {
5940
- const out = own2(this.flow, "output");
6136
+ const out = own3(this.flow, "output");
5941
6137
  const names2 = [];
5942
6138
  if (Array.isArray(out)) {
5943
6139
  out.forEach((item, i) => {
@@ -5946,10 +6142,10 @@ var Walker = class _Walker {
5946
6142
  }
5947
6143
  return { names: names2, declared: names2.length > 0 };
5948
6144
  }
5949
- const steps = own2(this.flow, "steps");
5950
- const step = isRecord(steps) ? own2(steps, stepId) : void 0;
5951
- const schema = isRecord(step) ? own2(step, "output_schema") : void 0;
5952
- 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;
5953
6149
  if (!Array.isArray(fields) || fields.length === 0) return { names: [], declared: false };
5954
6150
  const names = [];
5955
6151
  fields.forEach((f, i) => {
@@ -5968,8 +6164,8 @@ var Walker = class _Walker {
5968
6164
  );
5969
6165
  }
5970
6166
  const noOutput = status === STATUS_FAILED || status === STATUS_PAUSED_FOR_HUMAN;
5971
- const fieldsRec = own2(e, "fields");
5972
- const exactRec = own2(e, "exact");
6167
+ const fieldsRec = own3(e, "fields");
6168
+ const exactRec = own3(e, "exact");
5973
6169
  const fieldKeys = isRecord(fieldsRec) ? sortedKeys(fieldsRec) : [];
5974
6170
  const exactKeys = isRecord(exactRec) ? sortedKeys(exactRec) : [];
5975
6171
  const hasFields = fieldKeys.length > 0;
@@ -5987,7 +6183,7 @@ var Walker = class _Walker {
5987
6183
  `a case that ends in ${status} has no output to match; remove fields and exact, or expect status completed`
5988
6184
  );
5989
6185
  }
5990
- const minScore = numberOf(own2(e, "min_score"));
6186
+ const minScore = numberOf(own3(e, "min_score"));
5991
6187
  if (minScore !== void 0 && !scoreInRange(minScore)) {
5992
6188
  this.err(
5993
6189
  "example_min_score_range",
@@ -6014,7 +6210,7 @@ var Walker = class _Walker {
6014
6210
  }
6015
6211
  }
6016
6212
  }
6017
- const reference = own2(e, "reference");
6213
+ const reference = own3(e, "reference");
6018
6214
  if (isRecord(reference)) this.validateReference(`${path}.reference`, reference);
6019
6215
  const { names, declared } = this.outputNamesFor(kind, stepId);
6020
6216
  const checkKey = (field, key) => {
@@ -6041,12 +6237,12 @@ var Walker = class _Walker {
6041
6237
  for (const key of fieldKeys) {
6042
6238
  const fpath = `${path}.fields.${key}`;
6043
6239
  checkKey(fpath, key);
6044
- const matcher = own2(fieldsRec, key);
6240
+ const matcher = own3(fieldsRec, key);
6045
6241
  if (isRecord(matcher)) this.validateFieldMatcher(fpath, matcher);
6046
6242
  }
6047
6243
  for (const key of exactKeys) checkKey(`${path}.exact.${key}`, key);
6048
- const mustNot = this.stringList(own2(e, "must_not"), `${path}.must_not`);
6049
- 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`);
6050
6246
  const mustNotMsg = `must_not takes up to ${L.maxMustNot} statements of at most ${L.maxMustNotRunes} characters each, none empty`;
6051
6247
  if (mustNot.length > L.maxMustNot) {
6052
6248
  this.err("example_must_not_invalid", `${path}.must_not`, mustNotMsg);
@@ -6067,9 +6263,9 @@ var Walker = class _Walker {
6067
6263
  }
6068
6264
  });
6069
6265
  for (const key of fieldKeys) {
6070
- const matcher = own2(fieldsRec, key);
6266
+ const matcher = own3(fieldsRec, key);
6071
6267
  if (!isRecord(matcher)) continue;
6072
- const eq = own2(matcher, "equals");
6268
+ const eq = own3(matcher, "equals");
6073
6269
  if (typeof eq !== "string" || eq === "") continue;
6074
6270
  for (const banned of mustNotContain) {
6075
6271
  if (banned !== "" && equalFold(banned, eq)) {
@@ -6129,7 +6325,7 @@ var Walker = class _Walker {
6129
6325
  }
6130
6326
  return;
6131
6327
  }
6132
- const refRec = own2(r, "ref");
6328
+ const refRec = own3(r, "ref");
6133
6329
  if (!isRecord(refRec)) return;
6134
6330
  const ref = this.fileRefOf(refRec, `${path}.ref`);
6135
6331
  this.validateFileRef(`${path}.ref`, ref);
@@ -6142,22 +6338,22 @@ var Walker = class _Walker {
6142
6338
  }
6143
6339
  }
6144
6340
  expectationIsBinaryReferenceOnly(e, path) {
6145
- const reference = own2(e, "reference");
6146
- 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;
6147
6343
  if (!isRecord(refRec)) return false;
6148
6344
  const mediaType = this.s(refRec, "media_type", `${path}.reference.ref`);
6149
6345
  if (mediaType === "" || isTextualMediaType(mediaType)) return false;
6150
6346
  const status = this.s(e, "status", path);
6151
- const fields = own2(e, "fields");
6152
- const exact = own2(e, "exact");
6153
- 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);
6154
6350
  }
6155
6351
  validateFieldMatcher(path, m) {
6156
6352
  const L = EXAMPLES.limits;
6157
6353
  const matches = this.s(m, "matches", path);
6158
- const oneOf = own2(m, "one_of");
6159
- const approx = numberOf(own2(m, "approx"));
6160
- 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"));
6161
6357
  let operators = 0;
6162
6358
  if (has(m, "equals")) operators++;
6163
6359
  if (this.s(m, "contains", path) !== "") operators++;
@@ -6165,7 +6361,7 @@ var Walker = class _Walker {
6165
6361
  if (matches !== "") operators++;
6166
6362
  if (Array.isArray(oneOf) && oneOf.length > 0) operators++;
6167
6363
  if (approx !== void 0) operators++;
6168
- if (typeof own2(m, "present") === "boolean") operators++;
6364
+ if (typeof own3(m, "present") === "boolean") operators++;
6169
6365
  if (operators !== 1) {
6170
6366
  this.err(
6171
6367
  "example_field_matcher_invalid",
@@ -6192,12 +6388,12 @@ var Walker = class _Walker {
6192
6388
  // -- checkpoints ------------------------------------------------------
6193
6389
  validateCheckpoints(path, label, cps) {
6194
6390
  if (!isRecord(cps) || Object.keys(cps).length === 0) return;
6195
- const stepsRaw = own2(this.flow, "steps");
6391
+ const stepsRaw = own3(this.flow, "steps");
6196
6392
  const steps = isRecord(stepsRaw) ? stepsRaw : {};
6197
6393
  const stepIds = sortedKeys(steps);
6198
6394
  for (const id of sortedKeys(cps)) {
6199
6395
  const cpath = `${path}.checkpoints.${id}`;
6200
- const step = own2(steps, id);
6396
+ const step = own3(steps, id);
6201
6397
  if (!isRecord(step)) {
6202
6398
  this.err(
6203
6399
  "example_checkpoint_step_unknown",
@@ -6207,7 +6403,7 @@ var Walker = class _Walker {
6207
6403
  );
6208
6404
  continue;
6209
6405
  }
6210
- const next = own2(step, "next");
6406
+ const next = own3(step, "next");
6211
6407
  if (has(step, "for_each") || has(step, "loop") || isRecord(next) && has(next, "parallel")) {
6212
6408
  this.err(
6213
6409
  "example_checkpoint_step_composite",
@@ -6216,7 +6412,7 @@ var Walker = class _Walker {
6216
6412
  );
6217
6413
  continue;
6218
6414
  }
6219
- const cp = own2(cps, id);
6415
+ const cp = own3(cps, id);
6220
6416
  if (cp === null || cp === void 0) {
6221
6417
  this.validateExpectation(cpath, label, {}, "checkpoint", id);
6222
6418
  } else if (isRecord(cp)) {
@@ -6227,7 +6423,7 @@ var Walker = class _Walker {
6227
6423
  // -- variants ---------------------------------------------------------
6228
6424
  validateVariants(i, path, label, ex, hasInput, baseInput) {
6229
6425
  const L = EXAMPLES.limits;
6230
- const variants = own2(ex, "variants");
6426
+ const variants = own3(ex, "variants");
6231
6427
  if (!Array.isArray(variants) || variants.length === 0) return;
6232
6428
  if (variants.length > L.maxVariants) {
6233
6429
  this.err(
@@ -6290,8 +6486,8 @@ var Walker = class _Walker {
6290
6486
  `example ${q(both)} notes are ${provN} characters; the limit is ${L.maxProvenanceRunes}`
6291
6487
  );
6292
6488
  }
6293
- this.validateWeight(`${vpath}.weight`, both, numberOf(own2(v, "weight")));
6294
- const patch = own2(v, "input_patch");
6489
+ this.validateWeight(`${vpath}.weight`, both, numberOf(own3(v, "weight")));
6490
+ const patch = own3(v, "input_patch");
6295
6491
  const patchRec = isRecord(patch) ? patch : null;
6296
6492
  const hasPatch = patchRec !== null && Object.keys(patchRec).length > 0;
6297
6493
  const hasRef = has(v, "input_ref");
@@ -6308,7 +6504,7 @@ var Walker = class _Walker {
6308
6504
  `variant ${q(vlabel)} of example ${q(label)} changes neither the input nor the expectation`
6309
6505
  );
6310
6506
  }
6311
- const refRec = own2(v, "input_ref");
6507
+ const refRec = own3(v, "input_ref");
6312
6508
  if (isRecord(refRec)) {
6313
6509
  this.validateFileRef(`${vpath}.input_ref`, this.fileRefOf(refRec, `${vpath}.input_ref`));
6314
6510
  }
@@ -6323,7 +6519,7 @@ var Walker = class _Walker {
6323
6519
  this.checkVariantPatch(vpath, label, vlabel, baseInput, patchRec);
6324
6520
  }
6325
6521
  }
6326
- const expected = own2(v, "expected");
6522
+ const expected = own3(v, "expected");
6327
6523
  if (isRecord(expected)) {
6328
6524
  this.validateExpectation(`${vpath}.expected`, both, expected, "final", "");
6329
6525
  }
@@ -6334,11 +6530,11 @@ var Walker = class _Walker {
6334
6530
  * itself supplies. A null patch value deleting a secret is fine.
6335
6531
  */
6336
6532
  checkVariantPatch(vpath, label, vlabel, base, patch) {
6337
- const schema = own2(this.flow, "input_schema");
6533
+ const schema = own3(this.flow, "input_schema");
6338
6534
  if (isRecord(schema)) {
6339
6535
  for (const f of this.schemaFields(schema)) {
6340
6536
  if (f.type !== TYPE_SECRET) continue;
6341
- const val = own2(patch, f.name);
6537
+ const val = own3(patch, f.name);
6342
6538
  if (val !== void 0 && val !== null) {
6343
6539
  this.err(
6344
6540
  "example_secret_value",
@@ -6378,18 +6574,18 @@ var Walker = class _Walker {
6378
6574
  emit(`${path}.title`, this.s(ex, "title", path));
6379
6575
  emit(`${path}.guidance`, this.s(ex, "guidance", path));
6380
6576
  emit(`${path}.notes`, this.s(ex, "notes", path));
6381
- const input = own2(ex, "input");
6577
+ const input = own3(ex, "input");
6382
6578
  if (isRecord(input)) scanLeaves(`${path}.input`, input, 0, emit);
6383
- const expected = own2(ex, "expected");
6579
+ const expected = own3(ex, "expected");
6384
6580
  if (isRecord(expected)) this.scanExpectationLeaves(`${path}.expected`, expected, emit);
6385
- const cps = own2(ex, "checkpoints");
6581
+ const cps = own3(ex, "checkpoints");
6386
6582
  if (isRecord(cps)) {
6387
6583
  for (const id of sortedKeys(cps)) {
6388
- const cp = own2(cps, id);
6584
+ const cp = own3(cps, id);
6389
6585
  if (isRecord(cp)) this.scanExpectationLeaves(`${path}.checkpoints.${id}`, cp, emit);
6390
6586
  }
6391
6587
  }
6392
- const variants = own2(ex, "variants");
6588
+ const variants = own3(ex, "variants");
6393
6589
  if (Array.isArray(variants)) {
6394
6590
  variants.forEach((v, j) => {
6395
6591
  if (!isRecord(v)) return;
@@ -6397,34 +6593,34 @@ var Walker = class _Walker {
6397
6593
  emit(`${vpath}.title`, this.s(v, "title", vpath));
6398
6594
  emit(`${vpath}.guidance`, this.s(v, "guidance", vpath));
6399
6595
  emit(`${vpath}.provenance`, this.s(v, "provenance", vpath));
6400
- scanLeaves(`${vpath}.input_patch`, own2(v, "input_patch"), 0, emit);
6401
- const vexp = own2(v, "expected");
6596
+ scanLeaves(`${vpath}.input_patch`, own3(v, "input_patch"), 0, emit);
6597
+ const vexp = own3(v, "expected");
6402
6598
  if (isRecord(vexp)) this.scanExpectationLeaves(`${vpath}.expected`, vexp, emit);
6403
6599
  });
6404
6600
  }
6405
6601
  }
6406
6602
  scanExpectationLeaves(path, e, emit) {
6407
6603
  emit(`${path}.rubric`, this.s(e, "rubric", path));
6408
- const reference = own2(e, "reference");
6604
+ const reference = own3(e, "reference");
6409
6605
  if (isRecord(reference)) {
6410
6606
  emit(`${path}.reference.text`, this.s(reference, "text", `${path}.reference`));
6411
6607
  }
6412
- this.stringList(own2(e, "must_not"), `${path}.must_not`).forEach(
6608
+ this.stringList(own3(e, "must_not"), `${path}.must_not`).forEach(
6413
6609
  (s, j) => emit(`${path}.must_not[${j}]`, s)
6414
6610
  );
6415
- 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(
6416
6612
  (s, j) => emit(`${path}.must_not_contain[${j}]`, s)
6417
6613
  );
6418
- const fields = own2(e, "fields");
6614
+ const fields = own3(e, "fields");
6419
6615
  if (isRecord(fields)) {
6420
6616
  for (const key of sortedKeys(fields)) {
6421
- const m = own2(fields, key);
6617
+ const m = own3(fields, key);
6422
6618
  if (!isRecord(m)) continue;
6423
6619
  const fpath = `${path}.fields.${key}`;
6424
- scanLeaves(`${fpath}.equals`, own2(m, "equals"), 0, emit);
6620
+ scanLeaves(`${fpath}.equals`, own3(m, "equals"), 0, emit);
6425
6621
  emit(`${fpath}.contains`, this.s(m, "contains", fpath));
6426
6622
  emit(`${fpath}.not_contains`, this.s(m, "not_contains", fpath));
6427
- const oneOf = own2(m, "one_of");
6623
+ const oneOf = own3(m, "one_of");
6428
6624
  if (Array.isArray(oneOf)) {
6429
6625
  oneOf.forEach(
6430
6626
  (one, j) => scanLeaves(`${fpath}.one_of[${j}]`, one, 0, emit)
@@ -6432,7 +6628,7 @@ var Walker = class _Walker {
6432
6628
  }
6433
6629
  }
6434
6630
  }
6435
- scanLeaves(`${path}.exact`, own2(e, "exact"), 0, emit);
6631
+ scanLeaves(`${path}.exact`, own3(e, "exact"), 0, emit);
6436
6632
  }
6437
6633
  };
6438
6634
  function scoreInRange(v) {
@@ -6548,7 +6744,7 @@ function inputValueFailures(f, raw) {
6548
6744
  case TYPE_FILE2: {
6549
6745
  if (typeof raw === "string") return raw === "" ? [mismatch(f, TYPE_FILE2)] : [];
6550
6746
  if (isRecord(raw)) {
6551
- const ref = own2(raw, FILE_REF_KEY);
6747
+ const ref = own3(raw, FILE_REF_KEY);
6552
6748
  return typeof ref === "string" && ref !== "" ? [] : [mismatch(f, TYPE_FILE2)];
6553
6749
  }
6554
6750
  return [mismatch(f, TYPE_FILE2)];
@@ -6628,6 +6824,7 @@ function validateParsed(flow, opts, sources) {
6628
6824
  validateCredentialEndpointPairing(f, issues);
6629
6825
  validateExamples(f, issues);
6630
6826
  validateOrchestratorExons(f, issues);
6827
+ validateResidencyEnforcement(f, issues);
6631
6828
  validateUnknownKeys(f, issues);
6632
6829
  const templateStats = validateTemplates(f, issues, opts);
6633
6830
  const totalSteps = f.steps && typeof f.steps === "object" && !Array.isArray(f.steps) ? Object.keys(f.steps).length : 0;