Declarative language additions: reactor outputs, multiple projections, observable queries, attribute reasons and conditional rules - #45
Conversation
Five gaps where a document could not say something the application it describes actually does. A reactor trigger required a 'file' or an inline block, so the one construct whose meaning lived entirely in the escape hatch could not be written before the code existed. The body is now optional, and 'produces <Event>' and 'executes <Command>' state what the reaction does - resolved against the document's events and commands the same way command produces always has been. A slice could declare at most one projection, so a slice that keeps its decision model beside its view model had to drop one or invent a slice that does not exist. SliceSyntax.Projection becomes Projections. A query could not say whether it is live, though a reader binding to it has to build something different in each case. An 'observable' directive says so; unmarked stays one-shot. A second 'by' parameter silently overwrote the first and now reports. Concept attributes were bare markers, so the reason a value is personal data - purpose, lawful basis - had nowhere to go. Any attribute takes an optional quoted argument, and a bare attribute stays valid. A validation rule could not say that it only applies sometimes, and a bare path operand parsed without any stated meaning. Rules take a 'when' condition reusing the produces-when grammar, 'today' becomes a distinct node rather than a path indistinguishable from a property of that name, and a path operand is specified to resolve against the validated artifact's sibling properties.
|
Reviewer notes — this PR is deliberately left open for a call on the design, not merged. Labelled
Both break anything constructing or reading those nodes — #38 syntax differs from the issue's sketch. The issue proposed an indented #32 is partial — this is (a) and (b) only. The state-based Notes on the choices that were not forced:
Verification — |
The keywords were added to the tokenizer but not to the completion lists or the hover documentation, so 'observable' inside a query body and 'produces' / 'executes' inside a reactor trigger highlighted correctly while the editor still refused to suggest or explain them.
'@today' worked as a rule operand but not as the rule's subject, so a reader who learned the escape in one position hit an error using it in the other. No validate-block directive collides with a property name, so the escape is not strictly needed there - but it costs nothing to accept and removes the inconsistency. Also covers attribute reasons holding characters that matter to the grammar - a close paren, an at sign, a literal backslash - and two attributes that both carry an argument, none of which the round-trip specs exercised.
|
Merge ordering note. See the note on #49 — that PR and this one each merge cleanly into |
Summary
Five language decisions that let a
.playdocument describe what the application it models actually does, instead of losing it to afilereference or an escape hatch. Each addition is additive — an existing document keeps its meaning.Added
produces <Event>andexecutes <Command>underon <Event>, resolved against the document's events and commands. (reactor: declare produced side effects (events and executed commands) #34)observablewhen it is a live subscription rather than a one-shot read. An unmarked query stays one-shot. (query: distinguish observable (live) queries from one-shot queries #37)@pii("Partner payout account — lawful basis: contract performance.")carries the reason instead of just the flag. A bare@piistays valid. (@pii: carry the reason/lawful-basis documentation, not just the marker #38)when <condition>clause, reusing theproduces whencondition grammar:newEndDate > endDate when isExtension == true message "…". (Validation language: conditional rules, cross-property operands, and state-based business rules #32)todayis a distinct expression rather than a property path, so a consumer can tell the keyword from a property of that name. The property is written@today. (Validation language: conditional rules, cross-property operands, and state-based business rules #32)Changed
filedirective or an inline code block.reactor X/on SomeEventis a valid statement of intent, which is what an author knows before any code exists. (Declarative-first: the language must describe everything before code exists - 'file' must never be required #40)SliceSyntax.ProjectionbecomesSliceSyntax.Projections— a breaking change for anything reading or constructing the node. (One-projection-per-slice limit drops real read models in generated documents #30)ConceptSyntax.AttributescarriesConceptAttributeSyntaxvalues rather than plain strings, so an attribute can hold its argument — a breaking change for anything reading the node. (@pii: carry the reason/lawful-basis documentation, not just the marker #38)endDate >= startDatehas a defined meaning. (Validation language: conditional rules, cross-property operands, and state-based business rules #32)Fixed
byparameter on a query silently overwrote the first; it now reports a diagnostic. (query: distinguish observable (live) queries from one-shot queries #37)