fix(workflow-executor): Full AI load-related — reference field + empty-list skip (PRD-751)#1751
Conversation
…cords (PRD-751) Full AI's auto-load called persistAndReturn with no pendingData, so the completed step only carried executionResult.record (a bare recordId). The front's record dropdown then fell back to the raw recordId instead of the reference field label (the issue was Full-AI-only; AI-assisted carries pendingData through its await-then-confirm flow). Persist the candidates' pendingData on the auto-load path too. Extracted followableRelationFields to share the availableFields build. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…ai-reference-field
|
Coverage Impact This PR will not change total coverage. Modified Files with Diff Coverage (1)
🛟 Help
|
…idate list is empty (PRD-751) Per the PRD-751 sync: in Full AI, an empty candidate list (no related record at all) now continues without a record (skip) instead of handing off to AI-assisted — a human couldn't pick one either. A non-empty list with no confident pick (ambiguous, or the AI judged none relevant) still degrades to the AI-assisted confirmation. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
| // confirmation — "No X to load" pre-checked when nothing fits, else its best guess pre-selected. | ||
| // Full AI with no candidate at all: a human couldn't pick one either, so continue without a | ||
| // record (skip) instead of handing off to AI-assisted (PRD-751 decision). | ||
| if (availableRecordIds.length === 0) { |
There was a problem hiding this comment.
🟡 Medium executors/load-related-record-step-executor.ts:439
In Full AI mode, when the AI-selected relation has zero linked records but another eligible relation does have records, resolveAndLoadAutomatic() now calls persistSkip(target) and marks the step successful with executionResult: { skipped: true }. The step silently completes without loading a record instead of degrading to the confirmation flow, where the user could switch relations via the existing relation-switch UI and recover the loadable path. The new availableRecordIds.length === 0 short-circuit in resolveAndLoadAutomatic() skips the degradation that the old code performed, and persistSkip writes a success outcome. Consider routing an empty candidate list to persistAwaitInput (as other non-confident paths already do) rather than persistSkip, so the user can still pick a different relation.
🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file @packages/workflow-executor/src/executors/load-related-record-step-executor.ts around line 439:
In Full AI mode, when the AI-selected relation has zero linked records but another eligible relation does have records, `resolveAndLoadAutomatic()` now calls `persistSkip(target)` and marks the step successful with `executionResult: { skipped: true }`. The step silently completes without loading a record instead of degrading to the confirmation flow, where the user could switch relations via the existing relation-switch UI and recover the loadable path. The new `availableRecordIds.length === 0` short-circuit in `resolveAndLoadAutomatic()` skips the degradation that the old code performed, and `persistSkip` writes a success outcome. Consider routing an empty candidate list to `persistAwaitInput` (as other non-confident paths already do) rather than `persistSkip`, so the user can still pick a different relation.
There was a problem hiding this comment.
This is intentional per the PRD-751 decision (documented on the ticket): in Full AI, an empty candidate list continues without a record (skip) rather than handing off to AI-assisted. There's no human in Full AI to switch relations — the confirmation flow is exactly the fallback the PO chose to drop for this case.
The sub-case you raise (the AI picks an empty relation while another has records) is about the relation choice (selectRelationToFollow), not the skip — routing back to a human confirmation would reintroduce the fallback the decision removed. If we ever want the AI to prefer relations that actually have records, that'd be a separate enhancement. Note it only applies to non-deterministic Full AI anyway: deterministic steps pin the relation, so there's a single eligible relation.
- drop the stale/duplicated JSDoc left on persistSkip when it was inserted above persistAndReturn (it described the wrong method); the names are self-documenting - log the Full AI auto-skip so an unexpectedly empty relation is auditable (consistent with the other anomaly logs in this executor) - tests: assert referenceFieldValue is carried on the auto-load pendingData (the point of the reference-field fix), and that persistSkip records executionParams + selectedRecordRef for downstream steps Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…ai-reference-field
christophebrun-forest
left a comment
There was a problem hiding this comment.
Manual tests OK
Tests OK
LGTM
## @forestadmin/workflow-executor [1.17.3](https://github.com/ForestAdmin/agent-nodejs/compare/@forestadmin/workflow-executor@1.17.2...@forestadmin/workflow-executor@1.17.3) (2026-07-17) ### Bug Fixes * **workflow-executor:** Full AI load-related — reference field + empty-list skip (PRD-751) ([#1751](#1751)) ([646a058](646a058))

Summary
Two PRD-751 fixes to the Full AI Load Related Record path in the executor (both in
load-related-record-step-executor.ts).1. Keep the reference field on loaded records
In Full AI, the run's record dropdown showed the raw
recordIdinstead of the record's reference field label (Full-AI-only — AI-assisted already carried the candidates through its await-then-confirm flow). The auto-load path calledpersistAndReturnwith nopendingData, so the completed step had noavailableRecordIdsfor the front to read. Now the candidates'pendingData(withreferenceFieldValue) is persisted on the auto-load path too.2. Auto-skip when the candidate list is empty
Per the sync with Brice (documented on PRD-751): in Full AI, an empty candidate list (no related record at all) now continues without a record (skip) instead of handing off to AI-assisted — a human couldn't pick one either. Unchanged: a non-empty list with no confident pick (ambiguous, or the AI judged none relevant) still degrades to the AI-assisted confirmation.
Testing
pendingData.availableRecordIdson auto-load; empty-list (BelongsTo / HasMany / BelongsToMany) now skips (executionResult: { skipped: true }, success); AI-assisted empty-list and "AI judged none relevant" cases still await input. 102 tests green.fixes PRD-751
🤖 Generated with Claude Code
Note
Fix empty-list skip and reference field handling in
LoadRelatedRecordStepExecutorfor full AI modeexecutionResult.skipped=true) via a newpersistSkipmethod and returns success instead of awaiting input.pendingData(candidate list, suggested field, available fields via the newfollowableRelationFieldshelper) so candidate labels are preserved.followableRelationFieldshelper to avoid duplicate inline computation acrosspersistAwaitInputandresolveAndLoadAutomatic.Macroscope summarized d8ca5a9.