fyflow-orchestration 0.10.0 → 0.11.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/AGENTS.md +173 -5
- package/README.md +1 -1
- package/dist/browser/chunks/{chunk-NA6QQAZ2.js → chunk-5CVSWDCB.js} +79 -12
- package/dist/browser/index.js +539 -3
- package/dist/browser/scheduler/index.js +1 -1
- package/dist/node/chunks/{chunk-NA6QQAZ2.js → chunk-5CVSWDCB.js} +79 -12
- package/dist/node/index.js +539 -3
- package/dist/node/scheduler/index.js +1 -1
- package/dist/types/index.d.ts +1 -0
- package/dist/types/src/definition/definition-schema.d.ts +23 -0
- package/dist/types/src/definition/types.d.ts +2 -1
- package/dist/types/src/definition/validate.d.ts +41 -2
- package/dist/types/src/definition/wiring.d.ts +10 -0
- package/dist/types/src/driver/driver.d.ts +1 -1
- package/dist/types/src/fold/run-state.d.ts +17 -0
- package/package.json +2 -1
package/dist/browser/index.js
CHANGED
|
@@ -9,23 +9,28 @@ import {
|
|
|
9
9
|
ConfigRefused,
|
|
10
10
|
DECLARED_POOL_KEYS,
|
|
11
11
|
DOCUMENT_KEYS,
|
|
12
|
+
DOC_KEYS_DECLARED,
|
|
12
13
|
DerivationRefused,
|
|
13
14
|
Driver,
|
|
14
15
|
DuplicateTaskId,
|
|
15
16
|
EDGE_KEYS_DECLARED,
|
|
17
|
+
EDGE_KEYS_REQUIRED,
|
|
16
18
|
GATE_TYPE_KEYS,
|
|
17
19
|
GateTypeRefused,
|
|
18
20
|
GroupConfigRefused,
|
|
19
21
|
GroupTypeMissing,
|
|
22
|
+
ID_RE_COPY,
|
|
20
23
|
INSTANCE_KEYS,
|
|
21
24
|
InvalidDefinition,
|
|
22
25
|
InvalidRunId,
|
|
23
26
|
InvalidTaskId,
|
|
24
27
|
KEY_PATH_RE,
|
|
28
|
+
KINDS_COPY,
|
|
25
29
|
MESSAGE_OPTION_KEYS,
|
|
26
30
|
MissingJoinPolicy,
|
|
27
31
|
MultipleRuns,
|
|
28
32
|
NODE_KEYS_DECLARED,
|
|
33
|
+
NODE_KEYS_REQUIRED,
|
|
29
34
|
NODE_TYPE_DECLARATION_KEYS,
|
|
30
35
|
NameCollision,
|
|
31
36
|
NameMissing,
|
|
@@ -42,6 +47,7 @@ import {
|
|
|
42
47
|
PREDICATE_ROOTS,
|
|
43
48
|
PoolTypeMissing,
|
|
44
49
|
RETRY_POLICY_KEYS,
|
|
50
|
+
ROUTABLE_STATES,
|
|
45
51
|
RegistryError,
|
|
46
52
|
ResumeRefused,
|
|
47
53
|
RunControlRefused,
|
|
@@ -145,7 +151,530 @@ import {
|
|
|
145
151
|
visibilityKey,
|
|
146
152
|
witness,
|
|
147
153
|
workersOf
|
|
148
|
-
} from "./chunks/chunk-
|
|
154
|
+
} from "./chunks/chunk-5CVSWDCB.js";
|
|
155
|
+
|
|
156
|
+
// src/definition/definition-schema.ts
|
|
157
|
+
var DRAFT_2020_12 = "https://json-schema.org/draft/2020-12/schema";
|
|
158
|
+
var idOrNonString = () => ({ anyOf: [ref("id"), { not: { type: "string" } }] });
|
|
159
|
+
var ref = (name) => ({ $ref: `#/$defs/${name}` });
|
|
160
|
+
function body(re, name) {
|
|
161
|
+
const s = re.source;
|
|
162
|
+
if (!s.startsWith("^") || !s.endsWith("$") || re.flags !== "") {
|
|
163
|
+
throw new Error(`definitionSchema: ${name} is no longer an anchored, flagless expression (${String(re)}) \u2014 its body cannot be reused as a pattern`);
|
|
164
|
+
}
|
|
165
|
+
return s.slice(1, -1);
|
|
166
|
+
}
|
|
167
|
+
function described(table, key, where) {
|
|
168
|
+
const d = Object.prototype.hasOwnProperty.call(table, key) ? table[key] : void 0;
|
|
169
|
+
if (d === void 0) throw new Error(`definitionSchema: ${where} declares the key "${key}" and no description is written for it`);
|
|
170
|
+
return d;
|
|
171
|
+
}
|
|
172
|
+
var DOC_DESCRIPTIONS = {
|
|
173
|
+
flowId: "The flow's id: 1-64 characters from [A-Za-z0-9_-] (FD-V16), the charset of spec/task-id.md \u2014 it is a segment of every task id this flow mints.",
|
|
174
|
+
version: "The definition's version, an integer >= 1 (FD-V21), managed by the author. The driver does not interpret it.",
|
|
175
|
+
entry: "The id of the node a run starts at. It must name a node of this document that is neither a join nor an end (FD-V3 \u2014 validateDefinition's, not this schema's).",
|
|
176
|
+
nodes: "One object per node, order irrelevant. Node ids are unique across the document (FD-V1 \u2014 validateDefinition's)."
|
|
177
|
+
};
|
|
178
|
+
var NODE_DESCRIPTIONS = {
|
|
179
|
+
id: "The node's id: 1-64 characters from [A-Za-z0-9_-] (FD-V16), unique in the document (FD-V1). It is a segment of the task id the node mints.",
|
|
180
|
+
kind: 'Which of the seven node kinds this is (FD-V24). There is no "decision" kind: a decision is an edge\'s `when`, and a decision with memory is a `gate`.',
|
|
181
|
+
edges: "Where the run goes from here, in order. The first eligible edge whose `when` holds is taken; an edge with no `on` routes `done` only.",
|
|
182
|
+
needs: "What this node receives instead of the previous node's output: an object whose keys name what the node receives and whose values are references (spec/flow-definition.md section 3, FD-V26). Where each reference points is validateDefinition's (FD-V27-FD-V29, FD-V49).",
|
|
183
|
+
settings: "Settings, a plain object.",
|
|
184
|
+
type: "A registered type's name."
|
|
185
|
+
};
|
|
186
|
+
var KIND_DESCRIPTIONS = {
|
|
187
|
+
task: {
|
|
188
|
+
kind: "A `task`: the one kind that is dispatched \u2014 one scheduler task, run by the worker of the node type it names.",
|
|
189
|
+
type: "The registered NODE type that runs this task (required since v0.19). Which names are registered is the registry's: FD-V32, validateDefinition's. The built-in \"Transform\" runs nothing but the node's own `transform` (FD-V46).",
|
|
190
|
+
pool: "A named pool INSTANCE of this node's type, from the registry's `pools` (FD-V38). Absent: the type's default instance, keyed by the type's name.",
|
|
191
|
+
settings: "Settings handed to the worker in its envelope, merged OVER the type's defaults. A plain object; what its worker's settingsSchema says of them is FD-V33's, validateDefinition's.",
|
|
192
|
+
transform: "An expression the node type's worker wrapper evaluates over this node's input before the worker sees it: exactly { lang, expr } (FD-V37). The language must be registered (FD-V35) and accept the expression (FD-V36) \u2014 validateDefinition's.",
|
|
193
|
+
optional: "true: the FLOW handles this task's failure \u2014 it ends `failed` and may route a `failed` edge. Absent or false: a failure out of retries waits for a person (`user_action`).",
|
|
194
|
+
retryPolicy: "How the scheduler retries a failed attempt, inside one task id: exactly { maxRetries, backoffMs } (FD-V30).",
|
|
195
|
+
workerGroups: "The resource groups the scheduler holds this task to: a non-empty list of distinct group ids (FD-V31). That each id is one the registry's `groups` declares is validateDefinition's.",
|
|
196
|
+
needs: NODE_DESCRIPTIONS.needs
|
|
197
|
+
},
|
|
198
|
+
fanout: {
|
|
199
|
+
kind: "A `fanout`: opens a region of N branches declared HERE, closed by the one `join` naming it. Dispatches nothing.",
|
|
200
|
+
branches: "The region's branch entries: at least two distinct node ids (FD-V9), each a task or an ask, none of them its own join (FD-V9, FD-V12 \u2014 validateDefinition's)."
|
|
201
|
+
},
|
|
202
|
+
map: {
|
|
203
|
+
kind: "A `map`: opens a region of ONE branch, opened once per item of an array at run time, closed by the one `join` naming it. Dispatches nothing.",
|
|
204
|
+
over: "The key, in the value that reaches the map, holding the array of items: 1-64 characters from [A-Za-z0-9_-] (FD-V25).",
|
|
205
|
+
branch: "The id of the one node each item's instance starts at \u2014 a task or an ask (FD-V25, validateDefinition's).",
|
|
206
|
+
needs: "What the map receives before it reads `over` (spec/flow-definition.md section 3, FD-V26)."
|
|
207
|
+
},
|
|
208
|
+
join: {
|
|
209
|
+
kind: "A `join`: closes the region its `of` opened, by the join policy the driver is given. Dispatches nothing.",
|
|
210
|
+
of: "The id of the `fanout` or `map` whose region this closes (FD-V6, validateDefinition's).",
|
|
211
|
+
edges: "Exactly one edge, carrying neither `when` nor `on` (FD-V7): a join has no outcome for either to read."
|
|
212
|
+
},
|
|
213
|
+
end: {
|
|
214
|
+
kind: "An `end`: terminates one path. No edges.",
|
|
215
|
+
outcome: "A non-empty, author-defined string (FD-V8). The driver does not interpret it."
|
|
216
|
+
},
|
|
217
|
+
gate: {
|
|
218
|
+
kind: "A `gate`: routes the branch that reaches it by a registered GATE type's decision, and hands on exactly what reached it \u2014 a decision with memory. Dispatches nothing.",
|
|
219
|
+
type: `The registered GATE type that decides: a built-in (${Object.keys(BUILT_IN_GATE_TYPES).sort().map((t) => `"${t}"`).join(", ")}) or one the registry's \`gateTypes\` adds (FD-V39, validateDefinition's).`,
|
|
220
|
+
settings: "Settings the gate type reads: a plain object (FD-V40). A `key`, where present, is a key path the library resolves over what reached the gate. What the type's settingsSchema says of the rest is validateDefinition's.",
|
|
221
|
+
edges: "One edge per route of the gate's type, each carrying `to` and `route` \u2014 an edge with no `route` carries the type's DEFAULT route, which may also be named (FD-V41). That every route is wired exactly once is validateDefinition's."
|
|
222
|
+
},
|
|
223
|
+
ask: {
|
|
224
|
+
kind: `An \`ask\`: waits for a PERSON, whose answer is its output and is routed by its edges as a task's settlement is. Never dispatched. A task's ${ASK_REFUSED_KEYS.map((k) => `\`${k}\``).join(", ")} are refused on an ask (FD-V47).`,
|
|
225
|
+
settings: "Opaque settings a UI reads: a plain object (FD-V21). The library never reads them.",
|
|
226
|
+
answerSchema: "The schema a `done` answer is held to, in the library's built-in schema subset (FD-V48, ADR 0053). That an `examples` entry conforms is validateDefinition's (ADR 0056).",
|
|
227
|
+
needs: "What the person is shown as the ask's input (spec/flow-definition.md section 3, FD-V26)."
|
|
228
|
+
}
|
|
229
|
+
};
|
|
230
|
+
var EDGE_DESCRIPTIONS = {
|
|
231
|
+
to: "The id of the node this edge leads to (FD-V2, validateDefinition's).",
|
|
232
|
+
on: 'The terminal states this edge is eligible for: a non-empty list of distinct "done" / "failed" (FD-V18). Absent: ["done"]. "user_action" suspends rather than routes.',
|
|
233
|
+
when: "The decision: a registered predicate NAME { predicate }, a declared COMPARISON { path, op, value, default?, length? }, or a flat GROUP { all } or { any } of comparisons (FD-V42-FD-V45). Absent: the edge is the default for its state.",
|
|
234
|
+
needs: "What this edge's predicate sees beyond its node's outcome \u2014 `needs`' grammar minus \".\" (FD-V26).",
|
|
235
|
+
route: "On a gate's edge, which of the gate type's routes it carries; absent: the type's DEFAULT route (FD-V41). Refused on every other kind's edge."
|
|
236
|
+
};
|
|
237
|
+
var RETRY_DESCRIPTIONS = {
|
|
238
|
+
maxRetries: "How many times a failed attempt is re-dispatched: an integer >= 0.",
|
|
239
|
+
backoffMs: "Milliseconds between a failed attempt and its retry: a finite number >= 0."
|
|
240
|
+
};
|
|
241
|
+
var TRANSFORM_DESCRIPTIONS = {
|
|
242
|
+
lang: "A registered language's name (FD-V35, validateDefinition's).",
|
|
243
|
+
expr: "Text that language compiles (FD-V36, validateDefinition's): `$` is the value this node receives, `$settings` its effective settings."
|
|
244
|
+
};
|
|
245
|
+
var PREDICATE_DESCRIPTIONS = {
|
|
246
|
+
predicate: "A registered predicate's name (FD-V4, validateDefinition's).",
|
|
247
|
+
path: `A key path over the decision's context, starting at ${PREDICATE_ROOTS.map((r) => `"${r}"`).join(" or ")} and naming a key beyond it (FD-V43).`,
|
|
248
|
+
op: `One of ${PREDICATE_OPS.join(", ")} (FD-V44). The ordering operators compare numbers and "startsWith" a string \u2014 a comparison between kinds is no match, never a coercion.`,
|
|
249
|
+
value: "The scalar compared against: null, a boolean, a number or a string (FD-V44).",
|
|
250
|
+
default: "What is compared where the path does not resolve or resolves to null: a scalar, or \u2014 with `length` \u2014 an array or a string (FD-V44).",
|
|
251
|
+
length: "Exactly true: compare the LENGTH of the array or string, against a number (FD-V44).",
|
|
252
|
+
all: "A flat group: a non-empty list of comparisons that must all hold (FD-V45).",
|
|
253
|
+
any: "A flat group: a non-empty list of comparisons of which one must hold (FD-V45)."
|
|
254
|
+
};
|
|
255
|
+
var SUBSET_DESCRIPTIONS = {
|
|
256
|
+
type: "One of the seven JSON types, or a non-empty list of distinct ones.",
|
|
257
|
+
required: "Property names an object must carry.",
|
|
258
|
+
properties: "A schema, in the subset, per property name.",
|
|
259
|
+
additionalProperties: "true or false only \u2014 never a schema.",
|
|
260
|
+
enum: "A non-empty list of the values allowed.",
|
|
261
|
+
const: "The one value allowed.",
|
|
262
|
+
minimum: "The smallest number allowed.",
|
|
263
|
+
maximum: "The largest number allowed.",
|
|
264
|
+
minLength: "The shortest string allowed: an integer >= 0.",
|
|
265
|
+
maxLength: "The longest string allowed: an integer >= 0.",
|
|
266
|
+
items: "ONE schema, in the subset, for every item \u2014 never a tuple.",
|
|
267
|
+
minItems: "The fewest items allowed: an integer >= 0.",
|
|
268
|
+
examples: "A non-empty list of values the schema accepts (that each conforms is ADR 0056's check, validateDefinition's).",
|
|
269
|
+
title: "An annotation: a string, constraining nothing (ADR 0098).",
|
|
270
|
+
description: "An annotation: a string, constraining nothing (ADR 0098).",
|
|
271
|
+
readOnly: "An annotation: true or false, constraining nothing (ADR 0098).",
|
|
272
|
+
writeOnly: "An annotation: true or false, constraining nothing (ADR 0098)."
|
|
273
|
+
};
|
|
274
|
+
var NUMERIC_OPS = ["lt", "lte", "gt", "gte"];
|
|
275
|
+
var STRING_OPS = ["startsWith"];
|
|
276
|
+
var ERROR_PART = "!error";
|
|
277
|
+
function nodeKeySchema(kind, key) {
|
|
278
|
+
switch (key) {
|
|
279
|
+
case "id":
|
|
280
|
+
return ref("id");
|
|
281
|
+
case "kind":
|
|
282
|
+
return { const: kind };
|
|
283
|
+
case "type":
|
|
284
|
+
case "pool":
|
|
285
|
+
return { type: "string" };
|
|
286
|
+
case "settings":
|
|
287
|
+
return kind === "gate" ? { type: "object", properties: { key: { type: "string", pattern: KEY_PATH_RE.source, description: "A key path: dot-separated object keys, each [A-Za-z0-9_-]{1,64} \u2014 no index, no wildcard, no expression (FD-V40)." } } } : { type: "object" };
|
|
288
|
+
case "transform":
|
|
289
|
+
return ref("transform");
|
|
290
|
+
case "optional":
|
|
291
|
+
return { type: "boolean" };
|
|
292
|
+
case "needs":
|
|
293
|
+
return ref("needs");
|
|
294
|
+
case "retryPolicy":
|
|
295
|
+
return ref("retryPolicy");
|
|
296
|
+
case "workerGroups":
|
|
297
|
+
return { type: "array", minItems: 1, uniqueItems: true, items: { type: "string" } };
|
|
298
|
+
// **`branches`' entries and `of` admit a NON-string** — W210's conformity reader, B1: the validator holds both only
|
|
299
|
+
// through the graph (`FD-V2`, `FD-V6` and `FD-V9` read a string and pass anything else over), so `of: null` on a join
|
|
300
|
+
// of no region and `["b", "c", 5]` are ACCEPTED there, and refusing them here would refuse what the validator accepts
|
|
301
|
+
// (ADR 0132 rule 2). A string is held to the id charset. That `FD-V21` should refuse the rest is Q774.
|
|
302
|
+
case "branches":
|
|
303
|
+
return { type: "array", minItems: 2, uniqueItems: true, items: idOrNonString() };
|
|
304
|
+
case "of":
|
|
305
|
+
return idOrNonString();
|
|
306
|
+
case "over":
|
|
307
|
+
case "branch":
|
|
308
|
+
return ref("id");
|
|
309
|
+
case "outcome":
|
|
310
|
+
return { type: "string", minLength: 1 };
|
|
311
|
+
case "answerSchema":
|
|
312
|
+
return ref("subsetSchema");
|
|
313
|
+
case "edges": {
|
|
314
|
+
if (kind === "join") return { type: "array", minItems: 1, maxItems: 1, items: ref("joinEdge") };
|
|
315
|
+
if (kind === "gate") return { type: "array", minItems: 1, items: ref("gateEdge") };
|
|
316
|
+
return { type: "array", minItems: 1, items: ref("edge") };
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
throw new Error(`definitionSchema: the "${kind}" kind declares the key "${key}" and no schema is written for it`);
|
|
320
|
+
}
|
|
321
|
+
function edgeKeySchema(key) {
|
|
322
|
+
switch (key) {
|
|
323
|
+
case "to":
|
|
324
|
+
return ref("id");
|
|
325
|
+
case "on":
|
|
326
|
+
return { type: "array", minItems: 1, uniqueItems: true, items: { enum: [...ROUTABLE_STATES] } };
|
|
327
|
+
case "when":
|
|
328
|
+
return ref("when");
|
|
329
|
+
case "needs":
|
|
330
|
+
return ref("edgeNeeds");
|
|
331
|
+
case "route":
|
|
332
|
+
return { type: "string" };
|
|
333
|
+
}
|
|
334
|
+
throw new Error(`definitionSchema: an edge declares the key "${key}" and no schema is written for it`);
|
|
335
|
+
}
|
|
336
|
+
var EDGE_KEYS_BY_SITE = {
|
|
337
|
+
edge: (k) => k !== "route",
|
|
338
|
+
joinEdge: (k) => k !== "route" && k !== "on" && k !== "when",
|
|
339
|
+
gateEdge: (k) => k === "to" || k === "route"
|
|
340
|
+
};
|
|
341
|
+
var SITE_DESCRIPTIONS = {
|
|
342
|
+
edge: "An edge of a task or an ask: { to, on?, when?, needs? }.",
|
|
343
|
+
joinEdge: "A join's one edge: { to, needs? } \u2014 neither `on` nor `when` (FD-V7).",
|
|
344
|
+
gateEdge: "A gate's edge: { to, route? } and nothing else (FD-V41)."
|
|
345
|
+
};
|
|
346
|
+
function edgeSchema(site) {
|
|
347
|
+
const keys = EDGE_KEYS_DECLARED.filter(EDGE_KEYS_BY_SITE[site]);
|
|
348
|
+
return {
|
|
349
|
+
description: SITE_DESCRIPTIONS[site],
|
|
350
|
+
type: "object",
|
|
351
|
+
required: EDGE_KEYS_REQUIRED.filter((k) => keys.includes(k)),
|
|
352
|
+
properties: Object.fromEntries(keys.map((k) => [k, { ...edgeKeySchema(k), description: described(EDGE_DESCRIPTIONS, k, "an edge") }])),
|
|
353
|
+
additionalProperties: false
|
|
354
|
+
};
|
|
355
|
+
}
|
|
356
|
+
function kindSchema(kind) {
|
|
357
|
+
const keys = NODE_KEYS_DECLARED[kind];
|
|
358
|
+
const required = NODE_KEYS_REQUIRED[kind];
|
|
359
|
+
if (keys === void 0 || required === void 0) throw new Error(`definitionSchema: the validator declares no keys for the kind "${kind}"`);
|
|
360
|
+
const own2 = KIND_DESCRIPTIONS[kind] ?? {};
|
|
361
|
+
return {
|
|
362
|
+
description: described(own2, "kind", `the "${kind}" kind`),
|
|
363
|
+
type: "object",
|
|
364
|
+
required: [...required],
|
|
365
|
+
properties: Object.fromEntries(keys.map((k) => [k, {
|
|
366
|
+
...nodeKeySchema(kind, k),
|
|
367
|
+
description: Object.prototype.hasOwnProperty.call(own2, k) ? own2[k] : described(NODE_DESCRIPTIONS, k, `the "${kind}" kind`)
|
|
368
|
+
}])),
|
|
369
|
+
additionalProperties: false
|
|
370
|
+
};
|
|
371
|
+
}
|
|
372
|
+
function subsetKeywordSchema(keyword) {
|
|
373
|
+
const nonNegInt = { type: "integer", minimum: 0 };
|
|
374
|
+
switch (keyword) {
|
|
375
|
+
case "type":
|
|
376
|
+
return { anyOf: [{ enum: [...SCHEMA_TYPES] }, { type: "array", minItems: 1, uniqueItems: true, items: { enum: [...SCHEMA_TYPES] } }] };
|
|
377
|
+
case "required":
|
|
378
|
+
return { type: "array", uniqueItems: true, items: { type: "string" } };
|
|
379
|
+
case "properties":
|
|
380
|
+
return { type: "object", additionalProperties: ref("subsetSchema") };
|
|
381
|
+
case "additionalProperties":
|
|
382
|
+
return { type: "boolean" };
|
|
383
|
+
case "enum":
|
|
384
|
+
return { type: "array", minItems: 1 };
|
|
385
|
+
case "const":
|
|
386
|
+
return {};
|
|
387
|
+
case "minimum":
|
|
388
|
+
case "maximum":
|
|
389
|
+
return { type: "number" };
|
|
390
|
+
case "minLength":
|
|
391
|
+
case "maxLength":
|
|
392
|
+
case "minItems":
|
|
393
|
+
return nonNegInt;
|
|
394
|
+
case "items":
|
|
395
|
+
return ref("subsetSchema");
|
|
396
|
+
case "examples":
|
|
397
|
+
return { type: "array", minItems: 1 };
|
|
398
|
+
case "title":
|
|
399
|
+
case "description":
|
|
400
|
+
return { type: "string" };
|
|
401
|
+
case "readOnly":
|
|
402
|
+
case "writeOnly":
|
|
403
|
+
return { type: "boolean" };
|
|
404
|
+
}
|
|
405
|
+
throw new Error(`definitionSchema: the schema subset declares the keyword "${keyword}" and no schema is written for it`);
|
|
406
|
+
}
|
|
407
|
+
function needsSchema(withSelf, description) {
|
|
408
|
+
return {
|
|
409
|
+
description,
|
|
410
|
+
type: "object",
|
|
411
|
+
minProperties: 1,
|
|
412
|
+
propertyNames: ref("id"),
|
|
413
|
+
additionalProperties: ref(withSelf ? "reference" : "edgeReference")
|
|
414
|
+
};
|
|
415
|
+
}
|
|
416
|
+
function referenceSchema(withSelf, id) {
|
|
417
|
+
const aimed = `${id}(?:${ERROR_PART})?\\??`;
|
|
418
|
+
const tokens = [...withSelf ? ["\\."] : [], "\\$payload", "\\$item", aimed];
|
|
419
|
+
return {
|
|
420
|
+
description: (withSelf ? '"." (what this node would have received), ' : "") + `"$payload" (what the run entered with), "$item" (the item of the map instance containing this node), a node id (that node's output), or a node id followed by "!error" (that node's error, null where it succeeded) \u2014 each node form with an optional "?" last (the node may not have run: absent, not refused), and as a one-element array (every output of that node visible on this node's path, in branch-path order; where each form is legal is FD-V28's) (FD-V26).`,
|
|
421
|
+
anyOf: [
|
|
422
|
+
{ type: "string", pattern: `^(?:${tokens.join("|")})$` },
|
|
423
|
+
{ type: "array", minItems: 1, maxItems: 1, items: { type: "string", pattern: `^${aimed}$` } }
|
|
424
|
+
]
|
|
425
|
+
};
|
|
426
|
+
}
|
|
427
|
+
function leafSchema(id) {
|
|
428
|
+
const path = `^(?:${PREDICATE_ROOTS.join("|")})(?:\\.${id})+$`;
|
|
429
|
+
const scalar = () => ({ type: ["null", "boolean", "number", "string"] });
|
|
430
|
+
const keySchemas = {
|
|
431
|
+
path: { type: "string", pattern: path },
|
|
432
|
+
op: { enum: [...PREDICATE_OPS] },
|
|
433
|
+
value: scalar(),
|
|
434
|
+
default: { anyOf: [scalar(), { type: "array", items: scalar() }] },
|
|
435
|
+
length: { const: true }
|
|
436
|
+
};
|
|
437
|
+
return {
|
|
438
|
+
description: "A declared comparison over the decision's context.",
|
|
439
|
+
type: "object",
|
|
440
|
+
required: [...PREDICATE_LEAF_REQUIRED],
|
|
441
|
+
properties: Object.fromEntries(PREDICATE_LEAF_KEYS.map((k) => {
|
|
442
|
+
const s = keySchemas[k];
|
|
443
|
+
if (s === void 0) throw new Error(`definitionSchema: a comparison declares the key "${k}" and no schema is written for it`);
|
|
444
|
+
return [k, { ...s, description: described(PREDICATE_DESCRIPTIONS, k, "a comparison") }];
|
|
445
|
+
})),
|
|
446
|
+
additionalProperties: false,
|
|
447
|
+
allOf: [
|
|
448
|
+
// `length: true` compares a length — a number — and a length has no prefix; its default stands in for the value.
|
|
449
|
+
{
|
|
450
|
+
if: { required: ["length"] },
|
|
451
|
+
then: { properties: { value: { type: "number" }, op: { not: { enum: [...STRING_OPS] } }, default: { type: ["array", "string"] } } }
|
|
452
|
+
},
|
|
453
|
+
// with no `length`: an ordering operator compares a number, and a default is a scalar.
|
|
454
|
+
{
|
|
455
|
+
if: { not: { required: ["length"] } },
|
|
456
|
+
then: { properties: { default: scalar() } }
|
|
457
|
+
},
|
|
458
|
+
{
|
|
459
|
+
if: { required: ["op"], properties: { op: { enum: [...NUMERIC_OPS] } } },
|
|
460
|
+
then: { anyOf: [{ required: ["length"] }, { properties: { value: { type: "number" } } }] }
|
|
461
|
+
},
|
|
462
|
+
{
|
|
463
|
+
if: { required: ["op"], properties: { op: { enum: [...STRING_OPS] } } },
|
|
464
|
+
then: { properties: { value: { type: "string" } } }
|
|
465
|
+
}
|
|
466
|
+
]
|
|
467
|
+
};
|
|
468
|
+
}
|
|
469
|
+
function definitionSchema(registry) {
|
|
470
|
+
if (registry !== void 0) checkRegistry(registry);
|
|
471
|
+
const s = staticSchema();
|
|
472
|
+
if (registry !== void 0) specialise(s, registry);
|
|
473
|
+
return s;
|
|
474
|
+
}
|
|
475
|
+
function staticSchema() {
|
|
476
|
+
const id = body(ID_RE_COPY, "ID_RE");
|
|
477
|
+
body(KEY_PATH_RE, "KEY_PATH_RE");
|
|
478
|
+
const defs = {
|
|
479
|
+
id: { description: "A node id: 1-64 characters from [A-Za-z0-9_-] (FD-V16).", type: "string", pattern: `^${id}$` },
|
|
480
|
+
node: {
|
|
481
|
+
description: `A node: one of ${KINDS_COPY.join(", ")}, told apart by \`kind\`.`,
|
|
482
|
+
type: "object",
|
|
483
|
+
required: ["kind"],
|
|
484
|
+
properties: { kind: { enum: [...KINDS_COPY] } },
|
|
485
|
+
allOf: KINDS_COPY.map((k) => ({ if: { required: ["kind"], properties: { kind: { const: k } } }, then: ref(`${k}Node`) }))
|
|
486
|
+
},
|
|
487
|
+
...Object.fromEntries(KINDS_COPY.map((k) => [`${k}Node`, kindSchema(k)])),
|
|
488
|
+
edge: edgeSchema("edge"),
|
|
489
|
+
joinEdge: edgeSchema("joinEdge"),
|
|
490
|
+
gateEdge: edgeSchema("gateEdge"),
|
|
491
|
+
needs: needsSchema(true, "A node's `needs`: a non-empty object, each key 1-64 characters from [A-Za-z0-9_-], each value a reference (FD-V26)."),
|
|
492
|
+
edgeNeeds: needsSchema(false, "An edge's `needs`: as a node's, minus \".\" \u2014 its predicate already has the outcome (FD-V26)."),
|
|
493
|
+
reference: referenceSchema(true, id),
|
|
494
|
+
edgeReference: referenceSchema(false, id),
|
|
495
|
+
retryPolicy: {
|
|
496
|
+
description: "Exactly the scheduler's shape (FD-V30).",
|
|
497
|
+
type: "object",
|
|
498
|
+
required: [...RETRY_POLICY_KEYS],
|
|
499
|
+
properties: Object.fromEntries(RETRY_POLICY_KEYS.map((k) => [k, {
|
|
500
|
+
...k === "maxRetries" ? { type: "integer", minimum: 0 } : { type: "number", minimum: 0 },
|
|
501
|
+
description: described(RETRY_DESCRIPTIONS, k, "a retryPolicy")
|
|
502
|
+
}])),
|
|
503
|
+
additionalProperties: false
|
|
504
|
+
},
|
|
505
|
+
transform: {
|
|
506
|
+
description: "Exactly { lang, expr }, both strings (FD-V37).",
|
|
507
|
+
type: "object",
|
|
508
|
+
required: [...TRANSFORM_KEYS],
|
|
509
|
+
properties: Object.fromEntries(TRANSFORM_KEYS.map((k) => [k, { type: "string", description: described(TRANSFORM_DESCRIPTIONS, k, "a transform") }])),
|
|
510
|
+
additionalProperties: false
|
|
511
|
+
},
|
|
512
|
+
when: {
|
|
513
|
+
description: "One of three shapes, told apart by its keys (FD-V42): a registered name, a declared comparison, or a flat group.",
|
|
514
|
+
oneOf: [ref("predicateName"), ref("comparison"), ref("group")]
|
|
515
|
+
},
|
|
516
|
+
predicateName: {
|
|
517
|
+
description: "A registered predicate, by name (FD-V4's lookup is validateDefinition's).",
|
|
518
|
+
type: "object",
|
|
519
|
+
required: [...PREDICATE_NAME_KEYS],
|
|
520
|
+
properties: Object.fromEntries(PREDICATE_NAME_KEYS.map((k) => [k, { type: "string", description: described(PREDICATE_DESCRIPTIONS, k, "a predicate name") }])),
|
|
521
|
+
additionalProperties: false
|
|
522
|
+
},
|
|
523
|
+
comparison: leafSchema(id),
|
|
524
|
+
group: {
|
|
525
|
+
description: "A FLAT group \u2014 `all` or `any`, never both, never nested, its members comparisons (FD-V45).",
|
|
526
|
+
oneOf: PREDICATE_GROUP_KEYS.map((k) => ({
|
|
527
|
+
type: "object",
|
|
528
|
+
required: [k],
|
|
529
|
+
properties: { [k]: { type: "array", minItems: 1, items: ref("comparison"), description: described(PREDICATE_DESCRIPTIONS, k, "a group") } },
|
|
530
|
+
additionalProperties: false
|
|
531
|
+
}))
|
|
532
|
+
},
|
|
533
|
+
subsetSchema: {
|
|
534
|
+
description: "A schema in the library's built-in subset (ADR 0053): a plain object using only these keywords \u2014 any other is refused, never ignored (Q278).",
|
|
535
|
+
type: "object",
|
|
536
|
+
properties: Object.fromEntries(SCHEMA_KEYWORDS.map((k) => [k, { ...subsetKeywordSchema(k), description: described(SUBSET_DESCRIPTIONS, k, "the schema subset") }])),
|
|
537
|
+
additionalProperties: false
|
|
538
|
+
}
|
|
539
|
+
};
|
|
540
|
+
return {
|
|
541
|
+
$schema: DRAFT_2020_12,
|
|
542
|
+
title: "FlowDefinition",
|
|
543
|
+
description: "The STATIC SHAPE of a fyflow-orchestration flow definition (spec/flow-definition.md). It carries every rule a node, an edge or a value decides by its own shape, and none that needs another node or a registry: whether a named node exists and what kind it is, reachability, cycles, regions and joins, where a `needs` reference points, and every registered name \u2014 node types, pools, groups, languages, predicates, gate types and their routes and settings. For all of those, and for the definition as a whole, the AUTHORITY is `validateDefinition(flow, registry)` \u2014 and `runtime.check(flow)` on a runtime. A document this schema refuses, validateDefinition refuses; one it accepts may still be refused there.",
|
|
544
|
+
type: "object",
|
|
545
|
+
required: [...DOC_KEYS_DECLARED],
|
|
546
|
+
properties: Object.fromEntries(DOC_KEYS_DECLARED.map((k) => {
|
|
547
|
+
const s = k === "flowId" || k === "entry" ? ref("id") : k === "version" ? { type: "integer", minimum: 1 } : k === "nodes" ? { type: "array", minItems: 1, items: ref("node") } : (() => {
|
|
548
|
+
throw new Error(`definitionSchema: the document declares the key "${k}" and no schema is written for it`);
|
|
549
|
+
})();
|
|
550
|
+
return [k, { ...s, description: described(DOC_DESCRIPTIONS, k, "the document") }];
|
|
551
|
+
})),
|
|
552
|
+
additionalProperties: false,
|
|
553
|
+
$defs: defs
|
|
554
|
+
};
|
|
555
|
+
}
|
|
556
|
+
var REGISTRY_DESCRIPTION = "The SHAPE of a fyflow-orchestration flow definition SPECIALISED TO ONE REGISTRY (spec/flow-definition.md section 1). Beyond the static shape it carries what the registry decides of a node by itself: a task's `type`, one of the registry's node types (FD-V32), and per type its `pool` (the type's own name or one of its named instances, FD-V38), its `settings` held to the type's worker settingsSchema (FD-V33) and, for a type that only transforms, a required `transform` (FD-V46); `workerGroups` from the registry's groups (FD-V31); `transform.lang` from its languages (FD-V35); a predicate NAME from its predicates (FD-V4); a gate's `type`, one of its gate types (FD-V39), and per type its `settings` held to the type's settingsSchema (FD-V40) and, for a STATIC gate type, each edge's `route` one of its routes (FD-V41). It does NOT cleanly carry, and leaves to the authority: FD-V33 over the EFFECTIVE settings \u2014 a node's settings merged over its type's defaults \u2014 so a settingsSchema's `required` is WEAKENED by the keys the defaults supply, and a default's own value and any top-level keyword but properties, required and additionalProperties are unchecked; a `minLength` above 1 inside an embedded registry schema, relaxed to half rounded up, because the registry's schema subset counts a string's UTF-16 units and JSON Schema its code points; a DERIVED gate type's routes, which its routesFor computes from each gate's settings; FD-V41's every route wired EXACTLY ONCE; a gate type's settingsProblem and a language's compile (FD-V36), which are code; a node type's worker inputSchema, which is RUNTIME input and is carried as an ANNOTATION only, at `$defs.inputSchema` in its type's branch; and every rule that needs another node \u2014 existence, kinds, reachability, cycles, regions, joins, where a `needs` reference points. For all of those, and for the definition as a whole, the AUTHORITY is `validateDefinition(flow, registry)` against THIS registry \u2014 and `runtime.check(flow)` on a runtime. A document this schema refuses, validateDefinition refuses against this registry; one it accepts may still be refused there.";
|
|
557
|
+
function relaxed(schema) {
|
|
558
|
+
const walk = (s) => {
|
|
559
|
+
if (typeof s.minLength === "number" && s.minLength > 1) s.minLength = Math.ceil(s.minLength / 2);
|
|
560
|
+
if (isObject(s.properties)) {
|
|
561
|
+
for (const p of Object.values(s.properties)) if (isObject(p)) walk(p);
|
|
562
|
+
}
|
|
563
|
+
if (isObject(s.items)) walk(s.items);
|
|
564
|
+
return s;
|
|
565
|
+
};
|
|
566
|
+
return walk(structuredClone(schema));
|
|
567
|
+
}
|
|
568
|
+
var isObject = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
|
|
569
|
+
var own = (o, k) => Object.prototype.hasOwnProperty.call(o, k);
|
|
570
|
+
var quoted = (names) => [...names].map((n) => JSON.stringify(n)).join(", ");
|
|
571
|
+
function nodeTypeBranch(name, t, workers, pools) {
|
|
572
|
+
const instances = [...pools].filter(([, p]) => p.type === name).map(([k]) => k);
|
|
573
|
+
const workerName = t.worker;
|
|
574
|
+
const worker = typeof workerName === "string" ? workers.get(workerName) : void 0;
|
|
575
|
+
const properties = {
|
|
576
|
+
pool: {
|
|
577
|
+
description: `A pool of "${name}": its own name (the default instance)${instances.length ? ` or a named instance of it \u2014 ${quoted(instances)}` : ""} (FD-V38).`,
|
|
578
|
+
enum: [name, ...instances]
|
|
579
|
+
}
|
|
580
|
+
};
|
|
581
|
+
const required = [];
|
|
582
|
+
const settingsSchema = worker?.settingsSchema;
|
|
583
|
+
if (settingsSchema !== void 0) {
|
|
584
|
+
const defaults = t.settings ?? {};
|
|
585
|
+
const left = (settingsSchema.required ?? []).filter((k) => !own(defaults, k));
|
|
586
|
+
const settings = {
|
|
587
|
+
description: `Settings held to worker "${String(workerName)}"'s settingsSchema, merged OVER the type's defaults` + (Object.keys(defaults).length ? ` (${quoted(Object.keys(defaults))} supplied by them)` : "") + " (FD-V33).",
|
|
588
|
+
type: "object"
|
|
589
|
+
};
|
|
590
|
+
if (isObject(settingsSchema.properties)) {
|
|
591
|
+
settings.properties = Object.fromEntries(Object.entries(settingsSchema.properties).map(([k, p]) => [k, relaxed(p)]));
|
|
592
|
+
}
|
|
593
|
+
if (settingsSchema.additionalProperties === false) settings.additionalProperties = false;
|
|
594
|
+
if (left.length) {
|
|
595
|
+
settings.required = left;
|
|
596
|
+
required.push("settings");
|
|
597
|
+
}
|
|
598
|
+
properties.settings = settings;
|
|
599
|
+
}
|
|
600
|
+
if (onlyTransforms(t)) required.push("transform");
|
|
601
|
+
const branch = {
|
|
602
|
+
description: onlyTransforms(t) ? `A task of the built-in type "${name}": it names no worker and runs only its own \`transform\`, which it must declare (FD-V46).` : `A task of node type "${name}", run by worker "${String(workerName)}".` + (worker?.inputSchema !== void 0 ? " What that worker receives as input is described at $defs.inputSchema here \u2014 an ANNOTATION: it is runtime input, and nothing in a definition is held to it." : ""),
|
|
603
|
+
properties
|
|
604
|
+
};
|
|
605
|
+
if (required.length) branch.required = required;
|
|
606
|
+
if (worker?.inputSchema !== void 0) branch.$defs = { inputSchema: structuredClone(worker.inputSchema) };
|
|
607
|
+
return branch;
|
|
608
|
+
}
|
|
609
|
+
function gateTypeBranch(name, t) {
|
|
610
|
+
const properties = {};
|
|
611
|
+
const branch = { description: "", properties };
|
|
612
|
+
if (t.settingsSchema !== void 0) {
|
|
613
|
+
properties.settings = relaxed(t.settingsSchema);
|
|
614
|
+
if (findings(t.settingsSchema, {}).length > 0) branch.required = ["settings"];
|
|
615
|
+
}
|
|
616
|
+
if (typeof t.routesFor !== "function") {
|
|
617
|
+
const set = routesOf(t, {});
|
|
618
|
+
if ("problem" in set) throw new Error(`definitionSchema: gate type "${name}" resolves no route set: ${set.problem}`);
|
|
619
|
+
properties.edges = {
|
|
620
|
+
items: {
|
|
621
|
+
properties: {
|
|
622
|
+
route: {
|
|
623
|
+
description: `One of "${name}"'s routes \u2014 ${quoted(set.routes)}; an edge with no \`route\` carries its default, "${set.defaultRoute}" (FD-V41).`,
|
|
624
|
+
enum: [...set.routes]
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
}
|
|
628
|
+
};
|
|
629
|
+
branch.description = `A gate of the STATIC gate type "${name}": routes ${quoted(set.routes)}, the default "${set.defaultRoute}". That each is wired exactly once is validateDefinition's (FD-V41).`;
|
|
630
|
+
} else {
|
|
631
|
+
branch.description = `A gate of the DERIVED gate type "${name}": its routes are computed from each gate's settings, so which \`route\` names exist is validateDefinition's (FD-V41).`;
|
|
632
|
+
}
|
|
633
|
+
return branch;
|
|
634
|
+
}
|
|
635
|
+
var branchOn = (key, name, then) => ({ if: { required: [key], properties: { [key]: { const: name } } }, then });
|
|
636
|
+
function specialise(s, registry) {
|
|
637
|
+
const defs = s.$defs;
|
|
638
|
+
const nodeTypes = nodeTypesOf(registry.nodeTypes);
|
|
639
|
+
const workers = workersOf(registry.workers);
|
|
640
|
+
const pools = poolsOf(registry.pools);
|
|
641
|
+
const gateTypes = gateTypesOf(registry.gateTypes);
|
|
642
|
+
const groups = [...new Set(registry.groups ?? [])];
|
|
643
|
+
const predicates = [...new Set(registry.predicates)];
|
|
644
|
+
const languages = [...languagesOf(registry.languages).keys()];
|
|
645
|
+
const task = defs.taskNode;
|
|
646
|
+
task.properties.type = {
|
|
647
|
+
...task.properties.type,
|
|
648
|
+
description: `The node type that runs this task: one of the registry's \u2014 ${quoted(nodeTypes.keys())} (FD-V32). What each type adds is its branch in this node's allOf.`,
|
|
649
|
+
enum: [...nodeTypes.keys()]
|
|
650
|
+
};
|
|
651
|
+
task.properties.workerGroups = {
|
|
652
|
+
...task.properties.workerGroups,
|
|
653
|
+
description: `The resource groups the scheduler holds this task to: a non-empty list of distinct ids of the registry's groups \u2014 ${groups.length ? quoted(groups) : "it declares none"} (FD-V31).`,
|
|
654
|
+
items: { type: "string", enum: groups }
|
|
655
|
+
};
|
|
656
|
+
task.allOf = [...nodeTypes].map(([n, t]) => branchOn("type", n, nodeTypeBranch(n, t, workers, pools)));
|
|
657
|
+
const transform = defs.transform;
|
|
658
|
+
transform.properties.lang = {
|
|
659
|
+
...transform.properties.lang,
|
|
660
|
+
description: `A language the registry declares \u2014 ${languages.length ? quoted(languages) : "it declares none"} (FD-V35). That it compiles \`expr\` is validateDefinition's (FD-V36).`,
|
|
661
|
+
enum: languages
|
|
662
|
+
};
|
|
663
|
+
const predicateName = defs.predicateName;
|
|
664
|
+
predicateName.properties.predicate = {
|
|
665
|
+
...predicateName.properties.predicate,
|
|
666
|
+
description: `A predicate the registry declares \u2014 ${predicates.length ? quoted(predicates) : "it declares none"} (FD-V4).`,
|
|
667
|
+
enum: predicates
|
|
668
|
+
};
|
|
669
|
+
const gate = defs.gateNode;
|
|
670
|
+
gate.properties.type = {
|
|
671
|
+
...gate.properties.type,
|
|
672
|
+
description: `The gate type that decides: one of ${quoted(gateTypes.keys())} \u2014 the built-ins and the registry's \`gateTypes\` (FD-V39). What each adds is its branch in this node's allOf.`,
|
|
673
|
+
enum: [...gateTypes.keys()]
|
|
674
|
+
};
|
|
675
|
+
gate.allOf = [...gateTypes].map(([g, t]) => branchOn("type", g, gateTypeBranch(g, t)));
|
|
676
|
+
s.description = REGISTRY_DESCRIPTION;
|
|
677
|
+
}
|
|
149
678
|
|
|
150
679
|
// src/definition/assist.ts
|
|
151
680
|
var TYPES = ["object", "array", "string", "number", "integer", "boolean", "null"];
|
|
@@ -260,11 +789,11 @@ function object(s, indent) {
|
|
|
260
789
|
const req = new Set(s.required ?? []);
|
|
261
790
|
const named = [...props.map(([k]) => k)];
|
|
262
791
|
const all = [...props, ...[...req].filter((k) => !named.includes(k)).map((k) => [k, {}])];
|
|
263
|
-
const
|
|
792
|
+
const body2 = all.map(([k, sub]) => `${indent} ${lit(k)}${req.has(k) ? "" : "?"}: ${tsTypeOf(sub, `${indent} `)};`).join("\n");
|
|
264
793
|
const rest = closed ? "" : `
|
|
265
794
|
${indent} [k: string]: unknown;`;
|
|
266
795
|
return `{
|
|
267
|
-
${
|
|
796
|
+
${body2}${rest}
|
|
268
797
|
${indent}}`;
|
|
269
798
|
}
|
|
270
799
|
function signatureOf(name, worker) {
|
|
@@ -300,23 +829,28 @@ export {
|
|
|
300
829
|
ConfigRefused,
|
|
301
830
|
DECLARED_POOL_KEYS,
|
|
302
831
|
DOCUMENT_KEYS,
|
|
832
|
+
DOC_KEYS_DECLARED,
|
|
303
833
|
DerivationRefused,
|
|
304
834
|
Driver,
|
|
305
835
|
DuplicateTaskId,
|
|
306
836
|
EDGE_KEYS_DECLARED,
|
|
837
|
+
EDGE_KEYS_REQUIRED,
|
|
307
838
|
GATE_TYPE_KEYS,
|
|
308
839
|
GateTypeRefused,
|
|
309
840
|
GroupConfigRefused,
|
|
310
841
|
GroupTypeMissing,
|
|
842
|
+
ID_RE_COPY as ID_RE,
|
|
311
843
|
INSTANCE_KEYS,
|
|
312
844
|
InvalidDefinition,
|
|
313
845
|
InvalidRunId,
|
|
314
846
|
InvalidTaskId,
|
|
315
847
|
KEY_PATH_RE,
|
|
848
|
+
KINDS_COPY as KINDS,
|
|
316
849
|
MESSAGE_OPTION_KEYS,
|
|
317
850
|
MissingJoinPolicy,
|
|
318
851
|
MultipleRuns,
|
|
319
852
|
NODE_KEYS_DECLARED,
|
|
853
|
+
NODE_KEYS_REQUIRED,
|
|
320
854
|
NODE_TYPE_DECLARATION_KEYS,
|
|
321
855
|
NameCollision,
|
|
322
856
|
NameMissing,
|
|
@@ -334,6 +868,7 @@ export {
|
|
|
334
868
|
PREDICATE_ROOTS,
|
|
335
869
|
PoolTypeMissing,
|
|
336
870
|
RETRY_POLICY_KEYS,
|
|
871
|
+
ROUTABLE_STATES,
|
|
337
872
|
RegistryError,
|
|
338
873
|
ResumeRefused,
|
|
339
874
|
RunControlRefused,
|
|
@@ -371,6 +906,7 @@ export {
|
|
|
371
906
|
checkRegistry,
|
|
372
907
|
checkWiring,
|
|
373
908
|
compileProblem,
|
|
909
|
+
definitionSchema,
|
|
374
910
|
derivePool,
|
|
375
911
|
describeFindings,
|
|
376
912
|
describePaths,
|