fyflow-orchestration 0.11.0 → 0.13.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.
@@ -86,10 +86,12 @@ export type PredicateOp = typeof PREDICATE_OPS[number];
86
86
  /** The two roots a predicate's key path may start at — the two members of `DecisionContext`, and no other. */
87
87
  export declare const PREDICATE_ROOTS: readonly ["outcome", "needs"];
88
88
  /**
89
- * **What a declared comparison may compare AGAINST** — a scalar, and nothing else (`FD-V44`).
89
+ * **What a declared comparison's LITERAL may be** — a scalar, and nothing else (`FD-V44`).
90
90
  * Every one of the ten predicate bodies in this tree compares to one (`0.5`, `50`, `true`,
91
91
  * `'r1:publish:'`, `0`), and admitting an object would need a deep-equality semantics with no
92
- * instance and no obvious right answer for `NaN`, key order or a prototype.
92
+ * instance and no obvious right answer for `NaN`, key order or a prototype. *Since v0.55 a comparison
93
+ * may compare against ANOTHER key path instead — `valueFrom` (ADR 0140) — and a resolved object or
94
+ * array there is no match, for the same reason.*
93
95
  */
94
96
  export type PredicateScalar = null | boolean | number | string;
95
97
  /** A registered predicate NAME, resolved against the registry at instantiation (`FD-V4`). */
@@ -97,20 +99,20 @@ export interface PredicateName {
97
99
  predicate: string;
98
100
  }
99
101
  /**
100
- * **One comparison over the decision's own context** — `FD-V43` owns the path and `FD-V44` the
101
- * operator and the value.
102
+ * **What every comparison carries, whichever right side it names** — `FD-V43` owns the path and `FD-V44` the
103
+ * operator and the modifiers.
102
104
  */
103
- export interface PredicateLeaf {
105
+ export interface PredicateLeafBase {
104
106
  /**
105
107
  * A KEY PATH over the `DecisionContext` itself, read by `readKeyPath` — the same resolution a
106
108
  * gate's `settings.key` gets, measured unchanged at this scope. **Its first segment is `outcome`
107
109
  * or `needs` and nothing else** (`FD-V43`), because a first segment that is neither resolves to
108
- * `undefined` in silence and a typo would be a wrong key rather than a refusal.
110
+ * `undefined` in silence and a typo would be a wrong key rather than a refusal. A key past the root may
111
+ * carry array indexes — `outcome.result.items[0].score` — and the root never does (v0.53, ADR 0137).
112
+ * **A `needs` path names a key that edge's `needs` DECLARES** (v0.55, P45 (g1)): any other is absent for ever.
109
113
  */
110
114
  path: string;
111
115
  op: PredicateOp;
112
- /** The literal compared against. Required — there is no operator here that takes one operand. */
113
- value: PredicateScalar;
114
116
  /**
115
117
  * **What is compared when the path does not resolve, or resolves to `null`.** Absent is NO MATCH
116
118
  * by default; where this is declared it is substituted instead — which is `?? 0` and `?? []`
@@ -135,6 +137,29 @@ export interface PredicateLeaf {
135
137
  */
136
138
  length?: true;
137
139
  }
140
+ /**
141
+ * **One comparison over the decision's own context — against a LITERAL, or against ANOTHER KEY PATH** (v0.55,
142
+ * [ADR 0140](../../doc/decisions/0140-a-comparison-may-compare-against-another-key-path-and-an-absent-one-is-no-match.md),
143
+ * P45 (a1)). Exactly one of `value` / `valueFrom` (`FD-V42`), so a TWO-member union rather than one interface with
144
+ * both optional — `PredicateGroup`'s precedent: `{ path, op }` with neither, and both at once, fail at L0. **The type
145
+ * change, stated** (P45 decision 8): until 0.13.0 `value` was required, so code READING `leaf.value` now sees
146
+ * `PredicateScalar | undefined` and tells the two apart by `'valueFrom' in leaf`.
147
+ */
148
+ export type PredicateLeaf = (PredicateLeafBase & {
149
+ /** The literal compared against. */
150
+ value: PredicateScalar;
151
+ valueFrom?: never;
152
+ }) | (PredicateLeafBase & {
153
+ /**
154
+ * **A key path over the SAME context, compared against as a literal would be** — the same roots as `path` (and
155
+ * the same `needs` rule), held to `FD-V43`; resolved by `readKeyPath` when the comparison is asked. Type-strict, a
156
+ * resolved `null` compared as `null`; **a resolved object or array is NO MATCH for every operator, `ne` included**;
157
+ * and **an ABSENT one is NO MATCH** — the left side's `default` does not stand in for it, so `x gt y` and `x lte y`
158
+ * are both false where `y` is absent. `default` and `length` are the LEFT side's only.
159
+ */
160
+ valueFrom: string;
161
+ value?: never;
162
+ });
138
163
  /**
139
164
  * **A FLAT group — `all` or `any`, and its members are LEAVES.** Nesting is refused by name
140
165
  * (`FD-V45`), and so is a `{ predicate }` member: a group holding a registered name could be
@@ -647,8 +672,9 @@ export interface GateNode {
647
672
  /**
648
673
  * **What the gate's type is configured with** — a plain object its type's `settingsSchema` accepts
649
674
  * (`FD-V40`), `{}` when absent. **`key` is the one setting the LIBRARY reads**: where present it is a
650
- * KEY PATH (`keyPathProblem`) over the value the gate receives, resolved by the driver and handed to
651
- * the type's `fn` as `ctx.key`.
675
+ * KEY PATH (`keyPathProblem`) over the value the gate receives — dotted object keys, each optionally
676
+ * followed by array indexes `[n]` since v0.53 (`files[0].series`, ADR 0137) — resolved by the driver and
677
+ * handed to the type's `fn` as `ctx.key`.
652
678
  */
653
679
  settings?: Readonly<Record<string, unknown>>;
654
680
  /** Each carries `to` and, optionally, `route` — and nothing else (`FD-V41`). */
@@ -663,7 +689,7 @@ export interface GateNode {
663
689
  * to be.)*
664
690
  */
665
691
  export interface GateContext {
666
- /** `settings.key` resolved over `input` by `readKeyPath` — `undefined` where the gate declares no `key` or a segment is missing. */
692
+ /** `settings.key` resolved over `input` by `readKeyPath` — `undefined` where the gate declares no `key`, a key is missing, or an index `[n]` is not an element of a real array. */
667
693
  readonly key: unknown;
668
694
  /** The value that reached the gate — what leaves it, unchanged, on the route `fn` returns. */
669
695
  readonly input: unknown;
@@ -18,7 +18,8 @@
18
18
  * ADR 0002 rule 3: this runs in full, at instantiation, before any task is queued.
19
19
  */
20
20
  import type { Finding, FlowDefinition, GateType, GateTypes, JsonSchema, StaticGateType, LanguageAdapter, Languages, NodeTypeEntry, NodeTypes, Pools, Registry, WorkerEntry, Workers } from './types.js';
21
- export { readKeyPath } from './condition.js';
21
+ export { keyPathSteps, readKeyPath } from './condition.js';
22
+ export type { KeyPathStep } from './condition.js';
22
23
  declare const KINDS: readonly ["task", "fanout", "map", "join", "end", "gate", "ask"];
23
24
  /**
24
25
  * **`FD-V16`'s charset — a flow's and a node's id** ([spec/task-id.md](../../spec/task-id.md)'s) — v0.50 (W210,
@@ -168,10 +169,15 @@ export declare function poolsOf(x: Pools | undefined): ReadonlyMap<string, {
168
169
  */
169
170
  export declare function languagesOf(x: Languages | undefined): ReadonlyMap<string, LanguageAdapter>;
170
171
  /**
171
- * **A KEY PATH — P24 stop-and-ask (d), answered**: dot-separated OBJECT keys, each segment in `FD-V16`'s
172
- * charset, over the value a gate receives. **No array index, no wildcard, no expression** — a key a flow
173
- * needs COMPUTED is computed in the task before the gate (P24 decision 5), because the driver has no
174
- * `async` and `evaluate()` in every expression language here returns a Promise (ADR 0051).
172
+ * **A KEY PATH — P24 stop-and-ask (d), answered; an array INDEX since v0.53** (P44 (c1),
173
+ * [ADR 0137](../../doc/decisions/0137-a-key-path-indexes-an-array-by-a-bracket-suffix-and-a-plain-segment-keeps-its-meaning.md)):
174
+ * dot-separated SEGMENTS over the value a gate receives, each an OBJECT key in `FD-V16`'s charset followed by zero or
175
+ * more bracket indexes `[n]` — `n` is `0` or `[1-9][0-9]{0,8}`, no leading zero, at most 999,999,999. **An index is a
176
+ * SUFFIX of a segment and never leads the path**, so the first step is always a key. A plain numeric segment (`xs.1`)
177
+ * is still a KEY. **No quoted key, no wildcard, no expression** — a key a flow needs COMPUTED is computed in the task
178
+ * before the gate (P24 decision 5), because the driver has no `async` and `evaluate()` in every expression language
179
+ * here returns a Promise (ADR 0051). **Its `source` is package surface and moved at v0.53**; every string it matched
180
+ * before it still matches, and resolves as before, since none held `[`.
175
181
  */
176
182
  export declare const KEY_PATH_RE: RegExp;
177
183
  /**
@@ -264,7 +270,7 @@ export declare const PREDICATE_GROUP_KEYS: readonly string[];
264
270
  * has owned *an edge's `when` names a predicate absent from the registry* since P1 and whose only
265
271
  * change at v0.27 is where the name is written.
266
272
  */
267
- export declare function predicateProblem(v: unknown): {
273
+ export declare function predicateProblem(v: unknown, edgeNeeds?: readonly string[]): {
268
274
  rule: string;
269
275
  message: string;
270
276
  } | null;
@@ -9,7 +9,7 @@
9
9
  * module derives the SCHEMA of that value from the producer side of each arc that reaches it, one
10
10
  * verdict per arc, in five shapes: an ordinary **edge** (the producer's `outputSchema`), a fan-out
11
11
  * **branch** (the same value the fan-out received — `JP-R11`), a map **item** (one element of the
12
- * `over` array the map received), a join's **record** (`JP-R12`'s, keyed by branch path),
12
+ * `over` array the map received), a join's **record** (`JP-R12`'s, keyed by each branch's own key),
13
13
  * and a **needs** composition (`FD-C1`'s table: `"."` is the edge's value, a node id is that node's
14
14
  * output, `[id]` an array of them, a `?` makes the key optional — and over a map's item, one
15
15
  * composed object per element, evaluated per element as the run does). The ENTRY has no arc: its
@@ -42,14 +42,14 @@
42
42
  * **A join successor's input is a DIFFERENT question** (decision 8), and the subset cannot say
43
43
  * *any key, each of shape S* — measured at W73's declaration: `additionalProperties: <schema>` is
44
44
  * refused by `schemaProblem`. So the record's shape is THIS MODULE's knowledge and not a keyword's:
45
- * for a `fanout` region the record schema is exact in its KEYS (every declared branch path a
46
- * property, no other key) and REQUIRES none of them — a branch that is lost has no entry, and a
45
+ * for a `fanout` region the record schema is exact in its KEYS (every declared branch ENTRY NODE ID a
46
+ * property, no other key — v0.25, ADR 0138; a branch path until 0.12.0) and REQUIRES none of them — a branch that is lost has no entry, and a
47
47
  * branch is lost by three roads no document shows (an `optional` task failing, a person resolving a
48
48
  * suspended task `failed`, a policy firing before it settles — `JP-R12`, `spec/join-policy.md`
49
49
  * section 2), so a consumer requiring a branch key is `no`; and for a `map` region it is an object whose keys are
50
- * branch paths minted at run time, each of the branch's output shape — carried internally as
50
+ * ITEM INDEXES minted at run time (`"0"`, `"1"`, …), each of the branch's output shape — carried internally as
51
51
  * `additionalProperties: <schema>` with a `branchKeys` marker, which `fits` reads and no author may
52
- * write. A consumer naming a property that is not a branch path never meets it.
52
+ * write. A consumer naming a property that is not an item index never meets it.
53
53
  *
54
54
  * **A transformed arc is verified on a SAMPLE, and the verdict says which sample** (ADR 0056 rule
55
55
  * 3, [Q301](../../doc/questions/q301.md)): the producer's first declared example, else the
@@ -276,10 +276,19 @@ export interface RunPauseOptions {
276
276
  }
277
277
  /**
278
278
  * **What a checkpoint's header says, and the number a resume refuses on** — `RN-R16`,
279
- * ADR 0064 rule 3. `1` at this version; it moves only when what a checkpoint CARRIES moves, and
279
+ * ADR 0064 rule 3. `2` at this version; it moves only when what a checkpoint CARRIES moves, and
280
280
  * a resume refuses a format it does not know — `ResumeRefused` with `reason: 'format'` (`RN-R23`, W89).
281
+ *
282
+ * **`1` until 0.12.0, and it moved because a join's collection moved** — `RN-R16` v0.36,
283
+ * [ADR 0138](../../doc/decisions/0138-a-join-hands-on-each-branch-under-its-own-key-and-a-checkpoint-of-the-old-keying-is-refused-by-format.md)
284
+ * (P44 (b), the maintainer's: no backward compatibility). A collection reaches a checkpoint through an `asked` element's
285
+ * `input`, a `gated` decision taken on a key path into it, and every fed outcome whose worker read it (P44 fact 4), so a
286
+ * format-1 run replayed under the own-key collection would refuse `diverged`, re-route a gate, or carry results computed
287
+ * from keys that no longer exist. **This driver carries ONE keying and reads no format 1**: every 0.11.0 checkpoint — a
288
+ * join in it or none — is refused `format` by `resume()`, `runtime.resume` and `inputOf`, before anything is replayed;
289
+ * and a 0.11.0 driver refuses this one's the same way.
281
290
  */
282
- export declare const CHECKPOINT_FORMAT = 1;
291
+ export declare const CHECKPOINT_FORMAT = 2;
283
292
  /**
284
293
  * **The header — the facts a run's EVENTS cannot regenerate** (`RN-R15`, ADR 0064 rule 2, P23
285
294
  * decision 4). Every other fact about a run is in its events, which the driver regenerates from
@@ -343,7 +352,8 @@ export interface Checkpoint {
343
352
  * **Widened by W158 with `cancelled`, and that is BREAKING for a consumer switching on `reason` exhaustively** —
344
353
  * `resumed`'s and `gated`'s precedent (ADR 0094 consequence 1). **And W171 RENAMED `stopped` to `halted`** (ADR 0102, P34
345
354
  * stop-and-ask (f)) — BREAKING, and loudly: a consumer's `reason === 'stopped'` no longer compiles, so it cannot silently
346
- * come to mean P34's resumable stop. A 0.7.0 checkpoint holding a `stopped` element is refused `halted`.
355
+ * come to mean P34's resumable stop. A 0.7.0 checkpoint holding a `stopped` element was refused `halted`; since
356
+ * `CHECKPOINT_FORMAT` 2 (ADR 0138) it is format 1 and refused `format` first.
347
357
  */
348
358
  export type ResumeRefusalReason = 'format' | 'run' | 'flow' | 'halted' | 'cancelled' | 'diverged';
349
359
  /**
@@ -415,7 +425,7 @@ export interface NodeInput {
415
425
  *
416
426
  * | reason | when | `index` |
417
427
  * |---|---|---|
418
- * | `format` | the run is not `{ header, events[] }`, its `header.format` is not {@link CHECKPOINT_FORMAT}, its header's three fields are not format 1's types, its `runId` is not a run id (`ID-R2`), or its entry payload does not clone — `resumeRefusal`'s header half, the one function | `null` |
428
+ * | `format` | the run is not `{ header, events[] }`, its `header.format` is not {@link CHECKPOINT_FORMAT}, its header's three fields are not the format's types, its `runId` is not a run id (`ID-R2`), or its entry payload does not clone — `resumeRefusal`'s header half, the one function | `null` |
419
429
  * | `flow` | `header.flowId` or `header.version` is not the definition's — no migration | `null` |
420
430
  * | `unknown` | the target cannot name anything in this run: a node id the definition lacks, a branch path that is not `spec/task-id.md`'s grammar, or a task id that does not parse, names another run, an attempt other than `0`, or a node that is neither a task nor an ask | `null` |
421
431
  * | `not-reached` | the replay did not hand the target anything within the stored prefix a reading verifies — which ends at the first `halted`, `stopped` or `cancelRequested` element, or at the stored events' end | the prefix's length |
@@ -1050,7 +1060,8 @@ export declare class Driver {
1050
1060
  private readonly firedJoins;
1051
1061
  /**
1052
1062
  * **What each branch carried into its join, keyed by region and then by
1053
- * `branchPath`** — [ADR 0037](../../doc/decisions/0037-what-a-branch-receives-is-a-property-of-the-fan-out-and-what-a-join-carries-is-a-property-of-the-region.md)
1063
+ * `branchPath`** — the FULL path, here where it is recorded; the collection a join hands on is keyed by each
1064
+ * branch's OWN key, derived from these paths by `collectArrivals` at the exit (ADR 0138) —[ADR 0037](../../doc/decisions/0037-what-a-branch-receives-is-a-property-of-the-fan-out-and-what-a-join-carries-is-a-property-of-the-region.md)
1054
1065
  * rule 4, and `JP-R11` in [spec/join-policy.md](../../spec/join-policy.md)
1055
1066
  * section 4.
1056
1067
  *
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fyflow-orchestration",
3
- "version": "0.11.0",
3
+ "version": "0.13.0",
4
4
  "description": "Flow orchestration over fyflow-scheduler: sequence, decision, fan-out and join",
5
5
  "keywords": [
6
6
  "workflow",