@cratis/pi 7.62.0 → 7.63.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 (103) hide show
  1. package/package/corpus/product-sync.json +9 -9
  2. package/package/corpus/skills/cratis-application-slice-conformance/SKILL.md +1 -1
  3. package/package/corpus/skills/cratis-arc-command/references/generated-values.md +27 -12
  4. package/package/corpus/skills/cratis-arc-command/references/shop-generation.md +17 -6
  5. package/package/corpus/skills/cratis-fundamentals-concept/SKILL.md +10 -2
  6. package/package/corpus/skills/cratis-fundamentals-concept/references/shop-generation.md +49 -6
  7. package/package/corpus/skills/cratis-screenplay-automations-and-translations/SKILL.md +43 -41
  8. package/package/corpus/skills/cratis-screenplay-automations-and-translations/references/cases-to-specify.md +11 -2
  9. package/package/corpus/skills/cratis-screenplay-automations-and-translations/references/integration-interview.md +24 -0
  10. package/package/corpus/skills/cratis-screenplay-automations-and-translations/references/public-events-and-direction.md +76 -10
  11. package/package/corpus/skills/cratis-screenplay-automations-and-translations/references/realization-and-gap-fill.md +5 -0
  12. package/package/corpus/skills/cratis-screenplay-automations-and-translations/references/todo-list-example.md +1 -1
  13. package/package/corpus/skills/cratis-screenplay-automations-and-translations/references/translate-example.md +39 -23
  14. package/package/corpus/skills/cratis-screenplay-automations-and-translations/references/translation-patterns.md +35 -12
  15. package/package/corpus/skills/cratis-screenplay-captures-and-reactions/SKILL.md +51 -81
  16. package/package/corpus/skills/cratis-screenplay-captures-and-reactions/references/atomic-batches-and-source-mappings.md +83 -0
  17. package/package/corpus/skills/cratis-screenplay-captures-and-reactions/references/capture-map-and-example.md +14 -4
  18. package/package/corpus/skills/cratis-screenplay-captures-and-reactions/references/reaction-forms.md +59 -0
  19. package/package/corpus/skills/cratis-screenplay-captures-and-reactions/references/record-capture-specifications.md +60 -0
  20. package/package/corpus/skills/cratis-screenplay-captures-and-reactions/references/specifying-triggers-and-clock.md +5 -1
  21. package/package/corpus/skills/cratis-screenplay-command-surface/SKILL.md +26 -28
  22. package/package/corpus/skills/cratis-screenplay-command-surface/references/described-handlers.md +82 -0
  23. package/package/corpus/skills/cratis-screenplay-command-surface/references/generated-values-and-responses.md +82 -28
  24. package/package/corpus/skills/cratis-screenplay-command-surface/references/protected-reads.md +113 -0
  25. package/package/corpus/skills/cratis-screenplay-command-surface/references/shop-generation.md +45 -12
  26. package/package/corpus/skills/cratis-screenplay-command-surface/references/text-and-match-rules.md +119 -0
  27. package/package/corpus/skills/cratis-screenplay-command-surface/references/validate-rules.md +14 -4
  28. package/package/corpus/skills/cratis-screenplay-command-surface/verification.json +10 -3
  29. package/package/corpus/skills/cratis-screenplay-event-modeling/SKILL.md +12 -12
  30. package/package/corpus/skills/cratis-screenplay-event-modeling/references/parsed-not-runnable.md +5 -3
  31. package/package/corpus/skills/cratis-screenplay-event-modeling/verification.json +5 -1
  32. package/package/corpus/skills/cratis-screenplay-legacy-extraction/SKILL.md +2 -2
  33. package/package/corpus/skills/cratis-screenplay-legacy-extraction/references/evidence-table-template.md +1 -1
  34. package/package/corpus/skills/cratis-screenplay-legacy-extraction/references/generated-recovery.md +51 -14
  35. package/package/corpus/skills/cratis-screenplay-legacy-extraction/references/intent-example.md +5 -0
  36. package/package/corpus/skills/cratis-screenplay-legacy-extraction/references/loss-report-template.md +2 -1
  37. package/package/corpus/skills/cratis-screenplay-legacy-extraction/references/rule-modeling.md +6 -3
  38. package/package/corpus/skills/cratis-screenplay-legacy-extraction/references/signal-to-intent.md +1 -1
  39. package/package/corpus/skills/cratis-screenplay-model-authoring/SKILL.md +22 -28
  40. package/package/corpus/skills/cratis-screenplay-model-authoring/references/choosing-generation.md +20 -7
  41. package/package/corpus/skills/cratis-screenplay-model-authoring/references/language-reference.md +12 -6
  42. package/package/corpus/skills/cratis-screenplay-model-authoring/references/mcp-loop.md +9 -1
  43. package/package/corpus/skills/cratis-screenplay-model-authoring/references/mcp-tools.md +58 -10
  44. package/package/corpus/skills/cratis-screenplay-model-authoring/verification.json +4 -2
  45. package/package/corpus/skills/cratis-screenplay-model-review/SKILL.md +2 -5
  46. package/package/corpus/skills/cratis-screenplay-model-review/references/anti-patterns.md +2 -2
  47. package/package/corpus/skills/cratis-screenplay-model-review/references/checklist.md +2 -2
  48. package/package/corpus/skills/cratis-screenplay-model-review/references/quick-self-check.md +2 -1
  49. package/package/corpus/skills/cratis-screenplay-model-review/references/review-questions.md +3 -2
  50. package/package/corpus/skills/cratis-screenplay-modeling-lifecycle/references/principles.md +1 -1
  51. package/package/corpus/skills/cratis-screenplay-modeling-lifecycle/references/vocabulary-map.md +1 -1
  52. package/package/corpus/skills/cratis-screenplay-read-surface/SKILL.md +2 -3
  53. package/package/corpus/skills/cratis-screenplay-read-surface/references/named-keys.md +3 -1
  54. package/package/corpus/skills/cratis-screenplay-render-and-gap-fill/SKILL.md +8 -3
  55. package/package/corpus/skills/cratis-screenplay-render-and-gap-fill/references/gap-fill-handoff.md +8 -0
  56. package/package/corpus/skills/cratis-screenplay-render-and-gap-fill/references/renderability-gate.md +6 -4
  57. package/package/corpus/skills/cratis-screenplay-scenario-coverage/SKILL.md +36 -29
  58. package/package/corpus/skills/cratis-screenplay-scenario-coverage/references/berth-reservations.md +6 -0
  59. package/package/corpus/skills/cratis-screenplay-scenario-coverage/references/invoicing-dues-design.md +15 -4
  60. package/package/corpus/skills/cratis-screenplay-scenario-coverage/references/invoicing-dues-example.md +25 -20
  61. package/package/corpus/skills/cratis-screenplay-scenario-coverage/references/public-event-coverage.md +14 -3
  62. package/package/corpus/skills/cratis-screenplay-scenario-coverage/references/scenario-examples.md +9 -3
  63. package/package/corpus/skills/cratis-screenplay-scenario-coverage/references/spec-forms-by-mode.md +7 -3
  64. package/package/corpus/skills/cratis-screenplay-slice-design/SKILL.md +3 -1
  65. package/package/corpus/skills/cratis-screenplay-slice-design/references/command-inventory.md +4 -4
  66. package/package/corpus/skills/cratis-screenplay-slice-design/references/rule-layers.md +4 -2
  67. package/package/corpus/skills/cratis-screenplay-slice-design/references/slicing.md +4 -3
  68. package/package/corpus/skills/cratis-screenplay-slice-design/references/worked-example.md +8 -8
  69. package/package/corpus/skills/cratis-screenplay-specifications/SKILL.md +49 -47
  70. package/package/corpus/skills/cratis-screenplay-specifications/references/actions-beyond-commands.md +11 -1
  71. package/package/corpus/skills/cratis-screenplay-specifications/references/generated-fixtures.md +48 -17
  72. package/package/corpus/skills/cratis-screenplay-specifications/references/vocabulary.md +14 -1
  73. package/package/corpus/skills/cratis-screenplay-streams-and-consistency/SKILL.md +25 -21
  74. package/package/corpus/skills/cratis-screenplay-streams-and-consistency/references/boundaries.md +2 -2
  75. package/package/corpus/skills/cratis-screenplay-streams-and-consistency/references/consistency-and-concurrency.md +9 -3
  76. package/package/corpus/skills/cratis-screenplay-streams-and-consistency/references/multi-service-models.md +4 -3
  77. package/package/corpus/skills/cratis-screenplay-streams-and-consistency/references/streams-example.md +7 -0
  78. package/package/corpus/skills/cratis-screenplay-toolchain/SKILL.md +30 -22
  79. package/package/corpus/skills/cratis-screenplay-toolchain/references/cheat-sheet-example.md +3 -1
  80. package/package/corpus/skills/cratis-screenplay-toolchain/references/cheat-sheet.md +47 -2
  81. package/package/corpus/skills/cratis-screenplay-toolchain/references/diagnostic-arguments.md +60 -0
  82. package/package/corpus/skills/cratis-screenplay-toolchain/references/diagnostics.md +65 -5
  83. package/package/corpus/skills/cratis-screenplay-toolchain/references/executable-subset.md +50 -22
  84. package/package/corpus/skills/cratis-screenplay-toolchain/references/generation-checks.md +93 -0
  85. package/package/corpus/skills/cratis-screenplay-toolchain/references/generation-strategies-example.md +117 -35
  86. package/package/corpus/skills/cratis-screenplay-toolchain/references/language-admission.md +46 -0
  87. package/package/corpus/skills/cratis-screenplay-toolchain/references/preferred-syntax.md +3 -1
  88. package/package/corpus/skills/cratis-screenplay-toolchain/references/renderable-subset.md +25 -10
  89. package/package/corpus/skills/cratis-screenplay-toolchain/references/screenplay-contract.json +1800 -50
  90. package/package/corpus/skills/cratis-screenplay-toolchain/references/screenplay-contract.version +1 -1
  91. package/package/corpus/skills/cratis-screenplay-toolchain/references/traps.md +5 -3
  92. package/package/corpus/skills/cratis-screenplay-toolchain/verification.json +6 -1
  93. package/package/corpus/skills/cratis-screenplay-ui-composition/SKILL.md +8 -53
  94. package/package/corpus/skills/cratis-screenplay-ui-composition/references/file-references.md +2 -2
  95. package/package/corpus/skills/cratis-screenplay-ui-composition/references/interaction-example.md +54 -0
  96. package/package/corpus/skills/cratis-screenplay-ui-composition/verification.json +6 -3
  97. package/package/corpus/skills/cratis-stage-rendering-and-sandbox/SKILL.md +30 -29
  98. package/package/corpus/skills/cratis-stage-rendering-and-sandbox/references/admission.md +36 -9
  99. package/package/corpus/skills/cratis-stage-rendering-and-sandbox/references/choosing-generation.md +28 -8
  100. package/package/corpus/skills/cratis-stage-rendering-and-sandbox/references/publication-and-recovery.md +31 -0
  101. package/package/corpus/skills/cratis-stage-rendering-and-sandbox/references/sandbox-and-specrunner.md +8 -0
  102. package/package/corpus/skills/cratis-stage-rendering-and-sandbox/verification.json +4 -1
  103. package/package.json +1 -1
@@ -22,6 +22,11 @@ recovery behavior rather than assuming this handler supplies all-or-nothing sett
22
22
  rejected model renderable, and never claim a whole-application V5 from a subset. Choose the route
23
23
  with `cratis-screenplay-render-and-gap-fill`.
24
24
 
25
+ Application-root `reaction batches atomic` also blocks Stage delivery: v22
26
+ refuses STAGE-ESM-016; mode in admitted v23–v25 refuses STAGE-ESM-043. Preserve the
27
+ per-occurrence/selected-branch batch boundary and independent invoked commands.
28
+ Atomic appends do not prove redelivery deduplication or external exactly-once effects.
29
+
25
30
  ## Where the pieces go (hand-written)
26
31
  | Model element | Realization | Skill |
27
32
  |---|---|---|
@@ -188,7 +188,7 @@ module Certification
188
188
  ## Design-only additions
189
189
 
190
190
  Two things a real queue often wants stay out of the complete model above: a list query (the
191
- visible queue) and a retry sweep that reads the whole view. The list query binds (Stage refuses a snapshot list); the sweep needs a code body the
191
+ visible queue) and a retry sweep that reads the whole view. The list query binds (Stage renders snapshot and observable lists); the sweep needs a code body the
192
192
  reference does not run, and durable per-item fan-out is outside the language. Say so
193
193
  in the verdict.
194
194
 
@@ -1,7 +1,12 @@
1
- # Example: a Translate slice
1
+ # Example: a capture and its follow-up Automation
2
+
3
+ ## Contents
4
+
5
+ - Model
6
+ - Notes for the reader
2
7
 
3
8
  A complete model: a webhook record from an outside proctoring service is captured, kept as an
4
- external fact in the provider's vocabulary, then translated by reactions into our facts. It
9
+ external fact in the provider's vocabulary, then followed by a separate Automation that records our result. It
5
10
  binds as ESM v6 (`executableReady: true`), standalone and through `cratis screenplay mcp`; a
6
11
  compiler that stops before v6 compiles it (V1) but rejects the Translate slice at binding
7
12
  (PLAY0268). `cratis render` refuses it (`STAGE-ESM-016` or `STAGE-ESM-024`, by renderer).
@@ -10,6 +15,8 @@ Read the slice `description`: it is the per-field disposition (map, translate, i
10
15
  states what this example does not do. Examples never show the whole integration contract; use
11
16
  `references/integration-contracts.md` and `references/worked-integration.md` for the rest.
12
17
 
18
+ ## Model
19
+
13
20
  ```screenplay
14
21
  // Translate slice. Correlation is created on OUR side: BookExam allocates the attempt id and the
15
22
  // realization hands it to the proctoring service as its reference; the service's webhook echoes
@@ -57,7 +64,7 @@ module Exams
57
64
  then denied
58
65
 
59
66
  slice Translate ImportProctorResults
60
- description "Per external field: reference -> correlation key (our attempt id, echoed); outcome -> translated to our enum; score -> kept; examinerNote -> ignored (free text, may hold personal data, no consumer). Repeated delivery: the first record of a key appends once (`when added`, Chronicle's first-observation rule); a later delivery of the same key appends nothing, even if the outcome or score changed, so it does not implement corrections. OneResultPerAttempt refuses a second local result. Changed outcomes and score-only corrections need an explicit correction policy (open decision, recorded in STATE.md, not an overwrite) before this is a complete integration."
67
+ description "Per external field: reference -> correlation key (our attempt id, echoed); outcome -> translated to our enum; score -> kept; examinerNote -> ignored (free text, may hold personal data, no consumer). Repeated delivery: the first record of a key appends once (`when added`); later records compare outcome only. An unchanged outcome appends nothing, even if the score changed, so it does not implement score corrections. OneResultPerAttempt refuses a second local result. Changed outcomes and score-only corrections need an explicit correction policy (open decision, recorded in STATE.md, not an overwrite) before this is a complete integration."
61
68
  capture ProctorResults
62
69
  source webhook
63
70
  path /webhooks/proctoring/results
@@ -70,15 +77,13 @@ module Exams
70
77
  when added
71
78
  outcome = $.outcome
72
79
  score = $.score
80
+ append ProctorResultReceived
81
+ when outcome
82
+ outcome = $.outcome
83
+ score = $.score
73
84
  event ProctorResultReceived
74
85
  outcome ProctorOutcome
75
86
  score Int
76
- event ExamPassed
77
- score Int
78
- event ExamFailed
79
- constraint OneResultPerAttempt
80
- unique event ExamPassed
81
- unique event ExamFailed
82
87
  specification TranslatingAPass
83
88
  when capture ProctorResults
84
89
  reference = "7e9d1c2b-4a3f-4e5d-8c6b-1a2b3c4d5e06"
@@ -91,18 +96,7 @@ module Exams
91
96
  then ExamPassed
92
97
  for "7e9d1c2b-4a3f-4e5d-8c6b-1a2b3c4d5e06"
93
98
  score = 87
94
- specification RefusingASecondResult
95
- given ExamPassed
96
- for "7e9d1c2b-4a3f-4e5d-8c6b-1a2b3c4d5e06"
97
- score = 87
98
- when append ProctorResultReceived
99
- for "7e9d1c2b-4a3f-4e5d-8c6b-1a2b3c4d5e06"
100
- outcome = "failed"
101
- score = 40
102
- then error "Constraint 'OneResultPerAttempt' is violated: the event source already has the constrained event."
103
-
104
- slice Automation TranslateProctorResults
105
- description "Our facts from the provider's: the translators react to the external fact the Translate slice records"
99
+ slice Automation RecordExamResult
106
100
  reaction PassTranslator
107
101
  when ProctorResultReceived
108
102
  outcome
@@ -115,11 +109,33 @@ module Exams
115
109
  outcome
116
110
  produces ExamFailed
117
111
  where outcome == "failed"
112
+ event ExamPassed
113
+ score Int
114
+ event ExamFailed
115
+ constraint OneResultPerAttempt
116
+ unique event ExamPassed
117
+ unique event ExamFailed
118
+ specification RefusingASecondResult
119
+ given ExamPassed
120
+ for "7e9d1c2b-4a3f-4e5d-8c6b-1a2b3c4d5e06"
121
+ score = 87
122
+ when append ProctorResultReceived
123
+ for "7e9d1c2b-4a3f-4e5d-8c6b-1a2b3c4d5e06"
124
+ outcome = "failed"
125
+ score = 40
126
+ then error "Constraint 'OneResultPerAttempt' is violated: the event source already has the constrained event."
118
127
  ```
119
128
 
120
- Notes for the reader:
129
+ ## Notes for the reader
121
130
 
122
- - A capture and the external fact it appends stay in the `Translate` slice; the translator reactions that answer that fact sit in an `Automation` slice beside it (a reaction in the capture's own directionless `Translate` slice is `PLAY0694`). `then` lists every new fact, so `TranslatingAPass` names both the external fact and ours.
131
+ - Keep the capture and its appended event in Translate; put reactions to that local
132
+ event in a separate Automation. Co-location in a directionless Translate warns
133
+ PLAY0694 and fails `--warnaserror`; explicit inbound refuses it with PLAY0616.
134
+ `then` lists every new fact, so `TranslatingAPass` includes the Automation result.
135
+ - `when added` records first sight; the separate `when outcome` append handles
136
+ later changes. For an update spec, seed the same reference with `given capture`.
137
+ Requires Screenplay 4.175.0 or later (`screenplay --version`); older evaluators
138
+ treat a first record's fields as changed.
123
139
  - The unauthenticated-booking spec needs an explicit `given caller` (empty means no caller);
124
140
  an authorized command exercised without one is PLAY0389 at binding.
125
141
  - Authenticity of the webhook, tenant ownership and a score-correction policy are not in the
@@ -1,5 +1,15 @@
1
1
  # Translation patterns
2
2
 
3
+ ## Contents
4
+
5
+ - 1. Where outside facts may enter
6
+ - 2. Correlation first
7
+ - 3. Two vocabularies
8
+ - 4. Per-field disposition
9
+ - 5. Dedup and ordering
10
+ - 6. Corrections from outside
11
+ - 7. Specifying translations
12
+
3
13
  Complete compiled example: `translate-example.md` (binds as ESM v6; a compiler that stops before v6
4
14
  compiles it but rejects the slice at binding).
5
15
 
@@ -7,8 +17,15 @@ compiles it but rejects the slice at binding).
7
17
  Only two routes, both in a `Translate` slice:
8
18
  - **`capture`** over a source (api poll, webhook, message topic): key, map, conditional
9
19
  appends. Change detection compares each record with the last one seen for the same key.
10
- - **translator `reaction`** over an event imported from another context (unquoted
11
- `import Context.Event`) or over the external fact a capture appended.
20
+ - **translator `reaction`** over a foreign public event declared with its origin.
21
+ Opaque unquoted imports do not bind. A reaction to a local event a capture
22
+ appended is a follow-up Automation in a separate slice, not another translation.
23
+
24
+ A directionless Translate with an unrouted reaction to its own capture's appends
25
+ (including children/nested) warns PLAY0694 and fails `--warnaserror`; explicitly
26
+ inbound local-event consumption is PLAY0616. Keep the capture in Translate and
27
+ choose a separate Automation slice and its specs; there is no automatic repair.
28
+ Requires Screenplay 4.176.0 or later (`screenplay --version`) for PLAY0694; older compilers leave the directionless shape unchecked.
12
29
  Not a translation: our own event-to-event follow-up (Automation), infrastructure plumbing,
13
30
  and raw database row changes published as-is.
14
31
 
@@ -25,8 +42,8 @@ thing by it. Keep it as a property when it is needed to correlate or deduplicate
25
42
  ## 3. Two vocabularies
26
43
  - The capture appends an **external fact** in the provider's terms (`ProctorResultReceived`
27
44
  with a translated `outcome`).
28
- - Translator reactions record **our facts** in business terms (`ExamPassed`, `ExamFailed`),
29
- each guarded by our constraints.
45
+ - Reactions to that local fact record further **our facts** (`ExamPassed`, `ExamFailed`)
46
+ in a separate Automation slice, each guarded by our constraints.
30
47
  - A further worker needs a distinct local decision, obligation or external effect; otherwise
31
48
  project views from our fact directly.
32
49
  - Name our facts for what they mean to us, not for the transport (`<X>Synced`,
@@ -78,11 +95,17 @@ is a new fact for us (`ResultCorrected`), never an overwrite. Mutually exclusive
78
95
  event with `released by` or a separate correction flow is right.
79
96
 
80
97
  ## 7. Specifying translations
81
- - `when capture <Capture>` with record fields (as the source names them) -> `then` the
82
- external fact and, under v6, what translator reactions appended (`then` lists every new
83
- fact).
84
- - `given capture` for the previous record when a condition compares (`from … to …`,
85
- unchanged redelivery).
86
- - `when append <ExternalFact>` -> `then <OurFact>` to test a translator reaction alone.
87
- - Case list: `cases-to-specify.md`. These forms parse (probed in
88
- `translate-example.md`) but are not executed by any local engine.
98
+ - Record sources: `when capture <Capture>` with source fields -> `then` every new
99
+ fact, including follow-up Automation appends. A first record of a key is added
100
+ only: use a separate `when added` append for first sight, keeping the field guard
101
+ for updates. Seed updates with `given capture` of the same key. Child/nested
102
+ additions follow the same rule; expressions, maps and unguarded appends are unchanged.
103
+ Requires Screenplay 4.175.0 or later (`screenplay --version`); older evaluators
104
+ treat first-record fields as changed.
105
+ - Event sources: `given <FromEvent>` / `when append <FromEvent>`, never capture
106
+ records (PLAY0701). The key is required on every source event (PLAY0700).
107
+ Read [public event captures](public-events-and-direction.md) for executable examples,
108
+ overlay semantics and their prerequisite.
109
+ - `when append <LocalFact>` -> `then <OurFact>` tests the follow-up Automation alone.
110
+ - Run admitted cases with `screenplay test <model>`; all selected specs must pass.
111
+ Case list: `cases-to-specify.md`.
@@ -26,30 +26,22 @@ Language claims follow Screenplay `reactions.md`, `triggers.md`, `captures.md` a
26
26
  `Documentation/reference/reaction-rendering.md`. Tool versions are covered in toolchain
27
27
  `SKILL.md`; run the examples at the pinned standalone tool before relying on them.
28
28
 
29
- ⚠️ **Which tool admits them depends on its Screenplay version.** The ESM level
30
- decides, not the slice type:
31
-
32
- - **A compiler that admits ESM v6 and v7:** `Automation` and
33
- `Translate` slices, reactions, declared triggers and captures bind, and the
34
- reference runner executes them. The complete example below is
35
- `executableReady` over `screenplay mcp`.
36
- - **A compiler that stops before ESM v6** refuses them and falsely reports PLAY0285
37
- (toolchain `references/diagnostics.md`).
29
+ The compiler's ESM admission decides, not the slice type. Reactions, triggers and
30
+ captures bind/reference-execute from v6; older compilers refuse them. Read toolchain
31
+ `references/diagnostics.md` when diagnosing skew or false PLAY0285 cascades.
38
32
  - **The CLI and Stage** render supported event-triggered Automation, not
39
33
  Translate/captures, non-event triggers or opaque bodies (`-024`). Role/authenticated `runs as`
40
34
  and semantic `from` render; claim/opaque gates, mixed effects and unsupported mappings remain refused;
41
35
  cascade specs remain `-011`. Keep refused scope as gap-fill. Full boundary and source
42
36
  citations: `cratis-stage-rendering-and-sandbox` `references/admission.md`.
43
37
 
44
- Model them whenever the `.play` file is the deliverable, and say which tool bound
45
- them (`cratis-screenplay-toolchain` `references/diagnostics.md` for messages).
46
- Method (the four-part automation test, loops, translations versus automations):
47
- `cratis-screenplay-automations-and-translations`.
38
+ Name the binding tool. For the automation test, loops and translation boundaries,
39
+ read `cratis-screenplay-automations-and-translations`.
48
40
 
49
41
  ## Public boundaries and observer selection
50
42
 
51
43
  Read [ESM v9 translation](../cratis-screenplay-automations-and-translations/references/public-events-and-direction.md)
52
- for `direction`, `source events`/`from`, and its typed Unsupported evaluation.
44
+ for `direction`, `source events`/`from`, typed event fixtures and per-key state folds.
53
45
  One `source events` capture consumes events from exactly one origin (event store).
54
46
  Split inputs from several external systems into one capture per origin; otherwise
55
47
  PLAY0687 reports an error, matching Chronicle's one-inbox-observer boundary.
@@ -60,12 +52,31 @@ for reaction/reducer `from Source[.Stream]`; unrouted facts never match.
60
52
 
61
53
  ## Specify what sets them off
62
54
 
63
- A specification names what sets the automation off: `when clock`, `when trigger`
64
- or `when capture`. Execute admitted scenarios through `screenplay test` or MCP
65
- `run-specifications`; source compilation alone is only authored evidence.
55
+ A specification names its input: `when clock` or `when trigger` for an automation,
56
+ `when capture` for a record source, and `when append <ForeignEvent>` for a capture
57
+ with `source events`. Seed the latter with `given <ForeignEvent>`, never `given capture`
58
+ or `when capture` (PLAY0701). Its key must be a required property of every `from`
59
+ event, never `$eventSourceId` or another context key (PLAY0700).
60
+
61
+ Requires Screenplay 4.171.0 or later (`screenplay --version`) for reference execution of captures over events and PLAY0700/0701; older tools leave event delivery unexecuted.
62
+
63
+ First sight is `added` only, not a field change. Read
64
+ [record capture specifications](references/record-capture-specifications.md) when
65
+ specifying first sight, updates, child/nested additions or unchanged records.
66
+ Execute admitted scenarios through `screenplay test` or MCP `run-specifications`;
67
+ source compilation alone is only authored evidence.
66
68
 
67
69
  Read [references/specifying-triggers-and-clock.md](references/specifying-triggers-and-clock.md) when writing a specification for a reaction, trigger or capture, or when the clock, occurrence or limit rules matter.
68
70
 
71
+ ## Atomic batches and event-source mappings
72
+
73
+ Start new models with application-root `reaction batches atomic`. One trigger's direct
74
+ productions, or one selected refusal branch, append all-or-none; invoked commands stay
75
+ separate. Legacy models without opt-in retain per-fact appends even at newer versions.
76
+ Read [atomic batches and source mappings](references/atomic-batches-and-source-mappings.md)
77
+ for batch failure assertions, PLAY0693, Stage STAGE-ESM-016/043 refusals and
78
+ `invokes` mappings from `$eventSourceId` / `$eventContext.eventSourceId`.
79
+
69
80
  ## Caller-less invokes and unprotected reads
70
81
 
71
82
  **Who is the caller of an `invokes`?** Without a declared actor, nobody.
@@ -90,7 +101,10 @@ ESM v6 the binder refuses to treat it as one: a trigger with `reads` that **prod
90
101
  directly**, or whose effect is an opaque body (`file` or an inline block), fails
91
102
  binding, because its decision dependency cannot be protected. A reaction that only
92
103
  `invokes` a command binds, and the decision, and any protection, belong to that
93
- command's own reads. Command `reads` give none yet either (`PLAY0271`).
104
+ command's own reads. Eligible command reads protect under application-root
105
+ `command reads protected` (ESM v25); legacy reads retain PLAY0271. Read command-surface
106
+ [protected reads](../cratis-screenplay-command-surface/references/protected-reads.md)
107
+ for admission and absence/conflict behavior. Stage admits v25 but refuses protected reads with STAGE-ESM-044.
94
108
  `where` over read paths out of scope, and `where` needs
95
109
  every operand to resolve from the trigger's declared scalar occurrence shape (listed in
96
110
  the input selection or not; nested paths and read aliases fail binding): keep the logic that uses the state in
@@ -123,25 +137,13 @@ The full capture excerpt (`source`, `key`, `map` with `translate`, two `append`
123
137
 
124
138
  Read [references/capture-map-and-example.md](references/capture-map-and-example.md) when writing a capture's `map` block, or when you need the excerpt of a capture with `append` and `children`.
125
139
 
126
- **`source <kind>`** takes free-form settings, so a typo is not caught; **`key <property>`** is required to bind (`PLAY0268`); **`append <Event>`** takes one `when` clause, and `or` and `and` cannot be mixed in one clause (split into two `append` blocks). Read [references/capture-map-and-example.md](references/capture-map-and-example.md) for source kinds, `key` and specification behavior, the `when` forms table, `children` and `nested`.
140
+ **`source <kind>`** takes free-form settings, so a typo is not caught; **`key <property>`** is required to bind (`PLAY0268`); **`append <Event>`** takes at most one `when` clause, and `or` and `and` cannot be mixed in one clause (split into two `append` blocks). Read [references/capture-map-and-example.md](references/capture-map-and-example.md) for source kinds, `key` and specification behavior, the `when` forms table, `children` and `nested`.
127
141
 
128
142
  ## `reaction`
129
143
 
130
- Excerpt; complete document: `references/complete-examples.md`,
131
- "Reaction on a declared trigger with `where` and `invokes`".
132
-
133
- ```screenplay excerpt
134
- slice Automation NotifyOnBuildFailure
135
- reaction NotifyOnFailure
136
- description "Tells the owning team when a watched build fails"
137
- when BuildFinished
138
- repository
139
- outcome
140
- invokes SendFailureNotice
141
- repository = repository
142
- outcome = outcome
143
- where outcome == "failed"
144
- ```
144
+ Read [reaction forms](references/reaction-forms.md) when choosing a trigger,
145
+ selecting occurrence values or mapping `produces` and `invokes`; complete documents
146
+ remain in `references/complete-examples.md`.
145
147
 
146
148
  A reaction declares **at least one trigger**; everything under a trigger is
147
149
  optional.
@@ -152,29 +154,13 @@ under `when`/`every`/`at`. `description`, `where` and `runs as` sit at reaction
152
154
  Outdenting an effect gives *Expected a trigger in reaction body, got 'invokes …'*
153
155
  (`PLAY0137`) — the compiler is looking for another trigger where the effect is.
154
156
 
155
- ### What sets it off
156
-
157
- | Form | Runs |
158
- | --- | --- |
159
- | `when <Name>` | on that event, declared trigger, or registered trigger |
160
- | `every <n> seconds\|minutes\|hours\|days` | on that interval (`n` ≥ 1) |
161
- | `at HH:mm` | every day at that time |
162
- | `at HH:mm on <Weekday>` | every week on that day |
163
- | `at HH:mm on day <n>` | every month on that day (`n` is 1–31) |
164
-
165
- Time is strictly `HH:mm`. Weekday is the full English name.
166
-
167
- ### The values a reaction takes
168
-
169
- A bare name under a trigger says the reaction **uses** that value from the
170
- occurrence. This is a **selection, not a declaration** — the shape belongs to the
171
- event or trigger. Taking a value the occurrence does not carry is reported.
172
-
173
157
  ### `where` — narrowing
174
158
 
175
159
  `where` uses the same condition grammar as `produces … when` and `require`:
176
160
  `==`, `!=`, the ordering operators, `contains` for a substring anywhere,
177
161
  `starts with` for one at the beginning, combined with `and`, `or` and parentheses.
162
+ These text-condition operators parse but refuse executable binding (PLAY0268);
163
+ literal property text rules are a separate v24 contract.
178
164
 
179
165
  ⚠️ **`where` belongs to the reaction, not to one trigger** — it says which
180
166
  occurrences are worth running for, whatever set them off. A second `where` on one
@@ -186,36 +172,16 @@ Inline `produces event <Name>` is command-only (`PLAY0474` in a reaction).
186
172
  Declare reaction-produced events separately and use plain `produces <Name>`.
187
173
  Do not extend the inline command destination default or its repairs to reactions.
188
174
 
189
- Excerpt; complete document: `references/complete-examples.md`,
190
- "Reaction with `produces` and `invokes`":
191
-
192
- ```screenplay excerpt
193
- reaction Provisioner
194
- when InvitationAccepted
195
- workspaceId
196
- produces WorkspaceProvisioned
197
- for workspaceId
198
- workspaceId = workspaceId
199
- invokes SendWelcomeMail
200
- workspaceId = workspaceId
201
- template = "welcome"
202
- ```
203
-
204
175
  A `produces` without `for` appends to the event source of the event that set the
205
176
  reaction off. A clock, application or built-in trigger has no such event, so what it
206
177
  produces needs `for` - a value the trigger carries, or literal text.
207
178
 
208
- **The different word is the point.** `produces` requests a fact append, subject to
209
- append-time constraints. `invokes` asks for a command, which additionally runs the
210
- command's authorization, validation and requirements, and may reject.
211
- Using `produces` for both would say those are the same kind of consequence.
179
+ `produces` requests an append; `invokes` also runs command gates and may reject.
212
180
 
213
181
  **Who is the caller of an `invokes`?** Nobody unless `runs as` declares the actor; see *Caller-less invokes and unprotected reads* above before writing one.
214
182
 
215
- Both are declarations of *what happens*, not of how — a trigger can state its
216
- consequences **and** carry a `file` or an inline block in a tagged fence
217
- (` ```csharp `) that implements them. That code is an implementation attachment:
218
- the model lists it (role, owner, content hash) but never runs it.
183
+ Trigger `file`/tagged-code attachments are inventoried, never reference-executed;
184
+ see the reaction forms reference for their boundary.
219
185
 
220
186
  ### What it decides from — trigger `reads`
221
187
 
@@ -237,11 +203,15 @@ Read [references/trigger-reads-example.md](references/trigger-reads-example.md)
237
203
 
238
204
  A `trigger` declares that a name exists and what an occurrence hands the reaction, never what makes it occur. Built-ins are `Startup` and `Shutdown`. An unknown name warns `PLAY0248`; **An application trigger is not a UI event** (`PLAY0326`); under a reaction trigger, values named `description`, `file`, `produces`, `invokes` or `reads` are written with `@`. Read [references/trigger-declaration.md](references/trigger-declaration.md) when declaring or registering a trigger or resolving a trigger name.
239
205
 
240
- ## Guidance, verbatim
206
+ ## Slice boundaries
207
+
208
+ Requires Screenplay 4.176.0 or later (`screenplay --version`) for PLAY0694; older compilers leave directionless capture-follow-up co-location unchecked.
241
209
 
242
- > - Reactions that only translate events into other events belong in `Translate`
243
- > slices when driven by external data (captures); event-to-event automation stays
244
- > in `Automation` slices.
210
+ > - A capture belongs in `Translate`; a reaction to the local event it appends
211
+ > belongs in a separate `Automation` slice. A directionless Translate containing
212
+ > both warns PLAY0694 (fails `--warnaserror`); explicit inbound refuses it with
213
+ > PLAY0616. A reaction translating a foreign public event can belong in inbound
214
+ > Translate.
245
215
  > - Keep reaction logic small; anything substantial belongs in a `file` reference
246
216
  > where it can be tested on its own.
247
217
  > - Describe the reaction before you implement it — a document full of `file` lines
@@ -267,8 +237,8 @@ A `trigger` declares that a name exists and what an occurrence hands the reactio
267
237
  - [ ] Every name a reaction takes is carried by the event or trigger.
268
238
  - [ ] Each trigger `reads` the views its automation decides from; `by` names a
269
239
  value the trigger takes, and clock triggers read without `by`.
270
- - [ ] Nobody reports trigger or command `reads` as protected; UI clicks are
271
- interactions, not triggers.
240
+ - [ ] Trigger reads are not protection; protected command reads require opt-in,
241
+ admission and separate target realization. UI clicks are interactions.
272
242
  - [ ] Every gated invocation declares its trusted actor with reaction `runs as`
273
243
  (ESM v10) or records the target gap explicitly; `given caller` is not that actor.
274
244
 
@@ -0,0 +1,83 @@
1
+ <!-- Copyright (c) Cratis. All rights reserved. -->
2
+ <!-- Licensed under the MIT license. See LICENSE file in the project root for full license information. -->
3
+
4
+ # Atomic reaction batches and event-source invocation mappings
5
+
6
+ ## Choose the batch boundary
7
+
8
+ Requires Screenplay 4.181.0 or later (`screenplay --version`) for atomic batches; older compilers cannot admit the declaration.
9
+
10
+ Start new models with application-root `reaction batches atomic`, before declarations.
11
+ Declare it once per composed application; imports inherit it. It selects ESM v22 or
12
+ later even before the first reaction. Duplicate, conflicting or invalid declarations
13
+ report PLAY0693. Do not automatically repair by removing it: that changes semantics.
14
+
15
+ One trigger occurrence's direct `produces` list is one all-or-none batch. Each selected
16
+ invocation-refusal branch's productions form another batch. Invoked commands retain
17
+ their own atomic appends; neither separate triggers nor occurrences are combined.
18
+ This is not a transaction around the cascade.
19
+
20
+ Candidates are materialized and append-validated before private projections and
21
+ publications. Primary facts are adopted first, then derived publications; only adopted
22
+ facts start cascades. The complete expanded result must fit the 1,000-new-fact budget
23
+ before adoption; given history does not count. A failed batch leaves its pre-batch
24
+ facts, read models and pending children unchanged. Earlier accepted batches/commands
25
+ remain. Violation order is authored production order, then ordinal constraint name;
26
+ SemanticRejected.Production carries the zero-based index, event contract and route.
27
+ Property-value reservations within a batch are not freed when a source changes value;
28
+ the same source may repeat its own claim.
29
+
30
+ Without the preamble, per-fact production remains legacy behavior, even at a higher
31
+ ESM version. Recompiling never opts an existing model in. Review migration explicitly.
32
+ Atomic batching does not admit direct-production stream routes or closing constraints,
33
+ deduplicate redelivery, promise atomic observer snapshots or resolve unknown storage
34
+ outcomes. `then error` alone is insufficient: also assert no facts from the failed
35
+ batch and unchanged read models with evaluator world/read-model assertions; earlier
36
+ accepted work can remain. `then no events` means accepted zero outcomes and cannot
37
+ accompany `then error`. Do not invent a mixed success/error specification form.
38
+
39
+ Stage refuses ESM v22 with STAGE-ESM-016. Even an admitted v23–v25 model carrying
40
+ atomic mode is refused with STAGE-ESM-043 by renderer, Host and specification executor.
41
+ Keep the declaration and report authorized gap-fill; do not promise a render date or
42
+ strip atomicity to lower the version.
43
+
44
+ MCP `describe-application` reports `reactionProductionMode` and
45
+ `reactionProductionReadiness`; ApplicationSyntax.reactionProductionMode is Atomic.
46
+ Source/AST proposals preserve it; readiness is not target realization.
47
+
48
+ ## Map the triggering event source
49
+
50
+ Requires Screenplay 4.197.1 or later (`screenplay --version`) for event-source `invokes` mappings; older compilers refuse them with PLAY0268.
51
+
52
+ Use context identity rather than duplicating an event source in event payload.
53
+ Complete model (atomic mode deliberately retained despite Stage's refusal):
54
+
55
+ ```screenplay
56
+ domain Orders
57
+ reaction batches atomic
58
+ module Fulfillment
59
+ feature Packing
60
+ slice StateChange PackOrder
61
+ command PackOrder
62
+ orderId String identifier
63
+ produces OrderPacked
64
+ for orderId
65
+ event OrderPacked
66
+ slice Automation PackPlacedOrder
67
+ event OrderPlaced
68
+ reaction PackPlacedOrder
69
+ when OrderPlaced
70
+ invokes PackOrder
71
+ orderId = $eventSourceId
72
+ ```
73
+
74
+ `$eventContext.eventSourceId` is equivalent. The source also works in reaction
75
+ `produces` mappings. The target must be a required scalar; reference execution checks
76
+ the value against that target type without conversion. Clock/application triggers
77
+ have no event source. This is neither clock context nor caller/audit identity and
78
+ does not select a new ESM version: it uses the reaction v6 mapping contract.
79
+ Keep authorization and a trusted reaction `runs as` where the invoked command is gated.
80
+
81
+ Run `screenplay <root> --warnaserror` and `screenplay test <root>`; expect source
82
+ validation and admitted scenarios to pass separately. A Stage refusal remains a
83
+ separate result even when both Screenplay checks pass.
@@ -49,10 +49,13 @@ convention, not enforcement. `source events` (`from <Event>` lines, ESM v9) is t
49
49
  its own closed grammar (PLAY0610/0612/0616/0619/0620).
50
50
 
51
51
  **`key <property>`** names the source property identifying an instance. From ESM v6
52
- a capture without a `key` does not bind (`PLAY0268`). In a specification the
52
+ a capture without a `key` does not bind (`PLAY0268`). For record sources the
53
53
  reference is handed records (`given capture`, `when capture`) and never contacts a
54
- `source`, which stays realization metadata; events append to the event source the
55
- record's `key` names, and `$context.occurred` is the scenario's `given clock`.
54
+ `source`, which stays realization metadata. For `source events`, present a declared
55
+ `from` event with `given <Event>` / `when append <Event>` (PLAY0701 otherwise);
56
+ `key` must be a required property of every source event, not a context key
57
+ (PLAY0700). Events append to the event source the key names, and
58
+ `$context.occurred` is supplied by the scenario's `given clock`.
56
59
 
57
60
  An event's external origin is declared on the `event` itself with `event X from "<origin>"` (ESM v9);
58
61
  outside records still enter through a `capture` in a `Translate` slice
@@ -60,7 +63,14 @@ outside records still enter through a `capture` in a `Translate` slice
60
63
 
61
64
  **`map`** reshapes properties before events are appended (rename, template, `translate`, `split`; mapping sources are `$.`, `$context.` and `$env.`); syntax is in the reference file linked above.
62
65
 
63
- **`append <Event>`** with optional `tag` lines and one `when` clause:
66
+ **First observation is added only**, at root, child and nested levels. Field-change
67
+ and transition guards need a previous record of the same key (`given capture`), or
68
+ earlier typed events for `source events`. Use a separate `when added` append for
69
+ first sight; keep the field guard for updates. Maps, expression guards and unguarded
70
+ record appends are unchanged. Complete runnable record cases:
71
+ [record-capture-specifications.md](record-capture-specifications.md).
72
+
73
+ **`append <Event>`** takes optional `tag` lines and at most one `when` clause:
64
74
 
65
75
  | `when` form | Appends when |
66
76
  | --- | --- |
@@ -0,0 +1,59 @@
1
+ <!-- Copyright (c) Cratis. All rights reserved. -->
2
+ <!-- Licensed under the MIT license. See LICENSE file in the project root for full license information. -->
3
+
4
+ # Reaction trigger and effect forms
5
+
6
+ Excerpts from `complete-examples.md`: "Reaction on a declared trigger with `where`
7
+ and `invokes`" and "Reaction with `produces` and `invokes`".
8
+
9
+ ```screenplay excerpt
10
+ slice Automation NotifyOnBuildFailure
11
+ reaction NotifyOnFailure
12
+ description "Tells the owning team when a watched build fails"
13
+ when BuildFinished
14
+ repository
15
+ outcome
16
+ invokes SendFailureNotice
17
+ repository = repository
18
+ outcome = outcome
19
+ where outcome == "failed"
20
+ ```
21
+
22
+ | Form | Runs |
23
+ | --- | --- |
24
+ | `when <Name>` | on that event, declared trigger, or registered trigger |
25
+ | `every <n> seconds\|minutes\|hours\|days` | on that interval (`n` ≥ 1) |
26
+ | `at HH:mm` | every day at that time |
27
+ | `at HH:mm on <Weekday>` | every week on that day |
28
+ | `at HH:mm on day <n>` | every month on that day (`n` is 1–31) |
29
+
30
+ Time is strictly `HH:mm`. Weekday is the full English name. A bare name under a
31
+ trigger selects a value from the occurrence; it is not a new declaration. Taking
32
+ a value absent from the event/trigger shape is reported.
33
+
34
+ ```screenplay excerpt
35
+ reaction Provisioner
36
+ when InvitationAccepted
37
+ workspaceId
38
+ produces WorkspaceProvisioned
39
+ for workspaceId
40
+ workspaceId = workspaceId
41
+ invokes SendWelcomeMail
42
+ workspaceId = workspaceId
43
+ template = "welcome"
44
+ ```
45
+
46
+ A `produces` without `for` appends to the source of the triggering event. Clock,
47
+ application and built-in triggers need an explicit destination. Producing requests
48
+ an append subject to constraints; invoking also runs command authorization,
49
+ validation and requirements and may reject. They are not interchangeable.
50
+
51
+ These are declarations, not implementations. A trigger can carry a `file` or
52
+ inline tagged fence beside its consequences; the model inventories role, owner
53
+ and content hash but does not execute that attachment. Stage mixed-effect
54
+ refusals and reference unsupported outcomes remain separate checks.
55
+
56
+ `where` is reaction-level, with only one occurrence allowed; combine conditions
57
+ with `and`/`or`. Its source grammar includes `contains` and `starts with`, but the
58
+ executable binder refuses those operators with PLAY0268. Use the literal property
59
+ rules for validation, not as a way around condition admission.