@vaudience/aigentflow-flow-validator 0.15.3

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/README.md ADDED
@@ -0,0 +1,214 @@
1
+ # aigentflow-flow-validator
2
+
3
+ Static, offline validator for [AIgentFlow](https://aigentflow.dev.ai.vaud.one) workflow YAML — for **Node**, the **browser**, and the **command line**.
4
+
5
+ It catches the structural and semantic problems in a flow definition _before_ you upload it to a server: missing required fields, dangling step references, malformed executor URIs, broken Go-template syntax, invalid `input_schema` fields, unbalanced query/response schemas, and more. It is a faithful port of the **static** checks performed by the AIgentFlow Go engine, so a flow that passes here passes the server's structural validation.
6
+
7
+ - **Zero-config, offline, deterministic.** No network, no credentials, no server.
8
+ - **Tiny + portable.** One runtime dependency (`yaml`); the library entry uses no Node built-ins, so it runs in browsers and bundlers unchanged.
9
+ - **Typed.** Ships TypeScript declarations and a stable, machine-readable result shape.
10
+ - **Parity-tracked.** Mirrors a pinned AIgentFlow flow-schema version — see [PARITY.md](./PARITY.md).
11
+
12
+ > **Scope:** this validator does **static** checks only. It does **not** check credentials, the model-compliance catalogue, or runtime template field-resolution — those require a live server and are out of scope. See [What it does not check](#what-it-does-not-check).
13
+
14
+ ---
15
+
16
+ ## Install
17
+
18
+ ```bash
19
+ npm install @vaudience/aigentflow-flow-validator
20
+ ```
21
+
22
+ You can also install straight from git (the `prepare` script builds `dist/`
23
+ automatically on install):
24
+
25
+ ```bash
26
+ npm install github:itsatony/aigentflow-flow-validator-js
27
+ ```
28
+
29
+ Requires Node ≥ 20 (for library + CLI use). For browser/bundler use, any modern bundler works.
30
+
31
+ ---
32
+
33
+ ## Usage
34
+
35
+ ### Node (ESM)
36
+
37
+ ```ts
38
+ import { validateFlow } from '@vaudience/aigentflow-flow-validator';
39
+
40
+ const result = validateFlow(yamlString);
41
+ if (!result.valid) {
42
+ for (const e of result.errors) {
43
+ console.error(`${e.code} [${e.field}]: ${e.message}`);
44
+ }
45
+ }
46
+ ```
47
+
48
+ ### Node (CommonJS)
49
+
50
+ ```js
51
+ const { validateFlow } = require('@vaudience/aigentflow-flow-validator');
52
+ const result = validateFlow(yamlString);
53
+ ```
54
+
55
+ ### Browser / bundler
56
+
57
+ The package's main entry pulls in no Node built-ins, so it works in the browser via any bundler (Vite, webpack, esbuild, Rollup):
58
+
59
+ ```ts
60
+ import { validateFlow } from '@vaudience/aigentflow-flow-validator';
61
+
62
+ const result = validateFlow(editor.getValue());
63
+ renderDiagnostics(result.errors, result.warnings);
64
+ ```
65
+
66
+ ### Already have a parsed object?
67
+
68
+ If you parsed the YAML yourself (or are validating JSON), skip the parse step:
69
+
70
+ ```ts
71
+ import { validateFlowObject } from '@vaudience/aigentflow-flow-validator';
72
+ const result = validateFlowObject(myFlowObject);
73
+ ```
74
+
75
+ ### CLI
76
+
77
+ ```bash
78
+ # Validate one or more files
79
+ npx aigentflow-validate flow.yaml
80
+ npx aigentflow-validate flows/*.yaml
81
+
82
+ # Read from stdin
83
+ cat flow.yaml | npx aigentflow-validate -
84
+
85
+ # Machine-readable output
86
+ npx aigentflow-validate --json flow.yaml
87
+
88
+ # Treat warnings as failures (for CI gating)
89
+ npx aigentflow-validate --strict flow.yaml
90
+ ```
91
+
92
+ Exit codes: **0** = valid, **1** = validation failed, **2** = usage error. Add it to CI to fail a build on a broken flow.
93
+
94
+ ```
95
+ ✓ flow.yaml: valid — 0 error(s), 1 warning(s), 4 step(s)
96
+ warn unreachable_step [steps.cleanup]
97
+ Step 'cleanup' is not reachable from start step
98
+ ↳ Add a path to this step or remove it if not needed
99
+ ```
100
+
101
+ ---
102
+
103
+ ## API
104
+
105
+ ### `validateFlow(yaml: string, options?): ValidationResult`
106
+
107
+ Parse flow YAML and validate it. Parse failures (syntax errors, duplicate keys) are reported as `error`-severity issues with line/column when available.
108
+
109
+ ### `validateFlowObject(flow: unknown, options?): ValidationResult`
110
+
111
+ Validate an already-parsed flow object.
112
+
113
+ ### `parseFlow(yaml: string): ParseOutput`
114
+
115
+ Low-level: parse YAML into `{ flow?, parseErrors, parseWarnings }` without validating.
116
+
117
+ ### `SPEC_VERSION: string`
118
+
119
+ The AIgentFlow flow-schema version this build tracks (e.g. `"2.802.0"`).
120
+
121
+ ### Options
122
+
123
+ | Option | Default | Effect |
124
+ | ------------------ | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
125
+ | `strictRegistries` | `false` | Report unknown orchestrator tool names and unknown template functions as **errors** instead of **warnings**. Off by default because the vendored allow-lists can lag the live AIgentFlow registries, and a false-positive error is worse than a missed lint. |
126
+
127
+ ### Result shape
128
+
129
+ ```ts
130
+ interface ValidationResult {
131
+ valid: boolean; // true when there are zero error-severity issues
132
+ errors: ValidationIssue[];
133
+ warnings: ValidationIssue[];
134
+ summary: {
135
+ totalSteps: number;
136
+ validSteps: number;
137
+ errorCount: number;
138
+ warningCount: number;
139
+ templatesFound: number;
140
+ templatesValid: number;
141
+ };
142
+ }
143
+
144
+ interface ValidationIssue {
145
+ field: string; // dotted path, e.g. "steps.fetch.query.url"
146
+ message: string; // human-readable description
147
+ code: string; // stable machine code, e.g. "step_not_found"
148
+ severity: 'error' | 'warning' | 'info';
149
+ stepId?: string;
150
+ line?: number;
151
+ column?: number;
152
+ context?: string;
153
+ suggestion?: string;
154
+ }
155
+ ```
156
+
157
+ `code` is the stable contract — branch on it programmatically. `message` wording may change between releases.
158
+
159
+ ---
160
+
161
+ ## What it checks
162
+
163
+ - **Required fields** — `aigentflow_version`, `name`, `start`, at least one step.
164
+ - **Unknown keys and value kinds** — any key a flow type does not declare, at every level (`unknown_yaml_key`), and a value of the wrong kind such as `next: end` (`invalid_type`). AIgentFlow refuses both at save, because the key would be silently dropped.
165
+ - **Steps** — `start` resolves to a real step; every non-loop step has an `executor`; loop steps don't; reserved `.` in step IDs and the reserved step ID `orchestrator` are rejected.
166
+ - **Executors** — `scheme://path` shape (error on malformed); unknown scheme (warning).
167
+ - **Query schema** — parameter types, `array` requires `items`, item-type validity, `min_items`/`max_items`, nested `object`/`array` recursion.
168
+ - **Response expectations** — valid data types; `array` requires `items`; `required` is boolean or template.
169
+ - **Error strategy** — action enum (`retry`/`fail`/`goto`/`continue`), `goto_step` existence, `max_delay` duration, `backoff_multiplier`, `retry_on` categories.
170
+ - **Connectivity** — `next.default` / `next.conditions[].goto` references (error; only `null` and `orchestrator` need no step, so `end` must name one, and is then an ordinary step); unreachable steps (warning); cycles (warning).
171
+ - **Parallel + orchestrator routing** — `next.parallel` rendezvous/steps; `orchestrator` next requires an orchestrator block.
172
+ - **Loop / for_each / throttle** — required fields, iteration limits, mutual exclusions, throttle ceilings.
173
+ - **Orchestrator / campaign** — exons presence, trigger types, timer intervals, tool names; campaign requires an orchestrator and at least one child flow, each naming a `flow_id` or `flow_name`; `max_credits_per_child` >= 0.
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
+ - **`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
+ - **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, a `nexus://` endpoint with no key of its own.
178
+ - **Credential bindings** — `stored/{provider}/{name}` format, `inject_as`, `credential`/`credentials` mutual exclusion.
179
+ - **Expression functions** — exactly one of `package`/`function`.
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.
181
+ - **Step `output_schema`** — the same JSON-Schema subset as `input_schema`, validated at step scope (and on loop sub-steps).
182
+ - **`quality_gate:`** — `rubric` required, `threshold` in `[0,1]`, `on_fail` enum (`fail`/`goto`/`retry`; `human` is rejected as not-yet-supported), `goto_step` existence + no self-goto when `on_fail=goto`, and the composite/parallel-member scope guards.
183
+ - **`tool_discovery`** — `eager`/`lazy`/`off` on the flow, the orchestrator, and a step `query` (empty and templated values skipped).
184
+ - **Mock scenarios** — each `delay` must be a Go duration (`100ms`, not `100`), judged by its written spelling: `0` saves, `0.0` does not.
185
+ - **`output:`** — no empty-string entries.
186
+ - **Templates** — Go `text/template` **syntax** across query, processing, and conditions.
187
+
188
+ ## What it does **not** check
189
+
190
+ These need a live server / org context and are intentionally out of scope:
191
+
192
+ - **Credentials** — whether a bound credential actually exists or is authorised.
193
+ - **Model compliance** — the `compliance:` block is enforced against the provider catalogue at flow-create time on the server.
194
+ - **`.exons` document bodies** — whether an inline `.exons` document parses and whether its tags can render (`exons_attributes`) needs the `.exons` template engine, which this package does not embed.
195
+ - **Template field resolution** — whether `.data.x.y` will actually be populated at runtime (we validate syntax, not data flow).
196
+ - **Publish gates** — `visibility`/`classification`/template-metadata publish rules are server- and org-context dependent.
197
+
198
+ A clean result here means the flow is **structurally** sound — not that it will execute successfully against your specific credentials and data.
199
+
200
+ ---
201
+
202
+ ## Versioning & parity
203
+
204
+ This validator tracks a specific AIgentFlow flow-schema version, exposed as `SPEC_VERSION`. The enum surface (executor schemes, data types, error actions, input-schema field types, template functions, …) lives in [`src/spec/aigentflow-spec.json`](./src/spec/aigentflow-spec.json) and the rule-by-rule mapping to the Go reference is documented in [PARITY.md](./PARITY.md). When AIgentFlow's flow grammar changes, the validator is updated and the spec version bumped.
205
+
206
+ ---
207
+
208
+ ## Contributing
209
+
210
+ See [CONTRIBUTING.md](./CONTRIBUTING.md). In short: `npm install`, then `npm run typecheck && npm run lint && npm test && npm run build`.
211
+
212
+ ## License
213
+
214
+ [MIT](./LICENSE) © vAudience.AI