feat(workflow-executor): deterministic source record for Update Data steps (PRD-777)#1761
feat(workflow-executor): deterministic source record for Update Data steps (PRD-777)#1761EnkiP wants to merge 2 commits into
Conversation
3 new issues
|
| const selectedRecordRef = preRecordedArgs?.selectedRecordStepId | ||
| ? await this.resolveSourceRecordRef(preRecordedArgs.selectedRecordStepId) |
There was a problem hiding this comment.
🟡 Medium executors/update-record-step-executor.ts:190
When preRecordedArgs.selectedRecordStepId is an empty string, handleFirstCall treats it as unset and silently falls back to AI/legacy record selection instead of calling resolveSourceRecordRef to resolve the configured ID. An Update Data step can update a different record than its deterministic configuration specifies. The truthiness check should be an explicit !== undefined check, like the load-related executor uses.
| const selectedRecordRef = preRecordedArgs?.selectedRecordStepId | |
| ? await this.resolveSourceRecordRef(preRecordedArgs.selectedRecordStepId) | |
| const selectedRecordRef = preRecordedArgs?.selectedRecordStepId !== undefined | |
| ? await this.resolveSourceRecordRef(preRecordedArgs.selectedRecordStepId) |
🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file @packages/workflow-executor/src/executors/update-record-step-executor.ts around lines 190-191:
When `preRecordedArgs.selectedRecordStepId` is an empty string, `handleFirstCall` treats it as unset and silently falls back to AI/legacy record selection instead of calling `resolveSourceRecordRef` to resolve the configured ID. An Update Data step can update a different record than its deterministic configuration specifies. The truthiness check should be an explicit `!== undefined` check, like the load-related executor uses.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
7fa69b5 to
2a2dbdd
Compare
|
Coverage Impact This PR will not change total coverage. Modified Files with Diff Coverage (2)
🛟 Help
|
…I-resolved value The build-time config lets the Editor pin the field while leaving the value to the runtime prompt. The 'fieldName and value must both be provided or both omitted' guard wrongly rejected that, throwing InvalidPreRecordedArgsError. Now a value-less fieldName pins the field and the AI resolves only the value. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
6a1f30f to
8dad337
Compare

Part of the deterministic Update Data step work.
fixes PRD-777
What
The
update-record(Update Data) step can now resolve its source record deterministically from a build-time-configured stable BPMN step id (selectedRecordStepId), mirroringread-record(Get Data) andtrigger-action— instead of always asking the AI to pick among the available records.Changes
UpdateRecordStepDefinitionSchema.preRecordedArgsgainsselectedRecordStepId(legacyselectedRecordStepIndexkept for back-compat;fieldName/valueunchanged).update-record-step-executor(handleFirstCall): whenselectedRecordStepIdis set, resolve viaresolveSourceRecordRef(revise-safe;WORKFLOW_START_STEP_ID→ base record). Falls back to legacy index / AI selection when unset.ServerWorkflowTaskUpdateData) + mapper forwardpreRecordedArgsforupdate-data.Tests
WORKFLOW_START_STEP_ID→ base record; unresolvable id → error.preRecordedArgs(selectedRecordStepId + fieldName + value).Companion PRs: forestadmin-server (orchestrator), forestadmin (editor UI).
🤖 Generated with Claude Code
Note
Add deterministic source record resolution and pre-recorded field/value support to Update Data steps
selectedRecordStepIdtoUpdateRecordStepDefinitionSchemaand theServerWorkflowTaskUpdateDatainterface as a stable alternative to the legacy index-basedselectedRecordStepIndexfor identifying the source record.UpdateRecordStepExecutor.handleFirstCallto support three configurations: bothfieldNameandvaluepre-recorded (use directly), onlyfieldNamepre-recorded (ask AI for value via newselectValueForFieldmethod), or neither (ask AI for both).buildZodSchemaForField/buildZodSchemaForPrimitiveforAiToolflag so boolean schemas bound into AI tools are plainz.boolean()(JSON Schema compatible) instead of usingz.preprocessstring coercion; coercion now happens after tool output."true"/"false") directly; coercion to native boolean occurs in the executor after the tool responds.Macroscope summarized 8dad337.