@cratis/pi 7.61.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 (132) hide show
  1. package/package/corpus/agents/spec-writer.md +2 -2
  2. package/package/corpus/harnesses/copilot/instructions/application-profile.instructions.md +2 -2
  3. package/package/corpus/harnesses/copilot/instructions/glossary.instructions.md +2 -2
  4. package/package/corpus/harnesses/copilot/instructions/specs.scenarios.csharp.instructions.md +7 -4
  5. package/package/corpus/harnesses/copilot/instructions/vertical-slices.instructions.md +22 -13
  6. package/package/corpus/product-sync.json +11 -10
  7. package/package/corpus/prompts/add-business-rule.prompt.md +1 -1
  8. package/package/corpus/rules/application-profile.md +2 -2
  9. package/package/corpus/rules/glossary.md +2 -2
  10. package/package/corpus/rules/specs.scenarios.csharp.md +7 -4
  11. package/package/corpus/rules/vertical-slices.md +22 -13
  12. package/package/corpus/skills/cratis-application-slice-conformance/SKILL.md +1 -1
  13. package/package/corpus/skills/cratis-application-slice-specifications/SKILL.md +4 -3
  14. package/package/corpus/skills/cratis-application-slice-specifications/references/query-and-decision-scenarios.md +12 -3
  15. package/package/corpus/skills/cratis-arc-authentication-authorization-and-identity/SKILL.md +12 -7
  16. package/package/corpus/skills/cratis-arc-authentication-authorization-and-identity/references/authorization.md +11 -11
  17. package/package/corpus/skills/cratis-arc-command/SKILL.md +3 -2
  18. package/package/corpus/skills/cratis-arc-command/references/decisions-and-routing.md +95 -51
  19. package/package/corpus/skills/cratis-arc-command/references/fresh-identifiers.md +5 -2
  20. package/package/corpus/skills/cratis-arc-command/references/generated-values.md +27 -12
  21. package/package/corpus/skills/cratis-arc-command/references/read-model-injection.md +9 -5
  22. package/package/corpus/skills/cratis-arc-command/references/shop-generation.md +17 -6
  23. package/package/corpus/skills/cratis-arc-command-validation/SKILL.md +99 -52
  24. package/package/corpus/skills/cratis-chronicle-decision-reads/SKILL.md +37 -15
  25. package/package/corpus/skills/cratis-chronicle-decision-reads/references/admission-and-ownership.md +3 -2
  26. package/package/corpus/skills/cratis-chronicle-decision-reads/references/choosing-how-a-rule-holds.md +277 -138
  27. package/package/corpus/skills/cratis-chronicle-event-constraints/SKILL.md +4 -4
  28. package/package/corpus/skills/cratis-chronicle-event-modeling/SKILL.md +6 -4
  29. package/package/corpus/skills/cratis-chronicle-read-model/SKILL.md +2 -1
  30. package/package/corpus/skills/cratis-chronicle-reducer/SKILL.md +6 -3
  31. package/package/corpus/skills/cratis-code-review/SKILL.md +6 -3
  32. package/package/corpus/skills/cratis-fundamentals-concept/SKILL.md +10 -2
  33. package/package/corpus/skills/cratis-fundamentals-concept/references/shop-generation.md +49 -6
  34. package/package/corpus/skills/cratis-screenplay-automations-and-translations/SKILL.md +43 -41
  35. package/package/corpus/skills/cratis-screenplay-automations-and-translations/references/cases-to-specify.md +11 -2
  36. package/package/corpus/skills/cratis-screenplay-automations-and-translations/references/integration-interview.md +24 -0
  37. package/package/corpus/skills/cratis-screenplay-automations-and-translations/references/public-events-and-direction.md +76 -10
  38. package/package/corpus/skills/cratis-screenplay-automations-and-translations/references/realization-and-gap-fill.md +5 -0
  39. package/package/corpus/skills/cratis-screenplay-automations-and-translations/references/todo-list-example.md +1 -1
  40. package/package/corpus/skills/cratis-screenplay-automations-and-translations/references/translate-example.md +39 -23
  41. package/package/corpus/skills/cratis-screenplay-automations-and-translations/references/translation-patterns.md +35 -12
  42. package/package/corpus/skills/cratis-screenplay-captures-and-reactions/SKILL.md +51 -81
  43. package/package/corpus/skills/cratis-screenplay-captures-and-reactions/references/atomic-batches-and-source-mappings.md +83 -0
  44. package/package/corpus/skills/cratis-screenplay-captures-and-reactions/references/capture-map-and-example.md +14 -4
  45. package/package/corpus/skills/cratis-screenplay-captures-and-reactions/references/reaction-forms.md +59 -0
  46. package/package/corpus/skills/cratis-screenplay-captures-and-reactions/references/record-capture-specifications.md +60 -0
  47. package/package/corpus/skills/cratis-screenplay-captures-and-reactions/references/specifying-triggers-and-clock.md +5 -1
  48. package/package/corpus/skills/cratis-screenplay-command-surface/SKILL.md +26 -28
  49. package/package/corpus/skills/cratis-screenplay-command-surface/references/described-handlers.md +82 -0
  50. package/package/corpus/skills/cratis-screenplay-command-surface/references/generated-values-and-responses.md +82 -28
  51. package/package/corpus/skills/cratis-screenplay-command-surface/references/protected-reads.md +113 -0
  52. package/package/corpus/skills/cratis-screenplay-command-surface/references/shop-generation.md +45 -12
  53. package/package/corpus/skills/cratis-screenplay-command-surface/references/text-and-match-rules.md +119 -0
  54. package/package/corpus/skills/cratis-screenplay-command-surface/references/validate-rules.md +14 -4
  55. package/package/corpus/skills/cratis-screenplay-command-surface/verification.json +10 -3
  56. package/package/corpus/skills/cratis-screenplay-event-modeling/SKILL.md +12 -12
  57. package/package/corpus/skills/cratis-screenplay-event-modeling/references/parsed-not-runnable.md +5 -3
  58. package/package/corpus/skills/cratis-screenplay-event-modeling/verification.json +5 -1
  59. package/package/corpus/skills/cratis-screenplay-legacy-extraction/SKILL.md +2 -2
  60. package/package/corpus/skills/cratis-screenplay-legacy-extraction/references/evidence-table-template.md +1 -1
  61. package/package/corpus/skills/cratis-screenplay-legacy-extraction/references/generated-recovery.md +51 -14
  62. package/package/corpus/skills/cratis-screenplay-legacy-extraction/references/intent-example.md +5 -0
  63. package/package/corpus/skills/cratis-screenplay-legacy-extraction/references/loss-report-template.md +2 -1
  64. package/package/corpus/skills/cratis-screenplay-legacy-extraction/references/rule-modeling.md +6 -3
  65. package/package/corpus/skills/cratis-screenplay-legacy-extraction/references/signal-to-intent.md +1 -1
  66. package/package/corpus/skills/cratis-screenplay-model-authoring/SKILL.md +22 -28
  67. package/package/corpus/skills/cratis-screenplay-model-authoring/references/choosing-generation.md +20 -7
  68. package/package/corpus/skills/cratis-screenplay-model-authoring/references/language-reference.md +12 -6
  69. package/package/corpus/skills/cratis-screenplay-model-authoring/references/mcp-loop.md +9 -1
  70. package/package/corpus/skills/cratis-screenplay-model-authoring/references/mcp-tools.md +58 -10
  71. package/package/corpus/skills/cratis-screenplay-model-authoring/verification.json +4 -2
  72. package/package/corpus/skills/cratis-screenplay-model-review/SKILL.md +2 -5
  73. package/package/corpus/skills/cratis-screenplay-model-review/references/anti-patterns.md +2 -2
  74. package/package/corpus/skills/cratis-screenplay-model-review/references/checklist.md +2 -2
  75. package/package/corpus/skills/cratis-screenplay-model-review/references/quick-self-check.md +2 -1
  76. package/package/corpus/skills/cratis-screenplay-model-review/references/review-questions.md +3 -2
  77. package/package/corpus/skills/cratis-screenplay-modeling-lifecycle/references/principles.md +1 -1
  78. package/package/corpus/skills/cratis-screenplay-modeling-lifecycle/references/vocabulary-map.md +1 -1
  79. package/package/corpus/skills/cratis-screenplay-read-surface/SKILL.md +2 -3
  80. package/package/corpus/skills/cratis-screenplay-read-surface/references/named-keys.md +3 -1
  81. package/package/corpus/skills/cratis-screenplay-render-and-gap-fill/SKILL.md +8 -3
  82. package/package/corpus/skills/cratis-screenplay-render-and-gap-fill/references/gap-fill-handoff.md +8 -0
  83. package/package/corpus/skills/cratis-screenplay-render-and-gap-fill/references/renderability-gate.md +6 -4
  84. package/package/corpus/skills/cratis-screenplay-scenario-coverage/SKILL.md +36 -29
  85. package/package/corpus/skills/cratis-screenplay-scenario-coverage/references/berth-reservations.md +6 -0
  86. package/package/corpus/skills/cratis-screenplay-scenario-coverage/references/invoicing-dues-design.md +15 -4
  87. package/package/corpus/skills/cratis-screenplay-scenario-coverage/references/invoicing-dues-example.md +25 -20
  88. package/package/corpus/skills/cratis-screenplay-scenario-coverage/references/public-event-coverage.md +14 -3
  89. package/package/corpus/skills/cratis-screenplay-scenario-coverage/references/scenario-examples.md +9 -3
  90. package/package/corpus/skills/cratis-screenplay-scenario-coverage/references/spec-forms-by-mode.md +7 -3
  91. package/package/corpus/skills/cratis-screenplay-slice-design/SKILL.md +3 -1
  92. package/package/corpus/skills/cratis-screenplay-slice-design/references/command-inventory.md +4 -4
  93. package/package/corpus/skills/cratis-screenplay-slice-design/references/rule-layers.md +4 -2
  94. package/package/corpus/skills/cratis-screenplay-slice-design/references/slicing.md +4 -3
  95. package/package/corpus/skills/cratis-screenplay-slice-design/references/worked-example.md +8 -8
  96. package/package/corpus/skills/cratis-screenplay-specifications/SKILL.md +49 -47
  97. package/package/corpus/skills/cratis-screenplay-specifications/references/actions-beyond-commands.md +11 -1
  98. package/package/corpus/skills/cratis-screenplay-specifications/references/generated-fixtures.md +48 -17
  99. package/package/corpus/skills/cratis-screenplay-specifications/references/vocabulary.md +14 -1
  100. package/package/corpus/skills/cratis-screenplay-streams-and-consistency/SKILL.md +25 -21
  101. package/package/corpus/skills/cratis-screenplay-streams-and-consistency/references/boundaries.md +2 -2
  102. package/package/corpus/skills/cratis-screenplay-streams-and-consistency/references/consistency-and-concurrency.md +14 -6
  103. package/package/corpus/skills/cratis-screenplay-streams-and-consistency/references/multi-service-models.md +4 -3
  104. package/package/corpus/skills/cratis-screenplay-streams-and-consistency/references/streams-example.md +7 -0
  105. package/package/corpus/skills/cratis-screenplay-toolchain/SKILL.md +30 -22
  106. package/package/corpus/skills/cratis-screenplay-toolchain/references/cheat-sheet-example.md +3 -1
  107. package/package/corpus/skills/cratis-screenplay-toolchain/references/cheat-sheet.md +47 -2
  108. package/package/corpus/skills/cratis-screenplay-toolchain/references/diagnostic-arguments.md +60 -0
  109. package/package/corpus/skills/cratis-screenplay-toolchain/references/diagnostics.md +65 -5
  110. package/package/corpus/skills/cratis-screenplay-toolchain/references/executable-subset.md +50 -22
  111. package/package/corpus/skills/cratis-screenplay-toolchain/references/generation-checks.md +93 -0
  112. package/package/corpus/skills/cratis-screenplay-toolchain/references/generation-strategies-example.md +117 -35
  113. package/package/corpus/skills/cratis-screenplay-toolchain/references/language-admission.md +46 -0
  114. package/package/corpus/skills/cratis-screenplay-toolchain/references/preferred-syntax.md +3 -1
  115. package/package/corpus/skills/cratis-screenplay-toolchain/references/renderable-subset.md +25 -10
  116. package/package/corpus/skills/cratis-screenplay-toolchain/references/screenplay-contract.json +1800 -50
  117. package/package/corpus/skills/cratis-screenplay-toolchain/references/screenplay-contract.version +1 -1
  118. package/package/corpus/skills/cratis-screenplay-toolchain/references/traps.md +5 -3
  119. package/package/corpus/skills/cratis-screenplay-toolchain/verification.json +6 -1
  120. package/package/corpus/skills/cratis-screenplay-ui-composition/SKILL.md +8 -53
  121. package/package/corpus/skills/cratis-screenplay-ui-composition/references/file-references.md +2 -2
  122. package/package/corpus/skills/cratis-screenplay-ui-composition/references/interaction-example.md +54 -0
  123. package/package/corpus/skills/cratis-screenplay-ui-composition/verification.json +6 -3
  124. package/package/corpus/skills/cratis-specifications-csharp/SKILL.md +3 -2
  125. package/package/corpus/skills/cratis-specifications-csharp/references/application-scenarios.md +1 -1
  126. package/package/corpus/skills/cratis-stage-rendering-and-sandbox/SKILL.md +30 -29
  127. package/package/corpus/skills/cratis-stage-rendering-and-sandbox/references/admission.md +36 -9
  128. package/package/corpus/skills/cratis-stage-rendering-and-sandbox/references/choosing-generation.md +28 -8
  129. package/package/corpus/skills/cratis-stage-rendering-and-sandbox/references/publication-and-recovery.md +31 -0
  130. package/package/corpus/skills/cratis-stage-rendering-and-sandbox/references/sandbox-and-specrunner.md +8 -0
  131. package/package/corpus/skills/cratis-stage-rendering-and-sandbox/verification.json +4 -1
  132. package/package.json +1 -1
@@ -4,9 +4,20 @@ Coverage for public events and routed producers.
4
4
 
5
5
  Outbound publication needs `when append <private>` and `then <PublicEvent>`:
6
6
  complete state, incomplete state, unchanged repeat, changed instance, separate
7
- source ids and the exported field boundary. Reference publication is executable;
8
- source-event captures and reached opaque event-target reducers are typed
9
- Unsupported. Read automations-and-translations `references/public-events-and-direction.md`.
7
+ source ids and the exported field boundary. Reference publication and admitted
8
+ source-event captures execute; reached opaque event-target reducers remain typed
9
+ Unsupported. Read automations-and-translations `references/public-events-and-direction.md`
10
+ for the prerequisite and complete typed capture specifications.
11
+
12
+ For `source events`, use `given <FromEvent>` / `when append <FromEvent>`, not
13
+ `given capture` / `when capture` (PLAY0701). Cover first added, unchanged overlays,
14
+ updates after ordered givens, properties retained across different event types,
15
+ and independent keys. The key must be required on every source event, not a
16
+ context key (PLAY0700); optional foreign fixture `for` is not that key.
17
+ Assertions list all follow-up facts, never the input append itself. Mixed capture
18
+ and reaction expectations may need `then events in any order`; this is not proof
19
+ of observer order or redelivery deduplication. Children/nested over events and
20
+ context members other than `occurred` are not admitted execution.
10
21
  For routed producers/observers, cover override versus inherited route, skipped
11
22
  production route failure, matching/wrong source/stream and unrouted facts;
12
23
  see toolchain `references/production-routes-and-filters.md`.
@@ -15,8 +15,10 @@ easily. Every excerpt below is copied verbatim from the complete document in
15
15
  `invoicing-dues-example.md`, which compiles with warnings as errors and whose 23 specifications
16
16
  pass in the reference evaluator; it also holds the declarations the excerpts depend on. The two
17
17
  compensation excerpts in section 4 come from `invoicing-dues-design.md` instead: that document
18
- holds the stored-state rules (`reads` + `require`), compiles but does not bind (PLAY0271,
19
- PLAY0268), so its specifications are design mode and do not run. A second
18
+ holds stored-state rules as a legacy control without `command reads protected`, so
19
+ it compiles but does not bind (PLAY0271/PLAY0268) and its design specs do not run.
20
+ Eligible reads can instead opt into v25; inspect admission and keep Stage refusal
21
+ separate (command-surface [protected reads](../../cratis-screenplay-command-surface/references/protected-reads.md)). A second
20
22
  complete example, with competing claims and denial fixtures, is `berth-reservations.md`. The category structure and the good/bad contrast follow the worked
21
23
  examples in `eventmodeling-elaborating-scenarios` by TrogonStack and by Martin Dilger and Nebulit GmbH (`provenance.md`), translated to
22
24
  Screenplay specifications.
@@ -104,7 +106,11 @@ in `invoicing-dues-design.md`; it is never prose and never a spec that pretends
104
106
  ## 3. External failure: the capture, then the retry
105
107
  Two separate obligations. First, the **capture specification**: concrete external input in, our
106
108
  facts out. The provider's refusal is a fact (never a `then error`), kept in the provider's
107
- vocabulary and then translated.
109
+ vocabulary; a separate Automation records the local outcome. The capture uses
110
+ `when added` for first sight and a separate `when outcome` for updates. An update
111
+ spec needs `given capture` with the same key's earlier record; the first record's
112
+ fields are not modifications (root, child or nested). See captures-and-reactions
113
+ `references/record-capture-specifications.md` for runnable first/update/repeat cases.
108
114
  ```screenplay excerpt parent=references/invoicing-dues-example.md#1
109
115
  specification TranslatingADeclinedCardResult
110
116
  when capture PaymentGatewayResults
@@ -21,7 +21,8 @@ Typed example/override forms: `cratis-screenplay-specifications`
21
21
  | Context `from`, single-result filters, `scoped to`, `performer` or composite `by` | yes | PLAY0268: query context, collection-only filtering, opaque scope/implementation or multipart lookup are unadmitted | no |
22
22
  | `then no readmodel <RM> for "<key>"` | yes | yes | no |
23
23
  | `when query` -> `then result` / `then no result` | yes | yes | same as `then query`: only the query-only cases below |
24
- | `given clock` / `when clock`, `when trigger`, `given`/`when capture` | yes | yes (standalone and any cratis whose compiler admits v6; an older bundle does not, see toolchain `references/executable-subset.md`) | no |
24
+ | `given clock` / `when clock`, `when trigger`, record-source `given`/`when capture` | yes | yes (standalone and any cratis whose compiler admits v6; an older bundle does not, see toolchain `references/executable-subset.md`) | no |
25
+ | Event-source capture fixtures | `given <FromEvent>` / `when append <FromEvent>`, not capture records (PLAY0701) | admitted root capture behavior executes; see `public-event-coverage.md` for prerequisites and limits | separate target admission |
25
26
  | Command spec listing reaction cascade events | yes (v6 semantics) | false PLAY0285 on an older cratis bundle only; see SKILL.md "Version skew" | no: STAGE-ESM-011; generated CommandScenario does not settle reactions |
26
27
  | `generated <name> = <value>` under `when`, `then returns` (ESM v7) | yes | yes on a compiler that admits v7 (PLAY0268 on an older bundle) | yes on Stage for supported UUID/String strategies and v15 freshness and scalar/named responses; unsupported types/combinations remain -028/-038 |
27
28
  | v15 generation strategy fixtures and used-source rejection | yes | strict encoding/size/case/version/variant; Contract for invalid pins, Concurrency for reused source | supported strategies/freshness render; invalid pins refuse -011, unpinned unordered/projected assertions -038; source: command-surface `references/generated-values-and-responses.md` |
@@ -35,7 +36,10 @@ Typed example/override forms: `cratis-screenplay-specifications`
35
36
  | Composite (JSON) values in specs | yes | yes | no |
36
37
  | Rules over dates or `today`, nested paths | spec them in design | rule does not bind: `recorded` | `recorded` |
37
38
  | Bodied rules, code policies | spec them | spec reported **unsupported**, never passed | no |
38
- | Command handlers, `file` constraints, query `performer`s | spec them in design | blocked: PLAY0268 at binding, no spec runs (V3 blocked) | no |
39
+ | Pending described command handlers (v23) | specify intent | binds; denial/validation execute, body-reaching specs Unsupported ImplementationBody; all-Unsupported is not green | STAGE-IMPL-002 even Stub mode |
40
+ | Attached command handlers, `file` constraints, query `performer`s | spec them in design | blocked: PLAY0268 at binding, no spec runs (V3 blocked) | no |
41
+ | Atomic reaction mode (v22) | declare for new models | failed batch adds no facts or view changes; earlier batches/commands remain; `then error` alone is insufficient | v22 STAGE-ESM-016; mode in admitted v23–v25 STAGE-ESM-043 |
42
+ | Protected command reads (v25) | declare opt-in for eligible reads | absence Validation; matching intervening facts Conflict; race vectors are not a new spec construct | protected reads STAGE-ESM-044; v25 pair admitted |
39
43
 
40
44
  Requires Screenplay 4.105.0 or later (`screenplay --version`) for list-query specifications, and 4.143.0 or later for collection equality filters (ESM v14).
41
45
 
@@ -49,7 +53,7 @@ older cratis bundle is available). Mark each such spec in the coverage matrix as
49
53
  `gap: <reason>` for the narrower modes so the verification and render phases know what will not execute.
50
54
 
51
55
  ## Executable mode
52
- - Every gated spec has `given caller`; every given/expected event has `for`, and so does every plain `produces <Name>` (inline `produces event` omits it and defaults to the identifier).
56
+ - Every gated spec has `given caller`; local given/expected events have `for`, and so does every plain `produces <Name>` (inline `produces event` omits it and defaults to the identifier). Foreign event fixtures driving captures may omit `for`; a supplied value is opaque source text, not the capture key.
53
57
  - Each read model has one key shared by its keyed `=> RM optional` queries; the identifier equals
54
58
  the projection's effective key (`cratis-screenplay-slice-design` `references/read-model-design.md`
55
59
  decision table). View specs assert through a keyed query.
@@ -157,7 +157,9 @@ When `.screenplay/identities.json` exists, adding, removing or renaming an addre
157
157
  Slice design is done when these hold; otherwise report what is open.
158
158
 
159
159
  - [ ] Every command: origin reachable and authorized; every input traced; rules placed by
160
- layer; stored-state rules recorded NOT enforced with a named target; no form-verb name.
160
+ layer; stored-state rules use admitted protected reads, or name the refused shape
161
+ and target gap; no form-verb name. Read [protected reads](../cratis-screenplay-command-surface/references/protected-reads.md)
162
+ for opt-in and Stage refusal; reference protection is not target realization.
161
163
  - [ ] Every command has a refusal inventory (success, each refusal with layer and message,
162
164
  denied persona); every gated command and query has a `then denied` row.
163
165
  - [ ] Every event is past tense, a specific change, and consumed or justified.
@@ -171,13 +171,13 @@ Rules for filling it:
171
171
  | AssignLocker | caller is not an attendant | `authorize IsAttendant` | denied: Customer | RefusingACustomerAssigningALocker |
172
172
  | AssignLocker | locker already has a request | constraint `OneRequestPerLocker` | "The locker is already assigned" | AppendingASecondAssignmentOfALocker (`when append`: the command's own `require` would reject first) |
173
173
  | AssignLocker | request already has a locker | constraint `OneLockerPerRequest` | "The request already has a locker" | gap |
174
- | AssignLocker | locker is not free | `reads` + `require`, NOT enforced today | "The locker is not free"; target: `[ProtectedDecision]` (Arc 22.39.0+; available to Stage 4.73.1 gap-fill, not emitted protection) or DCB on the locker stream | RejectingASecondAssignmentOfALocker (pins the message; blocked until the target exists) |
175
- | AssignLocker | request is not waiting | `reads` + `require`, NOT enforced today | "The request is not waiting for a locker" | gap (same) |
174
+ | AssignLocker | locker is not free | Legacy example lacks protected-read opt-in; inspect v25 admission and Stage gap | "The locker is not free"; target: `[ProtectedDecision]` (Arc 22.39.0+; available to Stage 4.73.1 gap-fill, not emitted protection) or DCB on the locker stream | RejectingASecondAssignmentOfALocker (pins the message; blocked until the target exists) |
175
+ | AssignLocker | request is not waiting | Legacy example lacks protected-read opt-in; inspect v25 admission and Stage gap | "The request is not waiting for a locker" | gap (same) |
176
176
  | LockerById, ListLockers | caller is anonymous | module `authorize IsAuthenticated` | denied: no caller | RefusingAnAnonymousLockerLookup, RefusingAnAnonymousLockerList |
177
177
  | RequestById | caller is anonymous | module `authorize IsAuthenticated` | denied: no caller | RefusingAnAnonymousRequestLookup |
178
178
 
179
- The gaps are the hand-off: most are cheap rejection specs, and two are blocked on a target the
180
- model cannot express yet. A model whose inventory shows no gaps at design time has probably
179
+ The gaps are the hand-off: most are cheap rejection specs, and two need protected-read admission plus separately verified target realization;
180
+ the legacy example has not opted into v25. A model whose inventory shows no gaps at design time has probably
181
181
  not been asked the refusal questions.
182
182
 
183
183
  ## Common mistakes
@@ -11,14 +11,16 @@ code only as XML doc comments (Stage#178): a rule that exists only in prose is u
11
11
  | who may ask | `authorize` with a policy (role, claim, authenticated) | enclosing gates combine with AND and run first. Gates every command and query in a feature shares go on the feature or module so a new path inherits them |
12
12
  | whose instance | policy `claim "x" matches subject` (the command identifier) or `matches <command property>` | executable; renders for text, Uuid, Date and DateTime subjects; an authorized command needs exactly one identifier (STAGE-ESM-015 otherwise) |
13
13
  | uniqueness, once-only facts | `constraint` (`unique ... on`, `unique event`) | append-time; the constraint name is its identity |
14
- | stored state (record exists, balance, current status) | `reads <View>` + `require <expr> message "..."` | stated intent, **NOT enforced in the model today** (PLAY0268/0271 at binding are expected in design mode). Name the target: Arc `[ProtectedDecision]` + `DecisionRead<T>` (Requires Arc 22.39.0 or later), Chronicle DCB (`concurrency` scope), or a constraint |
14
+ | stored state (record exists, balance, current status) | `reads <View>` + `require` with an indented message | opt eligible reads into `command reads protected` (v25); absence Validation, matching intervening facts Conflict. Legacy/refused shapes stay stated intent with a named target mechanism |
15
15
 
16
16
  An unguarded materialized read is unsafe for a protected decision; a guarded read is the
17
17
  supported route. Availability: `[ProtectedDecision]` and `DecisionRead<T>` exist in
18
18
  the Arc/Chronicle package set Stage scaffolds (see the Stage skill's `references/rendered-application.md`), but Stage does not emit
19
19
  protected decisions. Gap-fill must use an admitted projection/key shape and active
20
20
  unit-of-work enrollment; do not edit managed dependencies. Keep the `.play` rule
21
- NOT enforced until its target enforcement is separately verified. Forbidden: caller-supplied copies of state in `require`, boolean attestation
21
+ target enforcement separate from reference semantics until target tests verify it.
22
+ Read [protected command reads](../../cratis-screenplay-command-surface/references/protected-reads.md)
23
+ for admission and Stage's protected-read refusal (STAGE-ESM-044); never remove protection to obtain rendering. Forbidden: caller-supplied copies of state in `require`, boolean attestation
22
24
  inputs (`confirmsX == true`), rules in `handler` / implementation-hint prose.
23
25
 
24
26
  ## Authorization is executable
@@ -97,14 +97,15 @@ module Moorings
97
97
  Record, per slice, the events it consumes and which slice produces each. This is for
98
98
  orientation, not a build order: view specifications use synthetic `given` events, so slices
99
99
  are built and checked independently. A command or reaction may consult another slice's view
100
- (`reads`; unprotected in `.play`, see `rule-layers.md`). A slice never calls another slice's
100
+ (`reads`; eligible command reads can opt into v25 protection, trigger reads cannot;
101
+ see `rule-layers.md` for target gaps). A slice never calls another slice's
101
102
  command except through `invokes`. Dependencies run in one direction; a cycle through events
102
103
  means the story is a feedback loop that belongs in an `Automation` slice.
103
104
 
104
105
  The contract between slices is events: slice B depends on slice A because B's command, rule
105
106
  or view needs an event A produces. Two other edges are supported and recorded explicitly, never
106
- implied: `reads <View>` from another slice (unprotected, so a stored-state rule over it stays
107
- NOT enforced, `rule-layers.md`) and `invokes <Command>` from a reaction. No shared state or
107
+ implied: `reads <View>` from another slice (declare protected-command opt-in and
108
+ admission, or mark the legacy/refused shape and target gap, `rule-layers.md`) and `invokes <Command>` from a reaction. No shared state or
108
109
  other direct call. Name each
109
110
  slice after its element (the command, the view, the automation, the translation (capture or translator reaction)), not a broader feature name
110
111
  that spans several. Per slice, record:
@@ -1,13 +1,13 @@
1
1
  # Worked example: parcel lockers (design mode)
2
2
 
3
- One complete model for `cratis-screenplay-slice-design`. It is in **design mode**: V1 clean
4
- (compiles with warnings as errors); V3 is blocked on purpose by the `ListLockers` list query
5
- (`PLAY0268` at binding); `given clock` also failed binding on a cratis before 3.28.2 bundle (3.28.2 binds it)
6
- (`cratis-screenplay-toolchain` `SKILL.md`). Personas and screens are informational.
7
- The stored-state rules in `AssignLocker` (`reads` + `require`) are intent, not enforced today,
8
- and they also fail binding on their own: `PLAY0271` on each `reads`, and `PLAY0268` because the
9
- `require` operands (`locker.assigned`, `request.state`) must be command properties. So this
10
- document is design mode as a whole: V3 is blocked twice over and no specification runs here.
3
+ One complete legacy design-mode control for `cratis-screenplay-slice-design`, without
4
+ `command reads protected`. Its reads and read paths retain PLAY0271/PLAY0268, so no
5
+ specification runs here. List queries and clock fixtures bind on an admitting compiler;
6
+ they are not the remaining blocker. Personas and screens are informational.
7
+ Eligible command reads can opt into v25; inspect every projection/key/removal before
8
+ migration and retain Stage's separate refusal (STAGE-ESM-044; the v25 pair itself is admitted). Read
9
+ [protected reads](../../cratis-screenplay-command-surface/references/protected-reads.md).
10
+ The unenforced descriptions below refer to this legacy control, not all command reads.
11
11
  The specifications still seed every read-model source (`LockerInstalled`, `LockerRequested`,
12
12
  complete givens) so they are the right form once binding is possible.
13
13
  Lineage matrix: `field-lineage.md`. State-transition table and rule coverage: `slicing.md`.
@@ -40,41 +40,46 @@ Screenplay's reference runner executes specifications against an immutable
40
40
  in-memory world: no Arc, no Chronicle, no database, no network. Every downstream
41
41
  target has one normalized behavior to match.
42
42
 
43
- - It runs the capabilities the execution plan admits: declarative validation
44
- and `require` over command properties, conditional production, literal tags,
45
- declarative policies, `unique` constraints, and projections as Chronicle
46
- lowers them. The `cratis-screenplay-model-authoring` language reference lists
47
- what binds and what the plan admits.
48
- - Binding is not admission. These projection constructs bind, but the plan
49
- refuses them: a projection-level `remove via join`; `all` beside removals,
50
- `children` or `nested`; a `join`, `children` or `remove via join` inside
51
- `nested`; and any `$eventContext.<path>` other than `eventSourceId`, such as
52
- `$eventContext.occurred`. The limits apply at every ESM version.
53
- - A specification that needs **opaque code** — a bodied reducer, a rule with a
54
- body, a fenced `validate` block, a code policy, or (ESM v6) a reached reaction
55
- body — returns **unsupported** and
56
- never passes. Authorization is evaluated first, so a `then denied` case still
57
- runs when a portable policy decides it. Other specifications in the model run
58
- normally.
59
- - Unsupported reachable declarative constructs block the whole execution plan
60
- rather than running partially: no specification in the model runs, including
61
- the ones that never touch the refused construct.
62
- - Reactions: before ESM v6 they never run, not even after `when append`. From ESM
63
- v6 they run after every action, as in "Reactions and
64
- cascades" ([references/reactions-and-cascades.md](references/reactions-and-cascades.md)). A compiler that stops before ESM v6 fails `when clock`, `when trigger`
65
- and `when capture` binding with `PLAY0268`, and so reactions and captures.
66
- - Children defer until their parent exists; an ambiguous parent still fails closed.
67
- [Child ordering](references/child-ordering.md): specs and routing caveat.
68
-
69
- Requires Screenplay 4.149.1 or later (`screenplay --version`) for child deferral.
70
- - A rejected individual command or append leaves the world unchanged; an accepted
71
- one commits once, then the read models and queries are compared. There is no
72
- scenario-wide transaction in v6: when a later effect of a cascade or capture
73
- rejects, the earlier accepted facts and their projections remain.
74
-
75
- Unsupported is not passed. Report it as "needs a target", not as green. "Specified"
76
- and "bound" are never "passing": run the reference CLI/MCP route or the owning
77
- target tests, and name the engine, version and expected/discovered selection.
43
+ Binding is not plan admission. Read model-authoring's
44
+ [language reference](../cratis-screenplay-model-authoring/references/language-reference.md)
45
+ when distinguishing executable declarations, refused projection shapes and opaque
46
+ code. Reached opaque code is **unsupported**, never passed; portable denial may
47
+ still execute before it. Unsupported declarative constructs block the whole plan,
48
+ not just the specifications that touch them.
49
+
50
+ Read [reactions and cascades](references/reactions-and-cascades.md) when testing
51
+ ESM v6 actions; older compilers fail reaction/capture binding with PLAY0268.
52
+ Read [child ordering](references/child-ordering.md) for deferral;
53
+ an ambiguous parent still fails closed.
54
+ Requires Screenplay 4.149.1 or later (`screenplay --version`) for child deferral; older runners do not defer.
55
+
56
+ A rejected command/append leaves the world unchanged; an accepted one commits
57
+ before comparing views. V6 has no scenario-wide transaction: later cascade
58
+ failure does not roll back earlier accepted facts. Atomic mode boundaries are below.
59
+
60
+ Unsupported is not passed. Name a target. Run CLI/MCP reference execution
61
+ or target tests; name engine, version and expected/discovered selection.
62
+
63
+ ## Batches, described bodies, protected reads and text rules
64
+
65
+ - With `reaction batches atomic`, assert no facts from a failed direct-production or
66
+ selected refusal-branch batch and unchanged views through evaluator world assertions,
67
+ not only `then error`. `then no events` is acceptance and cannot accompany an error. Earlier
68
+ accepted batches/invoked commands remain; legacy absence retains per-fact appends.
69
+ Read [atomic boundaries](../cratis-screenplay-captures-and-reactions/references/atomic-batches-and-source-mappings.md).
70
+ - A described handler binds v23, but reaching its body returns Unsupported
71
+ ImplementationBody, naming command/RequirementId and emitting no events. Denial and
72
+ validation cases still run; an all-Unsupported run is never green. Read
73
+ [described handlers](../cratis-screenplay-command-surface/references/described-handlers.md).
74
+ - Protected command reads opt into v25. Test present/absent state and rule refusal;
75
+ matching decide/commit changes are Conflict / DecisionStateChanged, not validation
76
+ refusal. Race vectors are not new specification syntax. Read
77
+ [protected reads](../cratis-screenplay-command-surface/references/protected-reads.md).
78
+ - Literal text rules use ordinal UTF-16 comparison (v24); matches uses a portable
79
+ linear matcher, not platform regex. Old invalid/refused patterns plan as
80
+ UnsupportedValidation, not a successful check. Read
81
+ [text and match rules](../cratis-screenplay-command-surface/references/text-and-match-rules.md)
82
+ for boundary values and PLAY0699/0787. Reference success is not Stage admission.
78
83
 
79
84
  ## Descriptions, persona callers and case tables
80
85
 
@@ -102,8 +107,7 @@ Rules the binder enforces:
102
107
  - **`then result` and `then no result` need `when query`**, and `when query`
103
108
  needs one of them, `then denied` or a sole validation `then error` (`PLAY0465`). Each argument is a `by` or
104
109
  `filter` parameter of the query (`PLAY0468`).
105
- - **A clock instant is ISO 8601 with an offset or `Z`**, such as
106
- `"2026-10-05T08:00:00Z"` (`PLAY0461`); `given clock` appears at most once.
110
+ - **A clock instant is ISO 8601 with an offset or `Z`** (PLAY0461); one `given clock` maximum.
107
111
  - **`then` contains either events or an error — never both.** A rejection
108
112
  specification has exactly one rejection and no success outcome.
109
113
  - **`then denied` stands alone**: not with events, errors or state assertions
@@ -114,10 +118,8 @@ Rules the binder enforces:
114
118
  - **`null` only in optional read-model values.** A `null` in a command or event
115
119
  value is `PLAY0350`: an optional fact is a separate event.
116
120
 
117
- `PLAY0358` is a syntax error (`PLAY0388` also at parse time for extra text after `then denied`). `PLAY0350`, `PLAY0352`, `PLAY0388` (mixed with another outcome), `PLAY0389` and
118
- the one-rejection rule (`PLAY0273`) are reported only when the model binds, so
119
- `screenplay --warnaserror` does not show them. Check executable diagnostics
120
- (the MCP authoring tools) as well.
121
+ V1 does not report binding-only outcome errors; read `references/vocabulary.md`
122
+ for parse-versus-bind diagnostics and check executable diagnostics too.
121
123
 
122
124
  ## How outcomes are compared
123
125
 
@@ -154,12 +156,12 @@ Read [references/reactions-and-cascades.md](references/reactions-and-cascades.md
154
156
 
155
157
  ## Published-event specifications (released ESM v9)
156
158
 
157
- Use `when append <PrivateEvent>` then `then <PublicEvent>` for outbound publication,
158
- not `then readmodel`. The follow-up event list is exhaustive and ordered. Read
159
- [publication example and fold cases](../cratis-screenplay-automations-and-translations/references/public-events-and-direction.md).
160
- Events-source captures and reached opaque event-target reducers return typed
161
- Unsupported, not a pass. Composite view fixtures need every key part but remain
162
- unadmitted (PLAY0268); see read-surface `references/named-keys.md`.
159
+ Use `when append <PrivateEvent>` then `then <PublicEvent>`, not `then readmodel`;
160
+ follow-up events are exhaustive and ordered. Read
161
+ [publication and fold cases](../cratis-screenplay-automations-and-translations/references/public-events-and-direction.md)
162
+ when specifying outbound facts or event-source captures: it owns the minimum
163
+ compiler, PLAY0700/0701, key folding and Unsupported boundaries. Composite view
164
+ fixtures remain unadmitted; see read-surface `references/named-keys.md`.
163
165
 
164
166
  ## Reusable fixtures, routes and recovery intent
165
167
 
@@ -7,7 +7,17 @@ A slice is not always set off by a command. Name what does:
7
7
  | A view no event builds - its query has a `performer` | `given readmodel` …, `when query <Query>`, `then result` / `then no result` |
8
8
  | An automation driven by the clock | `given clock "<instant>"`, `when clock "<later instant>"` |
9
9
  | An automation driven by an application trigger | `when trigger <Trigger>` with the values it carries |
10
- | A translation driven by a capture | `given capture <Capture>` (the record as it was), `when capture <Capture>` (as it is now) |
10
+ | A translation driven by a record capture | `given capture <Capture>` (the record as it was), `when capture <Capture>` (as it is now) |
11
+ | A capture with `source events` | `given <FromEvent>`, `when append <FromEvent>`; capture-record fixtures are PLAY0701 |
12
+
13
+ A first record is `added` only, including child and nested records; field-change,
14
+ `and`/`or` and transition guards need earlier state for the same key. For first sight
15
+ add a separate `when added` append; for an update seed `given capture`. Requires
16
+ Screenplay 4.175.0 or later (`screenplay --version`); older record evaluators treat
17
+ first-record fields as changed. Complete cases: captures-and-reactions
18
+ [record capture specifications](../../cratis-screenplay-captures-and-reactions/references/record-capture-specifications.md).
19
+ Event captures use the typed event fixtures and overlay rules in
20
+ [public event captures](../../cratis-screenplay-automations-and-translations/references/public-events-and-direction.md).
11
21
 
12
22
  Use `given clock`, never `given time`, to state the scenario occurrence time and
13
23
  assert a value mapped from `$context.occurred`. In a command's `produces`, that
@@ -1,31 +1,42 @@
1
- ## Generated fixtures and return expectations (ESM v7 and v15)
1
+ # Generated fixtures and return expectations
2
2
 
3
- ### Choosing a strategy
3
+ ## Contents
4
+
5
+ - Choosing a strategy
6
+ - When not to
7
+ - Fixtures and outcomes
8
+
9
+ ## Choosing a strategy
4
10
 
5
11
  Use the [shop example](../../cratis-screenplay-command-surface/references/shop-generation.md):
6
12
  pin CustomerId (`cus_` + ULID), OrderId (TypeID) and InviteCode (NanoID) as
7
13
  whole values. ApiKey stays secret with no executable generation; do not write a
8
14
  passing issuance spec that invents its .NET Bytes(32) factory in Screenplay.
9
- OrderId pins do not realize Arc's received-time/tenant context either.
15
+ Pin InvoiceNumber's whole date/checksum reference and TicketNumber's integral
16
+ pickup-ticket value too; do not use numeric text for Int fixtures.
10
17
 
11
18
  Choose the concept's strategy for the job, then pin a whole value matching it:
12
19
  `for` for its generated identifier, named `generated` fixtures for other values.
13
20
  Use the shared [strategy reference](../../cratis-screenplay-command-surface/references/generated-values-and-responses.md)
14
- for UUID, time-ordered, typed/opaque text and byte-budget choices and exact shapes.
15
- `given clock` supplies `$context.occurred`, not a generated time-ordered ID;
21
+ for UUID, time-ordered, typed/opaque text, byte budgets, finite patterns and Int
22
+ range choices and exact shapes.
23
+ `given clock` supplies `$context.occurred` and pattern UTC date segments, not a generated time-ordered ID;
16
24
  a seed is not a portable fixture.
17
25
 
18
- ### When not to
26
+ ## When not to
19
27
 
20
28
  Pins do not prove randomness, authorization, idempotency, storage freshness or
21
29
  secret safety. Client-minted IDs stay inputs; gapless invoice numbering needs an
22
- allocator, not a random fixture. Pattern/random/rule and secret generation remain
23
- unadmitted. Source: Screenplay
30
+ allocator, not a random fixture or pattern. Check digits catch typos, not forgery;
31
+ short payload codes need uniqueness enforcement separate from source freshness.
32
+ Pattern/random/rule and checksum validation bind as v21. Stage renders
33
+ pattern/random/checksum under the version gates below; `generate rule` remains
34
+ STAGE-ESM-028. Generated secrets remain refused. Source: Screenplay
24
35
  `Documentation/screenplay/generated-values/choosing.md`.
25
36
 
26
- ### Fixtures and outcomes
37
+ ## Fixtures and outcomes
27
38
 
28
- A compiler that admits ESM v7 binds and runs these; Stage renders supported UUID/String generation strategies,
39
+ A compiler that admits ESM v7 binds and runs these; Stage renders supported UUID/String and Int random generation strategies,
29
40
  scalar/named responses, fixtures and `then returns`. Unsupported types/result combinations
30
41
  remain `STAGE-ESM-028`/`-038`; preserve refused specifications as gap-fill contracts. The model and rules are in `cratis-screenplay-command-surface`; the
31
42
  complete threaded model is the linked shop example. The excerpt below belongs
@@ -62,17 +73,37 @@ specification RegistersWithPinnedValues
62
73
  own destinations. For commands without a generated identifier `when ... for` keeps the destination assertion.
63
74
  UUID fixtures require canonical lowercase hyphenated form. From v15, pins must also match
64
75
  exact strategy size, case, UUID version/variant and zero trailing encoding bits; invalid pins are
65
- Contract rejections. Earlier models check canonical UUID type, not its version.
76
+ Contract rejections. A generated concept with rules selects v20 and checks pins
77
+ against both shape and rules, including implicit UUID. Rule failures are
78
+ `Rejected(Contract)` with `Generated fixture '<property>' fails concept '<Concept>' rules`,
79
+ never client validation failures or redraws. Earlier rule-free implicit-UUID
80
+ models check canonical UUID type, not its version.
66
81
  - A serialized concept generation strategy selects v15 and Guarded whole-source freshness for all
67
82
  generated destinations, including implicit UUIDs. Reusing a generated source with existing facts
68
- rejects the entire command with Concurrency, without append, response or silent retry. Below v15
69
- fixtures retain legacy reuse. See the complete [strategy example](../../cratis-screenplay-toolchain/references/generation-strategies-example.md)
83
+ rejects the entire command with Concurrency, without append, response or silent retry.
84
+ Models without a serialized strategy retain legacy reuse even when rules select v20. See the complete [strategy example](../../cratis-screenplay-toolchain/references/generation-strategies-example.md)
70
85
  and command-surface `references/generated-values-and-responses.md` for tagged sources.
71
- - `given clock` supplies `$context.occurred`; it does not synthesize UUIDv7, ULID or
72
- TypeID from that instant. Pin the whole identifier, never a seed. Stage's
73
- time-ordered factories use wall clock, not command-receipt time, and its clock
74
- specifications remain unsupported. Sources: Screenplay
86
+ - `given clock` supplies `$context.occurred` and requires all pattern date segments
87
+ to match the same UTC instant, including offset rollover and leap days. Without
88
+ a clock the reference runner checks digit widths, never today's wall clock.
89
+ Checksum pins check arithmetic only with an authored `validate checksum` rule;
90
+ a generation modifier alone checks suffix shape. It does not synthesize UUIDv7,
91
+ ULID or TypeID: pin the whole identifier, never a seed. Stage time-ordered
92
+ factories use receipt time; admitted command clock specs render. Sources: Screenplay
75
93
  `Documentation/screenplay/generated-values/choosing.md`; Stage
76
94
  `Documentation/reference/generated-values-rendering.md`.
95
+ - Attached generation bodies are not run: pin the resulting String;
96
+ an opaque validator still yields Unsupported. Stage allows unpinned rendered
97
+ generation only when every concept rule is Proven and the expectations support
98
+ relational captures. Unproven/Refuted rules need pins (-038); invalid pins fail
99
+ STAGE-ESM-011. Opaque/unsupported rules refuse -005 before pin evaluation.
100
+ Screenplay's reference runner and Stage's independent executor always need pins.
77
101
  - A reaction-invoked command that reaches generation is `Unsupported(IdentityAllocation)` (no fixture channel); a
78
102
  response-only command runs and its response is discarded.
103
+
104
+ Requires Screenplay 4.164.0 (`screenplay --version`) for v20 rule-bearing generated pins, 4.172.0 for v21 finite/rule strategies; older compilers refuse PLAY0268.
105
+ Requires Stage 4.95.0 for command clock specs and 4.109.0 for v20 rule-bearing pins; older renderers refuse those shapes.
106
+ Requires Stage 4.115.0 for v21 admission/all-Proven unpinned rendering, 4.117.0
107
+ for warning/info generated-concept rules, 4.118.0 for checksum validation and
108
+ 4.119.0 for pattern/random. Older renderers require rule-bearing pins or refuse
109
+ the respective rules/strategies with -038/-042/-028. `generate rule` remains -028.
@@ -1,3 +1,6 @@
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
+
1
4
  # The specification vocabulary
2
5
 
3
6
  This reference holds the given/when/then construct table and the enumeration and DateTime literal rules.
@@ -17,7 +20,7 @@ This reference holds the given/when/then construct table and the enumeration and
17
20
  | `given clock "<instant>"` | the ISO 8601 instant the scenario happens at |
18
21
  | `when clock "<instant>"` | the clock reaches an instant; scheduled reactions that are due run |
19
22
  | `when trigger <Trigger>` | an application trigger fires with the values beneath it |
20
- | `given capture` / `when capture <Capture>` | an earlier and the current record of a capture's source |
23
+ | `given capture` / `when capture <Capture>` | earlier/current records for non-event sources; for `source events` use typed `given <Event>` / `when append <Event>` (PLAY0701) |
21
24
  | `generated <name> = <value>` | beneath `when <Command>`: the fixture for a generated property other than the identifier (ESM v7); `for` beneath the `when` supplies the generated identifier |
22
25
  | `then returns [<value>]` | the command's response (ESM v7): `then returns "<uuid>"` for a scalar, `then returns` with named `field = value` lines for a subset of a record |
23
26
  | `then <EventType>` | an expected new event |
@@ -32,6 +35,16 @@ This reference holds the given/when/then construct table and the enumeration and
32
35
  | `for <value>` | the event source of a `given`/`then` event, or of the `when` command or appended event |
33
36
  | `<property> = <value>` | a literal, `null`, or a one-line JSON-shaped object or list: `lines = [{"sku":"A-1","quantity":2}]` |
34
37
 
38
+ ## Parse and binding diagnostics
39
+
40
+ PLAY0358 is a syntax error; PLAY0388 also occurs at parse time for extra text
41
+ after `then denied`. PLAY0350, PLAY0352, PLAY0388 for mixed outcomes, PLAY0389 and
42
+ the one-rejection rule PLAY0273 occur only at binding. Source validation alone
43
+ will not report them: check executable diagnostics as well. Clock instants need
44
+ an ISO 8601 offset or `Z`, for example `"2026-10-05T08:00:00Z"` (PLAY0461).
45
+
46
+ ## Literal spellings
47
+
35
48
  An enumeration value binds whether it is written bare
36
49
  (`status = sent`), qualified (`status = InvoiceStatus.sent`) or quoted, and a
37
50
  `DateTime` value binds as a plain ISO 8601 instant (`"2026-10-05T08:00:00Z"`).
@@ -26,17 +26,15 @@ Read [references/product-sources.md](references/product-sources.md) when checkin
26
26
  - Not for: projection and query syntax, reactions and captures, writing the specifications
27
27
  themselves (`cratis-screenplay-scenario-coverage`), Chronicle C# mechanics
28
28
  (`cratis-chronicle-event-modeling`). See Route near misses.
29
- - Model-first applies: when an accepted model covers the scope, change the model and its
30
- specifications, not code. Do not weaken authorization, `pii` or rules to make a model compile.
29
+ - Apply model-first per `cratis-screenplay-modeling-lifecycle`; never weaken
30
+ authorization, `pii` or rules to compile.
31
31
 
32
32
  ## Interview phase
33
- **Skip if** the user or the model already states the stream identities, who owns each module, how
34
- much autonomy each side has, the external systems, and rough growth. Otherwise ask only what is
35
- missing, one question at a time, with options. **Unattended:** assume the most conservative
36
- option, mark it `ASSUMED` in the slice or module `documentation` and in the session `STATE.md`
37
- (`.ai-work/screenplay/<model-slug>/STATE.md`), and continue.
38
-
39
- Ask only what is missing: (1) instance - what real-world thing the stream is about; (2) competition - what must never happen when two people act at once; (3) retry - what a repeated request should see; (4) ownership; (5) growth; (6) change - whether the event was ever stored in a running system. Read [references/interview-batch.md](references/interview-batch.md) for each question's follow-up; ownership options are in `references/boundaries.md`.
33
+ Read [interview prompts](references/interview-batch.md) when identity, competition,
34
+ retry, ownership, growth or stored-event history is unsettled. Ask only missing
35
+ questions, one at a time; ownership options are in `references/boundaries.md`.
36
+ Unattended work takes the conservative option and marks it `ASSUMED` in model
37
+ `documentation` and `.ai-work/screenplay/<model-slug>/STATE.md`.
40
38
 
41
39
  ## Procedure
42
40
  1. **Establish identity and membership.** For every `concept XId` used as an `identifier`, write
@@ -87,14 +85,10 @@ Ask only what is missing: (1) instance - what real-world thing the stream is abo
87
85
  (PLAY0270), not runtime propagation or generated C# `[Subject]`. Without a
88
86
  supplied subject, the runtime defaults to the event source; see command-surface
89
87
  `references/compliance.md` for allowed types and the policy/encryption distinction.
90
- 5. **Plan evolution** with `references/evolution.md`: classify each event change (additive,
91
- meaning change, rename, removal, split or merge) and write its compatibility scenarios before
92
- editing. Admit the **release baseline** in the release job; admitted
93
- revisions need `newGeneration`. Modes/CLI/MCP: `references/evolution.md`.
94
- Pin persisted/public enum member numbers before reordering or removing members (`references/evolution.md`, "Enum member numbers").
95
-
96
- Renames and other identity-affecting edits are made by the identity owner (the
97
- identity procedure in `cratis-screenplay-modeling-lifecycle`).
88
+ 5. **Plan evolution**: read `references/evolution.md` before editing stored contracts
89
+ for change classification, compatibility scenarios and enum-number safety.
90
+ After release-baseline admission, revisions need `newGeneration`. Identity-affecting edits belong to the
91
+ identity owner (`cratis-screenplay-modeling-lifecycle`).
98
92
  6. **Test ownership and interfaces** with `references/boundaries.md`: ownership interview,
99
93
  interface and processor inventory, one real interaction walked across each boundary, coupling
100
94
  check. Keep team, module, stream and deployment boundaries distinct; inbound facts via
@@ -108,15 +102,19 @@ Ask only what is missing: (1) instance - what real-world thing the stream is abo
108
102
  - `identifier` on an event property is PLAY0019; the source id is never payload by declaration.
109
103
  Copying it as a payload value is PLAY0469 (information, warning for inline events).
110
104
  - In the executable model a production's `for` must resolve to the command's scalar identifier:
111
- one command writes one stream declaratively (a handler is never admitted).
105
+ one command writes one stream declaratively; described handlers bind v23 but
106
+ their payload-only contract does not grant arbitrary destinations.
112
107
  - Constraint names are application-wide identities (PLAY0392); properties must be declared
113
108
  directly on the event (PLAY0391); never mix event and property rules under one name (PLAY0135);
114
109
  `ignore casing` is not allowed on `unique event` (PLAY0393).
115
110
  - Generations are declared in full, numbered 1..N without gaps, in the same slice (PLAY0446-0448); `id` pins are shared by all generations and unique application-wide (PLAY0472); `storedName` needs ESM v16. See `references/evolution.md` ("Generations, pins and storedName diagnostics").
116
111
 
117
- - `reads` is PLAY0271 and `require` over read-model paths is PLAY0268 at binding. A `concurrency`
118
- block compiles but is PLAY0271 at binding. Keep both when they state real intent; they are not
119
- protection. `description` text never reaches rendered code: a rule that lives only in prose is
112
+ - Application-root `command reads protected` admits eligible reads and single-level
113
+ requirement/mapping paths (v25). Absence rejects, matching decide/commit changes
114
+ conflict. Legacy reads remain PLAY0271/PLAY0268; `concurrency` remains unbound and
115
+ combining it with protected reads is PLAY0783. Read
116
+ [protected reads](../cratis-screenplay-command-surface/references/protected-reads.md)
117
+ for admission and Stage's STAGE-ESM-044 protected-read refusal (the v25 pair itself is admitted). `description` text never reaches rendered code: a rule that lives only in prose is
120
118
  unenforced there.
121
119
  - `pii` and `secret` bind as ESM v13;
122
120
  enum/identity compliance and protected events with explicit subject marks still
@@ -144,6 +142,12 @@ Requires Chronicle 19.59.6 or later (19.59.3 for the InMemory provider) for the
144
142
  - Give each invariant an authoritative atomic decision point and inspect every path that could
145
143
  violate it. A constraint violation rejects that command's whole append set; a reaction cascade
146
144
  is not one transaction. Declared semantics are not a passed concurrency test.
145
+ - New models declare `reaction batches atomic`: direct productions per trigger
146
+ occurrence and each selected refusal branch are separate batches; invoked commands
147
+ stay independent. Legacy absence retains per-fact appends. Stage refuses v22
148
+ with STAGE-ESM-016 and atomic mode in admitted v23–v25 with STAGE-ESM-043. Read
149
+ [atomic boundaries](../cratis-screenplay-captures-and-reactions/references/atomic-batches-and-source-mappings.md)
150
+ when defining failure rollback; batching is not redelivery deduplication.
147
151
  - Match duplicate protection to scope. A property constraint lets a source re-claim its own
148
152
  value; use `unique event` for a fact that is genuinely once-only in its lifecycle, without
149
153
  blocking legitimate repeated operations just to make retries safe.
@@ -80,8 +80,8 @@ For each affected boundary, identify:
80
80
 
81
81
  Use declaration addresses, not copies of payloads. Per slice, also record the events it consumes
82
82
  and which slice produces them, for orientation, not as a build order. A command or reaction may
83
- consult another slice's view (`reads`; unprotected in `.play`, see `consistency-and-concurrency.md`
84
- section 3); a slice calls another slice's command only through `invokes`.
83
+ consult another slice's view (`reads`; eligible commands opt into v25 protection,
84
+ trigger reads cannot; see `consistency-and-concurrency.md` section 3 for target gaps); a slice calls another slice's command only through `invokes`.
85
85
 
86
86
  ### Responsibility matrix and ownership timeline
87
87
  One compact matrix per feature shows who owns what; the timeline shows where a fact crosses.