@cratis/pi 7.63.0 → 7.65.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 (46) hide show
  1. package/package/corpus/product-sync.json +4 -4
  2. package/package/corpus/skills/cratis-fundamentals-concept/references/shop-generation.md +16 -3
  3. package/package/corpus/skills/cratis-screenplay-automations-and-translations/SKILL.md +2 -1
  4. package/package/corpus/skills/cratis-screenplay-captures-and-reactions/SKILL.md +3 -1
  5. package/package/corpus/skills/cratis-screenplay-command-surface/SKILL.md +13 -3
  6. package/package/corpus/skills/cratis-screenplay-command-surface/references/date-comparisons.md +100 -0
  7. package/package/corpus/skills/cratis-screenplay-command-surface/references/generated-values-and-responses.md +30 -0
  8. package/package/corpus/skills/cratis-screenplay-command-surface/references/protected-reads.md +15 -5
  9. package/package/corpus/skills/cratis-screenplay-command-surface/references/validate-rules.md +12 -2
  10. package/package/corpus/skills/cratis-screenplay-command-surface/verification.json +3 -0
  11. package/package/corpus/skills/cratis-screenplay-event-modeling/SKILL.md +2 -2
  12. package/package/corpus/skills/cratis-screenplay-event-modeling/references/parsed-not-runnable.md +1 -1
  13. package/package/corpus/skills/cratis-screenplay-legacy-extraction/references/generated-recovery.md +14 -2
  14. package/package/corpus/skills/cratis-screenplay-model-authoring/references/language-reference.md +3 -2
  15. package/package/corpus/skills/cratis-screenplay-model-review/references/anti-patterns.md +1 -1
  16. package/package/corpus/skills/cratis-screenplay-model-review/references/checklist.md +1 -1
  17. package/package/corpus/skills/cratis-screenplay-modeling-lifecycle/references/principles.md +1 -1
  18. package/package/corpus/skills/cratis-screenplay-modeling-lifecycle/references/vocabulary-map.md +1 -1
  19. package/package/corpus/skills/cratis-screenplay-render-and-gap-fill/SKILL.md +3 -2
  20. package/package/corpus/skills/cratis-screenplay-render-and-gap-fill/references/gap-fill-handoff.md +3 -1
  21. package/package/corpus/skills/cratis-screenplay-render-and-gap-fill/references/renderability-gate.md +6 -1
  22. package/package/corpus/skills/cratis-screenplay-scenario-coverage/SKILL.md +12 -1
  23. package/package/corpus/skills/cratis-screenplay-scenario-coverage/references/berth-reservations.md +5 -5
  24. package/package/corpus/skills/cratis-screenplay-scenario-coverage/references/invoicing-dues-design.md +1 -1
  25. package/package/corpus/skills/cratis-screenplay-scenario-coverage/references/spec-forms-by-mode.md +3 -2
  26. package/package/corpus/skills/cratis-screenplay-slice-design/references/rule-layers.md +1 -1
  27. package/package/corpus/skills/cratis-screenplay-slice-design/references/worked-example.md +1 -1
  28. package/package/corpus/skills/cratis-screenplay-specifications/SKILL.md +20 -0
  29. package/package/corpus/skills/cratis-screenplay-specifications/references/outcome-comparison.md +6 -0
  30. package/package/corpus/skills/cratis-screenplay-streams-and-consistency/SKILL.md +1 -1
  31. package/package/corpus/skills/cratis-screenplay-streams-and-consistency/references/consistency-and-concurrency.md +3 -2
  32. package/package/corpus/skills/cratis-screenplay-streams-and-consistency/references/streams-example.md +1 -1
  33. package/package/corpus/skills/cratis-screenplay-toolchain/SKILL.md +4 -2
  34. package/package/corpus/skills/cratis-screenplay-toolchain/references/diagnostics.md +6 -3
  35. package/package/corpus/skills/cratis-screenplay-toolchain/references/executable-subset.md +20 -4
  36. package/package/corpus/skills/cratis-screenplay-toolchain/references/language-admission.md +21 -4
  37. package/package/corpus/skills/cratis-screenplay-toolchain/references/renderable-subset.md +7 -3
  38. package/package/corpus/skills/cratis-screenplay-toolchain/references/screenplay-contract.json +1429 -25
  39. package/package/corpus/skills/cratis-screenplay-toolchain/references/screenplay-contract.version +1 -1
  40. package/package/corpus/skills/cratis-screenplay-toolchain/references/traps.md +1 -1
  41. package/package/corpus/skills/cratis-stage-rendering-and-sandbox/SKILL.md +12 -4
  42. package/package/corpus/skills/cratis-stage-rendering-and-sandbox/references/admission.md +8 -3
  43. package/package/corpus/skills/cratis-stage-rendering-and-sandbox/references/rendered-application.md +41 -1
  44. package/package/corpus/skills/cratis-stage-rendering-and-sandbox/references/sandbox-and-specrunner.md +32 -1
  45. package/package/corpus/skills/cratis-stage-rendering-and-sandbox/references/scene-runtime.md +10 -0
  46. package/package.json +1 -1
@@ -46,7 +46,7 @@
46
46
  ],
47
47
  "rules": []
48
48
  },
49
- "notes": "Source-checked Stage v4.103.0: exact ESM v1-v17 and v19, not v18 or v20 (v18 admitted from 4.106.0 and v20 from 4.109.0, taught with Requires lines; 4.104-4.108 not otherwise reviewed). Snapshot/live collection queries, identity-mapping all projections, stored event names, event-id publication checks, release-baseline warnings, command clock/receipt-time generation, conditional and multi-command slices, generated text constraints, no-event and bounded redelivery specs, refusal branches. Query concept validation still uses primitive workaround; Stage#370 released in 4.106.0. CLI v3.62.0 bundles Stage 4.99.0, not 4.103.0. Generated-values-only delta checked at v4.127.0: v21/all-Proven unpinned specs from 4.115.0, warning/info generated rules 4.117.0, checksum validation 4.118.0, pattern/random factories/Host/executor 4.119.0; generate rule still STAGE-ESM-028. Language admission reconciled at the same v4.127.0 tag: exact v1-v21 and v23-v25 pairs; v22/v26 and mixed pairs -016, protected reads -044, atomic mode -043, described bodies STAGE-IMPL-002 even Stub mode; v24 first admitted 4.124.0 (absent 4.123.0). Other deltas not reviewed; synced unchanged. No new render/browser/Docker probe."
49
+ "notes": "Source-checked Stage v4.103.0: exact ESM v1-v17 and v19, not v18 or v20 (v18 admitted from 4.106.0 and v20 from 4.109.0, taught with Requires lines; 4.104-4.108 not otherwise reviewed). Snapshot/live collection queries, identity-mapping all projections, stored event names, event-id publication checks, release-baseline warnings, command clock/receipt-time generation, conditional and multi-command slices, generated text constraints, no-event and bounded redelivery specs, refusal branches. Query concept validation still uses primitive workaround; Stage#370 released in 4.106.0. CLI v3.62.0 bundles Stage 4.99.0, not 4.103.0. Generated-values-only delta checked at v4.127.0: v21/all-Proven unpinned specs from 4.115.0, warning/info generated rules 4.117.0, checksum validation 4.118.0, pattern/random factories/Host/executor 4.119.0; generate rule still STAGE-ESM-028. Language admission reconciled at the same v4.127.0 tag: exact v1-v21 and v23-v25 pairs; v22/v26 and mixed pairs -016, protected reads -044, atomic mode -043, described bodies STAGE-IMPL-002 even Stub mode; v24 first admitted 4.124.0 (absent 4.123.0). Reviewed v4.128.0-v4.130.0 deltas for Cratis/AI#739: v4.128.0 new-application self-reducing Cratis C# profile (CreateNewApplicationProfile, ReducerConventionInput.Read, WithReducerConvention; existing callers classic); shared SemanticValidationRules.Check confirmed (already present in v4.127.1, so no new 4.128.0 minimum claimed); v4.129.0 semantic Host/executor protected reads, presence before requirements/generation, read-backed requirements/mappings, non-Error requirements STAGE-ESM-045 including reaction invocations, Host fault on any outside append (stricter than reference scoped conflict). Renderer/legacy Host/structural runner retain STAGE-ESM-044. v4.130.0 root-template shell, options/appearance and fail-closed startup/planning findings reviewed in stage-rendering.md, RootShell.cs and stageShell.ts. Exact pairs remain v1-v21 and v23-v25; v26 refused STAGE-ESM-016 and Stage#473 still open. Earlier unreviewed deltas remain as noted above, so synced stays at the last fully reviewed release. No new render/browser/Docker probe."
50
50
  },
51
51
  {
52
52
  "id": "arc",
@@ -171,9 +171,9 @@
171
171
  }
172
172
  ],
173
173
  "synced": {
174
- "version": "4.198.0",
174
+ "version": "4.199.0",
175
175
  "date": "2026-10-16",
176
- "by": "Cratis/AI#576"
176
+ "by": "Cratis/AI#735"
177
177
  },
178
178
  "covers": {
179
179
  "skills": [
@@ -201,7 +201,7 @@
201
201
  ],
202
202
  "rules": []
203
203
  },
204
- "notes": "Standalone 4.198.0 and byte-identical compiler contract pinned. Cratis/AI#576: mechanical compiler catch-up. Language batch #717/#722/#723/#724/#720/#728/#734 teaches atomic reaction batches (v22), described payload handlers (v23), portable linear matching, ordinal text rules (v24), protected command reads (v25), diagnostic arguments and event-source invokes mappings. Facts read at Screenplay v4.198.0 and introducing tags; Stage v4.127.0 admits exact v1-v21 and v23-v25 pairs but refuses v22/v26 and mixed pairs (STAGE-ESM-016), protected reads (044), atomic mode (043) and described handlers (STAGE-IMPL-002), even Stub mode. Stage text rules execute/render; no new renderer/runtime probe or Stage pin uplift. Cratis/AI#706: application navigation regions (module inherit, extend or override), toolbar slice buttons, blueprint template references and sample data packs in cratis-screenplay-ui-composition (references/application-shell.md), with the canonical shell vector and the rejection codes PLAY0710-PLAY0722 and PLAY0740-PLAY0765. Examples moved to the executable-state rules since 4.164: translator reactions in an Automation slice beside the Translate slice (PLAY0694) and the first record of a capture key appended with `when added`. Earlier: Standalone 4.164.0 and byte-identical compiler contract pinned. Cratis/AI#663: one origin per capture (PLAY0687). #668: executable no-event/redelivery v17. #684: concept query-argument validation in every version and query-error assertions v18. #681: executable refusal branches and refusal values v19. #666: proposal summary/severity counts and exact structural source proposals. Generated-concept rules select v20 with PLAY0688/0689 proofs and derived-matches repair; generated secrets and preview strategies remain refused. Release-baseline from-esm admission reads storedName. Standalone binding is not renderer admission: Stage 4.103.0 admits v1-v17 and v19; CLI 3.62.0 bundles Screenplay 4.159.0 / Stage 4.99.0 and renders through v16. Prior evidence remains unless superseded; no new renderer, Docker or browser probe."
204
+ "notes": "Standalone 4.199.0 and byte-identical compiler contract pinned. Cratis/AI#735: chronological Date/DateTime ordering in command conditions and command/property literal validation (ESM v26), UTC tick precision and pre-rule offset validation; then matching remains ordinal. Source-checked Screenplay v4.199.0 commands, diagnostics, interoperability and specifications documentation plus decision 0087. Stage v4.127.1 still refuses v26 with STAGE-ESM-016 (stage-rendering.md and SemanticVersionFeatures.Supports); no render/runtime probe. Cratis/AI#576: prior mechanical compiler catch-up. Language batch #717/#722/#723/#724/#720/#728/#734 teaches atomic reaction batches (v22), described payload handlers (v23), portable linear matching, ordinal text rules (v24), protected command reads (v25), diagnostic arguments and event-source invokes mappings. Facts read at Screenplay v4.198.0 and introducing tags; Stage v4.127.0 admits exact v1-v21 and v23-v25 pairs but refuses v22/v26 and mixed pairs (STAGE-ESM-016), protected reads (044), atomic mode (043) and described handlers (STAGE-IMPL-002), even Stub mode. Stage text rules execute/render; no new renderer/runtime probe or Stage pin uplift. Cratis/AI#706: application navigation regions (module inherit, extend or override), toolbar slice buttons, blueprint template references and sample data packs in cratis-screenplay-ui-composition (references/application-shell.md), with the canonical shell vector and the rejection codes PLAY0710-PLAY0722 and PLAY0740-PLAY0765. Examples moved to the executable-state rules since 4.164: translator reactions in an Automation slice beside the Translate slice (PLAY0694) and the first record of a capture key appended with `when added`. Earlier: Standalone 4.164.0 and byte-identical compiler contract pinned. Cratis/AI#663: one origin per capture (PLAY0687). #668: executable no-event/redelivery v17. #684: concept query-argument validation in every version and query-error assertions v18. #681: executable refusal branches and refusal values v19. #666: proposal summary/severity counts and exact structural source proposals. Generated-concept rules select v20 with PLAY0688/0689 proofs and derived-matches repair; generated secrets and preview strategies remain refused. Release-baseline from-esm admission reads storedName. Standalone binding is not renderer admission: Stage 4.103.0 admits v1-v17 and v19; CLI 3.62.0 bundles Screenplay 4.159.0 / Stage 4.99.0 and renders through v16. Prior evidence remains unless superseded; no new renderer, Docker or browser probe."
205
205
  },
206
206
  {
207
207
  "id": "scene",
@@ -74,9 +74,10 @@ has 74 random bits and the TypeID `order_` prefix. Default NanoID is 21 symbols
74
74
  with 126 bits; bytes use unpadded base64url (43 symbols for 32 bytes).
75
75
 
76
76
  `IGeneratableInContext<TSelf>` requires `static abstract TSelf New(GenerationContext)`.
77
- `GenerationContext` holds one captured `DateTimeOffset Now` and a portable String
78
- `Tenant`; `DefaultTenant` is the zero-GUID string, never a display name or empty
79
- string. The shop passes time and tenant together, for example:
77
+ Fundamentals' `Cratis.Concepts.GenerationContext` is a readonly record struct with
78
+ one captured `DateTimeOffset Now` and a String `Tenant`; `DefaultTenant` is the
79
+ zero-GUID string, never a display name or empty string. The shop passes time and
80
+ tenant together, for example:
80
81
 
81
82
  ```csharp excerpt
82
83
  var context = new GenerationContext(
@@ -91,6 +92,18 @@ A domain factory can read Tenant, but arbitrary tenant IDs cannot be inserted
91
92
  into a TypeID prefix (only lowercase letters/underscores, letter endpoints).
92
93
  Do not present a tenant-prefixed custom string as standard TypeID.
93
94
 
95
+ For Screenplay `generate rule`, this Fundamentals type is the **Cratis C# target's**
96
+ binding of the language-neutral Now/Tenant descriptor, not the universal runtime
97
+ type. `Cratis.Screenplay.Contexts.GenerationContext` remains a BCL-only record with
98
+ portable `TenantId Tenant`, not a Fundamentals alias. The selected provider, not
99
+ `csharp` or a file reference, chooses the binding. Portable C# uses `context.Now`,
100
+ BCL operations and tenant text (for example `$"{context.Tenant}"`, compared ordinally).
101
+ Passing the whole context to `GenerateValue.*`, naming/constructing GenerationContext,
102
+ using `DefaultTenant` or reading `Tenant.Value` is target-bound. Never add a bridge
103
+ or claim Stage renders a rule merely because its Cratis binding is defined; read
104
+ [generation context binding](../../cratis-screenplay-command-surface/references/generated-values-and-responses.md#generation-context-binding)
105
+ for the compiler prerequisite and renderer refusal.
106
+
94
107
  Use the context form only for time/tenant-dependent generation. If both interfaces
95
108
  are implemented, callers choose context; the interfaces themselves do not dispatch.
96
109
  Time-ordered built-in context overloads reject default Now (`MissingGenerationTime`)
@@ -171,7 +171,8 @@ or actor that nobody confirmed. Read `references/worked-integration.md` when you
171
171
  separate binder check.
172
172
  - A trigger with `reads` that `produces` directly fails binding: decide in a command.
173
173
  Command reads can protect with `command reads protected` and admitted shapes (v25);
174
- trigger reads cannot. Stage refuses protected reads (STAGE-ESM-044); target protection remains a separate check.
174
+ trigger reads cannot. The Cratis C# renderer refuses protected reads (STAGE-ESM-044);
175
+ semantic execution is separate from generated-app protection.
175
176
  - An authorized command exercised in a spec without `given caller` is PLAY0389 at binding.
176
177
  - A list query (`=> Item[]`) binds (a snapshot list is not rendered, `STAGE-ESM-010`);
177
178
  a clock sweep that iterates items needs a code body the reference does not run
@@ -104,7 +104,9 @@ binding, because its decision dependency cannot be protected. A reaction that on
104
104
  command's own reads. Eligible command reads protect under application-root
105
105
  `command reads protected` (ESM v25); legacy reads retain PLAY0271. Read command-surface
106
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.
107
+ for admission and absence/conflict behavior. Stage admits v25; the Cratis C# renderer refuses protected reads with STAGE-ESM-044.
108
+ Semantic Host/executor support is separate; non-Error protected requirements refuse -045,
109
+ including reaction-invoked commands.
108
110
  `where` over read paths out of scope, and `where` needs
109
111
  every operand to resolve from the trigger's declared scalar occurrence shape (listed in
110
112
  the input selection or not; nested paths and read aliases fail binding): keep the logic that uses the state in
@@ -151,7 +151,8 @@ view name when that view is read once.
151
151
  Opt eligible state reads into application-root `command reads protected` (v25).
152
152
  Absence rejects; matching intervening facts conflict. Read [protected reads](references/protected-reads.md)
153
153
  for strict admission, paths and PLAY0780–0786. Legacy reads stay unprotected;
154
- reads/concurrency cannot combine (PLAY0783). Stage refuses protected reads (STAGE-ESM-044), not v25 itself.
154
+ reads/concurrency cannot combine (PLAY0783). The Cratis C# renderer refuses protected reads (STAGE-ESM-044), not v25 itself;
155
+ semantic Host/executor support is separate.
155
156
  Uniqueness still uses a constraint; reference success is not target realization.
156
157
 
157
158
  Do not use `reads` to fetch data the caller could supply. A composite-key view's `by` block is
@@ -177,11 +178,18 @@ optional `severity`, sharing the condition grammar with `produces … when`:
177
178
  `and` binds tighter than `or`, parentheses group. A conditional rule is an
178
179
  implication: `require isExtension == false or newEndDate > endDate`.
179
180
 
181
+ Requires Screenplay 4.199.0 (ESM v26; `screenplay --version`) for Date/DateTime
182
+ comparisons; older binders report PLAY0268. Read [date comparisons](references/date-comparisons.md)
183
+ when ordering a retention window with `require to >= from`, comparing instants
184
+ across offsets, or rejecting offset-less inputs before rules. It covers admitted
185
+ positions, PLAY0268/0273, ordinal `then` matching and Stage's v26 refusal.
186
+
180
187
  **Rules whose logic is code.** A bare `rule <Name>` has no portable meaning (`PLAY0268`) and a bodied rule binds only as
181
188
  opaque code. Read [references/validate-rules.md](references/validate-rules.md) when a rule's logic must live in a `file`
182
189
  or fenced code body.
183
190
 
184
- **Put format rules on the `concept`, not the command.** A concept carries its own
191
+ **Put format rules on the `concept`, not the command** (except date comparisons,
192
+ which bind only on command properties, not as concept rules). A concept carries its own
185
193
  `validate` block and every use inherits it — that is Screenplay's type system, and
186
194
  a rule that travels is worth more than one that is repeated.
187
195
 
@@ -281,7 +289,9 @@ Four contexts, and **what each omits is load-bearing** — when writing a code b
281
289
  bundle compatibility and execution are separate checks.
282
290
  - [ ] No unintended `PLAY0478` or `PLAY0479` information remains.
283
291
  - [ ] At most one command property carries `identifier`, and no event property does.
284
- - [ ] Format rules live on the `concept`; state-dependent rules are specifications.
292
+ - [ ] Format rules live on the `concept` except command-only date comparisons;
293
+ state-dependent rules are specifications. DateTime comparisons preserve UTC
294
+ ticks; specs include missing-offset Validation rejection.
285
295
  - [ ] Every `authorize` combining policies writes `and`/`or` explicitly.
286
296
  - [ ] Protected reads opt in, meet admission and distinguish reference protection
287
297
  from target realization; legacy reads and `concurrency` imply no protection.
@@ -0,0 +1,100 @@
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
+ # Chronological command date comparisons
5
+
6
+ Requires Screenplay 4.199.0 (ESM v26; `screenplay --version`); older binders refuse date comparisons with PLAY0268. Upgrade the compiler without weakening the rule.
7
+
8
+ Use `==`, `!=`, `>`, `>=`, `<` or `<=` with matching primitives: Date/Date or
9
+ DateTime/DateTime. A concept may type a command property; date rules on the concept
10
+ itself remain refused. These are the admitted positions:
11
+
12
+ | Position | Left | Right |
13
+ | --- | --- | --- |
14
+ | `require`, `produces when` | Required scalar command property | Required scalar command property of the same primitive, or literal |
15
+ | Command/property validation rule | Subject property | Literal only |
16
+
17
+ `Date` orders calendar dates without a time zone. `DateTime` compares UTC instants
18
+ at tick precision (seven fractional digits), including `==`/`!=`: different offsets
19
+ can name equal instants. Literal operands bind to canonical text (`yyyy-MM-dd`, or
20
+ UTC `yyyy-MM-ddTHH:mm:ss.fffffffZ`). An unparsable date literal or an offset-less
21
+ DateTime literal in an admitted position reports PLAY0273.
22
+
23
+ Every participating DateTime input must carry an offset or `Z`. Otherwise input
24
+ validation rejects the command with Validation **before any rule or condition**,
25
+ even if the comparison would short-circuit or its production would be skipped.
26
+ Targets must enforce this before deserialization attaches a local offset, and
27
+ preserve tick precision or refuse the comparison; JavaScript `Date` alone truncates
28
+ precision. Client validators omit date ordering rules. Optional absent values still
29
+ pass validation rules other than `not empty`; optional condition operands refuse.
30
+
31
+ PLAY0268 still refuses mixed Date/DateTime, `$context` operands (including
32
+ `$context.occurred`), `today`, protected read paths, date rules on concepts and
33
+ reaction `where`. A refused whole comparison reports only PLAY0268, without
34
+ validating its literals. A `given clock` does not admit `today` or now.
35
+ Stage refuses v26 with STAGE-ESM-016; standalone binding/reference execution is
36
+ not rendering. Preserve the rule and route delivery to authorized gap-fill.
37
+
38
+ ## Retention window and rejection specifications
39
+
40
+ Two required DateTime inputs express a caller-chosen interval, not the server's
41
+ clock. Keep state-dependent retention-policy reads separately protected; this
42
+ example models only interval ordering. `then` matching remains ordinal, as do
43
+ keys, constraints and freshness: preserve the exact produced payload spelling,
44
+ not a different offset that happens to name the same instant.
45
+
46
+ ```screenplay
47
+ concept WindowId : Uuid
48
+ module Retention
49
+ feature Windows
50
+ slice StateChange KeepWindow
51
+ command KeepWindow
52
+ windowId WindowId identifier
53
+ from DateTime
54
+ to DateTime
55
+ validate
56
+ require to >= from
57
+ message "The window must not end before it starts"
58
+ produces event WindowKept
59
+ from DateTime = from
60
+ to DateTime = to
61
+ specification AcceptingEqualInstantsWithDifferentOffsets
62
+ when KeepWindow
63
+ windowId = "3fa85f64-5717-4562-b3fc-2c963f66afa6"
64
+ from = "2026-10-01T10:00:00+02:00"
65
+ to = "2026-10-01T08:00:00Z"
66
+ then WindowKept
67
+ for "3fa85f64-5717-4562-b3fc-2c963f66afa6"
68
+ from = "2026-10-01T10:00:00+02:00"
69
+ to = "2026-10-01T08:00:00Z"
70
+ specification RejectingAnInvertedWindowByOneTick
71
+ when KeepWindow
72
+ windowId = "3fa85f64-5717-4562-b3fc-2c963f66afa6"
73
+ from = "2026-10-01T08:00:00.0000002Z"
74
+ to = "2026-10-01T08:00:00.0000001Z"
75
+ then error "The window must not end before it starts"
76
+ specification AcceptingAnIncreasingWindow
77
+ when KeepWindow
78
+ windowId = "3fa85f64-5717-4562-b3fc-2c963f66afa6"
79
+ from = "2026-10-01T08:00:00Z"
80
+ to = "2026-10-01T09:00:00Z"
81
+ then WindowKept
82
+ for "3fa85f64-5717-4562-b3fc-2c963f66afa6"
83
+ from = "2026-10-01T08:00:00Z"
84
+ to = "2026-10-01T09:00:00Z"
85
+ ```
86
+
87
+ Extract the complete fence into an ignored `.ai-work/` model folder. Run
88
+ `screenplay <folder> --warnaserror --no-color` (zero errors/warnings), then
89
+ `screenplay test <folder>` (all three specifications passed, none Unsupported).
90
+
91
+ ## Missing-offset input rejection
92
+
93
+ Add a `RejectingAMissingOffset` test at the evaluator-request or target input
94
+ boundary: submit `from = "2026-10-01T08:00:00"` with a valid `to`, then reverse which
95
+ input lacks an offset. Expect Validation before any rule, no facts, and the message
96
+ `DateTime command property 'from' requires an explicit offset or Z.` (or `'to'`).
97
+ Include a skipped-condition case where applicable. A typed `.play` fixture with
98
+ that invalid value refuses binding with PLAY0273; `then error` does not turn it
99
+ into an executed runtime rejection. Record the target test separately, not as a
100
+ passing `.play` specification or a `given clock` workaround.
@@ -5,6 +5,7 @@
5
5
  - Choosing a strategy
6
6
  - When not to
7
7
  - The concept declares how; the property declares that
8
+ - Generation context binding
8
9
  - Inspect and edit generation through MCP
9
10
  - Generated-concept rules (ESM v20)
10
11
  - Version and freshness
@@ -94,6 +95,35 @@ checks only suffix shape on fixtures. `generate sequence` stays reserved (PLAY06
94
95
  and compliance markers on generated concepts, including secrets, remain refused.
95
96
  Never remove classification to make a model bind.
96
97
 
98
+ ## Generation context binding
99
+
100
+ Requires Screenplay 4.181.1 or later (`screenplay --version`) for per-target context
101
+ binding and tenant value formatting; older context documentation does not establish
102
+ that binding. The version-1 ValueGeneration descriptor is language-neutral: `Now`
103
+ (an instant), portable `TenantId` `Tenant`, and a String result. The selected provider,
104
+ not a `csharp` fence or file attachment, chooses the native context type.
105
+
106
+ The Cratis C# target (Arc and Stage's Cratis target contract) binds it to Fundamentals'
107
+ `Cratis.Concepts.GenerationContext` (`DateTimeOffset Now`, `string Tenant`). BCL-only
108
+ hosts can use `Cratis.Screenplay.Contexts.GenerationContext` (`Now`, `TenantId Tenant`);
109
+ that package stays BCL-only. The types are name-compatible, not type-identical.
110
+
111
+ For portable C# bodies, use `context.Now`, BCL operations and the tenant as text:
112
+ `$"{context.Tenant}:{context.Now:yyyyMMdd}"`. `TenantId` formats as its value;
113
+ compare that formatted string ordinally when a tenant comparison is needed.
114
+ Passing `context` to `GenerateValue.*`, naming `GenerationContext` or
115
+ `GenerationContext.DefaultTenant`, constructing a context, or reading
116
+ `context.Tenant.Value` is target-bound.
117
+
118
+ For example, `generate rule TenantReceiptNew` can own the inline `csharp` body
119
+ `return $"{context.Tenant}:{GenerateValue.Ulid(context)}";` on the Cratis C# binding.
120
+ Do not insert a bridge to Screenplay's record or promise another provider accepts it.
121
+ Arc can recover such self-contained compound bodies under the adapter gate in
122
+ [generated recovery](../../cratis-screenplay-legacy-extraction/references/generated-recovery.md).
123
+ Recovery does not run the body; reference execution consumes a String pin, opaque
124
+ entropy cannot supply an identifier, and Stage rendering still refuses `generate rule`
125
+ with STAGE-ESM-028. A target binding contract is not released renderer support.
126
+
97
127
  ## Inspect and edit generation through MCP
98
128
 
99
129
  A concept `generation` summary and entropy repairs are available.
@@ -105,9 +105,19 @@ explicit `apply`. The repair inserts into the domain document or sole document,
105
105
  refuses ambiguous roots and requires individual review, never fix-all. It changes
106
106
  absence/conflict behavior, not merely formatting.
107
107
 
108
- Stage admits ESM v25 but refuses protected reads with STAGE-ESM-044 in rendering,
109
- Host serving and specification execution; a reference pass is not Stage or Arc
110
- realization. Preserve the model's protection and deliver authorized hand-written
111
- consistency enforcement through the render-and-gap-fill workflow. Never remove
112
- the preamble to get a render. `screenplay <root> --warnaserror` must exit zero;
108
+ Stage admits ESM v25, but the Cratis C# renderer refuses protected reads with
109
+ STAGE-ESM-044: no artifacts are emitted. Preserve protection and deliver authorized
110
+ hand-written enforcement through render-and-gap-fill; never remove the preamble.
111
+
112
+ Requires Stage 4.129.0 for semantic Host/specification-executor protected reads;
113
+ older engines refuse STAGE-ESM-044. They require presence before requirements or
114
+ generation and use stored read properties in requirements and produced mappings,
115
+ including reaction-invoked commands. Any non-Error requirement on a protected
116
+ command refuses STAGE-ESM-045 before execution, even when a rejection is expected.
117
+ Legacy Host and structural runner still refuse the preamble with STAGE-ESM-044.
118
+ The semantic Host faults on any outside append, even an unrelated one, before
119
+ committing an accepted command: stricter than dependency-scoped reference conflicts,
120
+ not proof of full conflict parity. Read Stage's [sandbox boundaries](../../cratis-stage-rendering-and-sandbox/references/sandbox-and-specrunner.md#protected-command-reads).
121
+ A semantic-engine pass is separate from reference behavior and from generated Arc
122
+ protection. `screenplay <root> --warnaserror` must exit zero;
113
123
  `screenplay test <root>` separately establishes reference behavior, not target support.
@@ -23,6 +23,16 @@ modifier generates check digits but does not add validation. Check digits catch
23
23
  typos, not forgery. For generated-concept proof statuses, deterministic regex
24
24
  limits and PLAY0688 repairs, read [generated rules](generated-values-and-responses.md#generated-concept-rules-esm-v20).
25
25
 
26
+ ## Date and DateTime comparisons
27
+
28
+ Requires Screenplay 4.199.0 (ESM v26; `screenplay --version`); older binders refuse
29
+ with PLAY0268. Command/property rules admit `==`, `!=`, `>`, `>=`, `<`, `<=` against
30
+ a same-primitive date literal only, for example `to >= "2026-01-01T00:00:00Z"` on
31
+ DateTime. Property-to-property comparisons instead use `require to >= from`.
32
+ Date rules on concepts remain refused; an absent optional value passes rules
33
+ except `not empty`. Read [date comparisons](date-comparisons.md) for UTC ticks,
34
+ input offsets, refused positions and the complete retention-window specifications.
35
+
26
36
  ## `not empty` means non-blank text
27
37
 
28
38
  On text, `not empty` rejects null, empty text and whitespace-only text; at least
@@ -75,5 +85,5 @@ implementation. Attached command handlers and `file` constraints remain PLAY0268
75
85
  Literal text rules, portable patterns and Studio desugaring: [text and match rules](text-and-match-rules.md).
76
86
  Stage renders pure reducer transitions and opaque policy bodies, but refuses command and
77
87
  concept code validations and rule predicates (STAGE-ESM-005): those are gap-fill code. Prefer a
78
- declarative rule when one can say it. What binds and what the executable model rejects (Date and
79
- DateTime comparisons, nested-path rules): `cratis-screenplay-toolchain` `references/executable-subset.md`.
88
+ declarative rule when one can say it. What binds and what the executable model rejects
89
+ (date comparisons outside command positions, nested-path rules): `cratis-screenplay-toolchain` `references/executable-subset.md`.
@@ -4,6 +4,9 @@
4
4
  "fixtures": [],
5
5
  "assertions": [
6
6
  { "kind": "play-compiles" },
7
+ { "kind": "skill-contains", "value": "require to >= from", "file": "references/date-comparisons.md" },
8
+ { "kind": "skill-contains", "value": "RejectingAMissingOffset", "file": "references/date-comparisons.md" },
9
+ { "kind": "skill-contains", "value": "STAGE-ESM-016", "file": "references/date-comparisons.md" },
7
10
  { "kind": "skill-contains", "value": "Unsupported (`ImplementationBody`)", "file": "references/described-handlers.md" },
8
11
  { "kind": "skill-contains", "value": "including Stub mode", "file": "references/described-handlers.md" },
9
12
  { "kind": "skill-contains", "value": "DecisionStateChanged", "file": "references/protected-reads.md" },
@@ -174,8 +174,8 @@ compile or will not be safe. Both are deliberate.
174
174
  rejects and matching decide/commit changes conflict. Read
175
175
  [protected reads](../cratis-screenplay-command-surface/references/protected-reads.md)
176
176
  for the strict shape and paths. Legacy reads remain PLAY0271; `concurrency` is
177
- not protection and cannot combine with protected reads. Stage refuses protected reads
178
- (STAGE-ESM-044), not v25 itself: name target enforcement separately rather than claiming a render.
177
+ not protection and cannot combine with protected reads. The Cratis C# renderer refuses protected reads
178
+ (STAGE-ESM-044), not v25 itself: semantic Host/executor support is not generated-app protection.
179
179
  Write state-dependent rules as `reads` plus `require` with an indented message;
180
180
  mark refused shapes as unenforced and name the intended target mechanism. Model uniqueness as a `unique` constraint. Never copy state into a
181
181
  command input, add an attestation flag, or hide the rule in `handler` prose. Do not
@@ -34,7 +34,7 @@ Tool versions and consumer boundaries: toolchain `SKILL.md`.
34
34
  | Compliance concepts | Bare `pii`/`personal` and `secret`, qualifiers and scope bind as v13; enum/identity compliance and events combining personal or explicitly subject-scoped secret values with an explicit `subject` mark refuse PLAY0268 at binding only. A CLI bundle that admits v13 binds markers; Stage renders v13 protection, not protected identities/enums or subject lineage. Never remove protection |
35
35
  | Identity details / processing purposes / event subject | Report-only metadata; executable detail reads refuse PLAY0268, not source declaration errors |
36
36
  | Composite stream ids | v8 routing; complete named parts/canonical comparisons, PLAY0515 refuses protected keys/sources; not a legacy text split |
37
- | Command reads/concurrency | Eligible reads opt into v25 with `command reads protected`; legacy reads/concurrency retain PLAY0271; Stage refuses protected reads (STAGE-ESM-044), not the v25 pair |
37
+ | Command reads/concurrency | Eligible reads opt into v25 with `command reads protected`; legacy reads/concurrency retain PLAY0271; the Cratis C# renderer refuses protected reads (STAGE-ESM-044), not the v25 pair; semantic Host/executor support is separate |
38
38
  | Invokes-only trigger reads | Report-only, not protected state; direct production with reads refuses |
39
39
  | Generated values/responses | v7 binding/reference execution; v15 strategies/strict fixtures/freshness. Stage renders supported UUID/String strategies, responses and fixtures; unsupported types/combinations remain -028/-038 |
40
40
  | Sources/streams and command/specification routes | v8 binding/reference execution; the CLI (toolchain `references/renderable-subset.md`) reaches Stage checks through its bundled ceiling (v16 without v17 support) |
@@ -123,8 +123,20 @@ Guid, RandomNumberGenerator and GenerateValue are allowlisted; multi-statement
123
123
  bodies can qualify. Compound time-based calls must pass the captured context.
124
124
  Private helpers, fields, DI, aliases/static imports, ambient time, raw Default
125
125
  comparisons and external dependencies remain SP0073; no file fallback is invented.
126
- This is the Cratis C# binding to Fundamentals' GenerationContext, not a universal
127
- runtime type. Opaque entropy is unknown, so a rule cannot supply an identifier.
126
+ For example, a proven forwarding factory returning
127
+ `new($"{context.Tenant}:{context.Now:yyyyMMdd}:{GenerateValue.Ulid(context)}")`
128
+ recovers `generate rule <Concept>New` with inline body
129
+ `return $"{context.Tenant}:{context.Now:yyyyMMdd}:{GenerateValue.Ulid(context)}";`.
130
+ The compound call remains a rule, not an inferred built-in ULID strategy.
131
+
132
+ This uses the Cratis C# binding to Fundamentals' `Cratis.Concepts.GenerationContext`,
133
+ not Screenplay's BCL-only record. Passing `context` to `GenerateValue.*` makes the
134
+ body target-bound; a `csharp` tag alone does not select that binding. `Now` and the
135
+ tenant formatted as text are the portable subset; other providers must admit the
136
+ body against their own native type. Read the command-surface [binding guide](../../cratis-screenplay-command-surface/references/generated-values-and-responses.md#generation-context-binding)
137
+ when deciding whether to retain target-bound code. Recovery preserves the body but
138
+ neither executes it nor proves another target can compile it. Opaque entropy is
139
+ unknown, so a rule cannot supply an identifier.
128
140
  The concept owns `generate`; each command property only marks generation.
129
141
  Use the shared [strategy reference](../../cratis-screenplay-command-surface/references/generated-values-and-responses.md)
130
142
  for exact encodings, ranges, entropy and admission, rather than duplicating them.
@@ -271,9 +271,10 @@ See read-surface `references/named-keys.md` for the collection-key exclusion alg
271
271
  | Atomic reaction batches (ESM v22) | Root `reaction batches atomic`; direct productions per occurrence and selected refusal branches are separate batches, commands independent; Stage refuses v22 and atomic mode |
272
272
  | Described handlers (ESM v23) | Pending implementation beside unconditional produces; payload-only contract, reached body Unsupported ImplementationBody; Stage STAGE-IMPL-002 even Stub mode |
273
273
  | Ordinal text rules (ESM v24) | contains/not contains/starts with/ends with on scalar non-enum text properties; quoted literals, not conditions; Stage semantic engines execute/render |
274
- | Protected command reads (ESM v25) | Root `command reads protected`; eligible read paths in requirements and production mappings, absence Validation, concurrent matching facts Conflict; Stage admits v25 but refuses protected reads STAGE-ESM-044 |
274
+ | Protected command reads (ESM v25) | Root `command reads protected`; eligible read paths in requirements and production mappings, absence Validation, concurrent matching facts Conflict; Stage admits v25; Cratis C# rendering refuses STAGE-ESM-044, semantic Host/executor execute admitted reads with non-Error protected requirements refused STAGE-ESM-045 |
275
+ | Chronological command dates (ESM v26) | Same-primitive Date/DateTime `==`, `!=`, `>`, `>=`, `<`, `<=` in require/produces-when (property or literal RHS) and command/property rules (literal RHS only). DateTime uses UTC ticks, participating offset-less inputs reject Validation before rules; then matching stays ordinal. Requires Screenplay 4.199.0 (`screenplay --version`); older binders refuse PLAY0268. Stage refuses v26 STAGE-ESM-016. Read command-surface `references/date-comparisons.md`. |
275
276
  | Current routing and actor admission | Sources/streams and command/specification routes bind and reference-execute as v8; reaction `runs as system role` supplies the invocation actor as v10. Whole-workspace binding determines executable availability; CLI/Stage realization remains separate |
276
- | Blocks binding (`PLAY0268`) | enum/identity compliance and events combining personal or explicitly subject-scoped secret values with explicit subject marks; a compiler that stops before v13 refuses all `pii`/`secret` concepts ("compliance attributes require portable data-subject semantics"), while v13 binds them and Stage renders protection; attached command `handler` (PLAY0035 beside productions; pending described intent instead binds v23), bare `rule <Name>`, read paths without protected opt-in or in unsupported positions such as `produces when`, dates and `today` in comparisons, `$context.tenant`/claims/roles/causation in `produces`, `$env` conditions, `file` constraints, unquoted `import` of an external contract, a read model with neither explicit `key` nor unambiguous query-based identity as described above (composite keys remain unadmitted), queries with context `from` sources (typed query context is unadmitted), single-result filters (collections only), `scoped to` (opaque scope), `performer` (opaque implementation) or composite `by` blocks; optional keyed and collection queries, including caller-supplied equality filters and observable delivery, bind, `$causedBy` and templates in projections |
277
+ | Blocks binding (`PLAY0268`) | enum/identity compliance and events combining personal or explicitly subject-scoped secret values with explicit subject marks; a compiler that stops before v13 refuses all `pii`/`secret` concepts ("compliance attributes require portable data-subject semantics"), while v13 binds them and Stage renders protection; attached command `handler` (PLAY0035 beside productions; pending described intent instead binds v23), bare `rule <Name>`, read paths without protected opt-in or in unsupported positions such as `produces when`, date comparisons with mixed primitives, optional condition operands, `$context`, protected read paths or `today`, date rules on concepts or reaction `where`, `$context.tenant`/claims/roles/causation in `produces`, `$env` conditions, `file` constraints, unquoted `import` of an external contract, a read model with neither explicit `key` nor unambiguous query-based identity as described above (composite keys remain unadmitted), queries with context `from` sources (typed query context is unadmitted), single-result filters (collections only), `scoped to` (opaque scope), `performer` (opaque implementation) or composite `by` blocks; optional keyed and collection queries, including caller-supplied equality filters and observable delivery, bind, `$causedBy` and templates in projections |
277
278
  | Blocks binding (`PLAY0271`, legacy meaning) | Command reads without protected opt-in and `concurrency`; combined protected reads/concurrency is PLAY0783 |
278
279
  | Deferred (`PLAY0269`, information) | Screens, layouts, templates, forms, contributions, UI profiles, themes, behaviors and `on`/`uses` |
279
280
  | Metadata only (`PLAY0270`, information) | `domain`, `seed`, `persona`, trigger and other descriptions, and `file` provenance on declarations |
@@ -64,7 +64,7 @@ the problem, the checks it violates, the fix, all pinned to one declaration.
64
64
  | Undeclared removal/append event | `remove with` or capture `append` names an undeclared event | V1 warns (PLAY0166, a failure under warnings as errors); binding fails PLAY0273 | C (executable) / D | declare or fix the name; run V3 |
65
65
  | Gated command invoked by a reaction without a declared actor | reaction `invokes` a command under a caller policy and has no `runs as system role "<Role>"` that satisfies the gate | the invocation carries no caller: rejected at run time | D (major) | declare `runs as system role "<Role>"` with the least-privilege role the gate admits (ESM v10, Screenplay 4.125.0; Stage 4.89.1 renders role/authenticated trusted actors, but claim-reading/opaque gates still refuse STAGE-ESM-034 and need gap-fill) or record another trusted-path decision - never just delete the gate. A matching `runs as system role` is the admitted trusted path, not a defect |
66
66
  | `reads` + `produces` reaction | reaction both reads a view and produces | fails binding | C (executable) | invoke a command, or produce without reads |
67
- | Unadmitted read claimed protected | rule "checked" by legacy command or trigger reads | no protected contract or target realization | D (major) | opt eligible command reads into `command reads protected` (v25); inspect shape, absence and conflict cases. Stage refuses protected reads (STAGE-ESM-044); distinguish reference protection from target evidence; checklist E3 |
67
+ | Unadmitted read claimed protected | rule "checked" by legacy command or trigger reads | no protected contract or target realization | D (major) | opt eligible command reads into `command reads protected` (v25); inspect shape, absence and conflict cases. The Cratis C# renderer refuses protected reads (STAGE-ESM-044); distinguish reference/semantic-engine evidence from generated-app protection; checklist E3 |
68
68
  | Caller-supplied state rule | `require currentStatus == "open"` where the caller sends `currentStatus` | the caller decides its own permission | D (major) | read authoritative stored state through admitted protected reads and `require`; mark legacy/refused shapes and target realization as gaps; checklist E3 |
69
69
  | `severity warning` as soft rule | rule meant to warn but still rejects | blocks valid requests | C semantics | remove or make it a real rule |
70
70
  | Relay events | `*Synced`, `*Forwarded` events that only move data | noise, not facts | D | translate once into a business fact |
@@ -123,7 +123,7 @@ the format in `worked-example.md`.
123
123
  |---|---|---|---|
124
124
  | E1 | Value formats on `concept`s; input rules on the command; uniqueness as `constraint`; access as `authorize` | declarations | D |
125
125
  | E2 | Every refusal has a message a person understands; constraint messages copied verbatim in specs | `message`, specs | D |
126
- | E3 | A state-dependent rule uses `reads` + `require` over authoritative state: eligible reads opt into `command reads protected` (v25), with required absence and decide/commit conflict cases. Legacy/refused reads are marked unenforced with a named target. Stage refuses protected reads (STAGE-ESM-044); reference protection is not target realization. Not: caller-supplied copies of state, attestation booleans (`confirmsX == true`), rules in `handler` / `implementation hint` prose, or `reads` treated as protection | slice `description`, `require`, `handler` | D (faking or hiding = major) |
126
+ | E3 | A state-dependent rule uses `reads` + `require` over authoritative state: eligible reads opt into `command reads protected` (v25), with required absence and decide/commit conflict cases. Legacy/refused reads are marked unenforced with a named target. The Cratis C# renderer refuses protected reads (STAGE-ESM-044); reference/semantic-engine evidence is not generated-app protection. Not: caller-supplied copies of state, attestation booleans (`confirmsX == true`), rules in `handler` / `implementation hint` prose, or `reads` treated as protection | slice `description`, `require`, `handler` | D (faking or hiding = major) |
127
127
  | E4 | `severity warning` is not used as "soft" validation (it still rejects) | validate lines | C semantics |
128
128
  | E5 | Preconditions are explicit; nothing relies on "obviously you can't" | descriptions, specs | Q |
129
129
  | E6 | Each invariant has an atomic enforcement point (name the storage provider where constraint admission matters); the race loser's outcome is specified | constraints, specs | D |
@@ -11,7 +11,7 @@ instruction for the work, not background reading. Skills that restate one cite i
11
11
  6. **Keep semantic identity independent of names, paths, layout and generated symbols.** Commit the identity catalog with the model.
12
12
  7. **Keep unsupported intent visible.** Return a precise gap and its owning issue; never weaken the model so rendering passes.
13
13
  8. **Write specifications with intent, including rejection and denial.** Never report an unexecuted or unsupported scenario as passed.
14
- 9. **Treat state reads as a correctness boundary.** Eligible command reads opt into `command reads protected` (v25); legacy/trigger reads remain unprotected. Stage refuses protected reads (STAGE-ESM-044), not the v25 pair: reference absence/conflict guarantees and verified target realization are different claims.
14
+ 9. **Treat state reads as a correctness boundary.** Eligible command reads opt into `command reads protected` (v25); legacy/trigger reads remain unprotected. The Cratis C# renderer refuses protected reads (STAGE-ESM-044), not the v25 pair: reference absence/conflict guarantees, semantic-engine execution and generated-app protection are different claims.
15
15
  10. **Separate event-source identity from event payload and choose destinations explicitly.**
16
16
  11. **Persisted event shape changes are evolution, never cleanup.** Keep historical generations.
17
17
  12. **Model external work as business intent.** Provider interfaces and transport mechanics stay out of the language.
@@ -21,7 +21,7 @@ speaks in them; never model board mechanics (lanes, node ids, positions).
21
21
  | Storyline (ordered beats) | a **family** of specifications sharing example data, each one transition (no storyline syntax) | several spec classes | specifications |
22
22
  | Field validation | concept `validate` (every use) / command `validate`, `require` | `ConceptValidator<T>` / `CommandValidator<T>` | command validation |
23
23
  | Role permission ("Cannot") | `policy` + `authorize` + `then denied` spec; ownership via `claim ... matches subject` | `[Authorize(Policy)]`, generated policies | authorization |
24
- | Precondition on stream state | `command reads protected` + eligible `reads`/`require` (v25 reference protection); legacy/refused reads remain stated intent. Stage refuses protected reads (STAGE-ESM-044); target Arc `[ProtectedDecision]` + `DecisionRead<T>` or Chronicle DCB needs separate verification | decision over a guarded read | command validation |
24
+ | Precondition on stream state | `command reads protected` + eligible `reads`/`require` (v25 reference protection); legacy/refused reads remain stated intent. The Cratis C# renderer refuses protected reads (STAGE-ESM-044); semantic-engine execution is separate from generated-app protection. Target Arc `[ProtectedDecision]` + `DecisionRead<T>` or Chronicle DCB needs separate verification | decision over a guarded read | command validation |
25
25
  | Generated id (`derived:uuid4()`) | `generated` (authorable, not executable) | id supplied before `Handle()` | commands |
26
26
  | External system / outbound call | `Translate` slice (inbound); `system`/`operation` (authorable, not executable) or Automation (outbound) | `ICommandOperation` / reactor | operations, reactors |
27
27
  | HTML mockup | `screen` Level 1 + board (`visualize-model`) | default Scene composition | ui composition |
@@ -35,8 +35,9 @@ Tool versions are covered in `cratis-screenplay-toolchain` `SKILL.md`; read it b
35
35
  ## Language modes that block target delivery
36
36
 
37
37
  Read [language admission](../cratis-screenplay-toolchain/references/language-admission.md)
38
- for v22–v25: Stage refuses atomic batches, described bodies (even Stub mode) and
39
- protected reads. Preserve contracts; reference success is not target realization.
38
+ for v22–v25: Stage rendering refuses atomic batches, described bodies (even Stub mode)
39
+ and protected reads. Semantic Host/executor support is not generated-app protection.
40
+ Preserve contracts; reference success is not target realization.
40
41
 
41
42
  ## Interview phase
42
43
  **Skip if** the request names the model root, the application name, the destination and the
@@ -111,7 +111,9 @@ invoked commands independent. Stage refuses v22 (STAGE-ESM-016) and atomic mode
111
111
  in admitted v23–v25 (STAGE-ESM-043); the declaration is not external-effect deduplication.
112
112
  For described handlers, hand off only payload computation under the v23 result
113
113
  contract; Stage STAGE-IMPL-002 means no stubs, even Stub mode. Protected v25 reads
114
- refuse STAGE-ESM-044 despite version admission and need target admission/enrollment tests; ordinary injection never supplies protection.
114
+ refuse Cratis C# rendering with STAGE-ESM-044 despite version admission and need
115
+ generated-app admission/enrollment tests; ordinary injection never supplies protection.
116
+ Semantic Host/executor support is a separate result, not generated-app enforcement.
115
117
 
116
118
  ## Re-delivery
117
119
  The work list is the full in-scope contract delta since the fallback record's last verified source
@@ -31,10 +31,15 @@ ESM). Only the probe answers renderability. `PLAY0270` entries are information,
31
31
  | Class | Meaning | Typical examples (each verified in `admission.md`) | Action |
32
32
  | --- | --- | --- | --- |
33
33
  | **Model fix (in mode)** | the model is in, or the user chose, renderable mode and breaks its own subset in a way that has a renderable equivalent with the same meaning | a `produces` whose `for` is not the command identifier; two projections for one read model (`-007`); a policy Stage cannot express portably (`-015`; role-only and opaque pure policies render) | edit request to the modeler session with address, change and rationale |
34
- | **Capability gap** | the intended meaning needs a construct Stage does not render yet | DateTime equality filters and required parameters after optional filters (`-010`); context/single-result filters, opaque `scoped to`/`performer` and composite `by` remain PLAY0268; Translate, clocks, captures, non-event triggers and opaque reaction bodies (`-024`); claim-reading/opaque `runs as` gates (`-034`), legacy `from` (`-035`), mixed effects in one handler (`-037`, retries can duplicate events; keep it whole), unsupported reaction mappings (`-039`); unsupported generated types/result combinations (`-028`/`-038`); `then no readmodel` (`-027`); evolved events (`STAGE-ESM-026`); unsupported expression/enum production conditions (`-006`; supported conditional productions render); legacy reads (`PLAY0271`), protected reads (STAGE-ESM-044 despite v25 admission); code validation (`-005`); protected identities/enums (`-040`) or unadmitted explicit subject lineage (`PLAY0268`); attached command handlers (PLAY0268), described handlers (v23, STAGE-IMPL-002 even Stub mode), atomic mode (STAGE-ESM-016 for v22, STAGE-ESM-043 in admitted v23–v25) | keep the model; fallback record entry; options a to c in `SKILL.md`; link the Stage issue |
34
+ | **Capability gap** | the intended meaning needs a construct Stage does not render yet | DateTime equality filters and required parameters after optional filters (`-010`); context/single-result filters, opaque `scoped to`/`performer` and composite `by` remain PLAY0268; Translate, clocks, captures, non-event triggers and opaque reaction bodies (`-024`); claim-reading/opaque `runs as` gates (`-034`), legacy `from` (`-035`), mixed effects in one handler (`-037`, retries can duplicate events; keep it whole), unsupported reaction mappings (`-039`); unsupported generated types/result combinations (`-028`/`-038`); `then no readmodel` (`-027`); evolved events (`STAGE-ESM-026`); unsupported expression/enum production conditions (`-006`; supported conditional productions render); legacy reads (`PLAY0271`), protected-read rendering (STAGE-ESM-044 despite v25 admission; semantic Host/executor support is separate); code validation (`-005`); protected identities/enums (`-040`) or unadmitted explicit subject lineage (`PLAY0268`); attached command handlers (PLAY0268), described handlers (v23, STAGE-IMPL-002 even Stub mode), atomic mode (STAGE-ESM-016 for v22, STAGE-ESM-043 in admitted v23–v25) | keep the model; fallback record entry; options a to c in `SKILL.md`; link the Stage issue |
35
35
  | **Tool skew** | the bundled compiler disagrees with documented semantics | the false `PLAY0285` on reaction cascades from an older bundle; codes the standalone compiler does not raise | record in the session state and the fallback record; never "fix" a correct model |
36
36
  | **Environment** | not the model | restore failures, missing SDK, a destination that is not writable | fix the environment or report blocked |
37
37
 
38
+ Requires Stage 4.129.0 for semantic Host/executor protected reads; older engines
39
+ refuse STAGE-ESM-044. Non-Error protected requirements refuse STAGE-ESM-045, including
40
+ reaction invocations. A semantic-engine pass does not resolve the rendering gap;
41
+ read [sandbox boundaries](../../cratis-stage-rendering-and-sandbox/references/sandbox-and-specrunner.md#protected-command-reads).
42
+
38
43
  ## Triage rules
39
44
  - A capability gap never becomes a model fix by deleting meaning. Turning a list screen into a
40
45
  keyed lookup, dropping `pii`, removing authorization or a rule, or splitting a conditional
@@ -87,6 +87,16 @@ when these inputs are unsettled; skip answered questions.
87
87
  ## Scenario types (decide each per command; detail in `references/scenario-catalogue.md`)
88
88
  Decide each of these per command: happy path; rule rejection (one spec per rule, exact pinned `then error`); denial (`given caller` without the policy, `then denied`, one per gated command and query); state violation; duplicate or retry; competing claim; alternative path; ordering; external failure; compensation; evolution; and the view pass. Read [references/scenario-catalogue.md](references/scenario-catalogue.md) ("Scenario types at a glance") for each type's question and usual shape.
89
89
 
90
+ For command Date/DateTime ordering, cover increasing and inverted intervals,
91
+ equality across offsets, a one-tick boundary and **each participating DateTime
92
+ input without an offset or Z**. That last case rejects with Validation before rules,
93
+ even if a condition short-circuits or a production is skipped. `then` stays ordinal;
94
+ never replace payload text with an equivalent instant. Read the complete
95
+ [retention-window specifications](../cratis-screenplay-command-surface/references/date-comparisons.md)
96
+ for the compiler prerequisite, admitted positions, refused `today` and Stage's v26
97
+ refusal. Missing-offset runtime coverage needs an evaluator-request or target input
98
+ test: a typed `.play` fixture rejects that value at binding with PLAY0273, before runtime.
99
+
90
100
  For recovery, `when redelivered <Event> to <Reaction>` must select one definitely
91
101
  matching effective given and no undecided candidate. It delivers only to the named
92
102
  reaction without re-appending the input; `then no events` explicitly checks no
@@ -126,7 +136,8 @@ proved and keep other guarantees as target requirements; recovery cases are in
126
136
  opaque source text, not the capture's content key.
127
137
  - Format rules belong on a `concept`: give each concept rule representative acceptance,
128
138
  rejection and boundary specs once (through one command that carries it), not on every use;
129
- never `n/a` automatically. Include a whitespace-only rejection for text `not empty`:
139
+ never `n/a` automatically. Date/DateTime comparisons are command-only, not concept rules.
140
+ Include a whitespace-only rejection for text `not empty`:
130
141
  this changes outcomes in every ESM version (Requires Screenplay 4.151.0 or later). Unicode/identity boundaries
131
142
  and evidence: command-surface `references/validate-rules.md`.
132
143
  A business rule gets one rejection spec if an expert could recognize it from its message;
@@ -4,7 +4,7 @@ This is a legacy control without `command reads protected`; the unprotected-read
4
4
  markers below describe that control, not all command reads. Eligible views can opt
5
5
  into v25; the date-rule blocker still remains. Read
6
6
  [protected reads](../../cratis-screenplay-command-surface/references/protected-reads.md)
7
- for admission and Stage's protected-read refusal (STAGE-ESM-044).
7
+ for admission and the Cratis C# renderer's protected-read refusal (STAGE-ESM-044).
8
8
 
9
9
  Complete, compiled design-mode model (marina guest berths) showing a coverage matrix turned into specifications: happy path, one rejection per rule, authorization denial, duplicate and retry, competing claim, state violation, alternative branches, compensation and a view lifecycle family. The matrix for it is in `coverage-matrix.md`; the catalogue (`scenario-catalogue.md`) names its specifications.
10
10
 
@@ -18,8 +18,8 @@ Complete, compiled design-mode model (marina guest berths) showing a coverage ma
18
18
  // + `require ... message` and marked NOT enforced in the slice descriptions, with their target
19
19
  // named. Binding reports PLAY0271/PLAY0268 for them (expected; Screenplay#129): such a model
20
20
  // is design-complete but not binding-ready, and that is reported, never "fixed" by deleting the
21
- // rules. The past-date rule (`night >= today`) is declarative too: ESM v1 has no runtime date,
22
- // so binding reports PLAY0268 on it (recorded as blocked, not moved into prose); the rule and its rejection
21
+ // rules. The past-date rule (`night >= today`) is declarative too: `today` has no runtime date
22
+ // value, so binding reports PLAY0268 on it (recorded as blocked, not moved into prose); the rule and its rejection
23
23
  // specification stay so the intent executes once a date value exists.
24
24
  // Verified: V1 (warnings as errors). V3 binding is blocked by the stored-state and date rules.
25
25
 
@@ -36,7 +36,7 @@ module Berths
36
36
  authorize IsHarbourOffice
37
37
 
38
38
  slice StateChange ReserveBerth
39
- description "One guest boat per berth per night. OneBoatPerBerthNight declares that two event sources cannot hold the same berth-night; the competing-claim specification pins the loser's rejection after an earlier holder. It neither runs two commands at once nor proves the runtime's index-and-append behaviour under failure: that needs target-level verification. A retried ReserveBerth with the same reservation id is refused by ReserveOnce: the fact occurs once, but the retry is NOT answered with success, so a client that lost the first acknowledgement must treat this rejection as 'already reserved' (idempotent handling is a target decision, recorded as an open question). The night must not be in the past: declared in `validate` (`night >= today`) with its rejection specification. Binding reports PLAY0268 for date comparisons today (ESM v1 has no runtime date value), so this rule is design-complete but blocks V3 until Screenplay supports it."
39
+ description "One guest boat per berth per night. OneBoatPerBerthNight declares that two event sources cannot hold the same berth-night; the competing-claim specification pins the loser's rejection after an earlier holder. It neither runs two commands at once nor proves the runtime's index-and-append behaviour under failure: that needs target-level verification. A retried ReserveBerth with the same reservation id is refused by ReserveOnce: the fact occurs once, but the retry is NOT answered with success, so a client that lost the first acknowledgement must treat this rejection as 'already reserved' (idempotent handling is a target decision, recorded as an open question). The night must not be in the past: declared in `validate` (`night >= today`) with its rejection specification. Binding reports PLAY0268 for the `today` operand, which has no runtime date value (comparisons between Date or DateTime command properties, or against literals, bind), so this rule is design-complete but blocks V3 until Screenplay supports `today`."
40
40
  command ReserveBerth
41
41
  reservationId ReservationId identifier
42
42
  berth BerthCode
@@ -99,7 +99,7 @@ module Berths
99
99
  boatLength = 31
100
100
  then error "Guest berths take boats up to 24 metres"
101
101
 
102
- // Declarative past-date rule; binding is blocked for date comparisons (see header).
102
+ // Declarative past-date rule; binding is blocked for the `today` operand (see header).
103
103
  specification RejectingANightInThePast
104
104
  given caller
105
105
  authenticated