@vaudience/aigentflow-flow-validator 0.19.0 → 0.21.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -304,6 +304,17 @@ function isValidGoDuration(input) {
304
304
  var RESERVED_STEP_ID_CHAR = ".";
305
305
  var RESERVED_STEP_ID_ORCHESTRATOR = "orchestrator";
306
306
  var DISPLAY_NAME_MAX_LEN = 80;
307
+ var YAML11_BOOL_WORDS = new Set(
308
+ ["y", "yes", "on", "n", "no", "off"].flatMap((w) => [
309
+ w,
310
+ w.toUpperCase(),
311
+ w[0].toUpperCase() + w.slice(1)
312
+ ])
313
+ );
314
+ function isBoolLike(v) {
315
+ if (v === null || typeof v === "boolean") return true;
316
+ return typeof v === "string" && YAML11_BOOL_WORDS.has(v);
317
+ }
307
318
  function validateBasicStructure(flow, issues) {
308
319
  if (!issues.nonEmptyStringOf(flow, "aigentflow_version", "")) {
309
320
  issues.error({
@@ -333,6 +344,14 @@ function validateBasicStructure(flow, issues) {
333
344
  });
334
345
  }
335
346
  }
347
+ if (flow.strict_templates !== void 0 && !isBoolLike(flow.strict_templates)) {
348
+ issues.error({
349
+ field: "strict_templates",
350
+ message: "strict_templates must be a boolean (true or false)",
351
+ code: "invalid_type",
352
+ suggestion: "Write 'strict_templates: true' or remove the key"
353
+ });
354
+ }
336
355
  const start = issues.stringOf(flow, "start", "");
337
356
  if (start === null || start === "") {
338
357
  issues.error({
@@ -432,7 +451,7 @@ function validateBasicStructure(flow, issues) {
432
451
 
433
452
  // src/spec/aigentflow-spec.json
434
453
  var aigentflow_spec_default = {
435
- specVersion: "2.820.0",
454
+ specVersion: "2.827.0",
436
455
  inputSchemaVersion: 1,
437
456
  executorSchemes: [
438
457
  "a2a",
@@ -456,6 +475,7 @@ var aigentflow_spec_default = {
456
475
  "geocoding",
457
476
  "geovisualize",
458
477
  "getmd",
478
+ "here",
459
479
  "homeassistant",
460
480
  "hosting",
461
481
  "http",
@@ -1257,6 +1277,39 @@ var aigentflow_spec_default = {
1257
1277
  }
1258
1278
  }
1259
1279
  },
1280
+ templateDefaultPiped: {
1281
+ code: "template_default_piped",
1282
+ messageFormat: "`default` takes the value FIRST, and a pipe passes the piped value LAST: `%s` is `default <fallback> <value>`, so the fallback is always the result",
1283
+ suggestion: 'write the value first and the fallback second, as a call: `{{ default .x "fallback" }}`'
1284
+ },
1285
+ complianceResidency: {
1286
+ code: "compliance_residency_unenforced",
1287
+ euResidencyCodes: ["EU", "DE", "FR", "IE", "NL", "IT", "ES"],
1288
+ regionLaneProviders: [
1289
+ "bedrock",
1290
+ "google",
1291
+ "azure",
1292
+ "openai",
1293
+ "assemblyai",
1294
+ "speechmatics",
1295
+ "deepgram",
1296
+ "mistral"
1297
+ ],
1298
+ aiProtocol: "ai",
1299
+ protocolSeparator: "://",
1300
+ regionParam: "region",
1301
+ enforceRegionParam: "enforce_region",
1302
+ baseUrlParamSuffix: "_base_url",
1303
+ enforceRegionTrueStrings: ["true", "1", "yes"],
1304
+ stepFieldFormat: "steps.%s.executor",
1305
+ loopStepFieldFormat: "steps.%s.loop.steps.%s.executor",
1306
+ orchestratorField: "orchestrator.exons",
1307
+ siteStepFormat: "step %q",
1308
+ siteLoopStepFormat: "loop sub-step %q of step %q",
1309
+ siteOrchestrator: "the orchestrator",
1310
+ 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",
1311
+ 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."
1312
+ },
1260
1313
  examples: {
1261
1314
  limits: {
1262
1315
  maxPerFlow: 50,
@@ -1527,6 +1580,7 @@ var aigentflow_spec_default = {
1527
1580
  rate_limit: "FlowRateLimitConfig",
1528
1581
  start: "scalar",
1529
1582
  steps: "map<StepDefinition>",
1583
+ strict_templates: "scalar",
1530
1584
  tags: "list<scalar>",
1531
1585
  template: "FlowTemplateMetadata",
1532
1586
  tool_discovery: "scalar",
@@ -1852,6 +1906,25 @@ var CREDENTIAL_ENDPOINT_PAIRING = {
1852
1906
  familyKeySeparator: aigentflow_spec_default.credentialEndpointPairing.familyKeySeparator,
1853
1907
  families: aigentflow_spec_default.credentialEndpointPairing.families
1854
1908
  };
1909
+ var COMPLIANCE_RESIDENCY = {
1910
+ code: aigentflow_spec_default.complianceResidency.code,
1911
+ euResidencyCodes: aigentflow_spec_default.complianceResidency.euResidencyCodes,
1912
+ regionLaneProviders: aigentflow_spec_default.complianceResidency.regionLaneProviders,
1913
+ aiProtocol: aigentflow_spec_default.complianceResidency.aiProtocol,
1914
+ protocolSeparator: aigentflow_spec_default.complianceResidency.protocolSeparator,
1915
+ regionParam: aigentflow_spec_default.complianceResidency.regionParam,
1916
+ enforceRegionParam: aigentflow_spec_default.complianceResidency.enforceRegionParam,
1917
+ baseUrlParamSuffix: aigentflow_spec_default.complianceResidency.baseUrlParamSuffix,
1918
+ enforceRegionTrueStrings: aigentflow_spec_default.complianceResidency.enforceRegionTrueStrings,
1919
+ stepFieldFormat: aigentflow_spec_default.complianceResidency.stepFieldFormat,
1920
+ loopStepFieldFormat: aigentflow_spec_default.complianceResidency.loopStepFieldFormat,
1921
+ orchestratorField: aigentflow_spec_default.complianceResidency.orchestratorField,
1922
+ siteStepFormat: aigentflow_spec_default.complianceResidency.siteStepFormat,
1923
+ siteLoopStepFormat: aigentflow_spec_default.complianceResidency.siteLoopStepFormat,
1924
+ siteOrchestrator: aigentflow_spec_default.complianceResidency.siteOrchestrator,
1925
+ messageFormat: aigentflow_spec_default.complianceResidency.messageFormat,
1926
+ suggestion: aigentflow_spec_default.complianceResidency.suggestion
1927
+ };
1855
1928
  var EXAMPLES = {
1856
1929
  limits: aigentflow_spec_default.examples.limits,
1857
1930
  idPattern: new RegExp(aigentflow_spec_default.examples.idPattern),
@@ -1869,6 +1942,11 @@ var EXAMPLES = {
1869
1942
  name: p.name,
1870
1943
  re: new RegExp(p.expr, p.flags)
1871
1944
  }))};
1945
+ var TEMPLATE_DEFAULT_PIPED = {
1946
+ code: aigentflow_spec_default.templateDefaultPiped.code,
1947
+ messageFormat: aigentflow_spec_default.templateDefaultPiped.messageFormat,
1948
+ suggestion: aigentflow_spec_default.templateDefaultPiped.suggestion
1949
+ };
1872
1950
 
1873
1951
  // src/validators/executors.ts
1874
1952
  var SCHEME_SEPARATOR = "://";
@@ -3832,6 +3910,117 @@ function splitPipeline(body) {
3832
3910
  return stages;
3833
3911
  }
3834
3912
 
3913
+ // src/template/gotmpl-default.ts
3914
+ var FUNCTION_NAME = "default";
3915
+ var PIPE = "|";
3916
+ var OPEN_PAREN = "(";
3917
+ var CLOSE_PAREN = ")";
3918
+ var MAX_NESTING_DEPTH = 100;
3919
+ var PIPELINE_KEYWORDS = /^(?:else\s+if|else\s+with|if|range|with|template|block)(?![\w$.])/;
3920
+ var NO_PIPELINE = /^(?:define|else|end|break|continue)(?![\w$.])/;
3921
+ var DECLARATION = /^\$\w*(?:\s*,\s*\$\w*)*\s*:?=/;
3922
+ function pipedDefaultPipelines(src) {
3923
+ const { actions, fatal } = lexActions(src);
3924
+ if (fatal) return [];
3925
+ const found = /* @__PURE__ */ new Set();
3926
+ try {
3927
+ for (const action of actions) {
3928
+ if (action.isComment || action.body === "") continue;
3929
+ scanAction(action.body, found);
3930
+ }
3931
+ } catch (err) {
3932
+ if (!(err instanceof RangeError)) throw err;
3933
+ return [];
3934
+ }
3935
+ return [...found].sort();
3936
+ }
3937
+ function scanAction(body, found) {
3938
+ let rest = body;
3939
+ const kw = PIPELINE_KEYWORDS.exec(rest);
3940
+ if (!kw && NO_PIPELINE.test(rest)) return;
3941
+ if (kw) {
3942
+ rest = rest.slice(kw[0].length).trimStart();
3943
+ const keyword = kw[0].replace(/\s+/g, " ");
3944
+ if (keyword === "template" || keyword === "block") {
3945
+ const q2 = rest[0];
3946
+ if (q2 === '"' || q2 === "`") {
3947
+ const end = scanString(rest, 0, q2);
3948
+ if (end === -1) return;
3949
+ rest = rest.slice(end + 1).trimStart();
3950
+ }
3951
+ }
3952
+ }
3953
+ if (rest === "") return;
3954
+ parsePipeline(rest, 0, false, found, 0);
3955
+ }
3956
+ function parsePipeline(src, start, nested, found, depth) {
3957
+ if (depth > MAX_NESTING_DEPTH) return { text: src.slice(start), end: src.length };
3958
+ let i = start;
3959
+ const n = src.length;
3960
+ let decl = "";
3961
+ const decMatch = DECLARATION.exec(src.slice(i));
3962
+ if (decMatch) {
3963
+ decl = decMatch[0].replace(/\s+/g, " ") + " ";
3964
+ i += decMatch[0].length;
3965
+ }
3966
+ const commands = [];
3967
+ let current = [];
3968
+ let firstWords = [];
3969
+ let pipedDefault = false;
3970
+ const pushCommand = () => {
3971
+ if (current.length > 0) {
3972
+ commands.push(current);
3973
+ firstWords.push(current[0]);
3974
+ }
3975
+ current = [];
3976
+ };
3977
+ while (i < n) {
3978
+ const c = src[i];
3979
+ if (c === " " || c === " " || c === "\n" || c === "\r") {
3980
+ i += 1;
3981
+ continue;
3982
+ }
3983
+ if (c === '"' || c === "`" || c === "'") {
3984
+ const end = scanString(src, i, c);
3985
+ const stop = end === -1 ? n - 1 : end;
3986
+ current.push(src.slice(i, stop + 1));
3987
+ i = stop + 1;
3988
+ continue;
3989
+ }
3990
+ if (c === OPEN_PAREN) {
3991
+ const inner = parsePipeline(src, i + 1, true, found, depth + 1);
3992
+ current.push(`(${inner.text})`);
3993
+ i = inner.end;
3994
+ continue;
3995
+ }
3996
+ if (c === CLOSE_PAREN) {
3997
+ if (nested) {
3998
+ i += 1;
3999
+ break;
4000
+ }
4001
+ i += 1;
4002
+ continue;
4003
+ }
4004
+ if (c === PIPE) {
4005
+ pushCommand();
4006
+ i += 1;
4007
+ continue;
4008
+ }
4009
+ let j = i;
4010
+ while (j < n && !/[\s|()"`']/.test(src[j])) j += 1;
4011
+ if (j === i) j = i + 1;
4012
+ current.push(src.slice(i, j));
4013
+ i = j;
4014
+ }
4015
+ pushCommand();
4016
+ firstWords.forEach((word, idx) => {
4017
+ if (idx > 0 && word === FUNCTION_NAME) pipedDefault = true;
4018
+ });
4019
+ const text = decl + commands.map((cmd) => cmd.join(" ")).join(` ${PIPE} `);
4020
+ if (pipedDefault) found.add(text);
4021
+ return { text, end: i };
4022
+ }
4023
+
3835
4024
  // src/validators/processingOperations.ts
3836
4025
  var PROCESSING_OP_GUARD_KEY = PROCESSING_OPERATIONS.guardKey;
3837
4026
  var PROCESSING_PHASES = ["pre_processing", "post_processing"];
@@ -3978,6 +4167,17 @@ function checkTemplateString(value, field, stepID, issues, stats, opts, demote =
3978
4167
  });
3979
4168
  }
3980
4169
  }
4170
+ if (errors.length > 0) return;
4171
+ for (const pipe of pipedDefaultPipelines(value)) {
4172
+ report({
4173
+ field,
4174
+ message: TEMPLATE_DEFAULT_PIPED.messageFormat.replace("%s", () => pipe),
4175
+ code: TEMPLATE_DEFAULT_PIPED.code,
4176
+ stepId: stepID,
4177
+ context: `Template: ${value}`,
4178
+ suggestion: TEMPLATE_DEFAULT_PIPED.suggestion
4179
+ });
4180
+ }
3981
4181
  }
3982
4182
  function walkStrings2(basePath, value, stepID, issues, stats, opts, check, demote = false) {
3983
4183
  if (isString(value)) {
@@ -5204,6 +5404,141 @@ function warnOrchestratorToolWithheld(flow, orch, report, issues) {
5204
5404
  }
5205
5405
  }
5206
5406
 
5407
+ // src/validators/complianceResidency.ts
5408
+ function own2(m, key) {
5409
+ if (!isRecord(m) || !Object.prototype.hasOwnProperty.call(m, key)) return void 0;
5410
+ return m[key];
5411
+ }
5412
+ function sprintf(format, ...args) {
5413
+ let i = 0;
5414
+ return format.replace(/%[sqv]/g, (verb) => {
5415
+ const arg = args[i++] ?? "";
5416
+ return verb === "%q" ? JSON.stringify(arg) : arg;
5417
+ });
5418
+ }
5419
+ function literalOrEmpty(s) {
5420
+ const t = goTrimSpace2(s);
5421
+ return t.includes(TEMPLATE_ACTION_OPEN) ? "" : t;
5422
+ }
5423
+ function euOnlyResidency(flow, issues) {
5424
+ const raw = own2(own2(flow, "compliance"), "residency");
5425
+ if (!isArray(raw)) return null;
5426
+ const codes = [];
5427
+ for (let i = 0; i < raw.length; i++) {
5428
+ if (raw[i] === null) continue;
5429
+ const code = issues.stringAt(raw[i], `compliance.residency[${i}]`);
5430
+ if (code === null) return null;
5431
+ codes.push(code);
5432
+ }
5433
+ if (codes.length === 0) return null;
5434
+ const eu = new Set(COMPLIANCE_RESIDENCY.euResidencyCodes);
5435
+ return codes.every((c) => eu.has(goTrimSpace2(c).toUpperCase())) ? codes : null;
5436
+ }
5437
+ function aiProvider(executor) {
5438
+ const prefix = COMPLIANCE_RESIDENCY.aiProtocol + COMPLIANCE_RESIDENCY.protocolSeparator;
5439
+ if (!executor.startsWith(prefix)) return "";
5440
+ const rest = executor.slice(prefix.length);
5441
+ const slash = rest.indexOf("/");
5442
+ const provider = slash > 0 ? rest.slice(0, slash) : "";
5443
+ return provider.includes(TEMPLATE_ACTION_OPEN) ? "" : provider;
5444
+ }
5445
+ function isRegionLane(provider) {
5446
+ const literal = literalOrEmpty(provider);
5447
+ return literal !== "" && COMPLIANCE_RESIDENCY.regionLaneProviders.includes(literal.toLowerCase());
5448
+ }
5449
+ function nonBlankString(m, key) {
5450
+ const v = own2(m, key);
5451
+ return typeof v === "string" && goTrimSpace2(v) !== "";
5452
+ }
5453
+ function queryEnforcesRegion(query) {
5454
+ const v = own2(query, COMPLIANCE_RESIDENCY.enforceRegionParam);
5455
+ if (typeof v === "boolean") return v;
5456
+ return typeof v === "string" && COMPLIANCE_RESIDENCY.enforceRegionTrueStrings.includes(v);
5457
+ }
5458
+ function flowDirectsEndpoint(flow, provider, issues) {
5459
+ const key = provider.toLowerCase();
5460
+ const inst = own2(own2(flow, "executor_config"), key);
5461
+ if (!isRecord(inst)) return false;
5462
+ const baseUrl = issues.stringOf(inst, "base_url", `executor_config.${key}`);
5463
+ return baseUrl !== null && goTrimSpace2(baseUrl) !== "";
5464
+ }
5465
+ function callPinsEndpoint(flow, provider, query, issues) {
5466
+ if (nonBlankString(query, COMPLIANCE_RESIDENCY.regionParam)) return true;
5467
+ if (queryEnforcesRegion(query)) return true;
5468
+ if (nonBlankString(query, provider.toLowerCase() + COMPLIANCE_RESIDENCY.baseUrlParamSuffix)) return true;
5469
+ return flowDirectsEndpoint(flow, provider, issues);
5470
+ }
5471
+ function validateResidencyEnforcement(flow, issues) {
5472
+ const residency = euOnlyResidency(flow, issues);
5473
+ if (residency === null) return;
5474
+ const warn = (site, field, stepId, provider) => {
5475
+ issues.warn({
5476
+ field,
5477
+ ...stepId === void 0 ? {} : { stepId },
5478
+ code: COMPLIANCE_RESIDENCY.code,
5479
+ message: sprintf(COMPLIANCE_RESIDENCY.messageFormat, site, provider, `[${residency.join(" ")}]`),
5480
+ suggestion: COMPLIANCE_RESIDENCY.suggestion
5481
+ });
5482
+ };
5483
+ const steps = flow.steps;
5484
+ if (isRecord(steps)) {
5485
+ for (const stepId of Object.keys(steps).sort()) {
5486
+ const step = steps[stepId];
5487
+ if (!isRecord(step)) continue;
5488
+ const calls = [
5489
+ {
5490
+ executor: issues.stringOf(step, "executor", `steps.${stepId}`) ?? "",
5491
+ query: own2(step, "query"),
5492
+ subId: null
5493
+ }
5494
+ ];
5495
+ for (const sub of loopSubStepsOfStep(stepId, step)) {
5496
+ calls.push({
5497
+ executor: issues.stringOf(sub.raw, "executor", sub.basePath) ?? "",
5498
+ query: own2(sub.raw, "query"),
5499
+ subId: issues.stringOf(sub.raw, "id", sub.basePath) ?? ""
5500
+ });
5501
+ }
5502
+ for (const call of calls) {
5503
+ const provider = aiProvider(call.executor);
5504
+ if (!isRegionLane(provider)) continue;
5505
+ if (callPinsEndpoint(flow, provider, call.query, issues)) continue;
5506
+ if (call.subId === null) {
5507
+ warn(
5508
+ sprintf(COMPLIANCE_RESIDENCY.siteStepFormat, stepId),
5509
+ sprintf(COMPLIANCE_RESIDENCY.stepFieldFormat, stepId),
5510
+ stepId,
5511
+ provider
5512
+ );
5513
+ } else {
5514
+ warn(
5515
+ sprintf(COMPLIANCE_RESIDENCY.siteLoopStepFormat, call.subId, stepId),
5516
+ sprintf(COMPLIANCE_RESIDENCY.loopStepFieldFormat, stepId, call.subId),
5517
+ stepId,
5518
+ provider
5519
+ );
5520
+ }
5521
+ }
5522
+ }
5523
+ }
5524
+ warnOrchestrator(flow, issues, warn);
5525
+ }
5526
+ function warnOrchestrator(flow, issues, warn) {
5527
+ const orch = flow.orchestrator;
5528
+ if (!isRecord(orch)) return;
5529
+ const source = issues.stringOf(orch, "exons", "orchestrator");
5530
+ if (source === null || source === "") return;
5531
+ const report = inspectExonsFrontmatter(source);
5532
+ if (report.parseError !== null || !report.specRead || !report.hasSpec) return;
5533
+ const provider = literalOrEmpty(report.provider);
5534
+ if (!isRegionLane(provider)) return;
5535
+ const region = issues.stringOf(orch, "region", "orchestrator");
5536
+ if (region !== null && goTrimSpace2(region) !== "") return;
5537
+ if (orch.enforce_region === true) return;
5538
+ if (flowDirectsEndpoint(flow, provider, issues)) return;
5539
+ warn(COMPLIANCE_RESIDENCY.siteOrchestrator, COMPLIANCE_RESIDENCY.orchestratorField, void 0, provider);
5540
+ }
5541
+
5207
5542
  // src/validators/examples.ts
5208
5543
  var KEY_EXAMPLES = "examples";
5209
5544
  var VISIBILITY_PUBLIC = "public";
@@ -5281,7 +5616,7 @@ function num(n) {
5281
5616
  function has(o, key) {
5282
5617
  return Object.prototype.hasOwnProperty.call(o, key) && o[key] !== null && o[key] !== void 0;
5283
5618
  }
5284
- function own2(o, key) {
5619
+ function own3(o, key) {
5285
5620
  return Object.prototype.hasOwnProperty.call(o, key) ? o[key] : void 0;
5286
5621
  }
5287
5622
  function setOwn(o, key, value) {
@@ -5333,7 +5668,7 @@ function mergePatch(target, patch, depth) {
5333
5668
  continue;
5334
5669
  }
5335
5670
  if (isRecord(pv)) {
5336
- const current = own2(target, k);
5671
+ const current = own3(target, k);
5337
5672
  const existing = isRecord(current) ? deepCopy(current, 0) : {};
5338
5673
  mergePatch(existing, pv, depth + 1);
5339
5674
  setOwn(target, k, existing);
@@ -5353,7 +5688,7 @@ function asFileRef(v) {
5353
5688
  if (keys.length === 0) return null;
5354
5689
  for (const k of keys) if (!FILE_REF_KEYS.has(k)) return null;
5355
5690
  const str = (k) => {
5356
- const x = own2(v, k);
5691
+ const x = own3(v, k);
5357
5692
  return typeof x === "string" ? x : "";
5358
5693
  };
5359
5694
  return {
@@ -5421,7 +5756,7 @@ var Walker = class _Walker {
5421
5756
  `the examples block is ${size} bytes; the limit is ${L.maxBlockBytes}. Move large inputs or target outputs to a file reference (https URL).`
5422
5757
  );
5423
5758
  }
5424
- const allHeld = examples.every((e) => isRecord(e) && own2(e, "hold_out") === true);
5759
+ const allHeld = examples.every((e) => isRecord(e) && own3(e, "hold_out") === true);
5425
5760
  if (allHeld) {
5426
5761
  this.warn(
5427
5762
  "examples_all_held_out",
@@ -5509,9 +5844,9 @@ var Walker = class _Walker {
5509
5844
  `example ${q(label)} notes are ${notesN} characters; the limit is ${L.maxNotesRunes}`
5510
5845
  );
5511
5846
  }
5512
- this.validateTags(path, label, own2(ex, "tags"));
5513
- this.validateWeight(`${path}.weight`, label, numberOf(own2(ex, "weight")));
5514
- const minScore = numberOf(own2(ex, "min_score"));
5847
+ this.validateTags(path, label, own3(ex, "tags"));
5848
+ this.validateWeight(`${path}.weight`, label, numberOf(own3(ex, "weight")));
5849
+ const minScore = numberOf(own3(ex, "min_score"));
5515
5850
  if (minScore !== void 0 && !scoreInRange(minScore)) {
5516
5851
  this.err(
5517
5852
  "example_min_score_range",
@@ -5527,7 +5862,7 @@ var Walker = class _Walker {
5527
5862
  `example ${q(label)} has side_effects ${q(sideEffects)}; use refuse or allow`
5528
5863
  );
5529
5864
  }
5530
- const holdOut = own2(ex, "hold_out") === true;
5865
+ const holdOut = own3(ex, "hold_out") === true;
5531
5866
  if (holdOut && this.isPublic()) {
5532
5867
  this.err(
5533
5868
  "example_holdout_in_public_flow",
@@ -5550,17 +5885,17 @@ var Walker = class _Walker {
5550
5885
  `example ${q(label)} has neither input nor input_ref; use input: {} for a flow that takes no input`
5551
5886
  );
5552
5887
  }
5553
- const rawInput = own2(ex, "input");
5888
+ const rawInput = own3(ex, "input");
5554
5889
  const baseInput = isRecord(rawInput) ? rawInput : null;
5555
5890
  if (baseInput !== null) {
5556
5891
  this.checkInput(`${path}.input`, label, baseInput, "example_input_invalid");
5557
5892
  }
5558
- const rawInputRef = own2(ex, "input_ref");
5893
+ const rawInputRef = own3(ex, "input_ref");
5559
5894
  if (isRecord(rawInputRef)) {
5560
5895
  this.validateFileRef(`${path}.input_ref`, this.fileRefOf(rawInputRef, `${path}.input_ref`));
5561
5896
  }
5562
5897
  let binaryOnly = false;
5563
- const expected = own2(ex, "expected");
5898
+ const expected = own3(ex, "expected");
5564
5899
  if (!has(ex, "expected")) {
5565
5900
  this.err(
5566
5901
  "example_expected_missing",
@@ -5579,7 +5914,7 @@ var Walker = class _Walker {
5579
5914
  "this example can be run but not scored"
5580
5915
  );
5581
5916
  }
5582
- this.validateCheckpoints(path, label, own2(ex, "checkpoints"));
5917
+ this.validateCheckpoints(path, label, own3(ex, "checkpoints"));
5583
5918
  this.validateVariants(i, path, label, ex, hasInput, baseInput);
5584
5919
  this.scanSecretLike(i, path, ex);
5585
5920
  }
@@ -5639,8 +5974,8 @@ var Walker = class _Walker {
5639
5974
  );
5640
5975
  return;
5641
5976
  }
5642
- const schema = own2(this.flow, "input_schema");
5643
- const query = own2(this.flow, "query");
5977
+ const schema = own3(this.flow, "input_schema");
5978
+ const query = own3(this.flow, "query");
5644
5979
  if (isRecord(schema)) {
5645
5980
  this.checkInputAgainstSchema(field, label, input, schema, code);
5646
5981
  } else if (isRecord(query) && Object.keys(query).length > 0) {
@@ -5708,29 +6043,29 @@ var Walker = class _Walker {
5708
6043
  }
5709
6044
  }
5710
6045
  schemaFields(schema) {
5711
- const raw = own2(schema, "fields");
6046
+ const raw = own3(schema, "fields");
5712
6047
  if (!Array.isArray(raw)) return [];
5713
6048
  const out = [];
5714
6049
  raw.forEach((f, i) => {
5715
6050
  if (!isRecord(f)) return;
5716
6051
  const base = `input_schema.fields[${i}]`;
5717
- const enumRaw = own2(f, "enum");
6052
+ const enumRaw = own3(f, "enum");
5718
6053
  const enumValues = [];
5719
6054
  if (Array.isArray(enumRaw)) {
5720
6055
  enumRaw.forEach((e, j) => {
5721
6056
  enumValues.push(e === null ? "" : this.issues.stringAt(e, `${base}.enum[${j}]`) ?? "");
5722
6057
  });
5723
6058
  }
5724
- const vw = own2(f, "visible_when");
6059
+ const vw = own3(f, "visible_when");
5725
6060
  out.push({
5726
6061
  name: this.s(f, "name", base),
5727
6062
  type: this.s(f, "type", base),
5728
- required: own2(f, "required") === true,
6063
+ required: own3(f, "required") === true,
5729
6064
  enumValues,
5730
6065
  visibleWhen: isRecord(vw) ? {
5731
6066
  field: this.s(vw, "field", `${base}.visible_when`),
5732
- equals: own2(vw, "equals"),
5733
- in: Array.isArray(own2(vw, "in")) ? own2(vw, "in") : []
6067
+ equals: own3(vw, "equals"),
6068
+ in: Array.isArray(own3(vw, "in")) ? own3(vw, "in") : []
5734
6069
  } : null
5735
6070
  });
5736
6071
  });
@@ -5741,7 +6076,7 @@ var Walker = class _Walker {
5741
6076
  const failures = [];
5742
6077
  for (const f of fields) {
5743
6078
  if (!isVisible(f, runInput)) continue;
5744
- const raw = own2(runInput, f.name);
6079
+ const raw = own3(runInput, f.name);
5745
6080
  if (raw === void 0 || raw === null) {
5746
6081
  if (f.required) {
5747
6082
  failures.push({
@@ -5852,7 +6187,7 @@ var Walker = class _Walker {
5852
6187
  /** The names `fields` / `exact` may use, and whether such a list is declared at all. */
5853
6188
  outputNamesFor(kind, stepId) {
5854
6189
  if (kind === "final") {
5855
- const out = own2(this.flow, "output");
6190
+ const out = own3(this.flow, "output");
5856
6191
  const names2 = [];
5857
6192
  if (Array.isArray(out)) {
5858
6193
  out.forEach((item, i) => {
@@ -5861,10 +6196,10 @@ var Walker = class _Walker {
5861
6196
  }
5862
6197
  return { names: names2, declared: names2.length > 0 };
5863
6198
  }
5864
- const steps = own2(this.flow, "steps");
5865
- const step = isRecord(steps) ? own2(steps, stepId) : void 0;
5866
- const schema = isRecord(step) ? own2(step, "output_schema") : void 0;
5867
- const fields = isRecord(schema) ? own2(schema, "fields") : void 0;
6199
+ const steps = own3(this.flow, "steps");
6200
+ const step = isRecord(steps) ? own3(steps, stepId) : void 0;
6201
+ const schema = isRecord(step) ? own3(step, "output_schema") : void 0;
6202
+ const fields = isRecord(schema) ? own3(schema, "fields") : void 0;
5868
6203
  if (!Array.isArray(fields) || fields.length === 0) return { names: [], declared: false };
5869
6204
  const names = [];
5870
6205
  fields.forEach((f, i) => {
@@ -5883,8 +6218,8 @@ var Walker = class _Walker {
5883
6218
  );
5884
6219
  }
5885
6220
  const noOutput = status === STATUS_FAILED || status === STATUS_PAUSED_FOR_HUMAN;
5886
- const fieldsRec = own2(e, "fields");
5887
- const exactRec = own2(e, "exact");
6221
+ const fieldsRec = own3(e, "fields");
6222
+ const exactRec = own3(e, "exact");
5888
6223
  const fieldKeys = isRecord(fieldsRec) ? sortedKeys(fieldsRec) : [];
5889
6224
  const exactKeys = isRecord(exactRec) ? sortedKeys(exactRec) : [];
5890
6225
  const hasFields = fieldKeys.length > 0;
@@ -5902,7 +6237,7 @@ var Walker = class _Walker {
5902
6237
  `a case that ends in ${status} has no output to match; remove fields and exact, or expect status completed`
5903
6238
  );
5904
6239
  }
5905
- const minScore = numberOf(own2(e, "min_score"));
6240
+ const minScore = numberOf(own3(e, "min_score"));
5906
6241
  if (minScore !== void 0 && !scoreInRange(minScore)) {
5907
6242
  this.err(
5908
6243
  "example_min_score_range",
@@ -5929,7 +6264,7 @@ var Walker = class _Walker {
5929
6264
  }
5930
6265
  }
5931
6266
  }
5932
- const reference = own2(e, "reference");
6267
+ const reference = own3(e, "reference");
5933
6268
  if (isRecord(reference)) this.validateReference(`${path}.reference`, reference);
5934
6269
  const { names, declared } = this.outputNamesFor(kind, stepId);
5935
6270
  const checkKey = (field, key) => {
@@ -5956,12 +6291,12 @@ var Walker = class _Walker {
5956
6291
  for (const key of fieldKeys) {
5957
6292
  const fpath = `${path}.fields.${key}`;
5958
6293
  checkKey(fpath, key);
5959
- const matcher = own2(fieldsRec, key);
6294
+ const matcher = own3(fieldsRec, key);
5960
6295
  if (isRecord(matcher)) this.validateFieldMatcher(fpath, matcher);
5961
6296
  }
5962
6297
  for (const key of exactKeys) checkKey(`${path}.exact.${key}`, key);
5963
- const mustNot = this.stringList(own2(e, "must_not"), `${path}.must_not`);
5964
- const mustNotContain = this.stringList(own2(e, "must_not_contain"), `${path}.must_not_contain`);
6298
+ const mustNot = this.stringList(own3(e, "must_not"), `${path}.must_not`);
6299
+ const mustNotContain = this.stringList(own3(e, "must_not_contain"), `${path}.must_not_contain`);
5965
6300
  const mustNotMsg = `must_not takes up to ${L.maxMustNot} statements of at most ${L.maxMustNotRunes} characters each, none empty`;
5966
6301
  if (mustNot.length > L.maxMustNot) {
5967
6302
  this.err("example_must_not_invalid", `${path}.must_not`, mustNotMsg);
@@ -5982,9 +6317,9 @@ var Walker = class _Walker {
5982
6317
  }
5983
6318
  });
5984
6319
  for (const key of fieldKeys) {
5985
- const matcher = own2(fieldsRec, key);
6320
+ const matcher = own3(fieldsRec, key);
5986
6321
  if (!isRecord(matcher)) continue;
5987
- const eq = own2(matcher, "equals");
6322
+ const eq = own3(matcher, "equals");
5988
6323
  if (typeof eq !== "string" || eq === "") continue;
5989
6324
  for (const banned of mustNotContain) {
5990
6325
  if (banned !== "" && equalFold(banned, eq)) {
@@ -6044,7 +6379,7 @@ var Walker = class _Walker {
6044
6379
  }
6045
6380
  return;
6046
6381
  }
6047
- const refRec = own2(r, "ref");
6382
+ const refRec = own3(r, "ref");
6048
6383
  if (!isRecord(refRec)) return;
6049
6384
  const ref = this.fileRefOf(refRec, `${path}.ref`);
6050
6385
  this.validateFileRef(`${path}.ref`, ref);
@@ -6057,22 +6392,22 @@ var Walker = class _Walker {
6057
6392
  }
6058
6393
  }
6059
6394
  expectationIsBinaryReferenceOnly(e, path) {
6060
- const reference = own2(e, "reference");
6061
- const refRec = isRecord(reference) ? own2(reference, "ref") : void 0;
6395
+ const reference = own3(e, "reference");
6396
+ const refRec = isRecord(reference) ? own3(reference, "ref") : void 0;
6062
6397
  if (!isRecord(refRec)) return false;
6063
6398
  const mediaType = this.s(refRec, "media_type", `${path}.reference.ref`);
6064
6399
  if (mediaType === "" || isTextualMediaType(mediaType)) return false;
6065
6400
  const status = this.s(e, "status", path);
6066
- const fields = own2(e, "fields");
6067
- const exact = own2(e, "exact");
6068
- 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);
6401
+ const fields = own3(e, "fields");
6402
+ const exact = own3(e, "exact");
6403
+ 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);
6069
6404
  }
6070
6405
  validateFieldMatcher(path, m) {
6071
6406
  const L = EXAMPLES.limits;
6072
6407
  const matches = this.s(m, "matches", path);
6073
- const oneOf = own2(m, "one_of");
6074
- const approx = numberOf(own2(m, "approx"));
6075
- const tolerance = numberOf(own2(m, "tolerance"));
6408
+ const oneOf = own3(m, "one_of");
6409
+ const approx = numberOf(own3(m, "approx"));
6410
+ const tolerance = numberOf(own3(m, "tolerance"));
6076
6411
  let operators = 0;
6077
6412
  if (has(m, "equals")) operators++;
6078
6413
  if (this.s(m, "contains", path) !== "") operators++;
@@ -6080,7 +6415,7 @@ var Walker = class _Walker {
6080
6415
  if (matches !== "") operators++;
6081
6416
  if (Array.isArray(oneOf) && oneOf.length > 0) operators++;
6082
6417
  if (approx !== void 0) operators++;
6083
- if (typeof own2(m, "present") === "boolean") operators++;
6418
+ if (typeof own3(m, "present") === "boolean") operators++;
6084
6419
  if (operators !== 1) {
6085
6420
  this.err(
6086
6421
  "example_field_matcher_invalid",
@@ -6107,12 +6442,12 @@ var Walker = class _Walker {
6107
6442
  // -- checkpoints ------------------------------------------------------
6108
6443
  validateCheckpoints(path, label, cps) {
6109
6444
  if (!isRecord(cps) || Object.keys(cps).length === 0) return;
6110
- const stepsRaw = own2(this.flow, "steps");
6445
+ const stepsRaw = own3(this.flow, "steps");
6111
6446
  const steps = isRecord(stepsRaw) ? stepsRaw : {};
6112
6447
  const stepIds = sortedKeys(steps);
6113
6448
  for (const id of sortedKeys(cps)) {
6114
6449
  const cpath = `${path}.checkpoints.${id}`;
6115
- const step = own2(steps, id);
6450
+ const step = own3(steps, id);
6116
6451
  if (!isRecord(step)) {
6117
6452
  this.err(
6118
6453
  "example_checkpoint_step_unknown",
@@ -6122,7 +6457,7 @@ var Walker = class _Walker {
6122
6457
  );
6123
6458
  continue;
6124
6459
  }
6125
- const next = own2(step, "next");
6460
+ const next = own3(step, "next");
6126
6461
  if (has(step, "for_each") || has(step, "loop") || isRecord(next) && has(next, "parallel")) {
6127
6462
  this.err(
6128
6463
  "example_checkpoint_step_composite",
@@ -6131,7 +6466,7 @@ var Walker = class _Walker {
6131
6466
  );
6132
6467
  continue;
6133
6468
  }
6134
- const cp = own2(cps, id);
6469
+ const cp = own3(cps, id);
6135
6470
  if (cp === null || cp === void 0) {
6136
6471
  this.validateExpectation(cpath, label, {}, "checkpoint", id);
6137
6472
  } else if (isRecord(cp)) {
@@ -6142,7 +6477,7 @@ var Walker = class _Walker {
6142
6477
  // -- variants ---------------------------------------------------------
6143
6478
  validateVariants(i, path, label, ex, hasInput, baseInput) {
6144
6479
  const L = EXAMPLES.limits;
6145
- const variants = own2(ex, "variants");
6480
+ const variants = own3(ex, "variants");
6146
6481
  if (!Array.isArray(variants) || variants.length === 0) return;
6147
6482
  if (variants.length > L.maxVariants) {
6148
6483
  this.err(
@@ -6205,8 +6540,8 @@ var Walker = class _Walker {
6205
6540
  `example ${q(both)} notes are ${provN} characters; the limit is ${L.maxProvenanceRunes}`
6206
6541
  );
6207
6542
  }
6208
- this.validateWeight(`${vpath}.weight`, both, numberOf(own2(v, "weight")));
6209
- const patch = own2(v, "input_patch");
6543
+ this.validateWeight(`${vpath}.weight`, both, numberOf(own3(v, "weight")));
6544
+ const patch = own3(v, "input_patch");
6210
6545
  const patchRec = isRecord(patch) ? patch : null;
6211
6546
  const hasPatch = patchRec !== null && Object.keys(patchRec).length > 0;
6212
6547
  const hasRef = has(v, "input_ref");
@@ -6223,7 +6558,7 @@ var Walker = class _Walker {
6223
6558
  `variant ${q(vlabel)} of example ${q(label)} changes neither the input nor the expectation`
6224
6559
  );
6225
6560
  }
6226
- const refRec = own2(v, "input_ref");
6561
+ const refRec = own3(v, "input_ref");
6227
6562
  if (isRecord(refRec)) {
6228
6563
  this.validateFileRef(`${vpath}.input_ref`, this.fileRefOf(refRec, `${vpath}.input_ref`));
6229
6564
  }
@@ -6238,7 +6573,7 @@ var Walker = class _Walker {
6238
6573
  this.checkVariantPatch(vpath, label, vlabel, baseInput, patchRec);
6239
6574
  }
6240
6575
  }
6241
- const expected = own2(v, "expected");
6576
+ const expected = own3(v, "expected");
6242
6577
  if (isRecord(expected)) {
6243
6578
  this.validateExpectation(`${vpath}.expected`, both, expected, "final", "");
6244
6579
  }
@@ -6249,11 +6584,11 @@ var Walker = class _Walker {
6249
6584
  * itself supplies. A null patch value deleting a secret is fine.
6250
6585
  */
6251
6586
  checkVariantPatch(vpath, label, vlabel, base, patch) {
6252
- const schema = own2(this.flow, "input_schema");
6587
+ const schema = own3(this.flow, "input_schema");
6253
6588
  if (isRecord(schema)) {
6254
6589
  for (const f of this.schemaFields(schema)) {
6255
6590
  if (f.type !== TYPE_SECRET) continue;
6256
- const val = own2(patch, f.name);
6591
+ const val = own3(patch, f.name);
6257
6592
  if (val !== void 0 && val !== null) {
6258
6593
  this.err(
6259
6594
  "example_secret_value",
@@ -6293,18 +6628,18 @@ var Walker = class _Walker {
6293
6628
  emit(`${path}.title`, this.s(ex, "title", path));
6294
6629
  emit(`${path}.guidance`, this.s(ex, "guidance", path));
6295
6630
  emit(`${path}.notes`, this.s(ex, "notes", path));
6296
- const input = own2(ex, "input");
6631
+ const input = own3(ex, "input");
6297
6632
  if (isRecord(input)) scanLeaves(`${path}.input`, input, 0, emit);
6298
- const expected = own2(ex, "expected");
6633
+ const expected = own3(ex, "expected");
6299
6634
  if (isRecord(expected)) this.scanExpectationLeaves(`${path}.expected`, expected, emit);
6300
- const cps = own2(ex, "checkpoints");
6635
+ const cps = own3(ex, "checkpoints");
6301
6636
  if (isRecord(cps)) {
6302
6637
  for (const id of sortedKeys(cps)) {
6303
- const cp = own2(cps, id);
6638
+ const cp = own3(cps, id);
6304
6639
  if (isRecord(cp)) this.scanExpectationLeaves(`${path}.checkpoints.${id}`, cp, emit);
6305
6640
  }
6306
6641
  }
6307
- const variants = own2(ex, "variants");
6642
+ const variants = own3(ex, "variants");
6308
6643
  if (Array.isArray(variants)) {
6309
6644
  variants.forEach((v, j) => {
6310
6645
  if (!isRecord(v)) return;
@@ -6312,34 +6647,34 @@ var Walker = class _Walker {
6312
6647
  emit(`${vpath}.title`, this.s(v, "title", vpath));
6313
6648
  emit(`${vpath}.guidance`, this.s(v, "guidance", vpath));
6314
6649
  emit(`${vpath}.provenance`, this.s(v, "provenance", vpath));
6315
- scanLeaves(`${vpath}.input_patch`, own2(v, "input_patch"), 0, emit);
6316
- const vexp = own2(v, "expected");
6650
+ scanLeaves(`${vpath}.input_patch`, own3(v, "input_patch"), 0, emit);
6651
+ const vexp = own3(v, "expected");
6317
6652
  if (isRecord(vexp)) this.scanExpectationLeaves(`${vpath}.expected`, vexp, emit);
6318
6653
  });
6319
6654
  }
6320
6655
  }
6321
6656
  scanExpectationLeaves(path, e, emit) {
6322
6657
  emit(`${path}.rubric`, this.s(e, "rubric", path));
6323
- const reference = own2(e, "reference");
6658
+ const reference = own3(e, "reference");
6324
6659
  if (isRecord(reference)) {
6325
6660
  emit(`${path}.reference.text`, this.s(reference, "text", `${path}.reference`));
6326
6661
  }
6327
- this.stringList(own2(e, "must_not"), `${path}.must_not`).forEach(
6662
+ this.stringList(own3(e, "must_not"), `${path}.must_not`).forEach(
6328
6663
  (s, j) => emit(`${path}.must_not[${j}]`, s)
6329
6664
  );
6330
- this.stringList(own2(e, "must_not_contain"), `${path}.must_not_contain`).forEach(
6665
+ this.stringList(own3(e, "must_not_contain"), `${path}.must_not_contain`).forEach(
6331
6666
  (s, j) => emit(`${path}.must_not_contain[${j}]`, s)
6332
6667
  );
6333
- const fields = own2(e, "fields");
6668
+ const fields = own3(e, "fields");
6334
6669
  if (isRecord(fields)) {
6335
6670
  for (const key of sortedKeys(fields)) {
6336
- const m = own2(fields, key);
6671
+ const m = own3(fields, key);
6337
6672
  if (!isRecord(m)) continue;
6338
6673
  const fpath = `${path}.fields.${key}`;
6339
- scanLeaves(`${fpath}.equals`, own2(m, "equals"), 0, emit);
6674
+ scanLeaves(`${fpath}.equals`, own3(m, "equals"), 0, emit);
6340
6675
  emit(`${fpath}.contains`, this.s(m, "contains", fpath));
6341
6676
  emit(`${fpath}.not_contains`, this.s(m, "not_contains", fpath));
6342
- const oneOf = own2(m, "one_of");
6677
+ const oneOf = own3(m, "one_of");
6343
6678
  if (Array.isArray(oneOf)) {
6344
6679
  oneOf.forEach(
6345
6680
  (one, j) => scanLeaves(`${fpath}.one_of[${j}]`, one, 0, emit)
@@ -6347,7 +6682,7 @@ var Walker = class _Walker {
6347
6682
  }
6348
6683
  }
6349
6684
  }
6350
- scanLeaves(`${path}.exact`, own2(e, "exact"), 0, emit);
6685
+ scanLeaves(`${path}.exact`, own3(e, "exact"), 0, emit);
6351
6686
  }
6352
6687
  };
6353
6688
  function scoreInRange(v) {
@@ -6463,7 +6798,7 @@ function inputValueFailures(f, raw) {
6463
6798
  case TYPE_FILE2: {
6464
6799
  if (typeof raw === "string") return raw === "" ? [mismatch(f, TYPE_FILE2)] : [];
6465
6800
  if (isRecord(raw)) {
6466
- const ref = own2(raw, FILE_REF_KEY);
6801
+ const ref = own3(raw, FILE_REF_KEY);
6467
6802
  return typeof ref === "string" && ref !== "" ? [] : [mismatch(f, TYPE_FILE2)];
6468
6803
  }
6469
6804
  return [mismatch(f, TYPE_FILE2)];
@@ -6546,6 +6881,7 @@ function validateParsed(flow, opts, sources) {
6546
6881
  validateCredentialEndpointPairing(f, issues);
6547
6882
  validateExamples(f, issues);
6548
6883
  validateOrchestratorExons(f, issues);
6884
+ validateResidencyEnforcement(f, issues);
6549
6885
  validateUnknownKeys(f, issues);
6550
6886
  const templateStats = validateTemplates(f, issues, opts);
6551
6887
  const totalSteps = f.steps && typeof f.steps === "object" && !Array.isArray(f.steps) ? Object.keys(f.steps).length : 0;