You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
service-automation: honour outcome: 'refused' on the flow end node — a terminal refused run status (distinct from failed) with the interpolated message persisted on the run (lane 2 of the #14945 ruling 2′) #15788
Filed by the domain:spec execution seat (session_01M59rPZZFzqhfMUPFqqZTkf, 2026-09-05T08:00Z) as execution lane (2) of the maintainer ruling on #14945 (5548735593, director seat, decision batch #42, verbatim 「13753 我让别人处理了,其他同意」), quoted verbatim:
Ruled: 2′. Shape, to be declared contract-first:
packages/spec flow schema: the end node accepts outcome?: 'completed' | 'refused' (default completed) and, when refused, a message string that goes through the same interpolation a screen description gets ({record.name} etc.); a refused end is a terminal state, never resumed.
run record / sys_automation_run: the run's terminal status carries the outcome (refused distinct from failed; a refusal is a successful evaluation that says no) and the rendered message.
runner (objectui FlowRunner): on refused, render the message with Close only, no Submit, no "completed" toast; the invoking action's successMessage stays suppressed exactly as today (silent — ⛔ do not touch).
Execution, contract-first (three lanes, sequenced): (1) domain:spec — schema + run-status vocabulary, forms row for the designer, docs (Clause-②: yes, @objectstack/specminor); (2) domain:services — service-automation honours refused at the end executor and persists the outcome/message (minor); (3) objectui ui seat — FlowRunner rendering (cross-repo card filed by the spec seat with Related: objectstack#14945). Re-verify the console half on today's tree first (the census ran on the 17.2.0 pin). Pins: a refused end with an interpolated message on a two-record fixture yields per-record text; no Submit rendered; no completion toast; successMessage still silent.
Lane (1) is dispatched on #14945 (spec seat). This card is lane (2) and lands in packages/services/service-automation — the services lane's; domain:* routing and priority are the triage seat's (the ruling keeps #14945 at priority:p2). Named reader: the domain:services execution seat, at dispatch time; the Blocked-by: line above is the unlock scan's — it returns this card to the queue when #14945 closes (the spec contract merged). Lane (3) is the objectui card filed alongside (linked from #14945's claim comment).
Deliverables (for the services seat's dispatch, against the spec contract as landed)
The end executor honours config.outcome === 'refused': interpolates config.message through the SAME interpolation the screen description uses (one implementation, not a second template engine), terminates the run with the refused outcome (distinct from failed — a refusal is a successful evaluation that says no), persists the outcome and the rendered message on the run record (sys_automation_run / the run status vocabulary the spec half declares), and never resumes it.
The paused-run silent behaviour is untouched (the invoking action's successMessage stays suppressed exactly as today) — pin it.
Pins: a refused end with an interpolated message on a two-record fixture yields per-record text; the run's terminal status reads refused with the rendered message; completed (default) is unchanged; a refused run is not resumable.
@objectstack/service-automationminor changeset; Clause-②: yes only if the executor's public envelope changes (say which).
Blocked-by: #14945
Related: #15429 · hotcrm#1288 · hotcrm#1555
Filed by the
domain:specexecution seat (session_01M59rPZZFzqhfMUPFqqZTkf, 2026-09-05T08:00Z) as execution lane (2) of the maintainer ruling on #14945 (5548735593, director seat, decision batch #42, verbatim 「13753 我让别人处理了,其他同意」), quoted verbatim:Lane (1) is dispatched on #14945 (spec seat). This card is lane (2) and lands in
packages/services/service-automation— the services lane's;domain:*routing and priority are the triage seat's (the ruling keeps #14945 atpriority:p2). Named reader: thedomain:servicesexecution seat, at dispatch time; theBlocked-by:line above is the unlock scan's — it returns this card to the queue when #14945 closes (the spec contract merged). Lane (3) is the objectui card filed alongside (linked from #14945's claim comment).Deliverables (for the services seat's dispatch, against the spec contract as landed)
endexecutor honoursconfig.outcome === 'refused': interpolatesconfig.messagethrough the SAME interpolation the screendescriptionuses (one implementation, not a second template engine), terminates the run with therefusedoutcome (distinct fromfailed— a refusal is a successful evaluation that says no), persists the outcome and the rendered message on the run record (sys_automation_run/ the run status vocabulary the spec half declares), and never resumes it.silentbehaviour is untouched (the invoking action'ssuccessMessagestays suppressed exactly as today) — pin it.refusedend with an interpolated message on a two-record fixture yields per-record text; the run's terminal status readsrefusedwith the rendered message;completed(default) is unchanged; arefusedrun is not resumable.@objectstack/service-automationminor changeset;Clause-②: yesonly if the executor's public envelope changes (say which).Fixesthis card; A flow cannot REFUSE with per-record text: the only channel that interpolates is a screendescription, and a message-only screen still renders Submit and toasts "completed" #14945 is referenced verb-less.Generated by Claude Code