fix(automation): array-form flow triggerType fails loudly, not silently never firing (#3481)#3484
Merged
Merged
Conversation
…ly never firing (#3481) An array `triggerType` on a flow start node (e.g. ['record-after-create', 'record-after-delete']) — the shape an author or AI authoring pass naturally reaches for to fire on multiple events — was accepted everywhere and armed nowhere. Multi-event unions are deliberately unsupported (#3457), but nothing said so: defineFlow passed the array, the engine's `typeof === 'string'` check folded it to no trigger and misclassified the flow as manual (so it never entered the binding audit), and the flow-trigger-readiness lint used the same narrowing and produced no finding. The flow bound to nothing and never fired, with zero output at any layer — the last authoring shape still slipping past the #3427/#3472 silent-never-fire guards. Defensive fix (arrays stay unsupported; they now fail loudly): - lint (validate-flow-trigger-readiness): an array triggerType with any record-* element yields a flow-trigger-unknown-event warning at os validate time, steering to record-after-write or one flow per event. - engine (resolveTriggerBinding): route such an array to the record_change trigger — as an unmappable single token is — instead of folding to a manual flow, so it reaches the trigger's bind-time rejection and the binding audit. - trigger (record-change): the bind-time rejection detects the array shape and emits a targeted warning (names the flow, points at record-after-write and #3457) rather than the generic unknown-token line. Each new test proves red against the pre-fix code first. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Contributor
📓 Docs Drift CheckThis PR changes 3 package(s): 7 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #3481.
Problem
An array
triggerTypeon a flow start node — the shape an author (or an AI authoring pass) naturally reaches for to fire on more than one event:was accepted everywhere and armed nowhere. Multi-event unions are deliberately unsupported (only the single tokens plus the
record-after-writecreate-OR-update union exist — see #3457), but nothing said so:configis an openz.record, sodefineFlowpasses the array.resolveTriggerBinding'stypeof config.triggerType === 'string'check folds the array toundefined→ the flow is misclassified as manual.getTriggerBindingAuditskips flows with no resolved trigger, so it never appears in the CLI startup summary.validate-flow-trigger-readinessused the sametypeofnarrowing →isRecordTriggeredfalse → zero findings.Net result: the flow binds to nothing and never fires, with zero output at any layer — the same silent-never-fire class as #3427 / #3472, and the last authoring shape still slipping past every guard.
Fix (defensive — arrays stay unsupported, they now fail loudly)
Contract-first (AGENTS.md Prime Directive #12): reject at authoring, don't add a consumer-side tolerance for the unsupported shape.
validate-flow-trigger-readiness): an arraytriggerTypecontaining anyrecord-*element now yields aflow-trigger-unknown-eventwarning atos validatetime, steering torecord-after-write(created-or-updated) or one flow per event.resolveTriggerBinding): such an array is routed to therecord_changetrigger — exactly as an unmappable single token (record-after-updated) already is — instead of folding to a manual flow, so it reaches the trigger's bind-time rejection.record-change): the bind-time rejection detects the array shape and emits a targeted warning (names the flow, points atrecord-after-writeand flow record trigger: consider multi-eventtriggerType(array / unions beyond create-or-update) #3457) rather than the generic unknown-token line.Scope is intentionally narrow: no new authoring form, no array semantics — that stays deferred under #3457. This only makes the unsupported shape loud.
Tests
Each new test proves red against the pre-fix code first, then green:
packages/lint/src/validate-flow-trigger-readiness.test.ts— array flagged (incl. arrays of individually-valid tokens); non-record array left alone.packages/services/service-automation/src/trigger-dispatch-observability.test.ts— array routed torecord_change(binding handed to the trigger, appears ingetActiveTriggerBindings); non-record array stays manual.packages/triggers/trigger-record-change/src/record-change-trigger.test.ts— targeted array warning, not bound; generic warning preserved for non-array bad tokens.Full suites green: lint 326, service-automation 356, trigger-record-change 49. DTS type-check clean for all three packages.
Refs #3457 (the deferred multi-event design + restart criteria), #3427 / #3446 (
record-after-write), #3472 (same-family silent defect).🤖 Generated with Claude Code