@cratis/pi 7.103.0 → 7.103.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.
- package/package/corpus/harnesses/copilot/instructions/scripting.instructions.md +22 -0
- package/package/corpus/rules/general.md +2 -2
- package/package/corpus/rules/scripting.md +21 -0
- package/package/corpus/skills/cratis-screenplay-command-surface/SKILL.md +26 -1
- package/package/corpus/skills/cratis-screenplay-projections/SKILL.md +17 -0
- package/package/corpus/skills/cratis-screenplay-render-and-gap-fill/SKILL.md +17 -0
- package/package/corpus/skills/cratis-screenplay-specifications/SKILL.md +8 -0
- package/package/corpus/skills/cratis-screenplay-toolchain/SKILL.md +1 -1
- package/package/corpus/skills/cratis-screenplay-toolchain/references/cheat-sheet-example.md +1 -0
- package/package/corpus/skills/cratis-screenplay-toolchain/references/fast-path.md +7 -0
- package/package/corpus/skills/cratis-screenplay-toolchain/references/traps.md +1 -0
- package/package/corpus/skills/cratis-screenplay-ui-composition/SKILL.md +40 -0
- package/package/corpus/skills/cratis-screenplay-ui-composition/references/response-continuations.md +1 -0
- package/package/corpus/skills/cratis-screenplay-ui-composition/references/worked-flow.md +1 -0
- package/package/corpus/skills/cratis-stage-rendering-and-sandbox/references/admission.md +3 -2
- package/package.json +1 -1
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
---
|
|
2
|
+
applyTo: "**/*.sh,**/*.py,**/*.mjs,**/*.cjs,**/*.ps1,**/scripts/**,**/tools/**,**/.github/workflows/**,**/.cratis/ai/hooks/**"
|
|
3
|
+
paths:
|
|
4
|
+
- "**/*.sh"
|
|
5
|
+
- "**/*.py"
|
|
6
|
+
- "**/*.mjs"
|
|
7
|
+
- "**/*.cjs"
|
|
8
|
+
- "**/*.ps1"
|
|
9
|
+
- "**/scripts/**"
|
|
10
|
+
- "**/tools/**"
|
|
11
|
+
- "**/.github/workflows/**"
|
|
12
|
+
- "**/.cratis/ai/hooks/**"
|
|
13
|
+
---
|
|
14
|
+
<!-- cratis-ai: generated Copilot instructions. Do not edit; rules/ is the source. -->
|
|
15
|
+
|
|
16
|
+
# Scripts and tooling
|
|
17
|
+
|
|
18
|
+
- Write repository scripts, CI helpers and tooling in Node (`.mjs`, or `.ts` limited to erasable syntax: no enums, no parameter properties), using only `node:` built-ins (`fs.glob`, `util.parseArgs`, `fetch`, `node:test`). Node and the .NET SDK are the only runtimes every Cratis build machine and runner is guaranteed to have.
|
|
19
|
+
- Use a C# file-based app (`dotnet run --file tool.cs`, `#:package` pinned) when the script needs .NET or Cratis libraries or shares types with the product. Do not use one in hooks or on per-call hot paths.
|
|
20
|
+
- Hooks under `.cratis/ai/hooks` are POSIX sh compatible with bash 3.2, or Node. Read stdin with `IFS= read -r -d '' x || true`, never `$(</dev/stdin)`.
|
|
21
|
+
- Do not add Python scripts or `python3` workflow steps to Cratis repositories unless the project itself is Python (for example the Chronicle Python client). Existing Python scripts are ported to Node opportunistically: when you substantially change one, port it in the same PR. There is no bulk port.
|
|
22
|
+
- Agents: edit files with the edit/write tools, query JSON with `gh --jq`/`jq`, and use `node -e` or `node --input-type=module - <<'EOF'` for ad-hoc logic. Never `python3 -c`, and never rewrite files by script.
|
|
@@ -149,11 +149,11 @@ A claim is only as good as the signal behind it — a build result, a test run,
|
|
|
149
149
|
| Before any browser call: production permit, handoff, artifact paths, evidence | `browser.md` |
|
|
150
150
|
| Whether you are allowed to do the thing you are able to do | `capability-is-not-authority.md` |
|
|
151
151
|
| Before running a command that could print a credential, or when a secret value appears in output | `secrets.md` |
|
|
152
|
-
| What must stop and ask a human | `capability-is-not-authority.md`
|
|
152
|
+
| What must stop and ask a human | `capability-is-not-authority.md` |
|
|
153
153
|
| What counts as evidence that something works | `verification-discipline.md` |
|
|
154
154
|
| Before writing a session note, plan or handover: where they may live (`.ai-work/` only) | `local-work-artifacts.md` |
|
|
155
155
|
| What may be written into the `.cratis/` folder (configuration and the corpus only, never deliverables) | `cratis-folder-is-configuration.md` |
|
|
156
|
-
| Exit-code meaning, scripts and wrappers that lose a verdict | `exit-codes-and-wrappers.md` |
|
|
156
|
+
| Exit-code meaning, scripts and wrappers that lose a verdict; which language a script uses | `exit-codes-and-wrappers.md`, `scripting.md` |
|
|
157
157
|
| Writing a scan, allowlist, script or CI check, or a destructive pass, that cannot pass vacuously | `guards-and-fuses.md` |
|
|
158
158
|
| How the shared corpus is installed, updated and rolled back | `ai-distribution.md` |
|
|
159
159
|
| Code-level event modeling / schema migration / calling commands from code / paging / cross-cutting metadata / multi-tenancy | the matching skills |
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
---
|
|
2
|
+
applyTo: "**/*.sh,**/*.py,**/*.mjs,**/*.cjs,**/*.ps1,**/scripts/**,**/tools/**,**/.github/workflows/**,**/.cratis/ai/hooks/**"
|
|
3
|
+
paths:
|
|
4
|
+
- "**/*.sh"
|
|
5
|
+
- "**/*.py"
|
|
6
|
+
- "**/*.mjs"
|
|
7
|
+
- "**/*.cjs"
|
|
8
|
+
- "**/*.ps1"
|
|
9
|
+
- "**/scripts/**"
|
|
10
|
+
- "**/tools/**"
|
|
11
|
+
- "**/.github/workflows/**"
|
|
12
|
+
- "**/.cratis/ai/hooks/**"
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
# Scripts and tooling
|
|
16
|
+
|
|
17
|
+
- Write repository scripts, CI helpers and tooling in Node (`.mjs`, or `.ts` limited to erasable syntax: no enums, no parameter properties), using only `node:` built-ins (`fs.glob`, `util.parseArgs`, `fetch`, `node:test`). Node and the .NET SDK are the only runtimes every Cratis build machine and runner is guaranteed to have.
|
|
18
|
+
- Use a C# file-based app (`dotnet run --file tool.cs`, `#:package` pinned) when the script needs .NET or Cratis libraries or shares types with the product. Do not use one in hooks or on per-call hot paths.
|
|
19
|
+
- Hooks under `.cratis/ai/hooks` are POSIX sh compatible with bash 3.2, or Node. Read stdin with `IFS= read -r -d '' x || true`, never `$(</dev/stdin)`.
|
|
20
|
+
- Do not add Python scripts or `python3` workflow steps to Cratis repositories unless the project itself is Python (for example the Chronicle Python client). Existing Python scripts are ported to Node opportunistically: when you substantially change one, port it in the same PR. There is no bulk port.
|
|
21
|
+
- Agents: edit files with the edit/write tools, query JSON with `gh --jq`/`jq`, and use `node -e` or `node --input-type=module - <<'EOF'` for ad-hoc logic. Never `python3 -c`, and never rewrite files by script.
|
|
@@ -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
|
|
|
@@ -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
|
|
@@ -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
|
|
255
|
-
property,
|
|
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
|