@cratis/pi 7.122.0 → 7.122.2

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 (20) hide show
  1. package/package/corpus/skills/cratis-screenplay-read-surface/SKILL.md +1 -1
  2. package/package/corpus/skills/cratis-screenplay-read-surface/references/named-keys.md +1 -1
  3. package/package/corpus/skills/cratis-screenplay-read-surface/verification.json +5 -1
  4. package/package/corpus/skills/cratis-screenplay-render-and-gap-fill/references/renderability-gate.md +1 -1
  5. package/package/corpus/skills/cratis-screenplay-streams-and-consistency/references/read-model-keys.md +4 -0
  6. package/package/corpus/skills/cratis-screenplay-streams-and-consistency/verification.json +2 -1
  7. package/package/corpus/skills/cratis-screenplay-toolchain/references/diagnostics.md +3 -3
  8. package/package/corpus/skills/cratis-screenplay-toolchain/references/executable-subset.md +1 -1
  9. package/package/corpus/skills/cratis-screenplay-toolchain/references/language-admission.md +1 -1
  10. package/package/corpus/skills/cratis-screenplay-toolchain/references/preferred-syntax.md +1 -1
  11. package/package/corpus/skills/cratis-screenplay-toolchain/verification.json +6 -1
  12. package/package/corpus/skills/cratis-screenplay-ui-composition/SKILL.md +2 -0
  13. package/package/corpus/skills/cratis-screenplay-ui-composition/references/change-alternatives.md +58 -0
  14. package/package/corpus/skills/cratis-screenplay-ui-composition/references/guarded-interactions.md +7 -5
  15. package/package/corpus/skills/cratis-screenplay-ui-composition/verification.json +13 -1
  16. package/package/corpus/skills/cratis-stage-rendering-and-sandbox/SKILL.md +1 -1
  17. package/package/corpus/skills/cratis-stage-rendering-and-sandbox/references/admission.md +4 -2
  18. package/package/corpus/skills/cratis-stage-rendering-and-sandbox/references/current-boundaries.md +8 -3
  19. package/package/corpus/skills/cratis-stage-rendering-and-sandbox/verification.json +7 -1
  20. package/package.json +1 -1
@@ -295,7 +295,7 @@ bindings; the selected command still enforces its own gate/rules/constraints.
295
295
  Read [guarded actions](references/guarded-actions.md) for the checked model,
296
296
  missing-versus-null behavior and source-versus-renderer boundary. For a gesture
297
297
  choosing a whole action list rather than one labeled command, use block-form
298
- `when`/`otherwise` on click/double click/select:
298
+ `when`/`otherwise` on click, double click, select or change:
299
299
  [guarded interactions](../cratis-screenplay-ui-composition/references/guarded-interactions.md).
300
300
 
301
301
  ## How a bare name resolves
@@ -229,7 +229,7 @@ Requires Stage 4.137.0 for v27 admission (older Stage refuses the whole model wi
229
229
  `STAGE-ESM-016`). The semantic Host runs composite-keyed read models and the CLI's `cratis run`
230
230
  default engine runs them (Requires Cratis CLI 3.75.0); the legacy `eventmodel` engine and the specification
231
231
  executor refuse them. Rendering refuses a read model with several key parts or a projection keyed by
232
- parts (`STAGE-ESM-048`) and a single-instance query by parts (`STAGE-ESM-047`, pending Chronicle#4265),
232
+ parts (`STAGE-ESM-048`; a DateTime part, a `Decimal` part or a concept over `Decimal` is always refused, because Chronicle keeps a decimal key part's scale and a replay can split `1.0` and `1.00` into two instances; the decimal refusal lifts with Stage#847 once Chronicle#5427 lands) and a single-instance query by parts (`STAGE-ESM-047`, pending Chronicle#4265),
233
233
  and publishes nothing, so `cratis render` cannot deliver it. Verify and reference-test the model with the
234
234
  standalone compiler, then hand the delivery to gap-fill
235
235
  (`cratis-screenplay-render-and-gap-fill`) with the model as the contract. Composite-keyed read models get
@@ -21,6 +21,10 @@
21
21
  { "kind": "skill-contains", "value": "warnings, not errors" },
22
22
  { "kind": "skill-contains", "value": "the executable model binds `observable` queries" },
23
23
  { "kind": "skill-contains", "value": "A compiling query is not evidence that access control works" },
24
- { "kind": "skill-contains", "value": "are planned but **not in the language yet**" }
24
+ { "kind": "skill-contains", "value": "are planned but **not in the language yet**" },
25
+ { "kind": "skill-contains", "value": "a `Decimal` part or a concept over `Decimal` is always refused", "file": "references/named-keys.md" },
26
+ { "kind": "skill-contains", "value": "a replay can split `1.0` and `1.00` into two instances", "file": "references/named-keys.md" },
27
+ { "kind": "skill-contains", "value": "the decimal refusal lifts with Stage#847 once Chronicle#5427 lands", "file": "references/named-keys.md" },
28
+ { "kind": "skill-contains", "value": "`when`/`otherwise` on click, double click, select or change:" }
25
29
  ]
26
30
  }
@@ -35,7 +35,7 @@ ESM). Only the probe answers renderability. `PLAY0270` entries are information,
35
35
  | Class | Meaning | Typical examples (each verified in `admission.md`) | Action |
36
36
  | --- | --- | --- | --- |
37
37
  | **Model fix (in mode)** | the model is in, or the user chose, renderable mode and breaks its own subset in a way that has a renderable equivalent with the same meaning | a `produces` whose `for` is not the command identifier; two projections for one read model (`-007`); a policy Stage cannot express portably (`-015`; role-only and opaque pure policies render) | edit request to the modeler session with address, change and rationale |
38
- | **Capability gap** | the intended meaning needs a construct Stage does not render yet | DateTime equality filters and required parameters after optional filters (`-010`); context/single-result filters, opaque `scoped to` and a list-query `by` block remain PLAY0268; an unsupported query performer (observable, a non-C# body, or a missing, changed or non-compiling body) becomes an explicit implementation gap, while a verified C# body renders ([performer bodies](../../cratis-screenplay-read-surface/SKILL.md#performer-bodies-are-rendered)); a read model with several key parts or a projection keyed by parts (v27) refuses `STAGE-ESM-048` and a single-instance query by parts `STAGE-ESM-047` (Chronicle#4265); Translate, clocks, captures, non-event triggers and opaque reaction bodies (`-024`); claim-reading/opaque `runs as` gates (`-034`), legacy `from` (`-035`), mixed effects in one handler (`-037`, retries can duplicate events; keep it whole), unsupported reaction mappings (`-039`); unsupported generated types/result combinations (`-028`/`-038`); `then no readmodel` (`-027`); evolved events (`STAGE-ESM-026`); unsupported expression/enum production conditions (`-006`; supported conditional productions render); legacy reads (`PLAY0271`), protected reads the renderer cannot preserve, or any protected read in an older CLI bundle (STAGE-ESM-044 despite v25 admission; semantic Host/executor support is separate); code validation (`-005`); protected identities/enums (`-040`) or unadmitted explicit subject lineage (`PLAY0268`); described handlers (v23, STAGE-IMPL-002 even Stub mode), atomic mode (STAGE-ESM-043; v22 admission Requires Stage 4.139.0, older Stage reports -016) | keep the model; fallback record entry; options a to c in `SKILL.md`; link the Stage issue |
38
+ | **Capability gap** | the intended meaning needs a construct Stage does not render yet | DateTime equality filters and required parameters after optional filters (`-010`); context/single-result filters, opaque `scoped to` and a list-query `by` block remain PLAY0268; an unsupported query performer (observable, a non-C# body, or a missing, changed or non-compiling body) becomes an explicit implementation gap, while a verified C# body renders ([performer bodies](../../cratis-screenplay-read-surface/SKILL.md#performer-bodies-are-rendered)); a read model with several key parts or a projection keyed by parts (v27) refuses `STAGE-ESM-048` (always for a DateTime or decimal key part; the decimal refusal lifts with Stage#847 once Chronicle#5427 lands) and a single-instance query by parts `STAGE-ESM-047` (Chronicle#4265); Translate, clocks, captures, non-event triggers and opaque reaction bodies (`-024`); claim-reading/opaque `runs as` gates (`-034`), legacy `from` (`-035`), mixed effects in one handler (`-037`, retries can duplicate events; keep it whole), unsupported reaction mappings (`-039`); unsupported generated types/result combinations (`-028`/`-038`); `then no readmodel` (`-027`); evolved events (`STAGE-ESM-026`); unsupported expression/enum production conditions (`-006`; supported conditional productions render); legacy reads (`PLAY0271`), protected reads the renderer cannot preserve, or any protected read in an older CLI bundle (STAGE-ESM-044 despite v25 admission; semantic Host/executor support is separate); code validation (`-005`); protected identities/enums (`-040`) or unadmitted explicit subject lineage (`PLAY0268`); described handlers (v23, STAGE-IMPL-002 even Stub mode), atomic mode (STAGE-ESM-043; v22 admission Requires Stage 4.139.0, older Stage reports -016) | keep the model; fallback record entry; options a to c in `SKILL.md`; link the Stage issue |
39
39
  | **Implementation attachment** | a permanent limitation, not future ESM admission | file/inline command handlers (PLAY0800; typed `subject` names the command) | keep the model contract and gap-fill the slice in code with a constrained implementation attachment; do not wait for a new ESM version |
40
40
  | **Tool skew** | the bundled compiler disagrees with documented semantics | the false `PLAY0285` on reaction cascades from an older bundle; codes the standalone compiler does not raise | record in the session state and the fallback record; never "fix" a correct model |
41
41
  | **Environment** | not the model | restore failures, missing SDK, a destination that is not writable | fix the environment or report blocked |
@@ -42,6 +42,10 @@ composite type only to carry flat parts: both hide the identity the model should
42
42
  composite-keyed view are PLAY0268. Stage v4.197.0 renders bounded scoped
43
43
  composite-key projections and equality-filtered lists; unsupported shapes retain
44
44
  STAGE-ESM-048 and single-instance lookup by parts retains STAGE-ESM-047.
45
+ DateTime parts and decimal parts (a `Decimal` primitive or a concept over
46
+ `Decimal`) are refused STAGE-ESM-048; a decimal part can split `1.0` and `1.00`
47
+ into two instances on replay, and the refusal lifts with Stage#847 once
48
+ Chronicle#5427 lands. Choose a non-decimal key part.
45
49
  Semantic Host support does not imply specification-executor support for
46
50
  multi-part keys. See [Stage key boundaries](../../cratis-stage-rendering-and-sandbox/references/current-boundaries.md#renderer-support-is-bounded).
47
51
 
@@ -24,6 +24,7 @@
24
24
  { "kind": "skill-contains", "value": "decision tree and red flags" },
25
25
  { "kind": "skill-contains", "value": "bind and reference-execute as ESM v8" },
26
26
  { "kind": "skill-contains", "value": "generated values give no\n idempotency, retry or deduplication guarantee" },
27
- { "kind": "skill-contains", "value": "Stage construct checks through its bundled ceiling" }
27
+ { "kind": "skill-contains", "value": "Stage construct checks through its bundled ceiling" },
28
+ { "kind": "skill-contains", "value": "Choose a non-decimal key part.", "file": "references/read-model-keys.md" }
28
29
  ]
29
30
  }
@@ -296,11 +296,11 @@ Routes do not by themselves select v17: redelivery executes as v17 (Requires Scr
296
296
 
297
297
  | Code | Severity | Meaning / fix |
298
298
  | --- | --- | --- |
299
- | PLAY0560 | E | Alternatives on a non-item trigger; only click/double click/select admit them. |
299
+ | PLAY0560 | E | Alternatives on a non-item trigger; only click, double click, select or change admit them. |
300
300
  | PLAY0561 | E | Alternatives mixed with plain actions or `where`; choose one form. |
301
301
  | PLAY0562 | E | Empty branch; supply a nonempty action list. |
302
302
  | PLAY0563 | E | One-line labeled-action `when … execute …` in an interaction; use an indented list. C# offers a typed repair. |
303
- | PLAY0564 | W/I | Item-trigger opaque `where` deprecated: a strict item condition warns with a C# repair to one `when`, no fallback; other text is information with no repair. Other triggers unchanged. |
303
+ | PLAY0564 | W/I | Item-trigger opaque `where` deprecated: a strict item condition warns with a C# repair to one `when`, no fallback; other text is information with no repair. Other triggers unchanged, including `change`, which keeps opaque `where`. |
304
304
 
305
305
  PLAY0563/0564 repairs need individual review and canonical formatting, refuse
306
306
  comment loss and do not support pinned evidence. TypeScript diagnoses but does
@@ -425,7 +425,7 @@ refusal reasons. Read [language admission](language-admission.md) before changin
425
425
  | PLAY0787 (W) | Exact deprecated Studio text-rule pattern; repair to literal rule or equality, preserving message/severity |
426
426
  | STAGE-ESM-043 | Atomic mode not realized in admitted v22–v27; retain declaration and gap-fill (v22 admission Requires Stage 4.139.0; older Stage reports -016) |
427
427
  | STAGE-ESM-047 | Single-instance query by composite key parts (v27) in the renderer, until Chronicle can look up composite keys (Chronicle#4265); keep the query, gap-fill |
428
- | STAGE-ESM-048 | Read model with several key parts, or projection keyed by parts (v27), in the renderer or legacy syntax engine; keep the model, gap-fill |
428
+ | STAGE-ESM-048 | Read model with several key parts, or projection keyed by parts (v27), in the renderer or legacy syntax engine; also a DateTime part or a decimal part (`Decimal` or concept over `Decimal`, replay can split `1.0`/`1.00`; lifts with Stage#847 once Chronicle#5427 lands). Keep the model, gap-fill |
429
429
  | STAGE-ESM-044 | Renderer refuses a protected read despite v25 admission: any protected read in a bundle that predates protected-read rendering, afterwards only shapes it cannot preserve (constrained events, read paths in `produces when`, optional/collection/composite/mistyped mapping targets, freshness scopes), naming the reason; the legacy Host/structural runner refuse the preamble. Semantic Host/executor support is separate; keep protection and gap-fill generated-app scope |
430
430
  | STAGE-ESM-045 | Non-Error protected requirement; semantic Host/executor refuse before execution, including reaction-invoked commands; keep severity and report Unsupported |
431
431
  | STAGE-IMPL-002 | Described handler body not realized by Stage, even Stub mode; no stubs emitted |
@@ -289,7 +289,7 @@ joins, `children`, `remove via join`, `every`, `all`, `nested`, `clear with`, `v
289
289
  and reducers on the composite-keyed read model, a list query with a `by` block, a
290
290
  non-optional single-instance return, and command reads (PLAY0271, or PLAY0781
291
291
  reason `by-parts` under `command reads protected`) or trigger reads that produce directly.
292
- Requires Stage 4.137.0 for v27 admission (older Stage refuses it with STAGE-ESM-016): the semantic Host runs composite-keyed read models end to end, and the specification executor refuses specifications over them as unsupported. The Cratis renderer refuses a read model with several key parts or a projection keyed by parts with STAGE-ESM-048 and a single-instance query by parts with STAGE-ESM-047 (Chronicle#4265); composite-keyed read models get no conventional `Get<ReadModel>ById` query. This is independent of standalone binding and reference execution. Read read-surface
292
+ Requires Stage 4.137.0 for v27 admission (older Stage refuses it with STAGE-ESM-016): the semantic Host runs composite-keyed read models end to end, and the specification executor refuses specifications over them as unsupported. The Cratis renderer refuses a read model with several key parts or a projection keyed by parts with STAGE-ESM-048 (always for a DateTime part or a decimal part, a `Decimal` primitive or a concept over `Decimal`, which a replay can split into `1.0` and `1.00` instances; the decimal refusal lifts with Stage#847 once Chronicle#5427 lands) and a single-instance query by parts with STAGE-ESM-047 (Chronicle#4265); composite-keyed read models get no conventional `Get<ReadModel>ById` query. This is independent of standalone binding and reference execution. Read read-surface
293
293
  [named keys](../../cratis-screenplay-read-surface/references/named-keys.md) for the
294
294
  complete example.
295
295
 
@@ -23,7 +23,7 @@ exact language/semantic pairs; binding, reference execution and rendering are se
23
23
  | v24 | `contains`, `not contains`, `starts with`, `ends with` property/concept rules | Ordinal UTF-16, absent optional passes; not text-condition operators | v24 admitted; semantic Host/executor and generated ordinal comparisons preserve rules |
24
24
  | v25 | Application-root `command reads protected` | Admitted reads in requirements/mappings, absence Validation, matching decide/commit changes Conflict | v25 admitted; Cratis renderer renders protected reads in a new enough bundle (STAGE-ESM-044 before it, and for shapes it cannot preserve); semantic Host/executor execute reads, non-Error protected requirements refuse STAGE-ESM-045 |
25
25
  | v26 | Chronological command Date/DateTime comparisons | Same-primitive `==`, `!=`, `>`, `>=`, `<`, `<=`; DateTime UTC ticks and pre-rule offset validation | v26 admitted; Host/executor run it; renderer supports admitted shapes with remaining STAGE-ESM-046 refusals; legacy engines refuse -046 |
26
- | v27 | A read model with two or more `key` marks | Untyped projection `key` blocks, equality-filter lists, single-instance `by` blocks, per-part fixtures | Host supports composite keys and key-part lookups; specification execution still refuses multi-part keys; renderer admits bounded scoped parts-key projections, with STAGE-ESM-048 for unsupported shapes and -047 for single-instance lookup |
26
+ | v27 | A read model with two or more `key` marks | Untyped projection `key` blocks, equality-filter lists, single-instance `by` blocks, per-part fixtures | Host supports composite keys and key-part lookups; specification execution still refuses multi-part keys; renderer admits bounded scoped parts-key projections, with STAGE-ESM-048 for unsupported shapes (including DateTime and decimal parts) and -047 for single-instance lookup |
27
27
  | v28 | `==`/`!=` between Uuid values in command `require` and `produces when` | Uuid properties, Uuid concepts and identities, canonical literals; protected read paths in `require` only | Stage admits v28; an admitting CLI passes it to Stage's matched-pair and construct gates |
28
28
  | v29 | `decimals <= N`; `add`/`subtract` by `a * b`; a concept mapped to another concept over the same primitive (decision 0098) | Decimal-places rule on a Decimal concept or property; the exact decimal product; the conversion is admitted only when the target declares no rule or compliance the source does not, never for enums, composites or optional into required | Stage admits v29; numeric projection arithmetic and admitted decimal/concept validation have target-specific paths |
29
29
  | v30 | A command `produces ... for <required scalar property>` (several event sources); a specification `given generated <Command>.<property> = <value>` (decision 0098) | Several sources in one accepted command; pinned generated values for reaction-invoked commands, taken in authored order | Stage admits v30; generated backends preserve per-production destinations. CLI render admits v30 with an admitting bundle |
@@ -21,7 +21,7 @@ covers deliberate legacy explanations in prose; stale entries fail.
21
21
  | Source/stream identity | Omit `id` unless preserving a previous stored name | A pin equal to the current name | PLAY0507 (information) |
22
22
  | Production route | Inherit the command's route | Repeating the same `stream` / `streamId` on a production | PLAY0664 (warning) |
23
23
  | Imports | Import only declarations not already declared by the application | Importing the application's own names | PLAY0290 (warning) |
24
- | Interaction guard | Block-form `when` alternatives | Opaque interaction `where` on click, double click or select | PLAY0564 (warning or information) |
24
+ | Interaction guard | Block-form `when` alternatives | Opaque interaction `where` on click, double click or select (a `change` keeps it) | PLAY0564 (warning or information) |
25
25
  | Projection transition cardinality | Source binding emits `One` | Constructed/deserialized ESM v1–v3 `ZeroOrOne` / `Many` | PLAY0445 (warning; ESM-only, not a source spelling) |
26
26
  | Command decision reads | `command reads protected` after reviewing every read's admission, absence and conflict semantics | Eligible legacy command reads without the application-root preamble | PLAY0786 (information; individual typed repair review, never fix-all) |
27
27
  | Profile shell | `root template <Name>` in a `ui profile` | `layout <Name>` in a `ui profile` | PLAY0791 (warning; quick fix) |
@@ -80,6 +80,11 @@
80
80
  { "kind": "skill-contains", "value": "Requires Screenplay 4.212.3", "file": "references/diagnostics.md" },
81
81
  { "kind": "skill-contains", "value": "`clear with` share one set of event names", "file": "references/diagnostics.md" },
82
82
  { "kind": "skill-contains", "value": "`join` events have their own set", "file": "references/diagnostics.md" },
83
- { "kind": "skill-contains", "value": "Each children, nested and variant\nblock starts fresh sets", "file": "references/diagnostics.md" }
83
+ { "kind": "skill-contains", "value": "Each children, nested and variant\nblock starts fresh sets", "file": "references/diagnostics.md" },
84
+ { "kind": "skill-contains", "value": "a decimal part (`Decimal` or concept over `Decimal`, replay can split `1.0`/`1.00`; lifts with Stage#847 once Chronicle#5427 lands)", "file": "references/diagnostics.md" },
85
+ { "kind": "skill-contains", "value": "a `Decimal` primitive or a concept over `Decimal`, which a replay can split into `1.0` and `1.00` instances", "file": "references/executable-subset.md" },
86
+ { "kind": "skill-contains", "value": "only click, double click, select or change admit them.", "file": "references/diagnostics.md" },
87
+ { "kind": "skill-contains", "value": "including `change`, which keeps opaque `where`", "file": "references/diagnostics.md" },
88
+ { "kind": "skill-contains", "value": "(a `change` keeps it)", "file": "references/preferred-syntax.md" }
84
89
  ]
85
90
  }
@@ -243,6 +243,8 @@ and [guarded interactions](references/guarded-interactions.md).
243
243
 
244
244
  Guarded alternatives and `where` deprecation:
245
245
  [guarded interactions](references/guarded-interactions.md).
246
+ Read [change alternatives](references/change-alternatives.md) when a component's
247
+ `on change` should choose an action list by the changed item, such as a kanban move.
246
248
 
247
249
  Read [interaction example](references/interaction-example.md) when wiring a
248
250
  named confirmation behavior and an inline refresh to the same screen.
@@ -0,0 +1,58 @@
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
+ # Choose an action list by the item a change carries
5
+
6
+ Requires Screenplay 4.251.0 (`screenplay --version`); older compilers refuse
7
+ alternatives on `on change` with `PLAY0560`. `on change` accepts the same block-form
8
+ `when`/`otherwise` alternatives as click, double click and select, and `item` is the
9
+ item that changed, with the changed property already holding its new value. The first
10
+ matching `when` runs once; with no match the `otherwise` list runs, or nothing runs when
11
+ there is none; a change with no item runs nothing, including the `otherwise` list.
12
+ Compiler admission is not proof that a Stage renderer executes the gesture.
13
+
14
+ An opaque `where` on `on change` stays valid and is not deprecated by `PLAY0564`, which
15
+ applies only to click, double click and select. Do not mix `where` with alternatives.
16
+
17
+ This complete model compiles on the standalone compiler from 4.251.0. The fence is an
18
+ excerpt only because the standalone verification pin predates that release.
19
+
20
+ ```screenplay excerpt
21
+ module Conference
22
+ feature Review
23
+ slice StateView TalkBoard
24
+ event TalkSubmitted
25
+ talkId String
26
+ status String
27
+ readmodel TalkSummary
28
+ talkId String
29
+ status String
30
+ projection Talks => TalkSummary
31
+ from TalkSubmitted
32
+ talkId = $eventSourceId
33
+ status = status
34
+ query AllTalks => TalkSummary[]
35
+ command AcceptTalk
36
+ talkId String
37
+ screen ReviewBoard
38
+ data TalkSummary[] via query AllTalks
39
+ component Cratis.Blueprint.Default.kanbanBoard talkBoard
40
+ property cards from query AllTalks
41
+ property cardId = "talkId"
42
+ property cardColumn = "status"
43
+ on change
44
+ when item.status == "accepted"
45
+ execute AcceptTalk
46
+ with talkId from item.talkId
47
+ otherwise
48
+ notify warning "A talk cannot move back to Submitted"
49
+ ```
50
+
51
+ The opaque form keeps compiling on the same board, in place of the `when` list:
52
+
53
+ ```screenplay excerpt
54
+ on change
55
+ where item.status == "accepted"
56
+ execute AcceptTalk
57
+ with talkId from item.talkId
58
+ ```
@@ -3,7 +3,7 @@
3
3
 
4
4
  # Choose a gesture's whole action list
5
5
 
6
- `on click`, `on double click` and `on select` accept ordered block-form `when`
6
+ `on click`, `on double click`, `on select` and `on change` accept ordered block-form `when`
7
7
  alternatives and an optional final `otherwise`. Use the same strict condition
8
8
  language and data-item subject as [guarded screen actions](../../cratis-screenplay-read-surface/references/guarded-actions.md):
9
9
  `item.<path>` compared with a literal, joined by `and`, `or` and parentheses.
@@ -47,17 +47,19 @@ unavailable command never falls through; backend commands retain their rules.
47
47
  Unlike labeled actions, no choice was displayed beforehand to refresh at click.
48
48
 
49
49
  A table click/double click uses the activated row; select uses the newly selected
50
- item, and clearing selection runs nothing. Elsewhere use the nearest enclosing
50
+ item, and clearing selection runs nothing; change uses the item that changed (see
51
+ [change alternatives](change-alternatives.md)). Elsewhere use the nearest enclosing
51
52
  single item or selected row, with guarded actions' sibling precedence. Check named
52
53
  behaviors at each `uses` site. Component `context` or `selectedItem` bindings do
53
54
  not supply the subject in this version; unresolved/equally near subjects report
54
55
  PLAY0346.
55
56
 
56
- Submit, event, change, interval and application triggers have no alternatives.
57
+ Submit, event, interval and application triggers have no alternatives.
57
58
  The one-line `on row-click navigate to … by …` remains unchanged. Opaque `where`
58
- on click/double click/select is deprecated (PLAY0564): strict item conditions warn
59
+ on click/double click/select is deprecated (PLAY0564); a `change` keeps its opaque
60
+ `where`, which PLAY0564 does not flag. Strict item conditions warn
59
61
  and C# offers a typed repair to one `when` with no fallback; other guard text is
60
- Information without repair. Other triggers' `where` remains unchanged. Repairs
62
+ Information without repair. Other triggers' `where`, including change, remains unchanged. Repairs
61
63
  require individual review, canonical formatting, preserve comments and refuse
62
64
  comment loss; TypeScript diagnoses but offers no repair. PLAY0563 has a C# repair
63
65
  expanding a one-line alternative to the block form. Neither repair supports
@@ -243,6 +243,18 @@
243
243
  "kind": "skill-contains",
244
244
  "value": "screen-shell-navigation-positive",
245
245
  "file": "references/application-shell.md"
246
- }
246
+ },
247
+ { "kind": "skill-contains", "value": "`on click`, `on double click`, `on select` and `on change` accept ordered block-form `when`", "file": "references/guarded-interactions.md" },
248
+ { "kind": "skill-contains", "value": "change uses the item that changed", "file": "references/guarded-interactions.md" },
249
+ { "kind": "skill-contains", "value": "a `change` keeps its opaque", "file": "references/guarded-interactions.md" },
250
+ { "kind": "skill-contains", "value": "Submit, event, interval and application triggers have no alternatives.", "file": "references/guarded-interactions.md" },
251
+ { "kind": "skill-contains", "value": "Requires Screenplay 4.251.0", "file": "references/change-alternatives.md" },
252
+ { "kind": "skill-contains", "value": "component Cratis.Blueprint.Default.kanbanBoard talkBoard", "file": "references/change-alternatives.md" },
253
+ { "kind": "skill-contains", "value": "notify warning \"A talk cannot move back to Submitted\"", "file": "references/change-alternatives.md" },
254
+ { "kind": "skill-contains", "value": "An opaque `where` on `on change` stays valid and is not deprecated by `PLAY0564`", "file": "references/change-alternatives.md" },
255
+ { "kind": "skill-contains", "value": "where item.status == \"accepted\"", "file": "references/change-alternatives.md" },
256
+ { "kind": "skill-contains", "value": "including the `otherwise` list", "file": "references/change-alternatives.md" },
257
+ { "kind": "skill-contains", "value": "Compiler admission is not proof that a Stage renderer executes the gesture.", "file": "references/change-alternatives.md" },
258
+ { "kind": "skill-contains", "value": "references/change-alternatives.md" }
247
259
  ]
248
260
  }
@@ -146,7 +146,7 @@ and unaudited-version refusals still stop first. Codes, limits and fixes:
146
146
  appends/absence beyond admitted specification shapes (`-011`/`-027`), evolution (`STAGE-ESM-026`), unsupported public/foreign-event uses
147
147
  (`-032`/`-033`), claim-reading/opaque `runs as` gates (`-034`), legacy filters (`-035`), production
148
148
  overrides (`-036`), unsupported code validation (`-005`), DateTime filters (`-010`),
149
- unsupported conditional productions, unsupported composite-key projection shapes (`STAGE-ESM-048`, and `-047` for a single-instance query by parts) and unsupported `all` shapes.
149
+ unsupported conditional productions, unsupported composite-key projection shapes, including DateTime and decimal key parts (`STAGE-ESM-048`, and `-047` for a single-instance query by parts) and unsupported `all` shapes.
150
150
  Protected reads render as Arc read protection in a new enough bundle; shapes it cannot preserve, and every protected read in an older bundle, refuse `STAGE-ESM-044` (see admission.md). Described handlers still refuse `STAGE-IMPL-002` even in Stub mode. Query-performer gaps are a separate contract, not a completed implementation.
151
151
  - **Attached command handlers (`PLAY0800`):** file/inline handlers permanently require
152
152
  constrained implementation attachments: gap-fill the slice in code, not by waiting
@@ -60,7 +60,9 @@ Requires Stage 4.135.0 for v26 admission; older Stage refuses v26 with STAGE-ESM
60
60
  Requires Stage 4.137.0 for v27 admission; older Stage refuses v27 with STAGE-ESM-016.
61
61
  The reviewed semantic Host runs composite-key read models and key-part
62
62
  lookups; specification execution still refuses multi-part keys. The renderer admits bounded scoped composite-key
63
- projections, not every parts-key shape; unsupported shapes retain STAGE-ESM-048.
63
+ projections, not every parts-key shape; unsupported shapes, including DateTime
64
+ and decimal key parts (a `Decimal` primitive or a concept over `Decimal`), retain
65
+ STAGE-ESM-048.
64
66
  Single-instance query lookup by parts still refuses STAGE-ESM-047 until
65
67
  Chronicle#4265. The legacy syntax engine retains STAGE-ESM-048. See
66
68
  [current composite-key boundaries](current-boundaries.md#renderer-support-is-bounded).
@@ -205,7 +207,7 @@ Requires Stage 4.90.0 for snapshot/live lists, 4.96.0 for non-text secrets and 4
205
207
  | `STAGE-ESM-042` | Unknown validation rule kinds; checksum on the legacy syntax path (semantic checksum renders) | Keep the rule; use an admitting semantic renderer or gap-fill |
206
208
  | `STAGE-ESM-043` | Atomic shapes the renderer cannot preserve: multiple same-event production triggers or routed direct productions; semantic execution supports atomic batches | Keep the batch boundary; gap-fill refused shapes without splitting it |
207
209
  | `STAGE-ESM-044` | A protected read the Cratis renderer cannot preserve faithfully, naming the reason (every protected read before Stage 4.138.0); the legacy Host/structural runner refuse the preamble | Keep protection; gap-fill the refused command; semantic Host/executor support is separate from generated-app enforcement |
208
- | `STAGE-ESM-047`, `-048` | `-048` unsupported composite-key projection shape (legacy syntax refuses composite models); `-047` rendered single-instance lookup by parts. Semantic Host supports composite keys and key-part lookups; specification execution still refuses multi-part keys | Keep the model; check [composite boundaries](current-boundaries.md#renderer-support-is-bounded) |
210
+ | `STAGE-ESM-047`, `-048` | `-048` unsupported composite-key projection shape, including a DateTime or decimal (`Decimal` or concept over `Decimal`) key part, whose refusal lifts with Stage#847 once Chronicle#5427 lands (legacy syntax refuses composite models); `-047` rendered single-instance lookup by parts. Semantic Host supports composite keys and key-part lookups; specification execution still refuses multi-part keys | Keep the model; check [composite boundaries](current-boundaries.md#renderer-support-is-bounded) |
209
211
  | `STAGE-ESM-046` | Compared DateTime concept with compliance or optionality, or a non-camel-case compared DateTime property; older renderers and legacy engines refuse all date comparisons | Keep the date rule and protection; see [date comparisons](date-comparisons.md) |
210
212
  | `STAGE-ESM-045` | Non-Error requirement on a protected command, including reaction-invoked commands; semantic admission refuses before reads, requirements or facts | Keep the severity contract; record the execution gap, never silently promote or drop the requirement |
211
213
  | `STAGE-IMPL-002` | Described command handler, naming command and RequirementId; also refused in Stub mode | Supply authorized implementation outside rendering; no described-body stub is emitted |
@@ -48,9 +48,14 @@ reviewed caller or report the CLI blocker. The introducing CLI minimums are in
48
48
  batch. Multiple production triggers on the same event and routed direct
49
49
  productions retain `STAGE-ESM-043`. Models without the atomic declaration keep
50
50
  their prior behavior.
51
- - **Composite keys:** required single non-date primitive/concept parts in a
52
- scoped projection with complete event-property parts keys for `from`/`remove
53
- with` blocks render. Reducers, flat projections, joins, nested/child blocks,
51
+ - **Composite keys:** required single non-date, non-decimal primitive/concept
52
+ parts in a scoped projection with complete event-property parts keys for
53
+ `from`/`remove with` blocks render. A DateTime part, a `Decimal` primitive
54
+ part or a concept over `Decimal` is refused `STAGE-ESM-048`: Chronicle keeps
55
+ a decimal key part's scale, so a replay can split one instance into two when
56
+ the same value arrives as `1.0` and `1.00`. The decimal refusal lifts only when
57
+ Stage#847 lands, which needs Chronicle#5427 to key those values as one
58
+ instance; do not normalize scale in the model to get around it. Reducers, flat projections, joins, nested/child blocks,
54
59
  partial keys, collisions and protected live queries over that composite shape
55
60
  remain refused. Single-instance lookup by parts remains `STAGE-ESM-047` even
56
61
  though composite projections and equality-filtered lists can render.
@@ -59,6 +59,12 @@
59
59
  { "kind": "skill-contains", "value": "The scaffold pins an exact release of every dependency", "file": "references/rendered-application.md" },
60
60
  { "kind": "skill-contains", "value": "STAGE-CRATIS-004", "file": "references/case-tables-and-whole-numbers.md" },
61
61
  { "kind": "skill-contains", "value": "STAGE-ESM-031", "file": "references/case-tables-and-whole-numbers.md" },
62
- { "kind": "skill-contains", "value": "Requires cratis CLI" }
62
+ { "kind": "skill-contains", "value": "Requires cratis CLI" },
63
+ { "kind": "skill-contains", "value": "a concept over `Decimal` is refused `STAGE-ESM-048`", "file": "references/current-boundaries.md" },
64
+ { "kind": "skill-contains", "value": "the same value arrives as `1.0` and `1.00`", "file": "references/current-boundaries.md" },
65
+ { "kind": "skill-contains", "value": "Stage#847 lands, which needs Chronicle#5427", "file": "references/current-boundaries.md" },
66
+ { "kind": "skill-contains", "value": "required single non-date, non-decimal primitive/concept", "file": "references/current-boundaries.md" },
67
+ { "kind": "skill-contains", "value": "Single-instance lookup by parts remains `STAGE-ESM-047`", "file": "references/current-boundaries.md" },
68
+ { "kind": "skill-contains", "value": "including DateTime and decimal key parts", "file": "SKILL.md" }
63
69
  ]
64
70
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cratis/pi",
3
- "version": "7.122.0",
3
+ "version": "7.122.2",
4
4
  "description": "Configuration-aware Cratis AI integration for Pi",
5
5
  "type": "module",
6
6
  "files": [