@cratis/pi 2.23.1 → 2.24.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.
- package/package/corpus/rules/general.md +2 -0
- package/package/corpus/rules/profiles.md +18 -1
- package/package/corpus/skills/cratis-chronicle-event-modeling/SKILL.md +8 -0
- package/package/corpus/skills/cratis-event-model-diagram/SKILL.md +7 -0
- package/package/corpus/skills/cratis-screenplay-captures-and-reactions/LICENSE +2 -0
- package/package/corpus/skills/cratis-screenplay-captures-and-reactions/SKILL.md +229 -0
- package/package/corpus/skills/cratis-screenplay-captures-and-reactions/verification.json +10 -0
- package/package/corpus/skills/cratis-screenplay-command-surface/LICENSE +2 -0
- package/package/corpus/skills/cratis-screenplay-command-surface/SKILL.md +270 -0
- package/package/corpus/skills/cratis-screenplay-command-surface/references/context.md +111 -0
- package/package/corpus/skills/cratis-screenplay-command-surface/verification.json +23 -0
- package/package/corpus/skills/cratis-screenplay-event-modeling/LICENSE +2 -0
- package/package/corpus/skills/cratis-screenplay-event-modeling/SKILL.md +204 -0
- package/package/corpus/skills/cratis-screenplay-event-modeling/references/nine-steps.md +219 -0
- package/package/corpus/skills/cratis-screenplay-event-modeling/verification.json +23 -0
- package/package/corpus/skills/cratis-screenplay-model-authoring/SKILL.md +25 -9
- package/package/corpus/skills/cratis-screenplay-projections/LICENSE +2 -0
- package/package/corpus/skills/cratis-screenplay-projections/SKILL.md +215 -0
- package/package/corpus/skills/cratis-screenplay-projections/references/pdl-grammar.md +241 -0
- package/package/corpus/skills/cratis-screenplay-projections/verification.json +11 -0
- package/package/corpus/skills/cratis-screenplay-read-surface/LICENSE +2 -0
- package/package/corpus/skills/cratis-screenplay-read-surface/SKILL.md +188 -0
- package/package/corpus/skills/cratis-screenplay-read-surface/verification.json +10 -0
- package/package/corpus/skills/cratis-screenplay-specifications/LICENSE +2 -0
- package/package/corpus/skills/cratis-screenplay-specifications/SKILL.md +199 -0
- package/package/corpus/skills/cratis-screenplay-specifications/verification.json +19 -0
- package/package/corpus/skills/cratis-screenplay-ui-composition/LICENSE +2 -0
- package/package/corpus/skills/cratis-screenplay-ui-composition/SKILL.md +231 -0
- package/package/corpus/skills/cratis-screenplay-ui-composition/verification.json +10 -0
- package/package/corpus/skills/cratis-stage-rendering-and-sandbox/SKILL.md +5 -2
- package/package/profile-catalog.json +8 -1
- package/package.json +1 -1
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: cratis-screenplay-specifications
|
|
3
|
+
description: Pin behavior in a Cratis Screenplay `.play` model with given/when/then `specification` blocks — prior events and read-model state, the command under test, expected events, read-model state, query results and rejections, plus what the reference execution actually runs. Use when writing acceptance criteria for a slice, specifying a rejection, or deciding whether a rule belongs in a specification or in the type system. Do not use for C# or TypeScript test code.
|
|
4
|
+
license: MIT
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Screenplay specifications
|
|
8
|
+
|
|
9
|
+
A `specification` is the acceptance criterion for a slice, written in the same
|
|
10
|
+
document as the behavior it pins. Given/when/then, in business language, with
|
|
11
|
+
concrete data.
|
|
12
|
+
|
|
13
|
+
## Verified product sources
|
|
14
|
+
|
|
15
|
+
| Package | Version | Purpose |
|
|
16
|
+
| --- | --- | --- |
|
|
17
|
+
| `Cratis.Screenplay` | `4.12.1` | Parser, semantic binder, reference execution |
|
|
18
|
+
|
|
19
|
+
Read from the Screenplay repository at tag `v4.12.1` (commit `122eee8`), against
|
|
20
|
+
`Documentation/screenplay/specifications.md` and
|
|
21
|
+
`Source/DotNET/Screenplay/Parsing/SpecificationParser.cs`. Reverify before
|
|
22
|
+
claiming another version behaves the same.
|
|
23
|
+
|
|
24
|
+
## The vocabulary
|
|
25
|
+
|
|
26
|
+
| Construct | Meaning |
|
|
27
|
+
| --- | --- |
|
|
28
|
+
| `given <EventType>` | prior state, established by replaying events before the command runs |
|
|
29
|
+
| `given readmodel <ReadModelType>` | prior read-model state, established directly |
|
|
30
|
+
| `when <CommandType>` | the command under test — **at most one**; a second is a compile error |
|
|
31
|
+
| `then <EventType>` | an event expected to be produced |
|
|
32
|
+
| `then readmodel <ReadModelType>` | the read-model state expected afterwards |
|
|
33
|
+
| `then query <Query>` | ordered query results for explicit arguments |
|
|
34
|
+
| `arguments` | the values supplied to the query |
|
|
35
|
+
| `result` | one expected query result; repeat for many |
|
|
36
|
+
| `then error "<message>"` | a rejection, for the named reason |
|
|
37
|
+
| `then error` | a rejection, for a reason this specification does not name |
|
|
38
|
+
| `<property> = <value>` | a property value, using the `produces` expression grammar |
|
|
39
|
+
|
|
40
|
+
`given`, `then`, `then readmodel`, `then query` and `then error` are each zero or
|
|
41
|
+
more.
|
|
42
|
+
|
|
43
|
+
## Command specifications
|
|
44
|
+
|
|
45
|
+
```screenplay
|
|
46
|
+
specification RegisteringADraftInvoice
|
|
47
|
+
given CustomerRegistered
|
|
48
|
+
customerId = "3fa85f64-5717-4562-b3fc-2c963f66afa6"
|
|
49
|
+
name = "Acme Corp"
|
|
50
|
+
when RegisterInvoice
|
|
51
|
+
invoiceId = "9c858901-8a57-4791-81fe-4c455b099bc9"
|
|
52
|
+
customerId = "3fa85f64-5717-4562-b3fc-2c963f66afa6"
|
|
53
|
+
invoiceNumber = "INV-000123"
|
|
54
|
+
then InvoiceRegistered
|
|
55
|
+
invoiceId = "9c858901-8a57-4791-81fe-4c455b099bc9"
|
|
56
|
+
invoiceNumber = "INV-000123"
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
**`then` contains either events or an error — never both.**
|
|
60
|
+
|
|
61
|
+
## Rejections — two forms, and they say different things
|
|
62
|
+
|
|
63
|
+
```screenplay
|
|
64
|
+
specification RejectingAnInvoiceWithNoLines
|
|
65
|
+
when RegisterInvoice
|
|
66
|
+
invoiceId = "9c858901-8a57-4791-81fe-4c455b099bc9"
|
|
67
|
+
then error "An invoice must have at least one line"
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
`then error "<message>"` says **rejected, for this reason** — pinning a constraint
|
|
71
|
+
violation or a validation message down deliberately.
|
|
72
|
+
|
|
73
|
+
```screenplay
|
|
74
|
+
specification RejectingAnInvoiceWhoseNumberIsAlreadyTaken
|
|
75
|
+
given InvoiceRegistered
|
|
76
|
+
invoiceNumber = "INV-000123"
|
|
77
|
+
when RegisterInvoice
|
|
78
|
+
invoiceNumber = "INV-000123"
|
|
79
|
+
then error
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Bare `then error` says **rejected, for a reason this specification does not name**.
|
|
83
|
+
Most specifications are this kind — the reason lives in the specification's name.
|
|
84
|
+
|
|
85
|
+
## View specifications
|
|
86
|
+
|
|
87
|
+
```screenplay
|
|
88
|
+
specification SendingADraftInvoice
|
|
89
|
+
given readmodel InvoiceListReadModel
|
|
90
|
+
invoiceId = "9c858901-8a57-4791-81fe-4c455b099bc9"
|
|
91
|
+
status = "draft"
|
|
92
|
+
when ChangeInvoiceStatus
|
|
93
|
+
status = "sent"
|
|
94
|
+
then readmodel InvoiceListReadModel
|
|
95
|
+
status = "sent"
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
**Views cannot reject events.** There are no error cases for a projection.
|
|
99
|
+
|
|
100
|
+
## Query specifications
|
|
101
|
+
|
|
102
|
+
```screenplay
|
|
103
|
+
specification LookingUpARegisteredProject
|
|
104
|
+
when RegisterProject
|
|
105
|
+
projectId = "3fa85f64-5717-4562-b3fc-2c963f66afa6"
|
|
106
|
+
name = "Screenplay"
|
|
107
|
+
then query ProjectById
|
|
108
|
+
arguments
|
|
109
|
+
projectId = "3fa85f64-5717-4562-b3fc-2c963f66afa6"
|
|
110
|
+
result
|
|
111
|
+
projectId = "3fa85f64-5717-4562-b3fc-2c963f66afa6"
|
|
112
|
+
name = "Screenplay"
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Results are compared **in order**. `then query` with no `result` block asserts the
|
|
116
|
+
query returns nothing.
|
|
117
|
+
|
|
118
|
+
## Business rule or type system?
|
|
119
|
+
|
|
120
|
+
Before writing an error specification, apply this test:
|
|
121
|
+
|
|
122
|
+
1. Does the error depend on **existing system state** — what events occurred?
|
|
123
|
+
→ business rule → write the specification.
|
|
124
|
+
2. Can the type system make the invalid state unrepresentable?
|
|
125
|
+
→ in Screenplay that means a `concept` with its own `validate` block, and the
|
|
126
|
+
rule travels with every use → **not** a specification.
|
|
127
|
+
3. Would a different business plausibly have a different rule here?
|
|
128
|
+
→ business rule → specification.
|
|
129
|
+
|
|
130
|
+
**Write specifications for:** *"Cannot cancel an already-paid invoice"*,
|
|
131
|
+
*"Cannot withdraw more than the balance"*, *"Maximum 100 lines per invoice"*.
|
|
132
|
+
|
|
133
|
+
**Do not write specifications for:** *"Invoice number must match INV-000000"*,
|
|
134
|
+
*"Name cannot be empty"*, *"Discount must be between 0 and 100"* — those belong on
|
|
135
|
+
the concept.
|
|
136
|
+
|
|
137
|
+
## Application-boundary coverage
|
|
138
|
+
|
|
139
|
+
Every slice should carry at least one specification whose `when` is the command a
|
|
140
|
+
real caller issues and whose `then` is observable at that same boundary — produced
|
|
141
|
+
events, read-model state, or query results. A specification satisfiable only by an
|
|
142
|
+
internal function describes a unit, not a slice acceptance criterion.
|
|
143
|
+
|
|
144
|
+
## Reference execution — what actually runs
|
|
145
|
+
|
|
146
|
+
Screenplay supplies a framework-neutral reference path: no Arc, no Chronicle, no
|
|
147
|
+
database, no filesystem, no network. It executes against an immutable in-memory
|
|
148
|
+
world so every downstream target has one normalized behavior to match.
|
|
149
|
+
|
|
150
|
+
> The minimum evaluator currently admits the RegisterProject-style vertical:
|
|
151
|
+
> `not empty` validation, unconditional event production, one affected read-model
|
|
152
|
+
> instance, optional snapshot lookup, and exact ordered specification results.
|
|
153
|
+
> Unsupported reachable capabilities **block plan creation** rather than producing
|
|
154
|
+
> a partial or stubbed execution.
|
|
155
|
+
|
|
156
|
+
A rejected execution returns the unchanged world. An accepted one commits its
|
|
157
|
+
facts and projected state once, then evaluates the requested queries against that
|
|
158
|
+
state.
|
|
159
|
+
|
|
160
|
+
⚠️ **`for <event-source-value>` is reserved for ESM v2.** The parser, printer and
|
|
161
|
+
syntax tree preserve it, but ESM v1 binding reports blocking diagnostic
|
|
162
|
+
`PLAY0268`. It cannot execute or render silently. Avoid it in a model that must
|
|
163
|
+
run today.
|
|
164
|
+
|
|
165
|
+
## Quality checklist
|
|
166
|
+
|
|
167
|
+
For every specification:
|
|
168
|
+
|
|
169
|
+
- [ ] Concrete, realistic values — never "valid user" or "some amount".
|
|
170
|
+
- [ ] Tests exactly one behavior, independent of other specifications.
|
|
171
|
+
- [ ] Business language matching the event-model vocabulary.
|
|
172
|
+
|
|
173
|
+
For command specifications:
|
|
174
|
+
|
|
175
|
+
- [ ] `given` contains only events, each with all its fields.
|
|
176
|
+
- [ ] `when` contains exactly one command with all its inputs.
|
|
177
|
+
- [ ] `then` contains **either** events **or** an error, never both.
|
|
178
|
+
- [ ] Error cases test business rules, not format validation.
|
|
179
|
+
|
|
180
|
+
For view specifications:
|
|
181
|
+
|
|
182
|
+
- [ ] `given readmodel` is the complete state before.
|
|
183
|
+
- [ ] `then readmodel` is the complete state after.
|
|
184
|
+
- [ ] No error cases — views cannot reject.
|
|
185
|
+
|
|
186
|
+
## Verify
|
|
187
|
+
|
|
188
|
+
- [ ] `screenplay <model> --warnaserror` reports zero errors and zero warnings.
|
|
189
|
+
- [ ] Every slice has at least one boundary specification.
|
|
190
|
+
- [ ] The rejections are specified, not only the happy path.
|
|
191
|
+
- [ ] No `given`/`when`/`then` clause names an element the model does not declare.
|
|
192
|
+
- [ ] No `for <event-source-value>` in a model that must reach a runtime.
|
|
193
|
+
|
|
194
|
+
## Route near misses
|
|
195
|
+
|
|
196
|
+
- The rules being specified: `cratis-screenplay-command-surface`.
|
|
197
|
+
- The projections being asserted on: `cratis-screenplay-projections`.
|
|
198
|
+
- Naming and scoping specifications generally: `cratis-specification-by-example`.
|
|
199
|
+
- C# specifications for hand-written Cratis code: `cratis-specifications-csharp`.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"skill": "cratis-screenplay-specifications",
|
|
3
|
+
"input": "Write given/when/then specifications for a Screenplay slice.",
|
|
4
|
+
"fixtures": [],
|
|
5
|
+
"assertions": [
|
|
6
|
+
{
|
|
7
|
+
"kind": "skill-contains",
|
|
8
|
+
"value": "**`then` contains either events or an error \u2014 never both.**"
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
"kind": "skill-contains",
|
|
12
|
+
"value": "Views cannot reject events"
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
"kind": "skill-contains",
|
|
16
|
+
"value": "PLAY0268"
|
|
17
|
+
}
|
|
18
|
+
]
|
|
19
|
+
}
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: cratis-screenplay-ui-composition
|
|
3
|
+
description: Compose the user interface of a Cratis Screenplay `.play` model — `layout` and its responsive `arrangement`, `screen template` and `dialog template`, command-bound `form` declarations, navigation `contribute` blocks, `ui profile`, `theme`, localized `$strings`, and `file` realization references. Use when declaring the application shell, a reusable screen shape, a command form, a navigation entry, or theming in a `.play` model. Do not use for a screen's own data and actions.
|
|
4
|
+
license: MIT
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# UI composition in Screenplay
|
|
8
|
+
|
|
9
|
+
Event Modeling's wireframe step is a first-class part of the language. The shell,
|
|
10
|
+
the reusable shapes inside it, the forms bound to commands, and the navigation
|
|
11
|
+
entries other modules contribute are all declared in the `.play` model.
|
|
12
|
+
|
|
13
|
+
## Verified product sources
|
|
14
|
+
|
|
15
|
+
| Package | Version | Purpose |
|
|
16
|
+
| --- | --- | --- |
|
|
17
|
+
| `Cratis.Screenplay` | `4.12.1` | Layout, template, form, contribution, profile and theme parsers |
|
|
18
|
+
|
|
19
|
+
Read from the Screenplay repository at tag `v4.12.1` (commit `122eee8`), against
|
|
20
|
+
`Documentation/screenplay/{templates,layout-arrangement,forms,contributions,ui-profile,theme,internationalization,file-references}.md`
|
|
21
|
+
and `Source/DotNET/Screenplay/Parsing/`. Reverify before claiming another version
|
|
22
|
+
behaves the same.
|
|
23
|
+
|
|
24
|
+
These constructs went unhighlighted and uncompleted by the Monaco and VS Code
|
|
25
|
+
language service until `Cratis/Screenplay#199` gave every construct the parser
|
|
26
|
+
dispatches on a keyword entry. On an older language-service version they still
|
|
27
|
+
look unrecognized — **check `screenplay`, not the editor**, because absent
|
|
28
|
+
highlighting was never evidence that a construct is wrong.
|
|
29
|
+
|
|
30
|
+
## `layout` — the application shell
|
|
31
|
+
|
|
32
|
+
One per application, declared at the top level and selected by a `ui profile`.
|
|
33
|
+
|
|
34
|
+
```screenplay
|
|
35
|
+
layout AppShell
|
|
36
|
+
topbar
|
|
37
|
+
navigation contributes Navigation
|
|
38
|
+
content
|
|
39
|
+
footer
|
|
40
|
+
|
|
41
|
+
arrangement flow
|
|
42
|
+
column
|
|
43
|
+
topbar height 56
|
|
44
|
+
row
|
|
45
|
+
navigation width 240
|
|
46
|
+
content grow
|
|
47
|
+
footer height 32
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
A slot is declared once by name, optionally marked
|
|
51
|
+
`contributes <ContributionPoint>` to make it a contribution target.
|
|
52
|
+
|
|
53
|
+
## `arrangement` — responsive `flow` or pixel-precise `freeform`
|
|
54
|
+
|
|
55
|
+
The size-class matrix is **2×2**: width `compact` or `regular`, height `compact`
|
|
56
|
+
or `regular` — phone landscape, phone portrait, desktop short, desktop tall.
|
|
57
|
+
|
|
58
|
+
**`arrangement flow`** nests slots under `row`, `column` or `grid` containers.
|
|
59
|
+
|
|
60
|
+
- A container may declare `gap <n>`.
|
|
61
|
+
- A slot leaf takes `width <n>`, `height <n>`, `grow`, and `span <n>` for grid tracks.
|
|
62
|
+
- `when width <class>[, height <class>]` or `when height <class>` **replaces the
|
|
63
|
+
entire tree** for that condition — it is not a partial override.
|
|
64
|
+
|
|
65
|
+
**`arrangement freeform`** declares one variant per matrix point:
|
|
66
|
+
|
|
67
|
+
```screenplay
|
|
68
|
+
arrangement freeform
|
|
69
|
+
variant width regular, height regular
|
|
70
|
+
place navigation at 0,0 size 240,fill
|
|
71
|
+
place content at 240,0 size fill,fill
|
|
72
|
+
variant width compact, height regular
|
|
73
|
+
place navigation hidden
|
|
74
|
+
place content at 0,0 size fill,fill
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
`place <Slot> at <x>,<y> size <w>,<h>` where either dimension may be `fill`, or
|
|
78
|
+
`place <Slot> hidden` to drop the slot from that variant entirely.
|
|
79
|
+
|
|
80
|
+
## `screen template` and `dialog template`
|
|
81
|
+
|
|
82
|
+
Declared at module level, referenced by screens.
|
|
83
|
+
|
|
84
|
+
```screenplay
|
|
85
|
+
screen template MasterDetail
|
|
86
|
+
fits slot content
|
|
87
|
+
sidebar
|
|
88
|
+
main
|
|
89
|
+
arrangement flow
|
|
90
|
+
row gap 16
|
|
91
|
+
sidebar width 280
|
|
92
|
+
main grow
|
|
93
|
+
|
|
94
|
+
dialog template RegisterInvoiceDialog
|
|
95
|
+
body
|
|
96
|
+
actions
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
`fits slot <name>` says which slot of its parent the template fills. **A dialog
|
|
100
|
+
template is a screen template in everything but one respect: it declares no
|
|
101
|
+
`fits slot`, because a dialog occupies no slot of the structure it opens over** —
|
|
102
|
+
writing one is an error.
|
|
103
|
+
|
|
104
|
+
A screen fills a template by naming it and providing slot bodies; a dialog is
|
|
105
|
+
filled exactly the same way, because from the screen's side there is no
|
|
106
|
+
difference. See `cratis-screenplay-read-surface` for the directives that go inside.
|
|
107
|
+
|
|
108
|
+
## `form` — bound to a command
|
|
109
|
+
|
|
110
|
+
```screenplay
|
|
111
|
+
form RegisterInvoiceForm for RegisterInvoice
|
|
112
|
+
populate via query GetInvoiceDefaults by customerId
|
|
113
|
+
field invoiceNumber label "Invoice #"
|
|
114
|
+
field customerId from item
|
|
115
|
+
field total compose using TotalCalculator
|
|
116
|
+
on submit navigate to InvoiceList
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
- At most one `populate` — `populate via query <Query> [by <param>]` or
|
|
120
|
+
`populate from item`.
|
|
121
|
+
- `field <property>` takes at most one of `from <source>` or `compose using
|
|
122
|
+
<Callback>`, plus an optional `label`.
|
|
123
|
+
- At most one `on submit navigate to <Screen> [by <param>]`.
|
|
124
|
+
|
|
125
|
+
⚠️ **A form is discovered, not referenced.** It never appears in a screen's
|
|
126
|
+
directive tree the way a `table` or `summary` does — it is found by its
|
|
127
|
+
`for <Command>` binding wherever that command is invoked. A form sits at module
|
|
128
|
+
level, so it disambiguates by module rather than by feature or slice.
|
|
129
|
+
|
|
130
|
+
## `contribute` — navigation from elsewhere
|
|
131
|
+
|
|
132
|
+
```screenplay
|
|
133
|
+
contribute to Navigation
|
|
134
|
+
navigate to InvoiceList
|
|
135
|
+
label "Invoices"
|
|
136
|
+
order 20
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
All three directives are optional and appear at most once each.
|
|
140
|
+
|
|
141
|
+
**Resolution walks outward:** a contribution first looks for a
|
|
142
|
+
`contributes <ContributionPoint>` slot among its **own module's** templates, then
|
|
143
|
+
outward to the nearest enclosing structure that declares a matching point. Three
|
|
144
|
+
tiers exist — application-wide (the layout declares the point), cross-module, and
|
|
145
|
+
module-level.
|
|
146
|
+
|
|
147
|
+
`navigate to <Screen> by <param>` is **not** string interpolation; it reuses the
|
|
148
|
+
same typed navigate binding a screen action uses.
|
|
149
|
+
|
|
150
|
+
⚠️ This iteration ships `navigate`, `label` and `order` only. Grouping beyond a
|
|
151
|
+
flat ordered list, and an explicit override for when nearest-enclosing is not the
|
|
152
|
+
point you mean, are deliberately left for later.
|
|
153
|
+
|
|
154
|
+
## `ui profile` and `theme`
|
|
155
|
+
|
|
156
|
+
```screenplay
|
|
157
|
+
ui profile Desktop
|
|
158
|
+
target platform web
|
|
159
|
+
target size regular
|
|
160
|
+
layout AppShell
|
|
161
|
+
theme Nordic
|
|
162
|
+
packages
|
|
163
|
+
Cratis.Components
|
|
164
|
+
|
|
165
|
+
theme Nordic
|
|
166
|
+
compatible with Cratis.Components
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
- `target platform` takes a comma-separated list. `web`, `ios` and `android` are
|
|
170
|
+
the documented examples; ⚠️ **the parser accepts any identifier** — there is no
|
|
171
|
+
enforced list, so a typo is silent.
|
|
172
|
+
- `target size` is documented as `compact`, `regular` or `expanded`; ⚠️ again any
|
|
173
|
+
identifier parses.
|
|
174
|
+
- `packages` are listed **in override-priority order** — a later package's `Button`
|
|
175
|
+
shadows an earlier one's — and `core`, the built-in vocabulary, is always the
|
|
176
|
+
final fallback.
|
|
177
|
+
- `compatible with` lists the packages a theme actually supports, each at most
|
|
178
|
+
once. A profile selecting a theme not declared compatible with one of its own
|
|
179
|
+
packages gets a compile-time **warning**.
|
|
180
|
+
|
|
181
|
+
## Localized strings
|
|
182
|
+
|
|
183
|
+
Localized text lives in companion `.strings` files — `MySystem.play` pairs with
|
|
184
|
+
`MySystem.<locale>.strings`, line-based, dotted keys, `=` assignment, `//`
|
|
185
|
+
comments. `{placeholder}` tokens are kept verbatim for runtime substitution.
|
|
186
|
+
|
|
187
|
+
Reference them with `$strings.<dotted.key>`, unquoted, anywhere a literal is
|
|
188
|
+
accepted in: a validation rule's `message`; a screen action, table column or
|
|
189
|
+
summary field `label`; a screen or section `title`; a contribution `label`; and a
|
|
190
|
+
form field `label`. The value is stored as the literal text `$strings.<key>`, and
|
|
191
|
+
the printer emits it unquoted so a round trip preserves it.
|
|
192
|
+
|
|
193
|
+
## `file` — realization metadata, never a substitute
|
|
194
|
+
|
|
195
|
+
Two meanings, one word. On a construct **with an implementation body** — a command
|
|
196
|
+
`handler`, a validation rule predicate, a query `performer`, a reducer rule, a
|
|
197
|
+
reaction trigger, a `constraint` and a `screen` — `file` stands in for the inline
|
|
198
|
+
body. It sits on the **screen itself**, not on a directive inside it: `File` is a
|
|
199
|
+
member of `ScreenSyntax`, and the directive types have no such member. On a **pure declaration** — `concept`, `type`, `event`, `readmodel`,
|
|
200
|
+
`projection`, `slice`, `specification`, top-level `trigger` — it only records
|
|
201
|
+
which file realizes it.
|
|
202
|
+
|
|
203
|
+
The rules: **repository relative, never absolute** (an absolute path is warning
|
|
204
|
+
`PLAY0264`); **never resolved** — the compiler does not look for the file, so a
|
|
205
|
+
stale path does not invalidate the document; and **never replaces the
|
|
206
|
+
declaration** — a `projection` still declares its blocks, an `event` still declares
|
|
207
|
+
its properties.
|
|
208
|
+
|
|
209
|
+
⚠️ `file <Identifier>` is read as a **property** named `file`, not a directive —
|
|
210
|
+
the type-reference shape wins the tie. `file Invoices/Register.cs` is a directive;
|
|
211
|
+
`file Attachment` is a property. In a `trigger` body the directive always wins, so
|
|
212
|
+
a trigger value named `file` is written `@file`.
|
|
213
|
+
|
|
214
|
+
## Verify
|
|
215
|
+
|
|
216
|
+
- [ ] `screenplay <model> --warnaserror` reports zero errors and zero warnings.
|
|
217
|
+
- [ ] Every slot a `contribute` targets is declared `contributes <Point>` somewhere
|
|
218
|
+
that encloses it.
|
|
219
|
+
- [ ] No `dialog template` declares `fits slot`.
|
|
220
|
+
- [ ] `packages` are ordered deliberately — later shadows earlier.
|
|
221
|
+
- [ ] Every theme a profile selects is `compatible with` one of its packages.
|
|
222
|
+
- [ ] `target platform` and `target size` values are spelled correctly; nothing
|
|
223
|
+
checks them.
|
|
224
|
+
- [ ] User-visible text is `$strings.` where the application is localized.
|
|
225
|
+
- [ ] No `file` reference is doing work the declaration should be doing.
|
|
226
|
+
|
|
227
|
+
## Route near misses
|
|
228
|
+
|
|
229
|
+
- A screen's own data, actions and name resolution: `cratis-screenplay-read-surface`.
|
|
230
|
+
- Deriving wireframes from the model (step 4): `cratis-screenplay-event-modeling`.
|
|
231
|
+
- Building the actual React application: `cratis-arc-react-page`, `cratis-components-styling`.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"skill": "cratis-screenplay-ui-composition",
|
|
3
|
+
"input": "Declare the application shell, a screen template and a command form.",
|
|
4
|
+
"fixtures": [],
|
|
5
|
+
"assertions": [
|
|
6
|
+
{ "kind": "skill-contains", "value": "A form is discovered, not referenced" },
|
|
7
|
+
{ "kind": "skill-contains", "value": "declares no\n`fits slot`" },
|
|
8
|
+
{ "kind": "skill-contains", "value": "override-priority order" }
|
|
9
|
+
]
|
|
10
|
+
}
|
|
@@ -234,8 +234,11 @@ runtime. A green `results.json` is not a passing integration test.
|
|
|
234
234
|
|
|
235
235
|
## Route near misses
|
|
236
236
|
|
|
237
|
-
- Writing or verifying the `.play` model itself:
|
|
238
|
-
`cratis-screenplay-
|
|
237
|
+
- Writing or verifying the `.play` model itself: `cratis-screenplay-model-authoring`
|
|
238
|
+
for the compiler and the admitted set, `cratis-screenplay-event-modeling` for the
|
|
239
|
+
modeling method, and the per-surface `cratis-screenplay-*` skills for the
|
|
240
|
+
constructs — command surface, projections, read surface, UI composition,
|
|
241
|
+
captures and reactions, specifications.
|
|
239
242
|
- Understanding the generated Arc command, validator or read model as C#:
|
|
240
243
|
`cratis-arc-command` and the Chronicle read-model guidance.
|
|
241
244
|
- Inspecting the Chronicle store the sandbox writes into: the Chronicle CLI or
|
|
@@ -676,7 +676,14 @@
|
|
|
676
676
|
{
|
|
677
677
|
"id": "cratis/screenplay",
|
|
678
678
|
"availableTargets": [
|
|
679
|
-
"cratis-screenplay-
|
|
679
|
+
"cratis-screenplay-captures-and-reactions",
|
|
680
|
+
"cratis-screenplay-command-surface",
|
|
681
|
+
"cratis-screenplay-event-modeling",
|
|
682
|
+
"cratis-screenplay-model-authoring",
|
|
683
|
+
"cratis-screenplay-projections",
|
|
684
|
+
"cratis-screenplay-read-surface",
|
|
685
|
+
"cratis-screenplay-specifications",
|
|
686
|
+
"cratis-screenplay-ui-composition"
|
|
680
687
|
],
|
|
681
688
|
"languages": [
|
|
682
689
|
"language-agnostic"
|