You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat(spec,service-automation): a flow variable can declare a defaultValue, so "declared" means "bound" (#4697) (#6998)
* feat(spec,service-automation): a flow variable can declare a `defaultValue` (#4697)
`FlowVariableSchema` gains an optional `defaultValue`, and the engine binds it
whenever no parameter supplies one — so a declared variable is bound on every
path and "declared" finally means "bound".
Before this, the engine bound an `isInput` variable only when the caller
supplied it (`params[name] !== undefined`), so every path that omitted the
parameter left the name unbound. Conditions are strict CEL, where an unbound
name does not read as `false` — it aborts the predicate and stops the run
(hotcrm#643: a screen collecting an optional checkbox, whose untouched path
aborted the outgoing edge and persisted nothing).
Both run entry points (`execute` and `executeWithoutRetry`) now seed from one
shared `seedDeclaredVariables` site, so the retry path behaves identically.
Additive: a declaration without `defaultValue` behaves exactly as before.
Also lands the docs half of the same gap — under strict CEL only the
`vars.`-scoped `has(vars.X)` tests bindedness; the bare `has(X.f)` aborts on
the very case it is written for. That truth table is measured against the live
evaluator in a test rather than asserted.
* docs(spec): regenerate the reference pages for FlowVariable.defaultValue (#4697)
Generator output only (`gen:schema && gen:docs`), never hand-edited: the new
key's row on the FlowVariable table, and the inline `variables` summary on the
two Flow tables gaining its `…` truncation marker now that the shape has a
fifth key.
`check:docs` reports `230 generated files in sync with packages/spec`.
---------
Co-authored-by: Claude <noreply@anthropic.com>
|**template**|`never`| optional |[REMOVED]`flow.template` was removed in @objectstack/spec 17.0.0 (#3896 audit close-out) — no designer or engine path ever read it, so flagging a flow as a template/subflow did nothing. Delete the key. Shared logic is invoked via a subflow NODE referencing the flow by name. |
|**active**|`never`| optional |[REMOVED]`flow.active` was removed in @objectstack/spec 17.0.0 (#3896 audit close-out) — it never had an effect: the engine arms flows from `status`, and `active: false` did NOT stop a flow (worse, the default read as disabled while the engine treated unset as enabled). Delete the key. Use `status: 'obsolete'` (or 'invalid') to unbind and disable a flow, `status: 'active'` to arm it. |
|**template**|`never`| optional |[REMOVED]`flow.template` was removed in @objectstack/spec 17.0.0 (#3896 audit close-out) — no designer or engine path ever read it, so flagging a flow as a template/subflow did nothing. Delete the key. Shared logic is invoked via a subflow NODE referencing the flow by name. |
|**active**|`never`| optional |[REMOVED]`flow.active` was removed in @objectstack/spec 17.0.0 (#3896 audit close-out) — it never had an effect: the engine arms flows from `status`, and `active: false` did NOT stop a flow (worse, the default read as disabled while the engine treated unset as enabled). Delete the key. Use `status: 'obsolete'` (or 'invalid') to unbind and disable a flow, `status: 'active'` to arm it. |
@@ -142,6 +142,7 @@ const result = FlowSchema.parse(data);
142
142
|**type**|`string`| ✅ | Data type (text, number, boolean, object, list) |
143
143
|**isInput**|`boolean`| ✅ | Is input parameter |
144
144
|**isOutput**|`boolean`| ✅ | Is output parameter |
145
+
|**defaultValue**|`any`| optional | Value bound at run start when no parameter supplies one — this is what makes a declared variable always bound. An explicitly supplied param wins, including `false` and `null`; the boundary is `params[name] !== undefined`. |
0 commit comments