@cratis/pi 7.128.0 → 7.129.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/package/corpus/product-sync.json +4 -4
  2. package/package/corpus/skills/cratis-application-slice-conformance/SKILL.md +1 -1
  3. package/package/corpus/skills/cratis-arc-react-page/references/from-screenplay.md +5 -5
  4. package/package/corpus/skills/cratis-screenplay-automations-and-translations/SKILL.md +6 -1
  5. package/package/corpus/skills/cratis-screenplay-automations-and-translations/references/automation-patterns.md +1 -1
  6. package/package/corpus/skills/cratis-screenplay-automations-and-translations/references/cases-to-specify.md +5 -5
  7. package/package/corpus/skills/cratis-screenplay-automations-and-translations/references/statemachines-and-workflows.md +164 -0
  8. package/package/corpus/skills/cratis-screenplay-automations-and-translations/references/todo-list-example.md +12 -15
  9. package/package/corpus/skills/cratis-screenplay-automations-and-translations/references/translate-example.md +10 -4
  10. package/package/corpus/skills/cratis-screenplay-captures-and-reactions/references/complete-examples.md +2 -2
  11. package/package/corpus/skills/cratis-screenplay-captures-and-reactions/references/invocation-identity.md +8 -2
  12. package/package/corpus/skills/cratis-screenplay-command-surface/SKILL.md +5 -4
  13. package/package/corpus/skills/cratis-screenplay-command-surface/references/described-handlers.md +12 -8
  14. package/package/corpus/skills/cratis-screenplay-command-surface/references/validate-rules.md +5 -5
  15. package/package/corpus/skills/cratis-screenplay-command-surface/verification.json +1 -1
  16. package/package/corpus/skills/cratis-screenplay-event-modeling/references/nine-steps.md +6 -3
  17. package/package/corpus/skills/cratis-screenplay-legacy-extraction/references/generated-recovery.md +4 -4
  18. package/package/corpus/skills/cratis-screenplay-model-authoring/references/language-reference.md +2 -2
  19. package/package/corpus/skills/cratis-screenplay-read-surface/references/named-keys.md +3 -1
  20. package/package/corpus/skills/cratis-screenplay-read-surface/references/screen-patterns.md +2 -2
  21. package/package/corpus/skills/cratis-screenplay-render-and-gap-fill/SKILL.md +4 -4
  22. package/package/corpus/skills/cratis-screenplay-render-and-gap-fill/references/renderability-gate.md +6 -5
  23. package/package/corpus/skills/cratis-screenplay-scenario-coverage/SKILL.md +2 -2
  24. package/package/corpus/skills/cratis-screenplay-scenario-coverage/references/invoicing-dues-design.md +0 -3
  25. package/package/corpus/skills/cratis-screenplay-scenario-coverage/references/invoicing-dues-example.md +8 -3
  26. package/package/corpus/skills/cratis-screenplay-scenario-coverage/references/scenario-examples.md +17 -9
  27. package/package/corpus/skills/cratis-screenplay-scenario-coverage/references/spec-forms-by-mode.md +4 -3
  28. package/package/corpus/skills/cratis-screenplay-scenario-coverage/references/version-skew.md +25 -14
  29. package/package/corpus/skills/cratis-screenplay-scenario-coverage/references/view-and-story-specs.md +7 -6
  30. package/package/corpus/skills/cratis-screenplay-scenario-coverage/verification.json +1 -1
  31. package/package/corpus/skills/cratis-screenplay-slice-design/references/read-model-design.md +1 -1
  32. package/package/corpus/skills/cratis-screenplay-slice-design/references/slicing.md +1 -1
  33. package/package/corpus/skills/cratis-screenplay-slice-design/references/worked-example.md +3 -3
  34. package/package/corpus/skills/cratis-screenplay-specifications/SKILL.md +4 -2
  35. package/package/corpus/skills/cratis-screenplay-specifications/references/actions-beyond-commands.md +4 -2
  36. package/package/corpus/skills/cratis-screenplay-specifications/references/child-ordering.md +12 -3
  37. package/package/corpus/skills/cratis-screenplay-specifications/references/reactions-and-cascades.md +70 -21
  38. package/package/corpus/skills/cratis-screenplay-specifications/references/vocabulary.md +3 -2
  39. package/package/corpus/skills/cratis-screenplay-specifications/verification.json +2 -2
  40. package/package/corpus/skills/cratis-screenplay-toolchain/SKILL.md +3 -3
  41. package/package/corpus/skills/cratis-screenplay-toolchain/references/automation-translate-example.md +5 -8
  42. package/package/corpus/skills/cratis-screenplay-toolchain/references/cheat-sheet-example.md +12 -11
  43. package/package/corpus/skills/cratis-screenplay-toolchain/references/cheat-sheet.md +1 -1
  44. package/package/corpus/skills/cratis-screenplay-toolchain/references/diagnostic-arguments.md +1 -1
  45. package/package/corpus/skills/cratis-screenplay-toolchain/references/diagnostics.md +2 -2
  46. package/package/corpus/skills/cratis-screenplay-toolchain/references/executable-subset.md +10 -7
  47. package/package/corpus/skills/cratis-screenplay-toolchain/references/language-admission.md +4 -1
  48. package/package/corpus/skills/cratis-screenplay-toolchain/references/preferred-syntax.md +4 -1
  49. package/package/corpus/skills/cratis-screenplay-toolchain/references/renderable-subset.md +4 -4
  50. package/package/corpus/skills/cratis-screenplay-toolchain/references/screenplay-contract-exceptions.json +0 -70
  51. package/package/corpus/skills/cratis-screenplay-toolchain/references/screenplay-contract.json +4743 -623
  52. package/package/corpus/skills/cratis-screenplay-toolchain/references/screenplay-contract.version +1 -1
  53. package/package/corpus/skills/cratis-screenplay-toolchain/references/traps.md +1 -1
  54. package/package/corpus/skills/cratis-screenplay-ui-composition/SKILL.md +6 -0
  55. package/package/corpus/skills/cratis-screenplay-ui-composition/references/action-subjects.md +73 -0
  56. package/package/corpus/skills/cratis-screenplay-ui-composition/references/file-references.md +4 -3
  57. package/package/corpus/skills/cratis-screenplay-ui-composition/references/response-continuations.md +1 -1
  58. package/package/corpus/skills/cratis-screenplay-ui-composition/references/worked-flow.md +1 -1
  59. package/package/corpus/skills/cratis-stage-rendering-and-sandbox/SKILL.md +6 -5
  60. package/package/corpus/skills/cratis-stage-rendering-and-sandbox/references/admission.md +8 -5
  61. package/package.json +1 -1
@@ -42,10 +42,10 @@ mode; query-performer gaps are a separate contract, not completed behavior. Prot
42
42
  support is not generated-app protection.
43
43
  Preserve contracts; reference success is not target realization.
44
44
 
45
- File/inline command handlers permanently require constrained attachments: gap-fill
46
- in code, not by waiting for ESM admission. Requires Screenplay 4.210.0
47
- (`screenplay --version`) for PLAY0800 and required typed `arguments.subject`;
48
- older binders use PLAY0268. Read [renderability gate](references/renderability-gate.md)
45
+ A file/inline command handler binds beside unconditional `produces` with a resolved
46
+ body (v23 result contract, Screenplay 4.250.0); without them it refuses PLAY0800 with a
47
+ required typed `arguments.subject`. 4.210.0 to 4.249.x refuse every attached handler
48
+ with PLAY0800; older binders use PLAY0268. Read [renderability gate](references/renderability-gate.md)
49
49
  when classifying a handler or other binding refusal; never parse message text.
50
50
 
51
51
  Inline bodies (`csharp`, `typescript`, `react`, `html`, `sql`, `java`) are opaque and reach the target
@@ -10,10 +10,11 @@ probe reports and choosing what to do. Do not copy the code table here.
10
10
  1. The CLI compiles and binds the **whole** model with its **bundled** Screenplay (the ESM level it renders is bounded by the bundle; older bundles bound less). Binding is never scoped:
11
11
  any binding error blocks even a `--scope` render. Binding errors are `PLAY0268` (outside the admitted vertical), `PLAY0269`
12
12
  (deferred), `PLAY0270` (report-only information), `PLAY0271` (legacy semantics) and `PLAY0273`
13
- (a specification shape). File/inline command handlers instead report PLAY0800
14
- (`CommandHandlerRequiresAttachment`), a permanent constrained-attachment requirement.
15
- Requires Screenplay 4.210.0 (`screenplay --version`); older bundled binders use
16
- PLAY0268 for these handlers. Hosts read the required typed `arguments.subject`
13
+ (a specification shape). A file/inline command handler without unconditional `produces`
14
+ or a resolved body instead reports PLAY0800 (`CommandHandlerRequiresAttachment`); beside
15
+ unconditional `produces` with a resolved body it binds as the v23 result contract.
16
+ Requires Screenplay 4.250.0 (`screenplay --version`); 4.210.0 to 4.249.x refuse every
17
+ attached handler with PLAY0800 and older bundled binders use PLAY0268 for these handlers. Hosts read the required typed `arguments.subject`
17
18
  to identify the command, never the message.
18
19
  2. Execution planning builds the plan and can emit `PLAN-*` diagnostics before Stage runs.
19
20
  3. Stage plans the target and admits or rejects each member: `STAGE-ESM-0xx`; profile and path
@@ -36,7 +37,7 @@ ESM). Only the probe answers renderability. `PLAY0270` entries are information,
36
37
  | --- | --- | --- | --- |
37
38
  | **Model fix (in mode)** | the model is in, or the user chose, renderable mode and breaks its own subset in a way that has a renderable equivalent with the same meaning | a `produces` whose `for` is not the command identifier; two projections for one read model (`-007`); a policy Stage cannot express portably (`-015`; role-only and opaque pure policies render) | edit request to the modeler session with address, change and rationale |
38
39
  | **Capability gap** | the intended meaning needs a construct Stage does not render yet | DateTime equality filters and required parameters after optional filters (`-010`); context/single-result filters, opaque `scoped to` and a list-query `by` block remain PLAY0268; an unsupported query performer (observable, a non-C# body, or a missing, changed or non-compiling body) becomes an explicit implementation gap, while a verified C# body renders ([performer bodies](../../cratis-screenplay-read-surface/SKILL.md#performer-bodies-are-rendered)); a read model with several key parts or a projection keyed by parts (v27) refuses `STAGE-ESM-048` (always for a DateTime or decimal key part; the decimal refusal lifts with Stage#847 once Chronicle#5427 lands) and a single-instance query by parts `STAGE-ESM-047` (Chronicle#4265); Translate, clocks, captures, non-event triggers and opaque reaction bodies (`-024`); claim-reading/opaque `runs as` gates (`-034`), legacy `from` (`-035`), mixed effects in one handler (`-037`, retries can duplicate events; keep it whole), unsupported reaction mappings (`-039`); unsupported generated types/result combinations (`-028`/`-038`); `then no readmodel` (`-027`); evolved events (`STAGE-ESM-026`); unsupported expression/enum production conditions (`-006`; supported conditional productions render); legacy reads (`PLAY0271`), protected reads the renderer cannot preserve, or any protected read in an older CLI bundle (STAGE-ESM-044 despite v25 admission; semantic Host/executor support is separate); code validation (`-005`); protected identities/enums (`-040`) or unadmitted explicit subject lineage (`PLAY0268`); described handlers (v23, STAGE-IMPL-002 even Stub mode), atomic mode (STAGE-ESM-043; v22 admission Requires Stage 4.139.0, older Stage reports -016) | keep the model; fallback record entry; options a to c in `SKILL.md`; link the Stage issue |
39
- | **Implementation attachment** | a permanent limitation, not future ESM admission | file/inline command handlers (PLAY0800; typed `subject` names the command) | keep the model contract and gap-fill the slice in code with a constrained implementation attachment; do not wait for a new ESM version |
40
+ | **Implementation attachment** | the handler shape, not future ESM admission | file/inline command handlers without unconditional `produces` or a resolved body (PLAY0800; typed `subject` names the command) | declare unconditional `produces` beside a resolved body, split variable outcomes into separate commands, or keep the model contract and gap-fill the slice in code |
40
41
  | **Tool skew** | the bundled compiler disagrees with documented semantics | the false `PLAY0285` on reaction cascades from an older bundle; codes the standalone compiler does not raise | record in the session state and the fallback record; never "fix" a correct model |
41
42
  | **Environment** | not the model | restore failures, missing SDK, a destination that is not writable | fix the environment or report blocked |
42
43
 
@@ -175,8 +175,8 @@ Use a separate `when added` append when initial observations should produce a fa
175
175
  Read captures-and-reactions `references/record-capture-specifications.md` for the
176
176
  prerequisite and runnable cases. Include first, changed and unchanged rows in the matrix.
177
177
 
178
- ## Version skew: reaction cascades and false PLAY0285
179
- Under ESM v6 a command spec's `then` lists the events reactions cascade from it; an older `cratis` bundle reports a **false PLAY0285** for it. Never delete the reaction. Read [references/version-skew.md](references/version-skew.md) when a spec with cascade events reports PLAY0285 or the bundled compiler is older than the standalone tool.
178
+ ## Reaction chains: one slice per specification
179
+ A specification runs only its own slice. Prove a chain across slices link by link: the command's spec states its own events, the Automation's `when append` spec states what it appends, and `then invokes <Command>` (ESM v34) states a command it invokes in another slice. Another slice's event in a spec is PLAY0285. Never delete the reaction. Read [references/version-skew.md](references/version-skew.md) when a spec reports PLAY0285 or the bundled compiler is older than the standalone tool.
180
180
 
181
181
  ## Gate
182
182
  A scope is spec-complete only when: the matrix has no `open`, `question` or `gap` cell (or the
@@ -203,9 +203,6 @@ module Invoicing
203
203
  then PaymentReversed
204
204
  for "9c1f0a52-6a4e-4b1c-9f55-0d2c7b8e1a01"
205
205
  amount = 130
206
- then RefundRequested
207
- for "9c1f0a52-6a4e-4b1c-9f55-0d2c7b8e1a01"
208
- amount = 130
209
206
 
210
207
  specification RejectingAReversalWithoutAReceivedPayment
211
208
  given caller
@@ -227,9 +227,6 @@ module Invoicing
227
227
  for "9c1f0a52-6a4e-4b1c-9f55-0d2c7b8e1a01"
228
228
  outcome = "declined"
229
229
  reason = "Card declined"
230
- then PaymentDeclined
231
- for "9c1f0a52-6a4e-4b1c-9f55-0d2c7b8e1a01"
232
- reason = "Card declined"
233
230
 
234
231
  slice Automation RecordPaymentOutcome
235
232
  reaction ReceivedTranslator
@@ -247,6 +244,14 @@ module Invoicing
247
244
  event PaymentReceived
248
245
  event PaymentDeclined
249
246
  reason String
247
+ specification RecordingADeclinedPayment
248
+ when append PaymentGatewayResultReceived
249
+ for "9c1f0a52-6a4e-4b1c-9f55-0d2c7b8e1a01"
250
+ outcome = "declined"
251
+ reason = "Card declined"
252
+ then PaymentDeclined
253
+ for "9c1f0a52-6a4e-4b1c-9f55-0d2c7b8e1a01"
254
+ reason = "Card declined"
250
255
 
251
256
  slice StateView OpenInvoices
252
257
  description "Todo list: membership means 'still to collect'; there is no status flag."
@@ -104,9 +104,9 @@ design-mode rejection spec and `recorded` in the matrix. See `RejectingSettlemen
104
104
  in `invoicing-dues-design.md`; it is never prose and never a spec that pretends to enforce it.
105
105
 
106
106
  ## 3. External failure: the capture, then the retry
107
- Two separate obligations. First, the **capture specification**: concrete external input in, our
108
- facts out. The provider's refusal is a fact (never a `then error`), kept in the provider's
109
- vocabulary; a separate Automation records the local outcome. The capture uses
107
+ Two separate obligations. First, the **capture specification**: concrete external input in, the
108
+ provider's fact out. The provider's refusal is a fact (never a `then error`), kept in the provider's
109
+ vocabulary; a separate Automation records the local outcome and states it in its own specification. The capture uses
110
110
  `when added` for first sight and a separate `when outcome` for updates. An update
111
111
  spec needs `given capture` with the same key's earlier record; the first record's
112
112
  fields are not modifications (root, child or nested). See captures-and-reactions
@@ -121,6 +121,15 @@ specification TranslatingADeclinedCardResult
121
121
  for "9c1f0a52-6a4e-4b1c-9f55-0d2c7b8e1a01"
122
122
  outcome = "declined"
123
123
  reason = "Card declined"
124
+ ```
125
+ The Automation that records the local outcome proves its own link in its own slice
126
+ (a specification runs only its slice, Screenplay decision 0115):
127
+ ```screenplay excerpt parent=references/invoicing-dues-example.md#1
128
+ specification RecordingADeclinedPayment
129
+ when append PaymentGatewayResultReceived
130
+ for "9c1f0a52-6a4e-4b1c-9f55-0d2c7b8e1a01"
131
+ outcome = "declined"
132
+ reason = "Card declined"
124
133
  then PaymentDeclined
125
134
  for "9c1f0a52-6a4e-4b1c-9f55-0d2c7b8e1a01"
126
135
  reason = "Card declined"
@@ -153,9 +162,11 @@ model; it tests the projection only, never the translation.
153
162
 
154
163
  ## 4. Compensation
155
164
  A reversal needs a paid history, the reversal action and the exact consequence. The command spec
156
- lists the declared consequence (`RefundRequested`); the reaction is also specified on its own.
157
- `RefundRequested` is a recorded request, not proof that money moved, and there is no
158
- `then <Command>` form. What the target must do to deliver the refund is a requirement, not a spec.
165
+ states the command's own fact (`PaymentReversed`); the `RequestRefunds` Automation states
166
+ `RefundRequested` in its own specification, because a specification runs only its own slice
167
+ (Screenplay decision 0115). `RefundRequested` is a recorded request, not proof that money moved.
168
+ An automation that invokes another slice's command states it with `then invokes <Command>`
169
+ (ESM v34). What the target must do to deliver the refund is a requirement, not a spec.
159
170
  From `invoicing-dues-design.md` (design mode; the specs do not run):
160
171
  ```screenplay excerpt parent=references/invoicing-dues-design.md#1 expect PLAY0516 test=unbound
161
172
  specification ReversingAReceivedPayment
@@ -174,9 +185,6 @@ specification ReversingAReceivedPayment
174
185
  then PaymentReversed
175
186
  for "9c1f0a52-6a4e-4b1c-9f55-0d2c7b8e1a01"
176
187
  amount = 130
177
- then RefundRequested
178
- for "9c1f0a52-6a4e-4b1c-9f55-0d2c7b8e1a01"
179
- amount = 130
180
188
 
181
189
  specification RequestingARefundAfterAReversal
182
190
  when append PaymentReversed
@@ -29,7 +29,8 @@ Typed example/override forms: `cratis-screenplay-specifications`
29
29
  | `when query` -> `then result` / `then no result` | yes | yes | same as `then query`: only the query-only cases below |
30
30
  | `given clock` / `when clock`, `when trigger`, record-source `given`/`when capture` | yes | yes (standalone and any cratis whose compiler admits v6; an older bundle does not, see toolchain `references/executable-subset.md`) | no |
31
31
  | Event-source capture fixtures | `given <FromEvent>` / `when append <FromEvent>`, not capture records (PLAY0701) | admitted root capture behavior executes; see `public-event-coverage.md` for prerequisites and limits | separate target admission |
32
- | Command spec listing reaction cascade events | yes (v6 semantics) | false PLAY0285 on an older cratis bundle only; see SKILL.md "Version skew" | no: STAGE-ESM-011; generated CommandScenario does not settle reactions |
32
+ | Command spec listing its own slice's reaction cascade events | yes (v6 semantics) | yes; another slice's event is PLAY0285 (decision 0115); see SKILL.md "Reaction chains" | no: STAGE-ESM-011; generated CommandScenario does not settle reactions |
33
+ | `then invokes <Command>` in an Automation spec | yes | yes, ESM v34 | Stage spec runner compares it; the Cratis renderer refuses models after v33 (STAGE-ESM-016) |
33
34
  | `generated <name> = <value>` under `when`, `then returns` (ESM v7) | yes | yes on a compiler that admits v7 (PLAY0268 on an older bundle) | yes on Stage for supported UUID/String strategies and v15 freshness and scalar/named responses; unsupported types/combinations remain -028/-038 |
34
35
  | v15 generation strategy fixtures and used-source rejection | yes | strict encoding/size/case/version/variant; Contract for invalid pins, Concurrency for reused source | supported strategies/freshness render; invalid pins refuse -011, unpinned unordered/projected assertions -038; source: command-surface `references/generated-values-and-responses.md` |
35
36
  | `then events in any order` | yes | yes | yes |
@@ -44,13 +45,13 @@ Typed example/override forms: `cratis-screenplay-specifications`
44
45
  | Date rules using `today`, `$context`, mixed `Date`/`DateTime`, concept or reaction-`where` positions; nested paths | spec them in design | rule does not bind: `recorded` | `recorded` |
45
46
  | Bodied rules, code policies | spec them | spec reported **unsupported**, never passed | no |
46
47
  | Pending described command handlers (v23) | specify intent | binds; denial/validation execute, body-reaching specs Unsupported ImplementationBody; all-Unsupported is not green | STAGE-IMPL-002 even Stub mode |
47
- | Attached command handlers | spec them in design | blocked: PLAY0800, no spec runs (V3 blocked); permanent constrained-attachment requirement, gap-fill in code | no |
48
+ | Attached command handlers | spec them in design | beside unconditional `produces` with a resolved body: binds v23, a spec reaching the body is Unsupported (`ImplementationBody`); otherwise PLAY0800, no spec runs | Stage renders a C# body; generated specifications execute verified synchronous C# handlers |
48
49
  | `file` constraints | spec them in design | blocked: PLAY0268 at binding, no spec runs (V3 blocked) | no |
49
50
  | Query `performer`s | spec them in design | opaque read: PLAY0270 information, left out of the executable model; a spec that reads it is left out, every other spec still runs ([version gate](../../cratis-screenplay-toolchain/references/executable-subset.md#code-attachments-what-binds-what-never-does); older compilers report PLAY0268) | no |
50
51
  | Atomic reaction mode (v22) | declare for new models | failed batch adds no facts or view changes; earlier batches/commands remain; `then error` alone is insufficient | v22 STAGE-ESM-016; mode in admitted v23–v27 STAGE-ESM-043 |
51
52
  | Protected command reads (v25) | declare opt-in for eligible reads | absence Validation; matching intervening facts Conflict; race vectors are not a new spec construct | Cratis C# rendering in a new enough bundle (STAGE-ESM-044 before, or for unpreservable shapes); semantic Host/executor execute admitted reads, non-Error protected requirements STAGE-ESM-045; v25 pair admitted |
52
53
 
53
- Requires Screenplay 4.210.0 (`screenplay --version`) for attached handlers to report PLAY0800; older binders use PLAY0268. Other PLAY0268 families are unchanged.
54
+ Requires Screenplay 4.250.0 (`screenplay --version`) for attached handlers beside `produces` to bind; 4.210.0 to 4.249.x report PLAY0800 for every attached handler and older binders use PLAY0268. Other PLAY0268 families are unchanged.
54
55
 
55
56
  Requires Screenplay 4.105.0 or later (`screenplay --version`) for list-query specifications, and 4.143.0 or later for collection equality filters (ESM v14).
56
57
 
@@ -1,14 +1,25 @@
1
- # Version skew: reaction cascades and false PLAY0285
2
-
3
- How to specify reaction cascades across compiler versions.
4
-
5
- Under ESM v6 a command spec's `then` lists the events reactions cascade from it. A compiler
6
- bundled in an older `cratis` reports a **false PLAY0285** for such
7
- a spec; the standalone `screenplay` and a `cratis` whose compiler admits v6 accept it.
8
- Neither checks that a cascade event is *missing*.
9
- - A compiler that admits v6 (standalone, or a current `cratis`): write the v6-correct spec
10
- (own productions plus cascade); validate with `screenplay <folder> --warnaserror --no-color`
11
- or `cratis screenplay validate <folder> --warnings-as-errors`.
12
- - Only an older `cratis` bundle and no standalone tool: keep the command spec to its own productions, specify the reaction in its
13
- Automation slice (`when append <Trigger>` -> `then <Produced>`), record the pending cascade
14
- expectation in `STATE.md` as known-incomplete. Never delete the reaction.
1
+ # Specifying reaction chains across slices and compiler versions
2
+
3
+ How to specify a chain of reactions, and what `PLAY0285` means on each compiler.
4
+
5
+ Requires Screenplay 4.246.0 or later (`screenplay --version`) for single-slice runs and `then invokes`.
6
+
7
+ A specification runs only the slice that declares it (Screenplay decision 0115, for every model
8
+ and version). A chain across slices is proved link by link:
9
+ - The command's slice: `when <Command>` states the command's own events.
10
+ - The Automation slice: `when append <Trigger>` states what its reaction appends, and
11
+ `then invokes <Command>` (ESM v34) states a command it invokes in another slice.
12
+ - The invoked command's slice: `when <Command>` states that command's events.
13
+
14
+ A command spec that states another slice's event is refused with `PLAY0285` (unreachable)
15
+ and fails at run time with "Expected N fact(s), got M". That is a modeling error: move
16
+ the expectation to the slice that produces it. Never delete the reaction.
17
+
18
+ Older compilers:
19
+ - A compiler older than ESM v6 does not trace reactions and can report `PLAY0285` on a
20
+ reaction in the specification's own slice. That is tool skew: validate with the
21
+ standalone `screenplay <folder> --warnaserror --no-color` or a current
22
+ `cratis screenplay validate <folder> --warnings-as-errors`, and record which tool gave which verdict.
23
+ - A compiler that predates `then invokes` refuses it. With only such a tool, keep the
24
+ automation's own appended facts in its spec and record the pending hand-over expectation
25
+ in `STATE.md` as known-incomplete.
@@ -142,12 +142,13 @@ not prove an entire list is empty: assert the unkeyed list query itself (an unke
142
142
  - **Projection lag**: a spec asserts the settled state. If a screen decision depends on the view
143
143
  being current (a booking screen that must not offer a taken berth), that is not protection:
144
144
  the command needs its own constraint, or the rule is `recorded` as target-enforced.
145
- - **Rebuild**: a view rebuilt from all facts must give the same rows. Mappings from
146
- `$eventContext.occurred` or other occurrence data cannot be executed:
147
- the reference runner refuses every event-context path except the event source id
148
- (`UnsupportedEventContext`), so specifications that reach that projection report unsupported. `given clock` does not change that; it supplies `$context.occurred`
149
- to command productions only. Record such projection cases as capability gaps (keep the
150
- mapping and the intended spec in design mode).
145
+ - **Rebuild**: a view rebuilt from all facts must give the same rows. The reference runner
146
+ refuses every event-context path except the event source id and, from Screenplay 4.254.0,
147
+ `$eventContext.occurred` in `from`, `every` and `children` blocks
148
+ (`UnsupportedEventContext` otherwise). `occurred` executes only for a fact appended during
149
+ the run under `given clock` (`when append` or a command's production); a `given` fact
150
+ carries no occurrence time and the specification reports unsupported. Record the
151
+ remaining cases as capability gaps (keep the mapping and the intended spec in design mode).
151
152
  - **Corrections and backdated facts**: a correction is a new fact; specify the view after it.
152
153
  If a fact carries a business date earlier than its occurrence, specify which date the view
153
154
  shows.
@@ -10,7 +10,7 @@
10
10
  { "kind": "skill-contains", "value": "Once, idempotent, exactly once are different claims" },
11
11
  { "kind": "skill-contains", "value": "Unauthorized is never `then error`" },
12
12
  { "kind": "skill-contains", "value": "find-specification-obligations" },
13
- { "kind": "skill-contains", "value": "false PLAY0285" },
13
+ { "kind": "skill-contains", "value": "A specification runs only its own slice." },
14
14
  { "kind": "skill-contains", "value": "One behaviour per spec" },
15
15
  { "kind": "skill-contains", "value": "No command has only two specs" },
16
16
  { "kind": "skill-contains", "value": "not scenario-complete" },
@@ -280,7 +280,7 @@ module Berths
280
280
  screen OpenBooking
281
281
  title "Open booking"
282
282
  data OpenBooking via query OpenBookingById
283
- action CancelBooking
283
+ action CancelBooking for item
284
284
  specification CancelledBookingLeavesTheList
285
285
  given caller
286
286
  authenticated
@@ -83,7 +83,7 @@ module Moorings
83
83
  query WaitingRequests => WaitingRequest[]
84
84
  screen WaitingListPage
85
85
  data WaitingRequest via query WaitingRequests
86
- action AssignBerth
86
+ action AssignBerth for item
87
87
  slice StateChange AssignBerth
88
88
  command AssignBerth
89
89
  berthRequestId BerthRequestId identifier
@@ -121,8 +121,8 @@ module Lockers
121
121
  column number label "Locker"
122
122
  column volume label "Volume (l)"
123
123
  column assigned label "Taken"
124
- action InstallLocker
125
- action AssignLocker
124
+ action InstallLocker for screen
125
+ action AssignLocker for item
126
126
  specification RefusingAnAnonymousLockerLookup
127
127
  given caller
128
128
  then query LockerById
@@ -273,7 +273,7 @@ module Lockers
273
273
  screen MyRequest
274
274
  title "My locker request"
275
275
  data RequestStatus via query RequestById
276
- action RequestLocker
276
+ action RequestLocker for screen
277
277
  specification FollowingARequestToAssignment
278
278
  given caller
279
279
  authenticated
@@ -186,8 +186,10 @@ Read [references/actions-beyond-commands.md](references/actions-beyond-commands.
186
186
 
187
187
  ## Reactions and cascades (ESM v6)
188
188
 
189
- From ESM v6 every action sets reactions off and `then` events compare every new fact, the action's and the reactions'. A specification whose action is a command goes in the slice that declares the command. A false `PLAY0285` on a cascade under a compiler that stops before ESM v6 is tool skew, not a modeling error: never delete the `then` line to silence it.
190
- Read [references/reactions-and-cascades.md](references/reactions-and-cascades.md) when a specification's expected events include what a reaction appends, when a cascade, clock tick or invoked command is involved, or when `cratis` reports `PLAY0285` on a model that `screenplay` accepts (it holds the "Version skew: cascades and the false `PLAY0285`" section).
189
+ From ESM v6 every action sets reactions off. A specification runs only the slice that declares it: only that slice's reactions, captures and publications run, and `then` events compare the new facts of that slice. A specification whose action is a command goes in the slice that declares the command and states the command's own events. Another slice's event is `PLAY0285` (unreachable): state it in the slice that produces it. An automation states a command it invokes in another slice with `then invokes <Command>` (ESM v34).
190
+ Read [references/reactions-and-cascades.md](references/reactions-and-cascades.md) when a specification's expected events include what a reaction appends, when a cascade, clock tick or invoked command is involved, or when a compiler reports `PLAY0285` (it holds the "Version skew and `PLAY0285`" section).
191
+
192
+ A `statemachine` or `workflow` (ESM v36) carries its own specifications with `then is`, `then sends`, `then starts`, `outcome`, `then completes`, `then fails at` and `then waits at`. Read automations-and-translations [state machines and workflows](../cratis-screenplay-automations-and-translations/references/statemachines-and-workflows.md) when specifying either.
191
193
 
192
194
  ## Published-event specifications (released ESM v9)
193
195
 
@@ -21,8 +21,10 @@ Event captures use the typed event fixtures and overlay rules in
21
21
 
22
22
  Use `given clock`, never `given time`, to state the scenario occurrence time and
23
23
  assert a value mapped from `$context.occurred`. In a command's `produces`, that
24
- mapping executes when the scenario has `given clock`. It is not the same as
25
- `$eventContext.occurred` in a projection, which the execution plan refuses (SKILL.md, "Reference execution — what actually runs").
24
+ mapping executes when the scenario has `given clock`. `$eventContext.occurred` in a
25
+ projection is the fact's occurrence time: the reference runner executes it in `from`,
26
+ `every` and `children` blocks for facts appended during the run under `given clock`, and a
27
+ `given` fact carries none (Unsupported).
26
28
 
27
29
  **Which tools bind these actions.** A compiler that admits ESM v6 binds the clock, trigger
28
30
  and capture actions, and the `Automation` and `Translate` slices, reactions and captures they
@@ -69,7 +69,10 @@ module Orders
69
69
  orderId = "00000000-0000-0000-0000-000000000001"
70
70
  then readmodel OrderView
71
71
  orderId = "00000000-0000-0000-0000-000000000001"
72
- lines = [{"lineNumber":1,"amount":10}]
72
+ lines
73
+ item
74
+ lineNumber = 1
75
+ amount = 10
73
76
  specification ChildBeforeGivenParent
74
77
  given LineAdded
75
78
  orderId = "00000000-0000-0000-0000-000000000001"
@@ -79,7 +82,10 @@ module Orders
79
82
  orderId = "00000000-0000-0000-0000-000000000001"
80
83
  then readmodel OrderView
81
84
  orderId = "00000000-0000-0000-0000-000000000001"
82
- lines = [{"lineNumber":1,"amount":10}]
85
+ lines
86
+ item
87
+ lineNumber = 1
88
+ amount = 10
83
89
  specification ParentBeforeChild
84
90
  given OrderAdded
85
91
  orderId = "00000000-0000-0000-0000-000000000001"
@@ -89,7 +95,10 @@ module Orders
89
95
  amount = 10
90
96
  then readmodel OrderView
91
97
  orderId = "00000000-0000-0000-0000-000000000001"
92
- lines = [{"lineNumber":1,"amount":10}]
98
+ lines
99
+ item
100
+ lineNumber = 1
101
+ amount = 10
93
102
  specification ParentNeverArrives
94
103
  given LineAdded
95
104
  orderId = "00000000-0000-0000-0000-000000000001"
@@ -1,9 +1,22 @@
1
+ ## Contents
2
+
3
+ - Reactions and cascades (ESM v6)
4
+ - An automation states the commands it invokes (ESM v34)
5
+ - The public event is stated in the publishing slice
6
+ - Version skew and `PLAY0285`
7
+
1
8
  ## Reactions and cascades (ESM v6)
2
9
 
3
10
  From ESM v6 every action sets reactions off: after a command, an append, a clock
4
11
  tick, a trigger or a capture record, each new fact runs the reactions to its event,
5
- and what those append or invoke runs more, until nothing is left. `then` events
6
- compare every new fact, the action's and the reactions'.
12
+ and what those append or invoke runs more, until nothing is left.
13
+
14
+ A specification runs only the slice that declares it (Screenplay decision 0115, every
15
+ model and version from Screenplay 4.246.0). Only that slice's reactions, captures and
16
+ outbound publications run; another slice's never do, so their facts cannot appear in
17
+ `then`, read-model or query assertions. `then` events compare the new facts of the
18
+ specification's own slice. A chain across slices is proved link by link: each slice's
19
+ specification states its own link.
7
20
 
8
21
  ```screenplay expect PLAY0469
9
22
  concept InvoiceId : Uuid
@@ -17,16 +30,12 @@ module Collections
17
30
  invoiceId = invoiceId
18
31
  event InvoiceSent
19
32
  invoiceId InvoiceId
20
- specification SendingAnInvoiceSchedulesAReminder
21
- given clock "2026-10-02T09:00:00Z"
33
+ specification SendingAnInvoice
22
34
  when SendInvoice
23
35
  invoiceId = "9c858901-8a57-4791-81fe-4c455b099bc9"
24
36
  then InvoiceSent
25
37
  for "9c858901-8a57-4791-81fe-4c455b099bc9"
26
38
  invoiceId = "9c858901-8a57-4791-81fe-4c455b099bc9"
27
- then ReminderScheduled
28
- for "9c858901-8a57-4791-81fe-4c455b099bc9"
29
- scheduledAt = "2026-10-02T09:00:00Z"
30
39
  slice Automation Reminders
31
40
  reaction ReminderScheduler
32
41
  description "Schedules a reminder when an invoice is sent"
@@ -37,11 +46,25 @@ module Collections
37
46
  scheduledAt = $context.occurred
38
47
  event ReminderScheduled
39
48
  scheduledAt DateTime
49
+ specification SendingAnInvoiceSchedulesAReminder
50
+ given clock "2026-10-02T09:00:00Z"
51
+ when append InvoiceSent
52
+ for "9c858901-8a57-4791-81fe-4c455b099bc9"
53
+ invoiceId = "9c858901-8a57-4791-81fe-4c455b099bc9"
54
+ then ReminderScheduled
55
+ for "9c858901-8a57-4791-81fe-4c455b099bc9"
56
+ scheduledAt = "2026-10-02T09:00:00Z"
40
57
  ```
41
58
 
42
59
  - A specification whose action is a command goes in the slice that declares that
43
60
  command, here `SendInvoice`, not in the `Automation` slice that reacts: a command
44
61
  from another slice is `PLAY0273` "command is unresolved in its slice" at binding.
62
+ It states the command's own events. The reminder is the `Reminders` slice's link,
63
+ stated there with `when append InvoiceSent`.
64
+ - Stating another slice's event in a command specification is `PLAY0285` (the
65
+ outcome is unreachable from the specification's slice) and fails at run time with
66
+ "Expected N fact(s), got M". Move the expectation to the slice that produces it;
67
+ never delete the reaction.
45
68
  - A reaction invocation without a declared actor has no caller and a gated
46
69
  command denies. Reaction `runs as system role "<Role>"` supplies the
47
70
  authenticated system actor (ESM v10); `given caller` does not. Each command is
@@ -59,21 +82,47 @@ module Collections
59
82
  or mixed effects (`-037`). Single-hop reaction append specs render; deeper appends and
60
83
  command specs cascading into reactions remain `-011`. Keep refused scope as gap-fill against this contract: `cratis-screenplay-render-and-gap-fill`.
61
84
 
62
- ### A command specification states the public event its slice publishes
85
+ ### An automation states the commands it invokes (ESM v34)
86
+
87
+ When a slice's reaction invokes a command another slice owns, that command is decided
88
+ against the world, so the reaction's `on refused` branches behave as before, but its
89
+ facts belong to the other slice and are not kept. The automation states the hand-over
90
+ with `then invokes`, the command and the values it passes (the complete model is the
91
+ `Reminders` slice in captures-and-reactions `references/complete-examples.md`):
92
+
93
+ ```screenplay excerpt
94
+ specification ClosingAPaidInvoice
95
+ when trigger PaymentFileArrived
96
+ invoiceId = "9c858901-8a57-4791-81fe-4c455b099bc9"
97
+ amount = 120
98
+ then invokes CloseInvoice
99
+ invoiceId = "9c858901-8a57-4791-81fe-4c455b099bc9"
100
+ reason = "paid"
101
+ ```
102
+
103
+ - When a specification states at least one `then invokes`, the invocations the slice's
104
+ reactions made must match them exactly in count and order (any order under
105
+ `then events in any order`), comparing only the stated values. A refused invocation
106
+ counts too. A specification that states none does not compare invocations.
107
+ - `then invokes` selects ESM v34. The Stage spec runner compares it; the Cratis
108
+ renderer refuses models after v33 with `STAGE-ESM-016`.
109
+ - The invoked command's own events are proved by that command's slice, in its own
110
+ `when <Command>` specification.
111
+
112
+ ### The public event is stated in the publishing slice
63
113
 
64
- When an outbound Translate slice publishes an event from the private events a command produces, the command's specification
65
- lists the public event after the private ones (`then ProductPriceChanged` after `then ProductPriceSet`). `PLAY0285` follows the
66
- outbound projection (decision 0098); the accepted path is proven where the command is. An exact fact count
67
- fails without it.
114
+ An outbound Translate slice that publishes a public event from private events states it
115
+ in its own `when append <PrivateEvent>` specification. The command that produces the
116
+ private event states only its own events (decision 0115 replaces the earlier rule that
117
+ the command's specification listed the public event).
68
118
 
69
- ### Version skew: cascades and the false `PLAY0285`
119
+ ### Version skew and `PLAY0285`
70
120
 
71
- `PLAY0285` (a specification's expected event contradicts every producer of its
72
- `when` command) runs in the syntax pass, with no binding. An older compiler does not trace
73
- reachability through reactions and `invokes`, so the example above passes `screenplay` (and is
74
- executable-ready over its MCP server) but fails an older `cratis screenplay validate` with
75
- `PLAY0285` "Specification outcome 'ReminderScheduled' cannot be produced by 'SendInvoice'",
76
- exit 5. If an older bundle still reports it, it is a tool skew, not a
77
- modeling error: do not delete the `then` line or move the event to make `cratis`
78
- green. Validate with the standalone tool or a current `cratis`, record which tool gave which
121
+ `PLAY0285` (a specification's expected event contradicts every possible producer of its
122
+ `when` command) follows the reactions, invocations and publications declared in the
123
+ specification's own slice. From Screenplay 4.246.0 it refuses another slice's event as
124
+ unreachable, and that is a modeling error: move the expectation to the slice that
125
+ produces the event. A compiler older than ESM v6 does not trace reactions at all and
126
+ can report `PLAY0285` on a reaction in the specification's own slice; that is tool skew.
127
+ Validate with the standalone tool or a current `cratis`, record which tool gave which
79
128
  verdict, and see `cratis-screenplay-toolchain`.
@@ -33,7 +33,8 @@ This reference holds the given/when/then construct table and the enumeration and
33
33
  | `then error` | a validation or constraint rejection, reason unnamed |
34
34
  | `then denied` | an authorization denial (`Unauthorized`) |
35
35
  | `for <value>` | the event source of a `given`/`then` event, or of the `when` command or appended event |
36
- | `<property> = <value>` | a literal, `null`, or a one-line JSON-shaped object or list: `lines = [{"sku":"A-1","quantity":2}]` |
36
+ | `<property> = <value>` | a scalar literal or `null` |
37
+ | `<property>` with an indented block | an object (`member = value` lines) or a list (one `item` line per element); `<property> none` is an empty list. Screenplay has no JSON: `lines = [...]` is PLAY0833 |
37
38
 
38
39
  ## Composite-keyed read models
39
40
 
@@ -42,7 +43,7 @@ read model with two or more `key` marks, and every specification over it, with P
42
43
 
43
44
  - `given readmodel` and `then readmodel` state every key part (missing part PLAY0351,
44
45
  repeated part PLAY0519).
45
- - `then no readmodel <Type> for {"part":"value",...}` names every part (missing PLAY0661,
46
+ - `then no readmodel <Type> for`, with one indented `part = value` line per part, names every part (missing PLAY0661,
46
47
  unknown PLAY0662, repeated member PLAY0294).
47
48
  - `when query` or `then query … arguments` supplies every `by` part of a single-instance
48
49
  query, or the equality filters of a list query (missing, unknown or repeated PLAY0468).
@@ -77,11 +77,11 @@
77
77
  },
78
78
  {
79
79
  "kind": "skill-contains",
80
- "value": "Version skew: cascades and the false `PLAY0285`"
80
+ "value": "Version skew and `PLAY0285`"
81
81
  },
82
82
  {
83
83
  "kind": "skill-contains",
84
- "value": "Specification outcome 'ReminderScheduled' cannot be produced", "file": "references/reactions-and-cascades.md"
84
+ "value": "never delete the reaction", "file": "references/reactions-and-cascades.md"
85
85
  },
86
86
  { "kind": "skill-contains", "value": "Examples typed from another document", "file": "references/examples-and-routes.md" },
87
87
  { "kind": "skill-contains", "value": "`PLAY0520`", "file": "references/examples-and-routes.md" }
@@ -114,9 +114,9 @@ with ordered imports means future files need explicit imports.
114
114
  filters, opaque `scoped to` and a `by` block on a list query remain PLAY0268; a `performer` query is an opaque read left out of the executable model (PLAY0270; [version gate](references/executable-subset.md#code-attachments-what-binds-what-never-does)). Read
115
115
  read-surface [equality filters](../cratis-screenplay-read-surface/references/equality-filters.md).
116
116
  Pending handlers beside unconditional productions bind as described commands (v23),
117
- but reached bodies are Unsupported; attached file/inline handlers refuse PLAY0800
118
- and require constrained implementation attachments (code gap-fill, not future ESM
119
- admission).
117
+ but reached bodies are Unsupported; attached file/inline handlers bind the same way
118
+ beside unconditional `produces` with a resolved body and otherwise
119
+ refuse PLAY0800.
120
120
  Requires Screenplay 4.210.0 (`screenplay --version`); older binders use PLAY0268 for this refusal. Read `arguments.subject`, not the message, for the command.
121
121
  Eligible protected reads opt into v25; legacy reads and `concurrency` retain PLAY0271.
122
122
  Concept compliance binds as v13 (precise refusals: command-surface `references/compliance.md`);
@@ -1,6 +1,6 @@
1
1
  # Automation and Translate example (ESM v6)
2
2
 
3
- Executable Automation and Translate slices. Binds as `executableReady` on the standalone tool and on the compiler bundled in the CLI; see [executable-subset.md](executable-subset.md) for what renders. Shows a reaction `produces` cascade, `invokes`, `where`, clock `at`, an application trigger, a capture with translate and a transition `when`, and v6 specifications.
3
+ Executable Automation and Translate slices. Binds as `executableReady` (ESM v34, for `then invokes`) on the standalone tool and on a CLI whose bundled compiler is Screenplay 4.246.0 or later; see [executable-subset.md](executable-subset.md) for what renders. Shows a reaction `produces` cascade, `invokes`, `where`, clock `at`, an application trigger, a capture with translate and a transition `when`, and v6 specifications. Each specification states only its own slice (Screenplay decision 0115); the automation states the command it invokes with `then invokes` (ESM v34).
4
4
 
5
5
  The `Renew` command is ungated so that the reaction can invoke it: this is a syntax demonstration, not a safe production design. Reactions invoke with no caller, so a real model needs a trusted path (see [cratis-screenplay-automations-and-translations](../../cratis-screenplay-automations-and-translations/SKILL.md)).
6
6
 
@@ -23,12 +23,9 @@ module Membership
23
23
  given clock "2026-10-05T09:00:00Z"
24
24
  when Subscribe
25
25
  memberId = "5b6c1f7e-2d3a-4e8b-9c0d-1a2b3c4d5e6f"
26
- then MemberSubscribed // v6: cascades are part of `then`
26
+ then MemberSubscribed // its own slice only: Onboarding states WelcomeSent
27
27
  for "5b6c1f7e-2d3a-4e8b-9c0d-1a2b3c4d5e6f"
28
28
  subscribedAt = "2026-10-05T09:00:00Z"
29
- then WelcomeSent
30
- for "5b6c1f7e-2d3a-4e8b-9c0d-1a2b3c4d5e6f"
31
- sentAt = "2026-10-05T09:00:00Z"
32
29
 
33
30
  slice StateChange Renew
34
31
  command Renew // ungated for the demo only: reactions invoke with no caller
@@ -78,9 +75,9 @@ module Membership
78
75
  when trigger RenewalFileArrived
79
76
  memberId = "5b6c1f7e-2d3a-4e8b-9c0d-1a2b3c4d5e6f"
80
77
  months = 12
81
- then MembershipRenewed
82
- for "5b6c1f7e-2d3a-4e8b-9c0d-1a2b3c4d5e6f"
83
- months = 12
78
+ then invokes Renew // ESM v34: the hand-over; Renew's slice proves MembershipRenewed
79
+ memberId = "5b6c1f7e-2d3a-4e8b-9c0d-1a2b3c4d5e6f"
80
+ months = 12
84
81
  specification IssuingTheWeeklyReport
85
82
  given clock "2026-10-05T07:00:00Z"
86
83
  when clock "2026-10-05T07:30:00Z"