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
{{ message }}
Repository navigation
Commit 25784cf
Browse filesBrowse the repository at this point in the historyBrowse files
* fix(automation,approvals): defer flow node-type validation until the plugin vocabulary is closed (#4771)
ADR-0018 makes the flow node-type vocabulary open and runtime-extensible: a
plugin contributes types via registerNodeExecutor() from its own init()/start().
AutomationServicePlugin.start() pulls flows from the ObjectQL registry and
validated each node type on the spot — ~0.8s before ApprovalsServicePlugin
registered the `approval` executor. Every showcase cold boot therefore asserted
that eight ADR-0019 approval flows "will fail at execution time", and all eight
were false. Worse, a deployment that genuinely lacks the approvals plugin
produced the identical eight, so the warning could not distinguish the two.
- AutomationEngine.sealNodeTypeVocabulary() declares the vocabulary closed and
runs the authoritative audit, warning once per offending flow. Idempotent.
- AutomationEngine.getUnknownNodeTypeAudit() exposes the same finding as state
(mirrors getTriggerBindingAudit) for hosts that read the engine, not the log.
- AutomationServicePlugin seals at kernel:bootstrapped — strictly after every
plugin's start() AND every kernel:ready handler (its own registers more flows).
- After sealing, registerFlow warns inline again: a Studio publish / dev reload
into a running server IS judged against a complete vocabulary. Timing fix, not
a mute.
- Disabled flows (obsolete/invalid) are skipped: a flow that cannot run cannot
fail at run time.
Same defect class, second half: ApprovalsServicePlugin logged "no automation
engine — approval node not registered" at info while dev defaults to warn, so
the real degradation was invisible exactly when it happened (#4632). Now warn,
naming consequence and remedy; the catch is narrowed to the service lookup so a
failure inside registerApprovalNode surfaces as itself; and the
service-exists-but-takes-no-executors branch, which logged nothing at all, warns
too.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015Br2xsJsczFsTR9bvbh2Ny
* docs(automation): flows.mdx 的节点 `type` 校验时机改为两阶段描述 (#4771)
表格原文说节点 type「is checked against the live action registry at
`registerFlow()`」。本 PR 之后这句不再为真:启动期注册的 flow 在词汇表封闭
(所有插件 start() 完毕)时统一校验,封闭之后的注册才回到即时校验。顺带写明
这条检查是 warn 而非拒绝,以及执行时的 NO_EXECUTOR 后果。
同文件其余提到 `registerFlow()` 的句子(config 键、条件表达式、ADR-0031 区域)
描述的是没有改动的校验,保持原样。
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015Br2xsJsczFsTR9bvbh2Ny
---------
Co-authored-by: Claude <noreply@anthropic.com>
Copy file name to clipboardExpand all lines: content/docs/automation/flows.mdx
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -137,7 +137,7 @@ Each node performs a specific action in the flow.
137
137
| Property | Type | Required | Description |
138
138
| :--- | :--- | :--- | :--- |
139
139
|`id`|`string`| ✅ | Unique node identifier |
140
-
|`type`|`string`| ✅ | Node type — a built-in id from the table above **or** a plugin-registered one. Per ADR-0018 the spec does not gate this with a closed enum; it is checked against the live action registry at `registerFlow()`|
140
+
|`type`|`string`| ✅ | Node type — a built-in id from the table above **or** a plugin-registered one. Per ADR-0018 the spec does not gate this with a closed enum; it is checked against the live action registry once that registry is complete — plugins contribute node types while they start, so flows registered during boot are checked in one pass when the vocabulary closes (all plugins started), and anything registered after that (Studio publish, dev reload) is checked immediately. Unknown types warn, never reject; executing one fails with `NO_EXECUTOR`|
141
141
|`label`|`string`| ✅ | Display label |
142
142
|`config`|`object`| optional | Type-specific configuration — the registered executor's `configSchema` owns its shape. Keys that schema does not declare are rejected at `registerFlow()`, and the built-in executors `parse()` the value against their Zod contract before running (#4277) |
143
143
|`connectorConfig`|`object`| optional |`{ connectorId, actionId, input }` for a `connector_action` node |
0 commit comments