@cratis/pi 7.103.0 → 7.103.1

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.
@@ -121,7 +121,32 @@ At most one command property may carry `identifier`. It names the value the
121
121
  runtime uses as the event source id, so **choosing it is choosing the stream
122
122
  boundary** — the highest-consequence decision in the slice. Leave it out only
123
123
  when the runtime should allocate a fresh `Uuid` (a command that creates
124
- something whose identity the caller does not supply).
124
+ something whose identity the caller does not supply); for a create command prefer
125
+ `generated identifier` below, which also keeps the id out of the rendered form.
126
+
127
+ **A command that creates something has no caller-supplied id.** Declare
128
+ `<id> <IdConcept> generated identifier` (ESM v7, Screenplay 4.68.0 or later) and `returns <id>` when the
129
+ caller needs it back. Symptom of getting it wrong: `organizationId OrganizationId identifier` on a create
130
+ command makes the rendered form ask the user to type an Organization Id. Keep plain `identifier` for
131
+ commands that act on an existing stream (the id comes from the selected row). Specifications pin the
132
+ allocated value with `for "<value>"` in `when` and `then` (see the generated-values reference). Read
133
+ [generated values](references/generated-values-and-responses.md) before writing one.
134
+
135
+ ```screenplay excerpt
136
+ command RegisterOrganization
137
+ organizationId OrganizationId generated identifier
138
+ name OrganizationName
139
+ produces event OrganizationRegistered
140
+ name OrganizationName = name
141
+ returns organizationId
142
+ specification RegistersAnOrganization
143
+ when RegisterOrganization
144
+ for "11111111-1111-1111-1111-111111111111"
145
+ name = "Acme"
146
+ then OrganizationRegistered
147
+ for "11111111-1111-1111-1111-111111111111"
148
+ name = "Acme"
149
+ ```
125
150
 
126
151
  - A second `identifier` on the same command is an error: *only one property can be
127
152
  the identifier*.
@@ -282,6 +282,23 @@ of a document a reader cannot check at a glance.
282
282
 
283
283
  Read [pdl-grammar.md](references/pdl-grammar.md) when checking exact syntax, interpreting a projection diagnostic code, or needing a worked example.
284
284
 
285
+ ## `STAGE-ESM-017` on a projection passes `validate` and fails at `render`
286
+
287
+ Symptom: `cratis screenplay validate --executable` exits 0, then `cratis render` (or `render --check`)
288
+ refuses with `STAGE-ESM-017` and a generic message whose location is a `sem1:<hash>`, not a source line
289
+ (seen on Stage 4.192.0 and CLI 3.94.0). Cause: `validate --executable` binds only Screenplay's model;
290
+ Stage's admission runs only in `render`. Check every `from` block in turn:
291
+
292
+ 1. **Key.** An event property or the event source. A root `from` also accepts a constant text key (nonempty, only letters, digits, `_`, space and `. / : * + -`); any other literal key, and a literal key outside a root, is refused.
293
+ 2. **Do not overwrite the key.** A mapping onto the key property must restate the key itself (`from E` keyed by the event source with `berthId = $eventSourceId`, or the key's own event property); mapping a different value onto it is refused (`MatchesKey`). Simplest is to leave the key property unmapped.
294
+ 3. **`$eventSourceId` into a non-key target** is admitted in a `from` block keyed by an event property, when every command and reaction producing the event addresses it with a non-collection value of exactly the target's type (optionality ignored). It is refused in `join`s, for a mismatched type, and for an event nothing produces.
295
+ 4. **No `$context.*`.** Map an event property instead and have the command set it. The compiler may refuse it first (`PLAY0152`); Stage refuses a context value in a projection with `STAGE-ESM-017`.
296
+ 5. **Targets.** A target path through an optional or non-composite intermediate is refused; an optional leaf and a path through required composites are fine. The event property mapped from must exist on the event.
297
+
298
+ Bisect: run `cratis render <root> --target cratis --name <App> --destination <dir> --check` (plans,
299
+ writes nothing), comment out `from` blocks one at a time until the error clears, then apply the list to
300
+ the block that cleared it. Reference: `cratis-stage-rendering-and-sandbox` `references/admission.md`.
301
+
285
302
  ## Verify
286
303
 
287
304
  - [ ] Standalone `screenplay <model> --warnaserror` reports zero errors and zero
@@ -178,6 +178,23 @@ Adapters and non-renderable scope follow the contract rules of `cratis-applicati
178
178
  Never `.cratis-render/` (the journal directory) and never `.ai-work/`.
179
179
  - Limits stated in this text are prompt policy unless a guard enforces them; say so.
180
180
 
181
+ ## Hand-written query logic and re-render
182
+
183
+ Symptom: a today-relative query (overdue, due today) was written by editing the body of a generated query
184
+ file; the next `render` refused with `Managed artifact '<file>' was modified by the user; pass --force to
185
+ replace it.` Query filters are equality only and there is no `today` in a filter or projection, so this
186
+ logic is gap-fill. Cause: a managed file's hash is in `.cratis-render.json`, and an edited one blocks the
187
+ whole re-render. What to do:
188
+
189
+ - Never edit a managed file. Put the logic in a new unmanaged file, for example `Customizations/<Name>.cs`
190
+ (compiled with the project, never replaced by `render`), with its own endpoint or query class, and record it
191
+ as gap-fill (`references/gap-fill-handoff.md`).
192
+ - `--force` replaces the edited managed file with the generated one and discards the edit; use it only with
193
+ approval that names the file.
194
+ - Screens reported as `PLAY0269` are information that the backend profile defers them. They are not
195
+ proof of a rendered screen: check the running app (`cratis-screenplay-toolchain` `references/fast-path.md`)
196
+ and list any authored screen that is missing as not rendered.
197
+
181
198
  ## Gate
182
199
 
183
200
  Before reporting done:
@@ -277,11 +277,19 @@ For view specifications:
277
277
  - [ ] Queries cover out-of-rule concept arguments with `then error`; a valid
278
278
  absent key uses `then no result`. Projections still cannot reject events.
279
279
 
280
+ ## Run the specs before calling the work done
281
+
282
+ Symptom: a model delivered with specifications that were never run. `screenplay test <root>` runs the
283
+ reference evaluator; after a render, run `dotnet test` (Debug) in the destination for the generated
284
+ specification classes. Report both results separately (`cratis-screenplay-toolchain` V4 and V5.tests); a
285
+ build that succeeds is not a test run, and `unbound`/`unsupported` is not a pass.
286
+
280
287
  ## Verify
281
288
 
282
289
  - [ ] Validate the complete root with warnings as errors, naming tool/version.
283
290
  Standalone tool version: `cratis-screenplay-toolchain/SKILL.md`. Run specification examples through
284
291
  `screenplay test`; expected unadmitted syntax reports unbound, not passed.
292
+ - [ ] `screenplay test` and, after a render, `dotnet test` were run and their counts reported.
285
293
  - [ ] Executable diagnostics are clean too: `PLAY0350`, `PLAY0352`, `PLAY0388`,
286
294
  `PLAY0389` and `PLAY0273` are only reported at binding.
287
295
  - [ ] Every slice has at least one boundary specification.
@@ -218,7 +218,7 @@ unresolved questions: the standalone tool has `--open-questions fail`; `cratis s
218
218
  does through `--open-questions report|fail`. It is separate from compilation and `--warnaserror`.
219
219
  Requires Cratis CLI 3.60.0 or later (`cratis --version`) for that option; older CLIs lack it.
220
220
 
221
- Read [fast path](references/fast-path.md) for the ordered requirements-to-running-app checklist (validate, `render --check`, render, build, run).
221
+ Read [fast path](references/fast-path.md) for the ordered requirements-to-running-app checklist (validate, `render --check`, render, build, run, check in a browser, run the specs).
222
222
 
223
223
  ## Route near misses
224
224
 
@@ -171,6 +171,7 @@ module Billing
171
171
  table InvoiceRow
172
172
  column number label "Number"
173
173
  action RegisterInvoice
174
+ label "Register invoice"
174
175
  specification ListingAnInvoice
175
176
  given caller // module + feature gates apply to the query too
176
177
  authenticated
@@ -20,5 +20,12 @@ Run these in order and stop at the first failure; each step catches what the one
20
20
  8. **Frontend:** in `<dir>`, `yarn` then `yarn dev` (npm: `npm install`, `npm run dev`); open the URL Vite
21
21
  prints. It proxies API calls to the backend.
22
22
 
23
+ 9. **Verify in a browser:** open the Vite URL, load every screen the model authored (sidebar and each screen title),
24
+ run one create command and one query, and read the console for errors. The check is the app, not the build:
25
+ a screen reported as `PLAY0269` (deferred from the backend profile, information only) is not evidence that
26
+ it was rendered. List any authored screen that is absent as not rendered; do not call it delivered.
27
+ 10. **Specs:** `dotnet test` in `<dir>` (the generated specifications) and `screenplay test <root>`; see
28
+ `cratis-screenplay-specifications`.
29
+
23
30
  The rendered `README.md` repeats steps 6-8 for the pinned scaffold. Re-render and gap-fill rules:
24
31
  `cratis-screenplay-render-and-gap-fill`.
@@ -72,3 +72,4 @@ Traps 39 to 44 are tool traps.
72
72
  45. A reducer cannot be re-keyed: its instances follow the event-source id, so a query `by` another identity type warns PLAY0690 (`--warnaserror` fails it; editors only show it when the host supplies native findings). Aggregate by a payload value with a projection keyed on each `from`, or a join: projections [reducer identity](../../cratis-screenplay-projections/references/reducer-identity.md).
73
73
  46. Enum members are lowercase identifiers (`hourly`, not `Hourly`; PLAY0009). A specification states every property of the command and events, optional ones too (PLAY0524). A read model with two `*Id` properties needs one keyed query, `query OrderById => Order optional` with `by orderId String` (PLAY0268 otherwise). A `require` message goes on the next indented line (trap 38). Screen list queries are `observable`.
74
74
  47. Cratis events have no optional properties (STAGE-ESM-005), and `validate --executable` does not catch it: run `cratis render <folder> --target cratis --name <App> --destination <dir> --check` right after validate, since it runs the renderer's admission and writes nothing.
75
+ 48. `STAGE-ESM-017` on a projection also passes `validate --executable` and shows only a `sem1:` location, not the `from` block. Run `render --check` after validate, then follow the checklist and bisect in projections `SKILL.md` ("`STAGE-ESM-017` on a projection").
@@ -270,6 +270,44 @@ precedence, PLAY0485 and examples.
270
270
 
271
271
  A `ui profile` selects the application shell with `root template` (an own layout or application-scope screen template, or `blueprint <B> <Name>` with an optional `version` pin), its shell `option` lines, an `appearance` block (`color scheme`, `accent`), the template new screens start from (`new screens use template`), the theme and the `packages`, listed in override-priority order (a later package shadows an earlier one); `target platform` and `target size` accept any identifier, so a typo is silent. The legacy `layout <Name>` line inside a profile still reads but warns `PLAY0791`: write `root template`. `PLAY0790` to `PLAY0799` check the shell. Read [references/ui-profile-and-theme.md](references/ui-profile-and-theme.md) when writing a profile or theme, or fixing a shell diagnostic.
272
272
 
273
+ ## A deliverable app declares its identity, titles and labels
274
+
275
+ Symptom: a rendered app titled "Cratis Stage" whose buttons and dialogs show raw command names. The renderer
276
+ defaults to those when the model is silent, so declare, in every deliverable app:
277
+
278
+ - the layout's `logo image "<path>" title "<text>"` inside `navigation topbar` or `navigation sidebar` (the
279
+ application title the shell shows; `logo initials` is only valid in a profile's `identity`);
280
+ - a `ui profile` with `root template`, shell `option` lines such as `option showFooter false`, and an `identity`
281
+ block (`name`, `logo initials`);
282
+ - a `title "<text>"` in each screen and a navigation `item <id> title "<text>" target <Module.Feature>` per screen;
283
+ - `label "<text>"` on **every** `action`.
284
+
285
+ ```screenplay excerpt
286
+ layout AppShell
287
+ category application
288
+ content
289
+
290
+ navigation sidebar
291
+ logo image "/assets/solocrm.svg" title "SoloCRM"
292
+ item organizations title "Organizations" target Crm.Organizations
293
+
294
+ ui profile Desktop
295
+ target platform web
296
+ root template AppShell
297
+ option showFooter false
298
+ identity
299
+ name "SoloCRM"
300
+ logo initials "SC"
301
+ ```
302
+
303
+ ```screenplay excerpt
304
+ screen Organizations
305
+ data OrganizationOverview[] via query AllOrganizations
306
+ title "Organizations"
307
+ action RegisterOrganization
308
+ label "New organization"
309
+ ```
310
+
273
311
  ## Localized strings
274
312
 
275
313
  Localized text lives in companion `.strings` files and is referenced unquoted as `$strings.<dotted.key>`. Read [references/localized-strings.md](references/localized-strings.md) when localizing messages, labels or titles.
@@ -294,6 +332,8 @@ Localized text lives in companion `.strings` files and is referenced unquoted as
294
332
  - [ ] Every theme a profile selects is `compatible with` one of its packages.
295
333
  - [ ] `target platform` and `target size` values are spelled correctly; nothing
296
334
  checks them.
335
+ - [ ] A deliverable app declares layout `logo ... title`, a `ui profile` with `option` lines and `identity`,
336
+ a `title` per screen and a `label` on every `action`.
297
337
  - [ ] User-visible text is `$strings.` where the application is localized.
298
338
  - [ ] No `file` reference is doing work the declaration should be doing.
299
339
  - [ ] Every click, submit and screen entry that does something has an `on` or
@@ -73,6 +73,7 @@ module Billing
73
73
  returns invoiceId
74
74
  screen CreateInvoiceScreen
75
75
  action CreateInvoice
76
+ label "Create invoice"
76
77
  slice StateView Details
77
78
  readmodel Invoice
78
79
  invoiceId InvoiceId
@@ -23,6 +23,7 @@ module Marina
23
23
  data BerthListView[] via query ListBerths
24
24
  action BookBerth
25
25
  navigate to BerthListScreen
26
+ label "Book berth"
26
27
  slice StateView BerthList
27
28
  readmodel BerthListView
28
29
  berthId BerthId
@@ -251,8 +251,9 @@ Stage renders two projection forms; the restrictions differ.
251
251
  inside a child are admitted), `nested`
252
252
  over an optional composite property, and `every`/`all` with set-from-event-source mappings. Keys
253
253
  are an event property or the event source. The key establishes the identifier, so it must
254
- end up unmapped: a mapping onto it is refused unless it copies the key's own event
255
- property, so an event-source key admits no mapping at all (`STAGE-ESM-017`). Auto-map
254
+ end up unmapped: a mapping onto it is refused unless it restates the key (the key's own
255
+ event property, `$eventSourceId` for an event-source key, or the same literal)
256
+ (`STAGE-ESM-017`). Auto-map
256
257
  counts as a mapping: if the event carries a property with the identifier's name and type,
257
258
  declare `no automap` and map the other properties explicitly. `from E` and
258
259
  `from E key $eventSourceId` render when the identifier ends up unmapped, whether or not
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cratis/pi",
3
- "version": "7.103.0",
3
+ "version": "7.103.1",
4
4
  "description": "Configuration-aware Cratis AI integration for Pi",
5
5
  "type": "module",
6
6
  "files": [