Skip to content

fix(automation): array-form flow triggerType fails loudly, not silently never firing (#3481) - #3484

Merged
os-zhuang merged 1 commit into
mainfrom
fix/3481-array-triggertype-silent
Jul 25, 2026
Merged

fix(automation): array-form flow triggerType fails loudly, not silently never firing (#3481)#3484
os-zhuang merged 1 commit into
mainfrom
fix/3481-array-triggertype-silent

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

Closes#3481.

Problem

An array triggerType on a flow start node — the shape an author (or an AI authoring pass) naturally reaches for to fire on more than one event:

config: {objectName: 'app_task',triggerType: ['record-after-create','record-after-delete']}

was accepted everywhere and armed nowhere. Multi-event unions are deliberately unsupported (only the single tokens plus the record-after-write create-OR-update union exist — see #3457), but nothing said so:

  1. spec — start-node config is an open z.record, so defineFlow passes the array.
  2. engineresolveTriggerBinding's typeof config.triggerType === 'string' check folds the array to undefined → the flow is misclassified as manual.
  3. binding auditgetTriggerBindingAudit skips flows with no resolved trigger, so it never appears in the CLI startup summary.
  4. lintvalidate-flow-trigger-readiness used the same typeof narrowing → isRecordTriggered false → 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.

  • lint (validate-flow-trigger-readiness): an array triggerType containing any record-* element now yields a flow-trigger-unknown-event warning at os validate time, steering to record-after-write (created-or-updated) or one flow per event.
  • engine (resolveTriggerBinding): such an array is routed to the record_change trigger — 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.
  • 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 flow record trigger: consider multi-event triggerType (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 to record_change (binding handed to the trigger, appears in getActiveTriggerBindings); 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

…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>
@vercel

vercelBot commented Jul 25, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

ProjectDeploymentActionsUpdated (UTC)
specReadyReadyPreview, CommentJul 25, 2026 2:45am

Request Review

@github-actionsgithub-actionsBot added size/m documentation Improvements or additions to documentation tests tooling labels Jul 25, 2026
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 3 package(s): @objectstack/lint, packages/services, packages/triggers.

7 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:

  • content/docs/automation/webhooks.mdx(via packages/services)
  • content/docs/kernel/runtime-services/audit-service.mdx(via packages/services)
  • content/docs/kernel/runtime-services/index.mdx(via packages/services)
  • content/docs/kernel/runtime-services/settings-service.mdx(via packages/services)
  • content/docs/permissions/authorization.mdx(via @objectstack/lint)
  • content/docs/plugins/packages.mdx(via packages/services)
  • content/docs/protocol/kernel/i18n-standard.mdx(via packages/services)

Advisory only. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs origin/main → pass the list as args.docs.

@os-zhuang
os-zhuang merged commit 9dcc0ae into mainJul 25, 2026
16 checks passed
@os-zhuang
os-zhuang deleted the fix/3481-array-triggertype-silent branch July 25, 2026 02:54
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationsize/mteststooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

flow record trigger: array-form triggerType is silently dead at every layer (no lint, no audit, no runtime warn)

1 participant

@os-zhuang