@vaudience/aigentflow-flow-validator 0.15.3 → 0.18.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/PARITY.md +178 -6
- package/README.md +2 -2
- package/dist/cli.js +1579 -89
- package/dist/index.cjs +1513 -88
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +10 -1
- package/dist/index.d.ts +10 -1
- package/dist/index.js +1513 -88
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/PARITY.md
CHANGED
|
@@ -4,7 +4,49 @@ This document maps every rule in this JavaScript validator back to the AIgentFlo
|
|
|
4
4
|
Go reference implementation, records the intentional divergences, and defines the
|
|
5
5
|
discipline for keeping the two in sync.
|
|
6
6
|
|
|
7
|
-
**Tracks AIgentFlow flow schema: `v2.
|
|
7
|
+
**Tracks AIgentFlow flow schema: `v2.819.0`** (`SPEC_VERSION` in [`src/spec/aigentflow-spec.json`](./src/spec/aigentflow-spec.json)), which removes the AigentChat executor (package 0.18.0, below). Earlier additions: the `examples:` block (package 0.17.0), `server_owned_query_key` (package 0.15.1) from the AIgentFlow release after v2.790.0, `credential_endpoint_unpaired` (package 0.15.2) from AIgentFlow v2.793.0 and the release after it, and `display_name_too_long` (package 0.15.3) from AIgentFlow v2.802.0.
|
|
8
|
+
|
|
9
|
+
> package 0.18.0 — **the AigentChat executor is removed**, in step with the reference
|
|
10
|
+
> (AIgentFlow v2.819.0; `specVersion` 2.819.0). The reference no longer registers the
|
|
11
|
+
> `nexus://` protocol or its `aigentchat://` alias, so the spec drops: `nexus` from
|
|
12
|
+
> `executorSchemes` (42 protocols); the `nexus` and `aigentchat` keys of
|
|
13
|
+
> `executorConfigEnvScopes.scopes`; the `nexus` row of `credentialEndpointPairing.families`
|
|
14
|
+
> together with `protocolAliases` and the row-level `storedKeyShape` shape (no row uses
|
|
15
|
+
> them now, so the validator code for them is gone too). A `nexus://` or `aigentchat://`
|
|
16
|
+
> step is now an ordinary unknown scheme: `unknown_executor_scheme` (warning), no
|
|
17
|
+
> credential/endpoint pairing, and a `${AIGENTFLOW_NEXUS_*}` reference under an
|
|
18
|
+
> `executor_config.nexus` key is judged like any key with an empty scope
|
|
19
|
+
> (`executor_config_env_scope`). `executor_config.*.service_channel` and
|
|
20
|
+
> `enable_streaming` stay known keys; the reference keeps them declared but inert.
|
|
21
|
+
> Fixtures: `warn-credential-endpoint-nexus.yaml` is deleted, and the nexus steps and
|
|
22
|
+
> scope entry are removed from `valid-credential-endpoint-own-key-own-url.yaml` and
|
|
23
|
+
> `valid-executor-config-env-scope.yaml`.
|
|
24
|
+
|
|
25
|
+
> package 0.17.0 — **the `examples:` block**, in step with the reference. The spec is
|
|
26
|
+
> regenerated (`specVersion` 2.811.0): `knownKeys` gains `ExampleDefinition`,
|
|
27
|
+
> `Expectation`, `Checkpoint`, `FieldMatcher`, `FileRef`, `ExampleReference` and
|
|
28
|
+
> `ExampleVariant`, `Flow.examples`, and the `trusted_output` / `allow_untrusted` /
|
|
29
|
+
> `untrusted` keys the previous spec lacked; and a new top-level `examples` section
|
|
30
|
+
> carries every limit, vocabulary, pattern, the credential-shaped-literal set and each
|
|
31
|
+
> code's severity. Rules and divergences are under [The examples block](#the-examples-block).
|
|
32
|
+
>
|
|
33
|
+
> | Rule (reference) | Codes | Severity | Module |
|
|
34
|
+
> | ---------------------------------------------------------- | ----------------------------------------------- | -------------- | ----------------------------------------------------- |
|
|
35
|
+
> | the `examples:` walker (every rule, one pass over a block) | 58 `example_*` / `examples_*` codes, spec table | error, warning | `validators/examples.ts`, spec `examples`, `goUrl.ts` |
|
|
36
|
+
> | the reference's blocked-host rule | `example_ref_blocked_host` | error | **not ported** (divergence #19) |
|
|
37
|
+
|
|
38
|
+
> package 0.16.0 — **the untrusted-input marker keys** (AIgentFlow v2.811.0).
|
|
39
|
+
> The spec's `knownKeys` gain `untrusted` on `QueryDefinition` and `InputSchemaField`, and
|
|
40
|
+
> `trusted_output` / `allow_untrusted` on `StepDefinition` and `LoopStepDefinition`;
|
|
41
|
+
> `specVersion` becomes `2.811.0`. No new rule: a misspelling of any of them is
|
|
42
|
+
> `unknown_yaml_key`, as for every other key. What the keys DO — a marked input is sealed
|
|
43
|
+
> in model-facing steps and placed only fenced in the user message, a tainted value in a
|
|
44
|
+
> sensitive data-executor parameter refuses the step unless `allow_untrusted` names it,
|
|
45
|
+
> `trusted_output` declassifies a step's output — is engine behaviour at run time and out
|
|
46
|
+
> of scope for static validation. Fixtures: `valid-untrusted-inputs.yaml`,
|
|
47
|
+
> `invalid-untrusted-misspelt.yaml`; focused test `v0160-untrusted-inputs.test.ts`.
|
|
48
|
+
> ||||||| /tmp/b.txt
|
|
49
|
+
> **Tracks AIgentFlow flow schema: `v2.802.0`** (`SPEC_VERSION` in [`src/spec/aigentflow-spec.json`](./src/spec/aigentflow-spec.json)), plus `server_owned_query_key` (package 0.15.1, below) from the AIgentFlow release after v2.790.0, and `credential_endpoint_unpaired` (package 0.15.2, below) from AIgentFlow v2.793.0 and the release after it, and `display_name_too_long` (package 0.15.3, below) from AIgentFlow v2.802.0.
|
|
8
50
|
|
|
9
51
|
> package 0.15.3 — **the optional top-level `display_name`** (AIgentFlow #187). The spec
|
|
10
52
|
> gains `display_name: scalar` on `Flow` and `specVersion` becomes `2.802.0`.
|
|
@@ -46,7 +88,7 @@ discipline for keeping the two in sync.
|
|
|
46
88
|
> is exactly `${NAME}` for one of the row's server variables on a row whose plugin
|
|
47
89
|
> expands references, and its endpoint (same order) is a literal: not templated, not a
|
|
48
90
|
> reference, and not of the same origin as the row's default. Implicit-credential
|
|
49
|
-
> families are not judged
|
|
91
|
+
> families are not judged.
|
|
50
92
|
> - **The default-origin comparison needs Go's URL semantics**, so `validators/goUrl.ts`
|
|
51
93
|
> ports `net/url.Parse` (what it refuses, and the scheme and host it extracts),
|
|
52
94
|
> `strings.TrimSpace` (Go trims U+0085 and keeps U+FEFF) and `strings.ToLower` (simple
|
|
@@ -856,7 +898,7 @@ max_retries` and `QualityGateDefinition.max_retries` are unchanged. Removing
|
|
|
856
898
|
> separate target functions; widening `hasCycle` too would invent a divergence
|
|
857
899
|
> and emit a spurious `potential_infinite_loop` on any rendezvous or error
|
|
858
900
|
> redirect back to an earlier step.
|
|
859
|
-
> 4. **`executorSchemes` is AIgentFlow's registered set exactly** (43 protocols,
|
|
901
|
+
> 4. **`executorSchemes` is AIgentFlow's registered set exactly** (43 protocols at v2.608.0, 42 since the AigentChat executor was removed,
|
|
860
902
|
> enumerated from `NewExecutorSchemaRegistry`). `web://` was missing, so a
|
|
861
903
|
> correct step warned; nine schemes AIgentFlow does not register (`openai`,
|
|
862
904
|
> `anthropic`, `perplexity`, `vertexai`, `ollama`, `vllm`, `aigentchat`,
|
|
@@ -953,6 +995,7 @@ Comparison contract: **error `code` + `valid` verdict**, not message wording. Th
|
|
|
953
995
|
| `executor_config` `${NAME}` references outside the key's scope (`executor_config_env_scope`) | `ValidateExecutorConfigEnvScopes` (parser.go) | `validators/executorConfigEnv.ts` | `v0150-save-door.test.ts`, `conformance.test.ts` |
|
|
954
996
|
| A step or loop sub-step `query:` declaring a server-owned key (`server_owned_query_key`) | `validateNoServerOwnedStepQueryKeys` (validation.go), `IsServerOwnedParamKey` | `validators/serverOwnedQueryKeys.ts` | `v0151-save-door.test.ts`, `conformance.test.ts` |
|
|
955
997
|
| An endpoint a server-supplied credential will never be sent to (`credential_endpoint_unpaired`, warning) | `validateCredentialEndpointPairing`, `validateFamilyCredentialEndpointPairing` (validation.go) | `validators/credentialEndpoint.ts`, `validators/goUrl.ts` | `v0152-credential-endpoint.test.ts`, `conformance.test.ts` |
|
|
998
|
+
| The `examples:` block: 58 codes, one walker (ids, inputs, references, expectations, checkpoints, variants) | the examples walker (`ValidateExamples`) | `validators/examples.ts`, `validators/goUrl.ts` | `examples.test.ts`, `conformance.test.ts` |
|
|
956
999
|
| Orchestrator `.exons` frontmatter: spec, provider, `requirements.resources`, `tools.allow` withholds | `validateOrchestrator` (parser.go), `validateOrchestratorToolAllowWithholds` | `validators/exons.ts` | `v0150-save-door.test.ts`, `conformance.test.ts` |
|
|
957
1000
|
| Credential bindings (`stored/...`, inject_as, exclusivity) | `validateStepCredentialBindings` | `validators/credentialBindings.ts` | `validate.test.ts` |
|
|
958
1001
|
| `input_schema` definition + ordering lint | `ValidateInputSchemaDefinition`, `LintInputSchemaFieldOrdering` | `validators/inputSchema.ts` | `validate.test.ts` |
|
|
@@ -1155,10 +1198,10 @@ number their shared divergences alike._
|
|
|
1155
1198
|
base URL), the service configuration an executor fills, and whether a client attaches
|
|
1156
1199
|
the deployment's service credential. Neither side reads them statically.
|
|
1157
1200
|
- **Default endpoints of rows the rule never reads are not carried** (`getmd://`, which
|
|
1158
|
-
is never judged
|
|
1201
|
+
is never judged). Verdict-neutral.
|
|
1159
1202
|
- **A `credentials:` mapping with a non-string key (looser, shared).** The reference
|
|
1160
|
-
|
|
1161
|
-
|
|
1203
|
+
decoded it into `map[any]any` for the since-removed `nexus://` own-key check; with that
|
|
1204
|
+
family gone the shared looseness no longer has a rule to act on.
|
|
1162
1205
|
- **JS only, looser: an endpoint shaped like a YAML timestamp is not read as a string.**
|
|
1163
1206
|
yaml.v3 decodes a PLAIN `2024-01-01` into `time.Time`, which the reference's
|
|
1164
1207
|
`.(string)` rejects; the `yaml` package gives a string and the source's quoting is not
|
|
@@ -1168,6 +1211,135 @@ number their shared divergences alike._
|
|
|
1168
1211
|
- **Not ported, verdict-neutral:** Go validates a bracketed IPv6 host with
|
|
1169
1212
|
`netip.ParseAddr`; a bracketed host is never a default's host either way.
|
|
1170
1213
|
|
|
1214
|
+
19. **`example_ref_blocked_host` is reference-only (0.16.0).** The reference refuses a file
|
|
1215
|
+
reference whose host is private or local (`localhost`, loopback, link-local and cloud
|
|
1216
|
+
metadata addresses, RFC 1918 and carrier-grade ranges, the unspecified address, and any
|
|
1217
|
+
name ending `.internal`, `.local` or `.localhost`). It reuses the server's own address
|
|
1218
|
+
tables, so a second literal table here would be another copy to keep in step; it is also
|
|
1219
|
+
advice, because the control is the run-time dialer. `https://localhost/a.json` therefore
|
|
1220
|
+
passes here (looser). The code is still listed in the spec's `examples.codes` table (it is
|
|
1221
|
+
the reference's code), and no fixture in this repository raises it.
|
|
1222
|
+
|
|
1223
|
+
20. **The example's inline input is judged by a NARROWED check (0.16.0; looser).** The
|
|
1224
|
+
reference judges an example's `input` (and a variant's patched input) with its full
|
|
1225
|
+
run-time input validator. This port has no value validator, so it judges only: an unknown
|
|
1226
|
+
field against `input_schema` (or against the declared `query` keys when there is no
|
|
1227
|
+
schema), a required field that is missing (honouring `visible_when`, and skipping a
|
|
1228
|
+
required `secret` field, which the person running the evaluation supplies), a value of the
|
|
1229
|
+
wrong KIND (`string`, `multiline`, `secret`, `enum` and `date` are strings; `number` is any
|
|
1230
|
+
YAML number, `.nan` and the infinities included, as the reference admits them; `bool` is a
|
|
1231
|
+
boolean; `array_of_strings` is a list of strings; `file` is a mapping whose keys are only
|
|
1232
|
+
`url`, `sha256`, `media_type` and `note`, else `example_file_input_needs_ref`) and an enum
|
|
1233
|
+
value outside its list. Not judged: `min_length` / `max_length`, `min` / `max`,
|
|
1234
|
+
`min_items` / `max_items`, `pattern`, the `YYYY-MM-DD` shape and calendar of a `date`, the
|
|
1235
|
+
256-key cap and the string-length cap. A document the reference accepts is never refused
|
|
1236
|
+
here; one it refuses only for those constraints is accepted here. The message wording of
|
|
1237
|
+
the four judged failures is the reference's, and the same `(code, field)` is reported.
|
|
1238
|
+
A date or timestamp a loader resolved to a date object (`validateFlowObject`) is read as the
|
|
1239
|
+
string a JSON body would carry; the `yaml` package this validator parses with leaves such a
|
|
1240
|
+
scalar a string, so for parsed text this is the identity.
|
|
1241
|
+
|
|
1242
|
+
21. **A field matcher's `matches` pattern is judged by length only (0.16.0; looser).** The
|
|
1243
|
+
reference compiles the pattern with its regular-expression engine (RE2), and RE2 and a
|
|
1244
|
+
JavaScript `RegExp` disagree about what is valid (`(?P<n>x)` is valid RE2 and a JS syntax
|
|
1245
|
+
error), so a compile check here could refuse what the reference accepts. This port judges
|
|
1246
|
+
the length (the spec's `limits.maxPatternLength`, counted in UTF-8 bytes as Go counts it)
|
|
1247
|
+
and the "exactly one operator" rule, and nothing about the pattern's syntax: `(` passes.
|
|
1248
|
+
|
|
1249
|
+
22. **Counts and wording that differ in the margin (0.16.0).**
|
|
1250
|
+
- The byte counts behind `example_input_too_large` and `examples_block_too_large` are
|
|
1251
|
+
measured over the JSON of the parsed document (for the block, with empty values
|
|
1252
|
+
omitted, as the reference's typed structs omit them), not over the reference's typed
|
|
1253
|
+
marshalling, which also escapes `<`, `>` and `&`. The count here is never larger than the
|
|
1254
|
+
reference's, so the verdict can differ only within a few bytes of the limit, and only
|
|
1255
|
+
looser; the number printed in the message can differ by those bytes.
|
|
1256
|
+
- `example_expectation_contradiction` compares with simple case folding per code point,
|
|
1257
|
+
as `strings.EqualFold` does; a code point whose fold orbit has three members is not
|
|
1258
|
+
followed.
|
|
1259
|
+
- A float in a message (`weight`, `min_score`) is printed as Go prints a `float64` with
|
|
1260
|
+
`%v` (shortest form, an exponent below `1e-4` and from `1e6`).
|
|
1261
|
+
- The recursion bound of 32 on a nested value is the reference's own and is not in the
|
|
1262
|
+
spec.
|
|
1263
|
+
|
|
1264
|
+
---
|
|
1265
|
+
|
|
1266
|
+
## The examples block
|
|
1267
|
+
|
|
1268
|
+
An `examples:` list records concrete cases inside the flow document: an input, what a good
|
|
1269
|
+
result looks like, why the case matters. The engine never reads it; the validator is the only
|
|
1270
|
+
reader here, so every rule is a judgement of the DOCUMENT at save time, pure and offline (no
|
|
1271
|
+
reference is fetched and no host is resolved). One walker, `validators/examples.ts`, reports
|
|
1272
|
+
every finding of a block in one pass; each finding's `field` is an index path
|
|
1273
|
+
(`examples[2].expected.fields.total`, `examples[0].variants[1].id`), never an id-based one,
|
|
1274
|
+
because an id can be invalid or duplicate while it is being reported.
|
|
1275
|
+
|
|
1276
|
+
**What is judged**, in the order the walker reads it:
|
|
1277
|
+
|
|
1278
|
+
- **The set.** At most 50 examples (`examples_too_many`); the block's JSON at most 256 KiB
|
|
1279
|
+
(`examples_block_too_large`); a warning when every example is held out
|
|
1280
|
+
(`examples_all_held_out`) and when the flow is public (`examples_published_with_public_flow`).
|
|
1281
|
+
- **Identity and prose.** `id` required, matching the spec's `idPattern`, unique
|
|
1282
|
+
(`example_id_missing` / `_invalid` / `_duplicate`); `title` non-blank, at most 80 code points;
|
|
1283
|
+
`guidance` at most 2000 code points, and a warning when it is absent
|
|
1284
|
+
(`example_guidance_missing`); `notes` at most 2000; `tags` at most 8, each matching
|
|
1285
|
+
`tagPattern`, none repeated (`example_tag_invalid`); `weight` above 0 and at most 10;
|
|
1286
|
+
`min_score` from 0 to 1; `side_effects` `refuse` or `allow`; `hold_out` refused on a public
|
|
1287
|
+
flow (`example_holdout_in_public_flow`).
|
|
1288
|
+
- **Input.** Exactly one of `input` / `input_ref` (`example_input_conflict`,
|
|
1289
|
+
`example_input_missing`; `input: {}` is a present, empty input); an inline input at most 32 KiB
|
|
1290
|
+
and judged as divergence #20 describes (`example_input_invalid`, `example_file_input_needs_ref`,
|
|
1291
|
+
`example_input_unvalidated` when the flow declares neither `input_schema` nor `query`).
|
|
1292
|
+
A value for a `secret` field is refused (`example_secret_value`), because examples are saved
|
|
1293
|
+
inside the flow.
|
|
1294
|
+
- **File references** (`input_ref`, a file-typed input, `expected.reference.ref`): `url` at most
|
|
1295
|
+
2048 bytes and parseable as Go parses a URL; a reserved scheme (`artifact`, `trove`, `aiv`,
|
|
1296
|
+
`s3`, `gs`) is refused by name (`example_ref_scheme_reserved`), any other non-`https` scheme
|
|
1297
|
+
too (`example_ref_scheme`); a login, a fragment or an empty host is `example_ref_invalid`;
|
|
1298
|
+
`sha256` is 64 lower-case hex digits, `media_type` is `type/subtype`, `note` at most 300;
|
|
1299
|
+
warnings for a reference with no `sha256` (`example_ref_unpinned`) and for a signed-link query
|
|
1300
|
+
key (`example_ref_signed_url`).
|
|
1301
|
+
- **Expectations** (`expected`, a checkpoint, a variant's replacing `expected`): `status` one of
|
|
1302
|
+
`completed`, `failed`, `paused_for_human`; `fields` and `exact` are mutually exclusive and
|
|
1303
|
+
absent when the case is meant to end `failed` or `paused_for_human`
|
|
1304
|
+
(`example_expected_conflict`); every `fields` / `exact` key is an output of the flow (a
|
|
1305
|
+
checkpoint: a field of the step's `output_schema`), or a warning when no list is declared;
|
|
1306
|
+
each field matcher has exactly one operator and `approx` pairs with a non-negative
|
|
1307
|
+
`tolerance` (`example_field_matcher_invalid`); `rubric` non-blank and at most 4000;
|
|
1308
|
+
`reference` has exactly one of `text` / `ref`, text at most 32 KiB, and a warning for a
|
|
1309
|
+
reference that is not text; `must_not` at most 12 statements of at most 300, none blank;
|
|
1310
|
+
`must_not_contain` at most 20 literals of 1 to 200; a warning when a field's `equals` is also
|
|
1311
|
+
forbidden by `must_not_contain`; an expectation must check something
|
|
1312
|
+
(`example_expected_empty`; `status: completed` alone checks nothing), and a missing
|
|
1313
|
+
`expected` is `example_expected_missing`. A reference the judge cannot read, alone, is the
|
|
1314
|
+
warning `examples_unreadable_by_judge`.
|
|
1315
|
+
- **Checkpoints.** The key must be a step of the flow, and not a `for_each`, `loop` or
|
|
1316
|
+
`next.parallel` step (`example_checkpoint_step_unknown`, `_composite`); a checkpoint cannot
|
|
1317
|
+
name a `status` (`example_checkpoint_status`).
|
|
1318
|
+
- **Variants.** At most 10; `id` matching `idPattern` and unique within the example;
|
|
1319
|
+
`origin` required with no default, `author` or `synthetic`; a variant must change the input
|
|
1320
|
+
or the expectation, and sets `input_patch` or `input_ref`, not both. The patch is an RFC 7386
|
|
1321
|
+
merge patch applied to the parent's inline input (a mapping merges, `null` deletes, anything
|
|
1322
|
+
else replaces; the input is never mutated) and the patched input is judged like the example's
|
|
1323
|
+
own (`example_variant_input_invalid`); a patch giving a secret a value is refused
|
|
1324
|
+
(`example_secret_value`), one deleting it with `null` is fine; a patch on a parent whose
|
|
1325
|
+
input is `input_ref` cannot be checked (`example_variant_unchecked`).
|
|
1326
|
+
- **Credential-shaped literals.** Every string leaf of an example, a checkpoint and a variant
|
|
1327
|
+
(title, guidance, notes, input, rubric, reference text, must_not, matcher operands, `exact`,
|
|
1328
|
+
patches) is matched against the spec's eight patterns (`example_secret_like_value`). The
|
|
1329
|
+
patterns are data (`examples.secretPatterns`, each with its flags); ordinary hyphenated slugs
|
|
1330
|
+
and prose must not match, and a test holds that.
|
|
1331
|
+
- **Unknown keys.** A typo at example, expectation, matcher, file-reference or variant depth is
|
|
1332
|
+
`unknown_yaml_key`, from the regenerated `knownKeys`: nothing is hand-listed.
|
|
1333
|
+
|
|
1334
|
+
Severities are the spec's `examples.codes` table, held to the walker by a test (each code's
|
|
1335
|
+
fixture asserts the walker's severity equals the table's).
|
|
1336
|
+
|
|
1337
|
+
**Measured.** The conformance corpus is shared byte for byte with the Go port; every fixture
|
|
1338
|
+
that carries an expected `(code, field, message)` agrees here, but the one divergence #21 names.
|
|
1339
|
+
Mutants of the rules (a secret pattern dropped, the id check disabled, the duplicate check,
|
|
1340
|
+
the weight bound, the origin vocabulary, the unknown-checkpoint code, the https-only scheme
|
|
1341
|
+
rule, the empty-expectation rule, the merge patch's null-delete) are each killed by a test.
|
|
1342
|
+
|
|
1171
1343
|
---
|
|
1172
1344
|
|
|
1173
1345
|
## Unknown keys and value kinds
|
package/README.md
CHANGED
|
@@ -116,7 +116,7 @@ Low-level: parse YAML into `{ flow?, parseErrors, parseWarnings }` without valid
|
|
|
116
116
|
|
|
117
117
|
### `SPEC_VERSION: string`
|
|
118
118
|
|
|
119
|
-
The AIgentFlow flow-schema version this build tracks (e.g. `"2.
|
|
119
|
+
The AIgentFlow flow-schema version this build tracks (e.g. `"2.819.0"`).
|
|
120
120
|
|
|
121
121
|
### Options
|
|
122
122
|
|
|
@@ -174,7 +174,7 @@ interface ValidationIssue {
|
|
|
174
174
|
- **Orchestrator `.exons` frontmatter** — the document must open with a closed `---` frontmatter spec (`orchestrator_exons_parse_failed`) that sets `execution.provider` (`orchestrator_exons_no_provider`) and declares no `requirements.resources` (`exons_resources_unhonoured`); a tool that `orchestrator.tools` and the definition's `tools.allow` disagree about is never offered (`orchestrator_tool_withheld`, warning). The document body is not parsed: that needs the `.exons` engine (see PARITY.md).
|
|
175
175
|
- **`executor_config` environment references** — a `${NAME}` value may name only the variables of the provider or protocol it is written under (`executor_config_env_scope`).
|
|
176
176
|
- **Server-owned query keys** — a step's or loop sub-step's `query:` may not declare `aiv_api_key`, `aiv_base_url` or `aiv_delegation`, which only the server sets (`server_owned_query_key`).
|
|
177
|
-
- **Credential endpoints** — an endpoint a server-supplied credential will never be sent to (warning, `credential_endpoint_unpaired`): an `ai://` `<provider>_base_url` or a literal `executor_config.<provider>.base_url` with no key of the flow's own, a family secret that is a server `${AIGENTFLOW_…}` variable beside a literal non-default endpoint
|
|
177
|
+
- **Credential endpoints** — an endpoint a server-supplied credential will never be sent to (warning, `credential_endpoint_unpaired`): an `ai://` `<provider>_base_url` or a literal `executor_config.<provider>.base_url` with no key of the flow's own, a family secret that is a server `${AIGENTFLOW_…}` variable beside a literal non-default endpoint.
|
|
178
178
|
- **Credential bindings** — `stored/{provider}/{name}` format, `inject_as`, `credential`/`credentials` mutual exclusion.
|
|
179
179
|
- **Expression functions** — exactly one of `package`/`function`.
|
|
180
180
|
- **`input_schema`** — version, field-name pattern, type enum, per-type constraints, `pattern` compilation, `visible_when` predicate + reference resolution, duplicate-name detection, file-ordering lint.
|