Summary
A command's produces block can state which event is appended and how its properties map, but not where it is appended: there is no way to express the target event source, and no way to express a handler that appends to several event sources in one decision. Both are first-class Arc shapes, and generators must currently drop them.
Evidence (real application)
Generating from the Ada application (Cratis.Arc.Screenplay 20.65.0):
- 10 ×
SP0013 [Information] The handler yields the identifier of the event source alongside the event, which Screenplay has no counterpart for — handlers returning (EventSourceId, TEvent) tuples to append somewhere other than the command's own stream.
- Multi-source appends are fully inexpressible: Ada's
Activate command returns IEnumerable<EventForEventSourceId> fanning out to four event sources in one decision (ContractPolicy, RequestDetail, RequestContract, CandidateWorkSurface). The generated document shows a plain produces list with no hint that the events land on different streams.
- Derived event-source identity is also unstatable:
StartMonth implements ICanProvideEventSourceId with TimesheetId.For(EngagementId, Year, Month) — the fact that the stream identity derives from command input is part of the slice's behavior (it is what makes the unique event constraint work) and the document cannot say it.
Other corners of the language already acknowledge event-source targeting: seeds have for "<event source id>", and projections have key expressions — produces is the gap.
Suggested direction
An optional targeting clause on produces (syntax open):
produces TimesheetStarted for key(engagementId, year, month)
produces ContractPolicyActivated for ContractPolicy
or an indented for <expr> line inside the produces block, reusing the PDL key-expression parser. Multi-source handlers then become several produces entries with different targets — which is exactly what the code does.
Context
Found while validating a generated 5,348-line document from a production Arc application against its source.
Summary
A command's
producesblock can state which event is appended and how its properties map, but not where it is appended: there is no way to express the target event source, and no way to express a handler that appends to several event sources in one decision. Both are first-class Arc shapes, and generators must currently drop them.Evidence (real application)
Generating from the Ada application (
Cratis.Arc.Screenplay20.65.0):SP0013 [Information] The handler yields the identifier of the event source alongside the event, which Screenplay has no counterpart for— handlers returning(EventSourceId, TEvent)tuples to append somewhere other than the command's own stream.Activatecommand returnsIEnumerable<EventForEventSourceId>fanning out to four event sources in one decision (ContractPolicy,RequestDetail,RequestContract,CandidateWorkSurface). The generated document shows a plainproduceslist with no hint that the events land on different streams.StartMonthimplementsICanProvideEventSourceIdwithTimesheetId.For(EngagementId, Year, Month)— the fact that the stream identity derives from command input is part of the slice's behavior (it is what makes theunique eventconstraint work) and the document cannot say it.Other corners of the language already acknowledge event-source targeting: seeds have
for "<event source id>", and projections havekeyexpressions —producesis the gap.Suggested direction
An optional targeting clause on
produces(syntax open):or an indented
for <expr>line inside the produces block, reusing the PDL key-expression parser. Multi-source handlers then become severalproducesentries with different targets — which is exactly what the code does.Context
Found while validating a generated 5,348-line document from a production Arc application against its source.