Skip to content

Commit 48e8d11

Browse files
committed
chore(spec): regenerate schemaless-node-config reference (gen:docs)
Claude-Session: https://claude.ai/code/session_01CiCTczDo7tGhafXjf61dUJ Co-authored-by: Claude <noreply@anthropic.com>
1 parent 395cc45 commit 48e8d11

1 file changed

Lines changed: 17 additions & 11 deletions

File tree

‎content/docs/references/automation/schemaless-node-config.mdx‎

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -66,13 +66,18 @@ The two halves reach different audiences, which is why they shipped together:
6666
nothing read — and then refuses, naming the `function` it does not have,
6767
instead of logging a line and reporting success as it used to.
6868

69-
`decision` stays export-only: nothing parses it at run time. It may carry no
70-
`conditions` at all when it branches purely on edge predicates, its executor
71-
reads `conditions` and nothing else, and its one other key — `mode` — is
72-
declared AHEAD of the engine change that reads it (#15429; see
73-
`DecisionConfigSchema`). Its enforcement remains the objectui
74-
reconciliation test, which is what #4278 was actually about (a form
75-
authoring keys nothing reads).
69+
`decision` is parsed at **registration**, for one key (#15429): the
70+
automation engine's `registerFlow` runs every decision node's config through
71+
`DecisionConfigSchema` and refuses the flow on any issue rooted at
72+
`mode` — a value outside the closed pair, or a `mode` beside a non-empty
73+
`conditions` list — with this schema's own sentence, and `os validate`
74+
reports the same issues as `flow-decision-mode-invalid`, so the two doors
75+
cannot disagree. A decision may carry no `conditions` at all when it
76+
branches purely on edge predicates; its executor reads `conditions` and
77+
nothing else, and the engine's traversal reads `mode`. Its strictness
78+
(unknown keys) still binds at authoring, in the published JSON Schema and in
79+
the objectui reconciliation test, which is what #4278 was actually about (a
80+
form authoring keys nothing reads).
7681

7782
Undeclared aliases are NOT part of these contracts: `subflow`'s historical
7883
`flow` spelling graduated into the ADR-0087 D2 conversion
@@ -96,9 +101,10 @@ door in front of its author, and the class it structurally could not cover is
96101
precisely the class with no second door. Closing these shapes is therefore
97102
not a duplicate check for `script` and `subflow`; it is their first one.
98103

99-
`decision` is still export-only, so its strictness binds at authoring
100-
(`tsc`), in the published JSON Schema, and in objectui's reconciliation —
101-
not at run time. It is closed anyway, because the campaign's whole finding
104+
`decision`'s strictness binds at authoring (`tsc`), in the published JSON
105+
Schema, and in objectui's reconciliation — not at run time, where the
106+
registration reader judges `mode` alone (#15429). It is closed anyway,
107+
because the campaign's whole finding
102108
is that a shape left open accretes a test, a form and a fixture that assert
103109
the openness, and then closing it is a migration instead of an edit.
104110

@@ -137,7 +143,7 @@ const result = DecisionConditionSchema.parse(data);
137143
| Property | Type | Required | Description |
138144
| :--- | :--- | :--- | :--- |
139145
| **conditions** | `{ label: string; expression: string }[]` | optional | Ordered decision branches (first true expression wins; omit to branch purely on edge conditions) |
140-
| **mode** | `Enum<'exclusive' \| 'inclusive'>` | optional | Declares how many out-edges an edge-branched decision takes when more than one out-edge condition holds: 'exclusive' = only the first, in the order the edges are declared (what an omitted mode means); 'inclusive' = every one that holds. Declared ahead of the engine change that reads it: until that lands, an edge-branched decision takes every out-edge whose condition holds, whatever this says. Refused beside a non-empty conditions list, which is first-match on its own: delete mode there, or move the branches onto the out-edges, delete conditions, and keep mode. |
146+
| **mode** | `Enum<'exclusive' \| 'inclusive'>` | optional | Declares how many out-edges an edge-branched decision takes when more than one out-edge condition holds: 'exclusive' = only the first, in the order the edges are declared (what an omitted mode means; the siblings after it are not evaluated and record a skipped step); 'inclusive' = every one that holds, one after another. When none holds the isDefault edge runs either way. Refused beside a non-empty conditions list, which is first-match on its own: delete mode there, or move the branches onto the out-edges, delete conditions, and keep mode. Flows written while every true branch ran keep that behaviour through the os migrate meta --from 17 conversion, which writes mode: inclusive onto every edge-branched decision with two or more conditioned out-edges. |
141147

142148
### Nested Shape: `DecisionConfig.conditions[number]`
143149

0 commit comments

Comments
 (0)