Skip to content

fix(intent): task-form button action wins over a stale model action (approve-as-reject) - #6349

Merged
delchev merged 1 commit into
masterfrom
fix/intent-task-form-action-wins
Jul 21, 2026
Merged

fix(intent): task-form button action wins over a stale model action (approve-as-reject)#6349
delchev merged 1 commit into
masterfrom
fix/intent-task-form-action-wins

Conversation

@delchev

@delchev delchev commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

In a multi-step submit -> approve flow, the second task's form completed down the reject branch no matter which button was clicked.

Cause (two spots): a prior task set an action process variable; form.js.template preloaded all process vars (incl. action='submit') into the model on open; and FormIntentGenerator's completion handler did Object.assign({ action: action }, $scope.model) — model last, so the stale action overwrote the clicked button. The ${action == 'approve'} gateway then saw submit → reject. Both buttons effectively sent submit; approve was impossible.

Fix:

  • FormIntentGenerator: rebuild the COMPLETE payload — copy the model minus action and control vars (__*, which are locators not entity data), then set action last (button wins).
  • form.js.template: don't preload the bare action process var into the model (the __* locators still load — the runtime uses them).

Test: the bug is in emitted client JS (the browser builds the payload), so the HTTP-only ITs — which construct the payload themselves — can't reach it. IntentEngineIT.assertForm now asserts the generated form code rebuilds the payload with the button action winning and no longer uses the buggy Object.assign. Runtime proof is a browser submit→approve flow (this bug was blocking the KF vacations approve path — verified on regeneration there).

Surfaced by a KeyFolders module review (vacations approve completing as reject).

🤖 Generated with Claude Code

…approve-as-reject)

In a multi-step flow (submit -> approve), the second task's form completed down
the wrong branch: a prior task set an 'action' process variable, form.js
preloaded it into the model on open, and the completion handler's
Object.assign({ action }, $scope.model) let that stale model 'action' overwrite
the clicked button -> the decision gateway (${action == 'approve'}) saw 'submit'
and took the reject branch. Both Approve and Reject effectively sent 'submit',
so a manager could never approve.

Two coordinated fixes:
- FormIntentGenerator: rebuild the COMPLETE payload explicitly - copy the model
  MINUS 'action' and control vars (__*, which are locators, not entity data),
  then set 'action' LAST so the button wins.
- form.js.template: never preload the bare 'action' process variable into the
  model (the __* locators still load - the runtime reads them).

The bug lives in emitted client JS (the browser builds the payload), so the
HTTP ITs - which build the payload themselves - cannot exercise it; IntentEngineIT
gains an emission assertion that the generated form code rebuilds the payload
with the button action winning and no longer uses the buggy Object.assign. The
runtime proof is a browser submit->approve flow (verified via the KF vacations
regen, which was blocked on exactly this).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@delchev
delchev merged commit 56697fc into master Jul 21, 2026
10 checks passed
@delchev
delchev deleted the fix/intent-task-form-action-wins branch July 21, 2026 17:41
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