@cratis/pi 7.106.0 → 7.108.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.
@@ -171,9 +171,9 @@
171
171
  }
172
172
  ],
173
173
  "synced": {
174
- "version": "4.235.0",
175
- "date": "2026-10-19",
176
- "by": "Cratis/AI#837"
174
+ "version": "4.244.0",
175
+ "date": "2026-10-20",
176
+ "by": "Cratis/AI#891"
177
177
  },
178
178
  "covers": {
179
179
  "skills": [
@@ -22,17 +22,35 @@ before an external effect. A request to verify does not authorize a push.
22
22
  1. Read `.github/workflows/` and the repository's tier policy. Follow reusable
23
23
  workflows and invoked scripts. Extract commands, solution and test selection,
24
24
  configuration, warning settings, analyzers, lint and formatting checks.
25
- 2. Prefer the repository's existing gate script. If none exists, keep a small
25
+ 2. Require an executable, repository-specific specification-project coverage
26
+ gate in CI; add one if absent and run its documented command locally where
27
+ inputs are available. Discover every spec project independently of CI's test
28
+ selection, then compare discovery with actual CI test commands and results.
29
+ Every project must run in some CI test job or be removed; a green subset,
30
+ a build-only job or solution membership is not execution coverage.
31
+ Follow reusable workflows and scripts, expand matrices and evaluate job/step
32
+ conditions for the relevant event and head SHA. Resolve project selection and
33
+ test filters; a command whose filters exclude all of a project's specs does
34
+ not cover it. A skipped conditional job cannot cover its assigned projects.
35
+ Keep command/filter mapping separate from runtime proof: correlate per-project
36
+ test results with the executed jobs for that SHA and require nonzero executed
37
+ specs per project. A static mapping alone cannot prove the tests ran.
38
+ Fail closed on empty or unknown discovery, unresolved selection/conditions,
39
+ missing results or uncovered projects. Print omitted project paths and the
40
+ missing/excluding job, command or filter so omissions are actionable. Pass only
41
+ when every discovered project has execution coverage; use repository tooling,
42
+ not a universal framework-specific scanner in this corpus.
43
+ 3. Prefer the repository's existing gate script. If none exists, keep a small
26
44
  local runner under `.ai-work/`, with each phase's real exit status preserved.
27
45
  Do not substitute only the touched projects for the final gate.
28
- 3. **Tier 1** is the whole-solution build with CI's configuration and warning
46
+ 4. **Tier 1** is the whole-solution build with CI's configuration and warning
29
47
  settings, lint/format, and every non-integration test project. For example,
30
48
  use Release with warnings as errors when that is what CI uses.
31
- 4. **Tier 2** adds integration tests. The repository's tier policy decides
49
+ 5. **Tier 2** adds integration tests. The repository's tier policy decides
32
50
  whether they run locally. The default is CI-backed integration only if CI
33
51
  runs that coverage, it passes before merge, and reviewer notes say it was
34
52
  deferred to CI. If CI lacks that coverage, do not claim it is verified.
35
- 5. Name anything CI runs that cannot run locally: services, platforms, secrets
53
+ 6. Name anything CI runs that cannot run locally: services, platforms, secrets
36
54
  or hosted checks. Say what ran instead and what remains unverified before
37
55
  pushing. Missing coverage is not a local pass.
38
56
 
@@ -113,7 +113,7 @@ module Integration
113
113
  source events
114
114
  from ShipmentDispatched
115
115
  from ShipmentDelivered
116
- key orderId
116
+ key orderId is event source
117
117
  append OrderDispatched
118
118
  when added
119
119
  carrier = $.carrier
@@ -163,6 +163,13 @@ must be required on every `from` event (PLAY0700); `$eventSourceId` and other co
163
163
  keys are refused. An empty or whitespace-only text key fails execution, even in a
164
164
  given before the action; non-text/non-numeric keys are Unsupported.
165
165
 
166
+ The example declares `is event source` because the producer sources every event by
167
+ `orderId`.
168
+ Requires Screenplay 4.242.0 and ESM v33. A fixture `for` must then equal the key;
169
+ without `for`, it takes the key. Unmarked captures stay unchanged. Other
170
+ sources or non-single-property keys report PLAY0809, with no automatic repair. Read
171
+ [event-source keys](../../cratis-screenplay-captures-and-reactions/references/capture-map-and-example.md#keying-by-the-event-source).
172
+
166
173
  Givens fold in authored order without appending. Each event overlays its top-level
167
174
  properties onto state for that typed key: absent properties retain earlier values;
168
175
  objects/lists replace whole values. First sight is `added` only, unchanged overlays
@@ -8,6 +8,10 @@
8
8
  { "kind": "skill-contains", "value": "then OrderShipped", "file": "references/public-events-and-direction.md" },
9
9
  { "kind": "skill-contains", "value": "typed Unsupported", "file": "references/public-events-and-direction.md" },
10
10
  { "kind": "play-compiles" },
11
+ { "kind": "skill-contains", "value": "key orderId is event source", "file": "references/public-events-and-direction.md" },
12
+ { "kind": "skill-contains", "value": "Requires Screenplay 4.242.0 and ESM v33", "file": "references/public-events-and-direction.md" },
13
+ { "kind": "skill-contains", "value": "PLAY0809, with no automatic repair", "file": "references/public-events-and-direction.md" },
14
+ { "kind": "skill-contains", "value": "Unmarked captures stay unchanged", "file": "references/public-events-and-direction.md" },
11
15
  { "kind": "skill-contains", "value": "`[ExecuteCommandsAsSystem(\"<role>\")]`" },
12
16
  { "kind": "skill-contains", "value": "ESM v10" },
13
17
  { "kind": "skill-contains", "value": "STAGE-ESM-024" },
@@ -1,5 +1,11 @@
1
1
  # Capture map and example
2
2
 
3
+ ## Contents
4
+
5
+ - Capture excerpt
6
+ - Capture `map`
7
+ - Keying by the event source
8
+
3
9
  ## Capture excerpt
4
10
 
5
11
  ```screenplay excerpt
@@ -57,6 +63,11 @@ reference is handed records (`given capture`, `when capture`) and never contacts
57
63
  (PLAY0700). Events append to the event source the key names, and
58
64
  `$context.occurred` is supplied by the scenario's `given clock`.
59
65
 
66
+ For a producer that sources every event by this key, declare
67
+ `key <property> is event source` (ESM v33, Screenplay 4.242.0).
68
+ See [Keying by the event source](#keying-by-the-event-source) below for the promise, fixture `for`
69
+ checks and the PLAY0809 restriction to single-property `source events` keys.
70
+
60
71
  An event's external origin is declared on the `event` itself with `event X from "<origin>"` (ESM v9);
61
72
  outside records still enter through a `capture` in a `Translate` slice
62
73
  (`cratis-screenplay-automations-and-translations` `references/public-events-and-direction.md`).
@@ -87,3 +98,71 @@ compile error. Split it into two `append` blocks.
87
98
 
88
99
  **`children <collection> identified by <path>`** and **`nested <path>`** each take
89
100
  an optional `map` and any number of `append` blocks.
101
+
102
+ ## Keying by the event source
103
+
104
+ Requires Screenplay 4.242.0 or later (`screenplay --version`). The marker selects
105
+ ESM v33 and serializes `keyIsEventSource` beside `sourceEvents`. A capture without
106
+ it keeps its earlier behavior, version and bytes.
107
+
108
+ Declare `key <property> is event source` only when the producer sources **every**
109
+ captured event by that property's value. This is a promise about the foreign
110
+ stream, not a request to move an event to another source. It lets a renderer that
111
+ admits v33 narrow an inbox history read by event source id. Binding and reference
112
+ execution do not prove the renderer or deployed observer realizes that promise.
113
+
114
+ Only a `source events` capture with a single property key may declare the marker.
115
+ Other capture sources or key shapes report PLAY0809, an error with no automatic
116
+ repair. The key must still be required on every `from` event (PLAY0700); the marker
117
+ does not permit `$eventSourceId` as the key expression.
118
+
119
+ ### Typed fixtures
120
+
121
+ - An explicit fixture `for` must equal the key. A mismatch rejects execution with
122
+ a contract rejection naming the capture, event and both values. Do not turn it
123
+ into an accepted `then no events` scenario.
124
+ - A fixture without `for` takes the key as its source **before** projections and
125
+ reactions see it, so `$eventSourceId` is the key.
126
+ - The check also runs while establishing givens, including a world with no action.
127
+ - Without the marker, an optional foreign fixture `for` stays opaque non-empty
128
+ text, independent of the capture key. Do not add the marker just to fix a fixture.
129
+
130
+ This complete model uses a producer that sources dispatches by `orderId`:
131
+
132
+ ```screenplay
133
+ module Shipping
134
+ feature Tracking
135
+ slice Translate ReceiveDispatches
136
+ direction inbound
137
+ event ParcelDispatched from "carrier"
138
+ orderId String
139
+ event DispatchRecorded
140
+ orderId String
141
+ capture DispatchFeed
142
+ source events
143
+ from ParcelDispatched
144
+ key orderId is event source
145
+ append DispatchRecorded
146
+ when added
147
+ orderId = $.orderId
148
+ specification RecordingADispatch
149
+ when append ParcelDispatched
150
+ for "order-42"
151
+ orderId = "order-42"
152
+ then DispatchRecorded
153
+ for "order-42"
154
+ orderId = "order-42"
155
+ specification TakingTheKeyAsSource
156
+ when append ParcelDispatched
157
+ orderId = "order-42"
158
+ then DispatchRecorded
159
+ for "order-42"
160
+ orderId = "order-42"
161
+ ```
162
+
163
+ Changing the first fixture's `for` to `"other-order"` rejects the run; it is not a
164
+ new stream to accept silently. Test that rejection and the given-only mismatch
165
+ through evaluator outcomes as well as the two successful source forms.
166
+
167
+ Authority: Screenplay [captures](https://github.com/Cratis/Screenplay/blob/main/Documentation/screenplay/captures.md#keying-by-the-event-source)
168
+ and [capture grammar](https://github.com/Cratis/Screenplay/blob/main/Documentation/screenplay/captures/grammar.md).
@@ -5,6 +5,14 @@
5
5
  "assertions": [
6
6
  { "kind": "skill-contains", "value": "unrouted facts never match" },
7
7
  { "kind": "skill-contains", "value": "source events" },
8
+ { "kind": "skill-contains", "file": "references/capture-map-and-example.md", "value": "PLAY0809, an error" },
9
+ { "kind": "skill-contains", "file": "references/capture-map-and-example.md", "value": "ESM v33" },
10
+ { "kind": "skill-contains", "file": "references/capture-map-and-example.md", "value": "key orderId is event source" },
11
+ { "kind": "skill-contains", "file": "references/capture-map-and-example.md", "value": "`keyIsEventSource` beside `sourceEvents`" },
12
+ { "kind": "skill-contains", "file": "references/capture-map-and-example.md", "value": "earlier behavior, version and bytes" },
13
+ { "kind": "skill-contains", "file": "references/capture-map-and-example.md", "value": "An explicit fixture `for` must equal the key" },
14
+ { "kind": "skill-contains", "file": "references/capture-map-and-example.md", "value": "A fixture without `for` takes the key as its source" },
15
+ { "kind": "skill-contains", "file": "references/capture-map-and-example.md", "value": "givens, including a world with no action" },
8
16
  { "kind": "play-compiles" },
9
17
  {
10
18
  "kind": "skill-contains",
@@ -8,6 +8,7 @@
8
8
  - Exact numeric source mode
9
9
  - Clause order inside a command (canonical)
10
10
  - Slice contents (typical)
11
+ - Event-source capture keys (ESM v33)
11
12
  - `$context.` paths (command `produces`)
12
13
  - `$eventContext.` (projections)
13
14
  - PDL quick reference (most forms are compiled in `pdl-example.md` or `cheat-sheet-example.md`; `remove via join` and `$eventContext.occurred` are not)
@@ -139,6 +140,17 @@ description, properties, `reads`, `authorize`, `validate`, `produces`/`handler`,
139
140
  - `slice Translate <Behaviour>`: capture and/or translator reaction + both vocabularies' events.
140
141
  - Declare each event once, in the slice that produces it; reference it by name elsewhere.
141
142
 
143
+ ## Event-source capture keys (ESM v33)
144
+
145
+ For inbound `source events` captures only, a single-property
146
+ `key <property> is event source` promises every incoming event is sourced by that
147
+ key (Screenplay 4.242.0; serializes `keyIsEventSource` beside `sourceEvents`).
148
+ Other sources/key shapes report PLAY0809, with no automatic repair. Explicit typed
149
+ fixture `for` must equal the key; omission takes the key before projections/reactions,
150
+ including givens without an action. Unmarked captures keep earlier semantics.
151
+ An admitting renderer may narrow history reads by event source id; binding is not target evidence.
152
+ Read [event-source keys](../../cratis-screenplay-captures-and-reactions/references/capture-map-and-example.md#keying-by-the-event-source) for the complete example.
153
+
142
154
  ## `$context.` paths (command `produces`)
143
155
  `occurred`, `tenant`, `command.<p>`, `arguments.<p>`, `causedBy.subject|name|userName`,
144
156
  `causation.type`, `identity.id|name|userName|isAuthenticated|roles|claims.<n>`.
@@ -5,6 +5,7 @@
5
5
  - Warnings that hide defects (always validate with `--warnings-as-errors`)
6
6
  - Source reference and identifier checks
7
7
  - Public events and translation direction
8
+ - Event-source capture keys
8
9
  - Explicit enum member numbers
9
10
  - Reserved stored names and event pins
10
11
  - Named keys, production routes and observer filters
@@ -97,6 +98,20 @@ Requires Screenplay 4.176.0 or later for PLAY0694; older compilers leave the
97
98
  legacy directionless co-location unchecked. Full capture execution and ordering:
98
99
  automations-and-translations `references/public-events-and-direction.md`.
99
100
 
101
+ ## Event-source capture keys
102
+
103
+ Requires Screenplay 4.242.0 or later (`screenplay --version`); the marker selects ESM v33.
104
+
105
+ | Code | Severity | Meaning / fix |
106
+ | --- | --- | --- |
107
+ | PLAY0809 | E | `key <property> is event source` outside a single-property `source events` capture key. Declare it only when every captured event is sourced by that property. Other sources or key shapes are errors, with no automatic repair. |
108
+
109
+ Marked typed fixtures reject an explicit `for` that differs from the key. Without
110
+ `for`, the fixture takes the key before projections/reactions. The contract checks
111
+ givens too, even without an action. This execution rejection is not PLAY0809 and
112
+ not a successful `then no events` outcome. Unmarked captures retain prior semantics.
113
+ Read captures-and-reactions [event-source keys](../../cratis-screenplay-captures-and-reactions/references/capture-map-and-example.md#keying-by-the-event-source).
114
+
100
115
  ## Explicit enum member numbers
101
116
 
102
117
  Source errors; the pins bind as ESM v12:
@@ -19,6 +19,7 @@ exact language/semantic pairs; binding, reference execution and rendering are se
19
19
  | 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 | v29 refused until Stage admits it |
20
20
  | 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 | v30 refused until Stage admits it |
21
21
  | v31 | A policy `require anonymous` for a public command or query | A deliberately public surface; the policy is the whole effective authorization | v31 refused until Stage admits it |
22
+ | v33 | `key <property> is event source` on a single-property `source events` capture (Screenplay 4.242.0; PLAY0809) | Serializes `keyIsEventSource` beside `sourceEvents`. Promises every incoming event is sourced by that key; explicit fixture `for` must equal it, while omission takes the key before projections/reactions. Checks also run on givens without an action. Unmarked captures keep earlier behavior/version/bytes | An admitting renderer may narrow history reads by event source id; binding alone does not prove target realization |
22
23
 
23
24
  Constructs of decision 0098 with no executable-model content need no version: application-level toolbar buttons in the layout's `navigation topbar` region (`button <id> title "..." slice <Slice>` with an optional indented `authorize <Policy>`), a command specification that states the public event its outbound Translate slice publishes (no more false `PLAY0285`), and a capture over events that copies a list (`lines = $.lines`) or fans out with `children lines identified by sku`. Check `screenplay --version` against the release that admitted v29 and v30 before relying on them.
24
25