@cratis/pi 7.127.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 (68) 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-onboarding-runtime/SKILL.md +10 -2
  5. package/package/corpus/skills/cratis-onboarding-runtime/references/default-offering.md +61 -0
  6. package/package/corpus/skills/cratis-onboarding-runtime/references/sign-up-review.md +52 -0
  7. package/package/corpus/skills/cratis-screenplay-authentication-and-onboarding/SKILL.md +1 -1
  8. package/package/corpus/skills/cratis-screenplay-authentication-and-onboarding/references/onboarding-directives.md +1 -1
  9. package/package/corpus/skills/cratis-screenplay-automations-and-translations/SKILL.md +6 -1
  10. package/package/corpus/skills/cratis-screenplay-automations-and-translations/references/automation-patterns.md +1 -1
  11. package/package/corpus/skills/cratis-screenplay-automations-and-translations/references/cases-to-specify.md +5 -5
  12. package/package/corpus/skills/cratis-screenplay-automations-and-translations/references/statemachines-and-workflows.md +164 -0
  13. package/package/corpus/skills/cratis-screenplay-automations-and-translations/references/todo-list-example.md +12 -15
  14. package/package/corpus/skills/cratis-screenplay-automations-and-translations/references/translate-example.md +10 -4
  15. package/package/corpus/skills/cratis-screenplay-captures-and-reactions/references/complete-examples.md +2 -2
  16. package/package/corpus/skills/cratis-screenplay-captures-and-reactions/references/invocation-identity.md +8 -2
  17. package/package/corpus/skills/cratis-screenplay-command-surface/SKILL.md +5 -4
  18. package/package/corpus/skills/cratis-screenplay-command-surface/references/described-handlers.md +12 -8
  19. package/package/corpus/skills/cratis-screenplay-command-surface/references/validate-rules.md +5 -5
  20. package/package/corpus/skills/cratis-screenplay-command-surface/verification.json +1 -1
  21. package/package/corpus/skills/cratis-screenplay-event-modeling/references/nine-steps.md +6 -3
  22. package/package/corpus/skills/cratis-screenplay-legacy-extraction/references/generated-recovery.md +4 -4
  23. package/package/corpus/skills/cratis-screenplay-model-authoring/references/language-reference.md +2 -2
  24. package/package/corpus/skills/cratis-screenplay-read-surface/references/named-keys.md +3 -1
  25. package/package/corpus/skills/cratis-screenplay-read-surface/references/screen-patterns.md +2 -2
  26. package/package/corpus/skills/cratis-screenplay-render-and-gap-fill/SKILL.md +4 -4
  27. package/package/corpus/skills/cratis-screenplay-render-and-gap-fill/references/renderability-gate.md +6 -5
  28. package/package/corpus/skills/cratis-screenplay-scenario-coverage/SKILL.md +2 -2
  29. package/package/corpus/skills/cratis-screenplay-scenario-coverage/references/invoicing-dues-design.md +0 -3
  30. package/package/corpus/skills/cratis-screenplay-scenario-coverage/references/invoicing-dues-example.md +8 -3
  31. package/package/corpus/skills/cratis-screenplay-scenario-coverage/references/scenario-examples.md +17 -9
  32. package/package/corpus/skills/cratis-screenplay-scenario-coverage/references/spec-forms-by-mode.md +4 -3
  33. package/package/corpus/skills/cratis-screenplay-scenario-coverage/references/version-skew.md +25 -14
  34. package/package/corpus/skills/cratis-screenplay-scenario-coverage/references/view-and-story-specs.md +7 -6
  35. package/package/corpus/skills/cratis-screenplay-scenario-coverage/verification.json +1 -1
  36. package/package/corpus/skills/cratis-screenplay-slice-design/references/read-model-design.md +1 -1
  37. package/package/corpus/skills/cratis-screenplay-slice-design/references/slicing.md +1 -1
  38. package/package/corpus/skills/cratis-screenplay-slice-design/references/worked-example.md +3 -3
  39. package/package/corpus/skills/cratis-screenplay-specifications/SKILL.md +4 -2
  40. package/package/corpus/skills/cratis-screenplay-specifications/references/actions-beyond-commands.md +4 -2
  41. package/package/corpus/skills/cratis-screenplay-specifications/references/child-ordering.md +12 -3
  42. package/package/corpus/skills/cratis-screenplay-specifications/references/reactions-and-cascades.md +70 -21
  43. package/package/corpus/skills/cratis-screenplay-specifications/references/vocabulary.md +3 -2
  44. package/package/corpus/skills/cratis-screenplay-specifications/verification.json +2 -2
  45. package/package/corpus/skills/cratis-screenplay-toolchain/SKILL.md +3 -3
  46. package/package/corpus/skills/cratis-screenplay-toolchain/references/automation-translate-example.md +5 -8
  47. package/package/corpus/skills/cratis-screenplay-toolchain/references/cheat-sheet-example.md +12 -11
  48. package/package/corpus/skills/cratis-screenplay-toolchain/references/cheat-sheet.md +1 -1
  49. package/package/corpus/skills/cratis-screenplay-toolchain/references/diagnostic-arguments.md +1 -1
  50. package/package/corpus/skills/cratis-screenplay-toolchain/references/diagnostics.md +2 -2
  51. package/package/corpus/skills/cratis-screenplay-toolchain/references/executable-subset.md +10 -7
  52. package/package/corpus/skills/cratis-screenplay-toolchain/references/language-admission.md +4 -1
  53. package/package/corpus/skills/cratis-screenplay-toolchain/references/preferred-syntax.md +4 -1
  54. package/package/corpus/skills/cratis-screenplay-toolchain/references/renderable-subset.md +4 -4
  55. package/package/corpus/skills/cratis-screenplay-toolchain/references/screenplay-contract-exceptions.json +0 -70
  56. package/package/corpus/skills/cratis-screenplay-toolchain/references/screenplay-contract.json +4743 -623
  57. package/package/corpus/skills/cratis-screenplay-toolchain/references/screenplay-contract.version +1 -1
  58. package/package/corpus/skills/cratis-screenplay-toolchain/references/traps.md +1 -1
  59. package/package/corpus/skills/cratis-screenplay-ui-composition/SKILL.md +6 -0
  60. package/package/corpus/skills/cratis-screenplay-ui-composition/references/action-subjects.md +73 -0
  61. package/package/corpus/skills/cratis-screenplay-ui-composition/references/file-references.md +4 -3
  62. package/package/corpus/skills/cratis-screenplay-ui-composition/references/response-continuations.md +1 -1
  63. package/package/corpus/skills/cratis-screenplay-ui-composition/references/worked-flow.md +1 -1
  64. package/package/corpus/skills/cratis-showrunner-herald/SKILL.md +5 -0
  65. package/package/corpus/skills/cratis-stage-rendering-and-sandbox/SKILL.md +6 -5
  66. package/package/corpus/skills/cratis-stage-rendering-and-sandbox/references/admission.md +8 -5
  67. package/package/corpus/skills/cratis-stage-rendering-and-sandbox/references/rendered-application.md +14 -5
  68. package/package.json +1 -1
@@ -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"
@@ -4,7 +4,7 @@ One complete document with every construct family. Design mode, not executable.
4
4
 
5
5
  Binding blockers in this legacy control without protected-read opt-in: unquoted
6
6
  import, legacy `reads` (PLAY0271), condition-only `starts with` (PLAY0268).
7
- Property/concept text rules bind v24; eligible protected reads bind v25. Caller-supplied collection equality filters bind as ESM v14; context and single-result filters remain blocked. Executable shapes are in the sibling examples. `RecordingAPayment` lists the `InvoiceClosed` cascade; an older bundled compiler rejected it with a false PLAY0285 ("outcome cannot be produced by 'RecordPayment'").
7
+ Property/concept text rules bind v24; eligible protected reads bind v25. Caller-supplied collection equality filters bind as ESM v14; context and single-result filters remain blocked. Executable shapes are in the sibling examples. `RecordingAPayment` states only `PaymentRecorded`: a specification runs only its own slice (Screenplay decision 0115), so `ReconcilingAPayment` states the hand-over with `then invokes CloseInvoice` and `ClosingAnInvoice` states `InvoiceClosed`.
8
8
 
9
9
  Concept compliance itself binds as ESM v13; reasons remain report-only PLAY0270. Stage renders v13 concept
10
10
  protection. Binder-only PLAY0268 refusals and subject-lineage limits: command-surface `references/compliance.md`.
@@ -91,7 +91,10 @@ module Billing
91
91
  invoiceId = "9c858901-8a57-4791-81fe-4c455b099bc9"
92
92
  number = "INV-000123"
93
93
  contact = "ada@example.com"
94
- lines = [{"sku": "A-1", "quantity": 2}]
94
+ lines
95
+ item
96
+ sku = "A-1"
97
+ quantity = 2
95
98
  then InvoiceRegistered
96
99
  for "9c858901-8a57-4791-81fe-4c455b099bc9"
97
100
  number = "INV-000123"
@@ -105,7 +108,7 @@ module Billing
105
108
  invoiceId = "9c858901-8a57-4791-81fe-4c455b099bc9"
106
109
  number = "INV-000000"
107
110
  contact = "ada@example.com"
108
- lines = []
111
+ lines none
109
112
  then error "Reserved number"
110
113
 
111
114
  specification RefusingAGuest
@@ -116,7 +119,7 @@ module Billing
116
119
  invoiceId = "9c858901-8a57-4791-81fe-4c455b099bc9"
117
120
  number = "INV-000123"
118
121
  contact = "ada@example.com"
119
- lines = []
122
+ lines none
120
123
  then denied
121
124
 
122
125
  specification RejectingAnEmptyEmail // one concept rejection spec, through this command
@@ -127,7 +130,7 @@ module Billing
127
130
  invoiceId = "9c858901-8a57-4791-81fe-4c455b099bc9"
128
131
  number = "INV-000123"
129
132
  contact = ""
130
- lines = []
133
+ lines none
131
134
  then error "An email is required"
132
135
 
133
136
  slice StateChange CancelInvoice
@@ -170,7 +173,7 @@ module Billing
170
173
  data InvoiceRow[] via query ListInvoices
171
174
  table InvoiceRow
172
175
  column number label "Number"
173
- action RegisterInvoice
176
+ action RegisterInvoice for screen
174
177
  label "Register invoice"
175
178
  specification ListingAnInvoice
176
179
  given caller // module + feature gates apply to the query too
@@ -226,9 +229,7 @@ module Billing
226
229
  then PaymentRecorded
227
230
  for "0b6f3f7e-3c1e-4a53-9f7e-2a1c3b4d5e6f"
228
231
  invoiceId = "9c858901-8a57-4791-81fe-4c455b099bc9"
229
- amount = 100
230
- then InvoiceClosed // ESM v6: the Reconciler cascade (amount > 0)
231
- for "9c858901-8a57-4791-81fe-4c455b099bc9"
232
+ amount = 100 // the Reconciler's InvoiceClosed is another slice's fact (decision 0115)
232
233
 
233
234
  module Housekeeping // no gates: this reaction declares no `runs as`, so its `invokes` has no caller
234
235
  description "Background follow-up"
@@ -286,8 +287,8 @@ module Housekeeping // no gates: this reaction
286
287
  for "0b6f3f7e-3c1e-4a53-9f7e-2a1c3b4d5e6f"
287
288
  invoiceId = "9c858901-8a57-4791-81fe-4c455b099bc9"
288
289
  amount = 100
289
- then InvoiceClosed
290
- for "9c858901-8a57-4791-81fe-4c455b099bc9"
290
+ then invokes CloseInvoice // ESM v34: the hand-over; CloseInvoice's slice proves InvoiceClosed
291
+ invoiceId = "9c858901-8a57-4791-81fe-4c455b099bc9"
291
292
 
292
293
  slice Translate LegacySync
293
294
  capture LegacyInvoices
@@ -49,7 +49,7 @@ examples belong to `cheat-sheet-example.md` and its siblings.
49
49
 
50
50
  | File | Mode | V1, warnings as errors | V3 (binds) |
51
51
  | --- | --- | --- | --- |
52
- | `cheat-sheet-example.md` | design: every construct family | 0 diagnostics, both tools (an older bundled compiler reported a false PLAY0285 on the `RecordingAPayment` cascade spec) | not ready by design (its header lists why; fewer blockers on the standalone tool) |
52
+ | `cheat-sheet-example.md` | design: every construct family | 0 diagnostics, both tools | not ready by design (its header lists why; fewer blockers on the standalone tool) |
53
53
  | `executable-example.md` | executable, StateChange and StateView | 0 diagnostics, both tools | ready, both tools |
54
54
  | `pdl-example.md` | executable projections | 0 diagnostics, both tools | ready, both tools |
55
55
  | `automation-translate-example.md` | executable Automation and Translate (ESM v6) | 0 diagnostics, both tools (an older bundled compiler could not bind it) | ready, both tools |
@@ -66,7 +66,7 @@ PLAY0781–PLAY0785 need Screenplay 4.207.0; earlier compilers omit these argume
66
66
  command gives one, else the read model name. The PLAY0781 `reason` keywords are listed in command-surface
67
67
  [protected reads](../../cratis-screenplay-command-surface/references/protected-reads.md); each refused read gets its own PLAY0781.
68
68
 
69
- Requires Screenplay 4.210.0 (`screenplay --version`) for PLAY0800 (`CommandHandlerRequiresAttachment`) and its `subject`; older binders report attached command handlers as PLAY0268. `arguments.subject.kind` is `command` and `path` names the command. Treat the refusal as permanent: deliver a constrained implementation attachment by code gap-fill, not by waiting for ESM admission. Switch on the code and navigate the subject, never match message text.
69
+ Requires Screenplay 4.210.0 (`screenplay --version`) for PLAY0800 (`CommandHandlerRequiresAttachment`) and its `subject`; older binders report attached command handlers as PLAY0268. `arguments.subject.kind` is `command` and `path` names the command. From Screenplay 4.250.0 the code fires only when the handler lacks unconditional `produces` or a resolved, nonempty body; fix that shape or gap-fill in code. Switch on the code and navigate the subject, never match message text.
70
70
 
71
71
  For PLAY0524, `step` is given, given readmodel, when, when append or then.
72
72
  `stepIndex` counts every authored given/when/then clause once across all forms,
@@ -443,12 +443,12 @@ Requires Stage 4.129.0 for semantic Host/executor protected reads; older engines
443
443
 
444
444
  ## Binding (V2 and V3) - see `executable-subset.md` for the full table
445
445
 
446
- Requires Screenplay 4.210.0 (`screenplay --version`) for PLAY0800 and its required typed `subject`; older binders attribute attached command handlers to PLAY0268. Other PLAY0268 refusal families are unchanged.
446
+ Requires Screenplay 4.210.0 (`screenplay --version`) for PLAY0800 and its required typed `subject`; older binders attribute attached command handlers to PLAY0268. From Screenplay 4.250.0 an attached handler beside unconditional `produces` with a resolved body binds instead. Other PLAY0268 refusal families are unchanged.
447
447
 
448
448
  | Code | Meaning | Fix |
449
449
  |---|---|---|
450
450
  | PLAY0268 | construct not representable in a supported ESM version yet (`executable-subset.md` lists unsupported query shapes, protected enum/identity concepts, read paths without opt-in or in `produces when`, Uuid ordering, different Uuid concepts and Uuid rules, and older bundled-compiler limits) | stay in design mode, or change the construct if the domain allows; never strip `pii`/authorization |
451
- | PLAY0800 | error `CommandHandlerRequiresAttachment`: a file/inline command handler requires a constrained implementation attachment; required typed `subject` identifies the command | permanent limitation: gap-fill the slice in code, not by waiting for ESM admission; hosts switch on the code and read `arguments.subject`, never match the message |
451
+ | PLAY0800 | error `CommandHandlerRequiresAttachment`: a file/inline command handler has no unconditional `produces` result contract or no resolved, nonempty, language-tagged body; required typed `subject` identifies the command | declare unconditional `produces` beside a resolved body, split variable outcomes into separate commands, or gap-fill the slice in code; hosts switch on the code and read `arguments.subject`, never match the message |
452
452
  | PLAY0269 / 0270 | UI deferred / authoring metadata (I) | none |
453
453
  | PLAY0271 | legacy `reads` or a `concurrency` block keeps its legacy meaning and cannot bind (error) | opt eligible command reads into v25 with reviewed preamble repair; `concurrency` remains unbound; uniqueness uses a constraint, target realization stays separate |
454
454
  | PLAY0273 | incoherent: ambiguous `for`, property not on event revision, operand type mismatch, derived `$eventContext` path, unparsable date literal or offset-less DateTime literal in an admitted v26 comparison, or a Uuid comparison literal that is not lowercase hyphenated (v28) | fix the reference or literal; DateTime needs offset/Z; Uuid literals are lowercase hyphenated |
@@ -328,7 +328,8 @@ for the result contract. Attached handlers remain unbound.
328
328
 
329
329
  Inline fences (`csharp`, `typescript`, `react`, `html`, `sql`, `java`) and `file <path>` attach
330
330
  code to an owner. Two kinds block binding (V3 blocked, no specification runs):
331
- the attached command `handler` (PLAY0800) and the `file` constraint (PLAY0268, see below).
331
+ an attached command `handler` without unconditional `produces` or a resolved body
332
+ (PLAY0800) and the `file` constraint (PLAY0268, see below).
332
333
  A query `performer` does not block: it is an opaque read, reported as information
333
334
  `PLAY0270` and left out of the executable model; a specification that reads it is left
334
335
  out, and every other specification still runs with `screenplay test`. That is the compiler fact only; Stage renders the body separately ([performer bodies](../../cratis-screenplay-read-surface/SKILL.md#performer-bodies-are-rendered)).
@@ -344,11 +345,13 @@ bodies still leave their owner non-executable.
344
345
  can only declare uniqueness: declare it with `unique ...`, and put other rules in command
345
346
  validation or a `require` condition.
346
347
 
347
- - A file/fenced command `handler` refuses PLAY0800, wrapped or direct: a permanent
348
- requirement for a constrained implementation attachment, not future ESM admission.
349
- Gap-fill the slice in code; hosts read the required typed `arguments.subject` for
350
- the command rather than matching message text.
351
- Requires Screenplay 4.210.0 (`screenplay --version`); older binders use PLAY0268.
348
+ - A file/fenced command `handler`, wrapped or direct, binds as the v23 result contract
349
+ beside unconditional `produces` with a resolved, nonempty, language-tagged body:
350
+ `produces` fixes the events, the body owns their
351
+ values, and a reached body is Unsupported (`ImplementationBody`). With no `produces`,
352
+ with `produces ... when` or with an unresolved body it refuses PLAY0800; hosts read the
353
+ required typed `arguments.subject` for the command rather than matching message text.
354
+ Requires Screenplay 4.250.0 or later (`screenplay --version`) for an attached handler beside `produces` to bind; 4.210.0 to 4.249.x refuse every attached handler with PLAY0800 and older binders use PLAY0268.
352
355
  A pending intent instead selects v23 with unconditional productions (PLAY0695 information).
353
356
  Missing productions use PLAY0696, conditional ones PLAY0697, duplicate handlers PLAY0698.
354
357
  Hints are not executable code, locks or confirmation.
@@ -383,7 +386,7 @@ bodies still leave their owner non-executable.
383
386
  | Uuid comparison with `<`, `>`, different concepts, optional operands, a validation rule or a concept rule | PLAY0268 | v28 admits `==`/`!=` in command conditions only, between the same concept or a bare Uuid and a concept |
384
387
  | Legacy `reads <View> ...` on a command | PLAY0271 (error) | `command reads protected` opts eligible views into v25; see command-surface protected reads |
385
388
  | `concurrency` block on a command | PLAY0271 (error) | "concurrency metadata keeps its legacy meaning and cannot bind to ESM v1" |
386
- | File/inline `handler` (see above) | PLAY0800 | permanent attachment requirement: gap-fill in code; pending described handlers instead bind v23, with body execution/rendering separate |
389
+ | File/inline `handler` without unconditional `produces` or a resolved body (see above) | PLAY0800 | declare unconditional `produces` beside a resolved body or gap-fill in code; pending and attached handlers beside `produces` bind v23, with body execution/rendering separate |
387
390
  | `$context.tenant`, roles, claims, causation | PLAY0268 | no portable scalar counterpart |
388
391
  | Arithmetic or raw expression in a `produces` mapping | PLAY0268 | |
389
392
  | Template `` `${x}` `` or `$causedBy` in a projection | PLAY0268 | |
@@ -30,8 +30,11 @@ exact language/semantic pairs; binding, reference execution and rendering are se
30
30
  | v31 | A policy `require anonymous` for a public command or query | A deliberately public surface; the policy is the whole effective authorization | v31 refused until Stage admits it |
31
31
  | v32 | A `source events` capture whose key is a typed scalar (for example a concept over Uuid) | The appended event's event-source identity keeps the key's type instead of Text (see the compiler minimums); other models keep their version and bytes | Stage admits v32 through a direct caller of the reviewed baseline; see [Stage admission](#stage-admission-and-execution) |
32
32
  | v33 | `key <property> is event source` on a single-property `source events` capture (Screenplay 4.242.0; PLAY0809) | Serializes `keyIsEventSource` beside `sourceEvents`. Promises every incoming event is sourced by that key; explicit fixture `for` must equal it, while omission takes the key before projections/reactions. Checks also run on givens without an action. Unmarked captures keep earlier behavior/version/bytes | An admitting renderer may narrow history reads by event source id; binding alone does not prove target realization |
33
+ | v34 | A specification `then invokes <Command>` (decision 0115; PLAY0815/PLAY0816) | Writes `thenInvocations` only when present. When one is stated, the slice's recorded invocations must match in count and order, comparing only stated values; a refused invocation counts | Stage spec runner compares it; the Cratis renderer refuses models after v33 with `STAGE-ESM-016` |
34
+ | v35 | Reserved for handler result contract v2 (decision 0119); no construct selects it | | |
35
+ | v36 | `statemachine` and `workflow` declarations (decision 0124; PLAY0834-PLAY0851) | Serializes `stateMachines` and `workflows`; specifications run them; earlier models keep their version and bytes | Stage refuses v36 models with `STAGE-ESM-016` |
33
36
 
34
- Constructs of decision 0098 with no executable-model content need no version: application-level toolbar buttons in the layout's `navigation topbar` region (`button <id> title "..." slice <Slice>` with an optional indented `authorize <Policy>`), a command specification that states the public event its outbound Translate slice publishes (no more false `PLAY0285`), and a capture over events that copies a list (`lines = $.lines`) or fans out with `children lines identified by sku`. Check `screenplay --version` against the release that admitted v29 and v30 before relying on them.
37
+ Constructs of decision 0098 with no executable-model content need no version: application-level toolbar buttons in the layout's `navigation topbar` region (`button <id> title "..." slice <Slice>` with an optional indented `authorize <Policy>`), and a capture over events that copies a list (`lines = $.lines`) or fans out with `children lines identified by sku`. Check `screenplay --version` against the release that admitted v29 and v30 before relying on them. Decision 0115 withdrew 0098's command specification that states the public event its outbound Translate slice publishes: a specification runs only its own slice, so the Translate slice states the public event in its own `when append` specification.
35
38
 
36
39
  ## Compiler and target minimums
37
40
 
@@ -5,7 +5,7 @@
5
5
 
6
6
  Use these forms when writing or reviewing `.play`. Acceptance of an older
7
7
  spelling is not a recommendation to teach it. Information diagnostics do not
8
- fail `--warnaserror`; the corpus verification gate rejects the twelve style codes
8
+ fail `--warnaserror`; the corpus verification gate rejects the thirteen style codes
9
9
  below even when a fence declares `expect`, unless an exact, reasoned migration
10
10
  exception exists in the verifier's preferred-syntax allowlist. That allowlist also
11
11
  covers deliberate legacy explanations in prose; stale entries fail.
@@ -24,8 +24,11 @@ covers deliberate legacy explanations in prose; stale entries fail.
24
24
  | Interaction guard | Block-form `when` alternatives | Opaque interaction `where` on click, double click or select (a `change` keeps it) | PLAY0564 (warning or information) |
25
25
  | Projection transition cardinality | Source binding emits `One` | Constructed/deserialized ESM v1–v3 `ZeroOrOne` / `Many` | PLAY0445 (warning; ESM-only, not a source spelling) |
26
26
  | Command decision reads | `command reads protected` after reviewing every read's admission, absence and conflict semantics | Eligible legacy command reads without the application-root preamble | PLAY0786 (information; individual typed repair review, never fix-all) |
27
+ | Combined policies | `authorize A and B` | `authorize A B` (adjacent policies mean `and`) | PLAY0825 (information; repair writes `and`) |
28
+ | Composite key | Indented key parts under `key` | `key {` ... `}` around parts the indentation already groups | PLAY0824 (information; repair removes the braces) |
27
29
  | Profile shell | `root template <Name>` in a `ui profile` | `layout <Name>` in a `ui profile` | PLAY0791 (warning; quick fix) |
28
30
  | Literal text rules | `starts with`, `ends with`, `contains`, `not contains` or equality, preserving message and severity | Exact deprecated Studio `matches` shapes | PLAY0787 (warning; not arbitrary regex rewriting) |
31
+ | Objects and lists | An indented block under the name: `member = value` lines, one `item` line per element, `<name> none` for an empty list | Inline JSON (`= {...}`, `= [...]`) - not accepted; Screenplay has no JSON | PLAY0833 (error; quick fix, and printing converts) |
29
32
 
30
33
  `query Q => observable?` is not a legacy optional type suffix and has no keyword
31
34
  replacement. Reaction/Translate `where` is current syntax, not an interaction
@@ -80,7 +80,7 @@ query performers have a separate explicit gap contract, not completed behavior.
80
80
  renders; multiple same-event triggers and routed productions retain STAGE-ESM-043. Literal
81
81
  text rules execute/render ordinal UTF-16 comparisons. Read [language admission](language-admission.md).
82
82
  A CLI's older bundled compiler may fail first: legacy reads/concurrency PLAY0271,
83
- attached handlers PLAY0800 (PLAY0268 before Screenplay 4.210.0). Protected reads bind v25. Non-Error protected requirements
83
+ attached handlers PLAY0800 (every attached handler, before the result-contract admission; PLAY0268 on the oldest binders). Protected reads bind v25. Non-Error protected requirements
84
84
  refuse STAGE-ESM-045, including reaction invocations; this is not a rendering result.
85
85
  Requires Stage 4.129.0 for semantic Host/executor protected reads (older engines refuse -044) and Stage 4.138.0 for the Cratis renderer to render them.
86
86
  Response-name authoring scopes are not rendered and Scene runtime does not supply them.
@@ -109,9 +109,9 @@ ids into routing to fit a renderer (PLAY0515).
109
109
  older renderers refuse snapshot lists with STAGE-ESM-010.
110
110
  context/single-result filters, and opaque `scoped to` block binding; a `performer` query is left out of the executable model ([version gate](executable-subset.md#code-attachments-what-binds-what-never-does)). Keep a list the domain needs and report
111
111
  the capability gap; marking it `observable` or keying it is a modeling decision for the user.
112
- - Attached file/inline handlers refuse PLAY0800 and require constrained implementation
113
- attachments: gap-fill in code, not by waiting for ESM admission.
114
- Requires Screenplay 4.210.0 (`screenplay --version`); older binders use PLAY0268.
112
+ - Attached file/inline handlers bind beside unconditional `produces` with a resolved body
113
+ and Stage renders a C# body; otherwise they refuse PLAY0800 (version gate:
114
+ [executable subset](executable-subset.md)).
115
115
  Pending handlers beside unconditional
116
116
  productions bind v23 but Stage still refuses rendering STAGE-IMPL-002 even in
117
117
  Stub mode. Semantic execution reports ImplementationBody only when reached
@@ -26,75 +26,5 @@
26
26
  "kind": "diagnostic",
27
27
  "value": "PLAY0686",
28
28
  "reason": "Explicit retirement notice, not an active diagnostic or repair recommendation. The published contract marks PLAY0686 retired. Remove when this notice is removed or replaced."
29
- },
30
- {
31
- "file": ".cratis/ai/skills/cratis-screenplay-authentication-and-onboarding/SKILL.md",
32
- "text": "screenplay environment ./model # one key per line, secrets marked \"(secret)\"",
33
- "kind": "cliCommand",
34
- "value": "environment",
35
- "reason": "Documents the onboarding and environment-key surface of Screenplay 4.259.0, which the pinned 4.245.0 contract predates. Remove when the pinned contract moves to 4.259.0 or later (the check then reports it unnecessary)."
36
- },
37
- {
38
- "file": ".cratis/ai/skills/cratis-screenplay-authentication-and-onboarding/SKILL.md",
39
- "text": "screenplay environment ./model --format json # key, secret, source, owner, description",
40
- "kind": "cliCommand",
41
- "value": "environment",
42
- "reason": "Documents the onboarding and environment-key surface of Screenplay 4.259.0, which the pinned 4.245.0 contract predates. Remove when the pinned contract moves to 4.259.0 or later (the check then reports it unnecessary)."
43
- },
44
- {
45
- "file": ".cratis/ai/skills/cratis-screenplay-authentication-and-onboarding/SKILL.md",
46
- "text": "screenplay environment ./model --format json # key, secret, source, owner, description",
47
- "kind": "cliOption",
48
- "value": "--format",
49
- "reason": "Documents the onboarding and environment-key surface of Screenplay 4.259.0, which the pinned 4.245.0 contract predates. Remove when the pinned contract moves to 4.259.0 or later (the check then reports it unnecessary)."
50
- },
51
- {
52
- "file": ".cratis/ai/skills/cratis-screenplay-authentication-and-onboarding/references/onboarding-directives.md",
53
- "text": "| `PLAY0826` | The `onboarding` line carries more than the keyword. | Move content into the body. |",
54
- "kind": "diagnostic",
55
- "value": "PLAY0826",
56
- "reason": "Documents the onboarding and environment-key surface of Screenplay 4.259.0, which the pinned 4.245.0 contract predates. Remove when the pinned contract moves to 4.259.0 or later (the check then reports it unnecessary)."
57
- },
58
- {
59
- "file": ".cratis/ai/skills/cratis-screenplay-authentication-and-onboarding/references/onboarding-directives.md",
60
- "text": "| `PLAY0827` | More than one `onboarding` block. | Merge them. |",
61
- "kind": "diagnostic",
62
- "value": "PLAY0827",
63
- "reason": "Documents the onboarding and environment-key surface of Screenplay 4.259.0, which the pinned 4.245.0 contract predates. Remove when the pinned contract moves to 4.259.0 or later (the check then reports it unnecessary)."
64
- },
65
- {
66
- "file": ".cratis/ai/skills/cratis-screenplay-authentication-and-onboarding/references/onboarding-directives.md",
67
- "text": "| `PLAY0828` | `onboarding` without `authentication`. | Declare the providers. Draft authoring reports a warning until the folder is assembled. |",
68
- "kind": "diagnostic",
69
- "value": "PLAY0828",
70
- "reason": "Documents the onboarding and environment-key surface of Screenplay 4.259.0, which the pinned 4.245.0 contract predates. Remove when the pinned contract moves to 4.259.0 or later (the check then reports it unnecessary)."
71
- },
72
- {
73
- "file": ".cratis/ai/skills/cratis-screenplay-authentication-and-onboarding/references/onboarding-directives.md",
74
- "text": "| `PLAY0829` | A line is not a directive, or one is malformed or incomplete. | Use the forms above. |",
75
- "kind": "diagnostic",
76
- "value": "PLAY0829",
77
- "reason": "Documents the onboarding and environment-key surface of Screenplay 4.259.0, which the pinned 4.245.0 contract predates. Remove when the pinned contract moves to 4.259.0 or later (the check then reports it unnecessary)."
78
- },
79
- {
80
- "file": ".cratis/ai/skills/cratis-screenplay-authentication-and-onboarding/references/onboarding-directives.md",
81
- "text": "| `PLAY0830` | A directive stated twice. | Keep one. |",
82
- "kind": "diagnostic",
83
- "value": "PLAY0830",
84
- "reason": "Documents the onboarding and environment-key surface of Screenplay 4.259.0, which the pinned 4.245.0 contract predates. Remove when the pinned contract moves to 4.259.0 or later (the check then reports it unnecessary)."
85
- },
86
- {
87
- "file": ".cratis/ai/skills/cratis-screenplay-authentication-and-onboarding/references/onboarding-directives.md",
88
- "text": "| `PLAY0831` | An invitation names a persona nothing declares. | Declare it with `persona`. |",
89
- "kind": "diagnostic",
90
- "value": "PLAY0831",
91
- "reason": "Documents the onboarding and environment-key surface of Screenplay 4.259.0, which the pinned 4.245.0 contract predates. Remove when the pinned contract moves to 4.259.0 or later (the check then reports it unnecessary)."
92
- },
93
- {
94
- "file": ".cratis/ai/skills/cratis-screenplay-authentication-and-onboarding/references/onboarding-directives.md",
95
- "text": "| `PLAY0832` | `emails` names an email onboarding does not send. | Use `invitation`, `welcome` or `signupDeclined`. |",
96
- "kind": "diagnostic",
97
- "value": "PLAY0832",
98
- "reason": "Documents the onboarding and environment-key surface of Screenplay 4.259.0, which the pinned 4.245.0 contract predates. Remove when the pinned contract moves to 4.259.0 or later (the check then reports it unnecessary)."
99
29
  }
100
30
  ]