Skip to content

fix(workflow-executor): no record on a global action's approval [PRD-688]#1723

Merged
Scra3 merged 1 commit into
feature/prd-688-approval-on-full-ai-trigger-actionfrom
fix/prd-688-global-action-no-record
Jun 29, 2026
Merged

fix(workflow-executor): no record on a global action's approval [PRD-688]#1723
Scra3 merged 1 commit into
feature/prd-688-approval-on-full-ai-trigger-actionfrom
fix/prd-688-global-action-no-record

Conversation

@Scra3

@Scra3 Scra3 commented Jun 29, 2026

Copy link
Copy Markdown
Member

Problem

A workflow Trigger Action step that triggers a global action (one that runs on no record, e.g. "Create new card") was attaching the step's source record to the action — so the approval request it files showed a Resource (#3, #4…) that makes no sense for a global action. (The standalone MCP path is already fine: the AI passes no record for a global action.)

Fix

The executor now reads the action scope and omits the record for global actions:

  • types/validated/collection.ts: ActionSchema.type ('single'|'bulk'|'global', optional — resilient to orchestrator drift).
  • trigger-record-action-step-executor.ts: don't pass id when action.type === 'global'. Single/bulk actions keep their record.

The type is forwarded by the orchestrator in ForestAdmin/forestadmin-server#8344 (companion PR). If an older orchestrator doesn't send it, type is undefined → current behavior (no regression).

Notes

Refs PRD-688

🤖 Generated with Claude Code

Note

Fix approval record attachment for global actions in workflow executor

  • Global actions run on no record, but the executor was incorrectly attaching a record id when calling agent.executeAction.
  • Adds an optional isGlobal flag to ActionTarget and an optional type field ('single' | 'bulk' | 'global') to ActionSchemaSchema in collection.ts.
  • In trigger-record-action-step-executor.ts, when action.type === 'global', the id field is omitted from the executeAction call; single and bulk actions are unchanged.

🖇️ Linked Issues

Fixes PRD-688.

📊 Macroscope summarized f05e549. 2 files reviewed, 0 issues evaluated, 0 issues filtered, 0 comments posted

🗂️ Filtered Issues

No issues evaluated.

@linear-code

linear-code Bot commented Jun 29, 2026

Copy link
Copy Markdown

PRD-688

@qltysh

qltysh Bot commented Jun 29, 2026

Copy link
Copy Markdown

1 new issue

Tool Category Rule Count
qlty Structure Function with many returns (count = 6): handleFirstCall 1

@Scra3 Scra3 force-pushed the fix/prd-688-global-action-no-record branch from c5b0c15 to e85cdd6 Compare June 29, 2026 20:07

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Medium

isGlobal is only set on the transient ActionTarget in handleFirstCall, but pauseForConfirmation never persists it — only displayName, name, and selectedRecordRef are saved. On re-entry in Branch A, saveFrontendResult rebuilds the target without isGlobal, so the flag is lost. Because paused flows execute natively on the frontend, a global action in Manual or AutomatedWithConfirmation mode keeps carrying the source selectedRecordRef, causing the frontend to submit the source record and create approval requests wrongly linked to it. Consider persisting isGlobal in pauseForConfirmation's pendingData and restoring it when rebuilding the target in the confirmation handler.

🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file @packages/workflow-executor/src/executors/trigger-record-action-step-executor.ts around line 136:

`isGlobal` is only set on the transient `ActionTarget` in `handleFirstCall`, but `pauseForConfirmation` never persists it — only `displayName`, `name`, and `selectedRecordRef` are saved. On re-entry in Branch A, `saveFrontendResult` rebuilds the target without `isGlobal`, so the flag is lost. Because paused flows execute natively on the frontend, a global action in `Manual` or `AutomatedWithConfirmation` mode keeps carrying the source `selectedRecordRef`, causing the frontend to submit the source record and create approval requests wrongly linked to it. Consider persisting `isGlobal` in `pauseForConfirmation`'s `pendingData` and restoring it when rebuilding the target in the confirmation handler.

@Scra3 Scra3 force-pushed the feature/prd-688-approval-on-full-ai-trigger-action branch from 563eb37 to afb1453 Compare June 29, 2026 20:16
…proval

A global action runs on no record, so the executor must not pass the Trigger
Action step's source record when triggering it — otherwise the approval request
it files is wrongly linked to that record (shows a Resource that makes no sense).
Read the action `type` (forwarded by the orchestrator) and omit the record id
for global actions; single/bulk actions keep their record.

Refs PRD-688

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@Scra3 Scra3 force-pushed the fix/prd-688-global-action-no-record branch from e85cdd6 to f05e549 Compare June 29, 2026 20:17
isGlobal: action.type === 'global',
};

const form = await this.context.agent.getActionForm({

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Medium executors/trigger-record-action-step-executor.ts:155

handleFirstCall sets isGlobal on target and executeOnExecutor omits the record id for global actions, but the getActionForm call at line 156 always passes id: selectedRecordRef.recordId. AgentPort.getActionForm forwards that as recordIds: [id], so global actions with forms or load/change hooks still run in the context of the source record — showing record-scoped form data, triggering record-dependent hooks, or failing when the global action expects no record. The fix should also omit the id here when target.isGlobal is true.

🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file @packages/workflow-executor/src/executors/trigger-record-action-step-executor.ts around line 155:

`handleFirstCall` sets `isGlobal` on `target` and `executeOnExecutor` omits the record id for global actions, but the `getActionForm` call at line 156 always passes `id: selectedRecordRef.recordId`. `AgentPort.getActionForm` forwards that as `recordIds: [id]`, so global actions with forms or load/change hooks still run in the context of the source record — showing record-scoped form data, triggering record-dependent hooks, or failing when the global action expects no record. The fix should also omit the id here when `target.isGlobal` is true.

@Scra3 Scra3 merged commit f05e549 into feature/prd-688-approval-on-full-ai-trigger-action Jun 29, 2026
13 of 15 checks passed
@Scra3 Scra3 deleted the fix/prd-688-global-action-no-record branch June 29, 2026 20:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant