@cratis/pi 7.127.0 → 7.129.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.
- package/package/corpus/product-sync.json +4 -4
- package/package/corpus/skills/cratis-application-slice-conformance/SKILL.md +1 -1
- package/package/corpus/skills/cratis-arc-react-page/references/from-screenplay.md +5 -5
- package/package/corpus/skills/cratis-onboarding-runtime/SKILL.md +10 -2
- package/package/corpus/skills/cratis-onboarding-runtime/references/default-offering.md +61 -0
- package/package/corpus/skills/cratis-onboarding-runtime/references/sign-up-review.md +52 -0
- package/package/corpus/skills/cratis-screenplay-authentication-and-onboarding/SKILL.md +1 -1
- package/package/corpus/skills/cratis-screenplay-authentication-and-onboarding/references/onboarding-directives.md +1 -1
- package/package/corpus/skills/cratis-screenplay-automations-and-translations/SKILL.md +6 -1
- package/package/corpus/skills/cratis-screenplay-automations-and-translations/references/automation-patterns.md +1 -1
- package/package/corpus/skills/cratis-screenplay-automations-and-translations/references/cases-to-specify.md +5 -5
- package/package/corpus/skills/cratis-screenplay-automations-and-translations/references/statemachines-and-workflows.md +164 -0
- package/package/corpus/skills/cratis-screenplay-automations-and-translations/references/todo-list-example.md +12 -15
- package/package/corpus/skills/cratis-screenplay-automations-and-translations/references/translate-example.md +10 -4
- package/package/corpus/skills/cratis-screenplay-captures-and-reactions/references/complete-examples.md +2 -2
- package/package/corpus/skills/cratis-screenplay-captures-and-reactions/references/invocation-identity.md +8 -2
- package/package/corpus/skills/cratis-screenplay-command-surface/SKILL.md +5 -4
- package/package/corpus/skills/cratis-screenplay-command-surface/references/described-handlers.md +12 -8
- package/package/corpus/skills/cratis-screenplay-command-surface/references/validate-rules.md +5 -5
- package/package/corpus/skills/cratis-screenplay-command-surface/verification.json +1 -1
- package/package/corpus/skills/cratis-screenplay-event-modeling/references/nine-steps.md +6 -3
- package/package/corpus/skills/cratis-screenplay-legacy-extraction/references/generated-recovery.md +4 -4
- package/package/corpus/skills/cratis-screenplay-model-authoring/references/language-reference.md +2 -2
- package/package/corpus/skills/cratis-screenplay-read-surface/references/named-keys.md +3 -1
- package/package/corpus/skills/cratis-screenplay-read-surface/references/screen-patterns.md +2 -2
- package/package/corpus/skills/cratis-screenplay-render-and-gap-fill/SKILL.md +4 -4
- package/package/corpus/skills/cratis-screenplay-render-and-gap-fill/references/renderability-gate.md +6 -5
- package/package/corpus/skills/cratis-screenplay-scenario-coverage/SKILL.md +2 -2
- package/package/corpus/skills/cratis-screenplay-scenario-coverage/references/invoicing-dues-design.md +0 -3
- package/package/corpus/skills/cratis-screenplay-scenario-coverage/references/invoicing-dues-example.md +8 -3
- package/package/corpus/skills/cratis-screenplay-scenario-coverage/references/scenario-examples.md +17 -9
- package/package/corpus/skills/cratis-screenplay-scenario-coverage/references/spec-forms-by-mode.md +4 -3
- package/package/corpus/skills/cratis-screenplay-scenario-coverage/references/version-skew.md +25 -14
- package/package/corpus/skills/cratis-screenplay-scenario-coverage/references/view-and-story-specs.md +7 -6
- package/package/corpus/skills/cratis-screenplay-scenario-coverage/verification.json +1 -1
- package/package/corpus/skills/cratis-screenplay-slice-design/references/read-model-design.md +1 -1
- package/package/corpus/skills/cratis-screenplay-slice-design/references/slicing.md +1 -1
- package/package/corpus/skills/cratis-screenplay-slice-design/references/worked-example.md +3 -3
- package/package/corpus/skills/cratis-screenplay-specifications/SKILL.md +4 -2
- package/package/corpus/skills/cratis-screenplay-specifications/references/actions-beyond-commands.md +4 -2
- package/package/corpus/skills/cratis-screenplay-specifications/references/child-ordering.md +12 -3
- package/package/corpus/skills/cratis-screenplay-specifications/references/reactions-and-cascades.md +70 -21
- package/package/corpus/skills/cratis-screenplay-specifications/references/vocabulary.md +3 -2
- package/package/corpus/skills/cratis-screenplay-specifications/verification.json +2 -2
- package/package/corpus/skills/cratis-screenplay-toolchain/SKILL.md +3 -3
- package/package/corpus/skills/cratis-screenplay-toolchain/references/automation-translate-example.md +5 -8
- package/package/corpus/skills/cratis-screenplay-toolchain/references/cheat-sheet-example.md +12 -11
- package/package/corpus/skills/cratis-screenplay-toolchain/references/cheat-sheet.md +1 -1
- package/package/corpus/skills/cratis-screenplay-toolchain/references/diagnostic-arguments.md +1 -1
- package/package/corpus/skills/cratis-screenplay-toolchain/references/diagnostics.md +2 -2
- package/package/corpus/skills/cratis-screenplay-toolchain/references/executable-subset.md +10 -7
- package/package/corpus/skills/cratis-screenplay-toolchain/references/language-admission.md +4 -1
- package/package/corpus/skills/cratis-screenplay-toolchain/references/preferred-syntax.md +4 -1
- package/package/corpus/skills/cratis-screenplay-toolchain/references/renderable-subset.md +4 -4
- package/package/corpus/skills/cratis-screenplay-toolchain/references/screenplay-contract-exceptions.json +0 -70
- package/package/corpus/skills/cratis-screenplay-toolchain/references/screenplay-contract.json +4743 -623
- package/package/corpus/skills/cratis-screenplay-toolchain/references/screenplay-contract.version +1 -1
- package/package/corpus/skills/cratis-screenplay-toolchain/references/traps.md +1 -1
- package/package/corpus/skills/cratis-screenplay-ui-composition/SKILL.md +6 -0
- package/package/corpus/skills/cratis-screenplay-ui-composition/references/action-subjects.md +73 -0
- package/package/corpus/skills/cratis-screenplay-ui-composition/references/file-references.md +4 -3
- package/package/corpus/skills/cratis-screenplay-ui-composition/references/response-continuations.md +1 -1
- package/package/corpus/skills/cratis-screenplay-ui-composition/references/worked-flow.md +1 -1
- package/package/corpus/skills/cratis-showrunner-herald/SKILL.md +5 -0
- package/package/corpus/skills/cratis-stage-rendering-and-sandbox/SKILL.md +6 -5
- package/package/corpus/skills/cratis-stage-rendering-and-sandbox/references/admission.md +8 -5
- package/package/corpus/skills/cratis-stage-rendering-and-sandbox/references/rendered-application.md +14 -5
- package/package.json +1 -1
|
@@ -171,9 +171,9 @@
|
|
|
171
171
|
}
|
|
172
172
|
],
|
|
173
173
|
"synced": {
|
|
174
|
-
"version": "
|
|
175
|
-
"date": "2026-
|
|
176
|
-
"by": "Cratis/AI#
|
|
174
|
+
"version": "5.1.0",
|
|
175
|
+
"date": "2026-11-02",
|
|
176
|
+
"by": "Cratis/AI#975"
|
|
177
177
|
},
|
|
178
178
|
"covers": {
|
|
179
179
|
"skills": [
|
|
@@ -201,7 +201,7 @@
|
|
|
201
201
|
],
|
|
202
202
|
"rules": []
|
|
203
203
|
},
|
|
204
|
-
"notes": "Cratis/AI#820: reviewed v4.245.0 release; protected-read constraint precedence preserved. Review correction: removed unsupported parser-repair and inbound-public refusal release attributions and the incorrect PLAY0136 event-key claim, restoring prior teaching. Published contract asset is byte-identical to the previous snapshot; pin and compatibility entry advanced together. Prior: Cratis/AI#779: reference-runner capability refusals taught as scoped per specification (introduced in v4.213.2, Cratis/Screenplay#897) from the v4.216.0 tool and MCP documentation and plan source: an unadmitted projection (UnsupportedEventContext, UnsupportedProjectionBlock) marks unsupported only the specifications that reach it or its read model, the others run and planIssues lists deferred issues; application-level issues still block every selected specification; no new render/runtime probe. Prior: Cratis/AI#776: PLAY0802 ReservedStoredName (introduced in v4.213.3, Cratis/Screenplay#893) taught from the v4.216.0 compilers and documentation: stored event source `Default` and stored event stream `All` (ordinal, name or `id` pin) refused at authoring time, a pin away from the reserved name valid, PLAY0273 kept as the binding backstop; no new render/runtime probe. Prior: Cratis/AI#784: standalone Screenplay 4.216.0 pinned; compiler contract replaced by the v4.216.0 release asset (adds the propose-repair destinationIntent v1 schema and PLAY0802 ReservedStoredName). Source-checked decision 0096 and the MCP reference for the explicit author-intent PLAY0470 repair: repair-intents discovery, intentActions feature detection, complete per-production selections, retained production-destination report and identity views, explicit apply and refusals. No new render/runtime probe. Prior: Cratis/AI#771: standalone Screenplay 4.213.0 pinned; regenerated compiler contract is byte-identical to the v4.213.0 release asset and unchanged from 4.212.4. Reviewed the full v4.212.4-v4.213.0 delta against tagged decision 0093 and MCP reference: pre-binding container identities and stable binding/migration continuity, own-slice member substitutions, containerIdentities completeness/ambiguity/collision refusals, retained ambiguous notes, explicit semanticRenames/retirements, binding fixes through MCP, exact reopen exception, notes/identity rollback and exact-ID re-add anchoring. No grammar, binder, ESM or diagnostic-code changes; no new render/runtime probe. Prior: Cratis/AI#772: standalone Screenplay 4.212.4 pinned; regenerated compiler contract is byte-identical to the v4.212.4 release asset. Source-checked joined-event automap/no automap overrides and level fallback in executable binding; PLAY0380 covers only all inside children/nested. No new render/runtime probe. Prior: Cratis/AI#769: standalone Screenplay 4.212.3 pinned; regenerated compiler contract is byte-identical to the v4.212.3 release asset. Source-checked both compilers and projection documentation for PLAY0801 DuplicateEventInProjectionScope: shared from/removal/clear set, separate join set, fresh sets per children/nested/variant level, and no two-row update through repeated from blocks with different keys. No new render/runtime probe. Prior: Cratis/AI#768: standalone Screenplay 4.212.2 pinned; regenerated compiler contract is byte-identical to the v4.212.2 release asset (unchanged from the previous contract). Source-checked v4.212.0 split-model dotted note targets, open-workspace applicationIdentity and complete add/reanchor substitutions; unbound container identities are not claimed. v4.212.1 aligns PLAY0535 collection fields, optional parameters and single-result identity inference. v4.212.2 counts read-only query denials for SPEC004, not SPEC006. No new render/runtime probe. Prior: Cratis/AI#762 and #761: source-checked v4.210.0 and v4.211.0 contracts for PLAY0800 CommandHandlerRequiresAttachment (required typed subject, permanent code-attachment requirement, other PLAY0268 families unchanged), independent reference remove/add batches, located same-text ambiguity conflicts and string MCP conflict/move-report document fields. v4.211.1 mapping changes inspected but excluded from this guidance update at the user's request; no typed PLAY0273 property/type arguments are claimed. Standalone Screenplay 4.211.1 and its compiler contract pinned; the contract is a byte-identical copy of the v4.211.1 release asset. No new render/runtime probe. Prior: Standalone 4.205.0 and byte-identical compiler contract pinned. Cratis/AI#746: Uuid ==/!= in command require and produces when (ESM v28): same-concept rule, bare Uuid against a concept, canonical literals, protected read paths in require only; PLAY0268 (different concepts, ordering, Uuid validation and concept rules, read paths in produces when) and PLAY0273 (non-canonical literal) checked against the 4.205.0 compiler, v28 selection read from the MCP executable-model view; Stage admits exact v1-v21 and v23-v26 pairs so v28 is refused STAGE-ESM-016, not probed against a Stage image; CLI 3.74.0 renders through v26. Prior: Standalone 4.204.0 and byte-identical compiler contract pinned. Cratis/AI#702 and #691: PLAY0690 reducer identity (Screenplay 4.170.0, native compiler only) and the screenplay.json validation gate (Screenplay 4.165.0; cratis screenplay validate reads it from CLI 3.65.0) are taught and probed against the 4.204.0 compiler. Cratis/AI#743: flat composite read-model keys (ESM v27): untyped projection key blocks on root from and remove with, equality-filter lists, single-instance by blocks and per-part fixtures, with PLAY0661/PLAY0662/PLAY0268 refusals checked against the 4.204.0 compiler; Stage origin/main still refuses v27 with STAGE-ESM-016 (stage-rendering.md); Stage v4.135.0 v26 admission (Host and executor run date comparisons; renderer STAGE-ESM-046) was source-checked for this sync; no render or runtime probe. Prior: Standalone 4.201.0 and byte-identical compiler contract pinned. Cratis/AI#733: the ui profile root template, shell options, appearance and new screens default (PLAY0788-PLAY0799, quick fix for the legacy layout line, ui-profiles MCP tool, 44 tools). Cratis/AI#735: chronological Date/DateTime ordering in command conditions and command/property literal validation (ESM v26), UTC tick precision and pre-rule offset validation; then matching remains ordinal. Source-checked Screenplay v4.199.0 commands, diagnostics, interoperability and specifications documentation plus decision 0087. Stage v4.127.1 still refuses v26 with STAGE-ESM-016 (stage-rendering.md and SemanticVersionFeatures.Supports); no render/runtime probe. Cratis/AI#576: prior mechanical compiler catch-up. Language batch #717/#722/#723/#724/#720/#728/#734 teaches atomic reaction batches (v22), described payload handlers (v23), portable linear matching, ordinal text rules (v24), protected command reads (v25), diagnostic arguments and event-source invokes mappings. Facts read at Screenplay v4.198.0 and introducing tags; Stage v4.127.0 admits exact v1-v21 and v23-v25 pairs but refuses v22/v26 and mixed pairs (STAGE-ESM-016), protected reads (044), atomic mode (043) and described handlers (STAGE-IMPL-002), even Stub mode. Stage text rules execute/render; no new renderer/runtime probe or Stage pin uplift. Cratis/AI#706: application navigation regions (module inherit, extend or override), toolbar slice buttons, blueprint template references and sample data packs in cratis-screenplay-ui-composition (references/application-shell.md), with the canonical shell vector and the rejection codes PLAY0710-PLAY0722 and PLAY0740-PLAY0765. Examples moved to the executable-state rules since 4.164: translator reactions in an Automation slice beside the Translate slice (PLAY0694) and the first record of a capture key appended with `when added`. Earlier: Standalone 4.164.0 and byte-identical compiler contract pinned. Cratis/AI#663: one origin per capture (PLAY0687). #668: executable no-event/redelivery v17. #684: concept query-argument validation in every version and query-error assertions v18. #681: executable refusal branches and refusal values v19. #666: proposal summary/severity counts and exact structural source proposals. Generated-concept rules select v20 with PLAY0688/0689 proofs and derived-matches repair; generated secrets and preview strategies remain refused. Release-baseline from-esm admission reads storedName. Standalone binding is not renderer admission: Stage 4.103.0 admits v1-v17 and v19; CLI 3.62.0 bundles Screenplay 4.159.0 / Stage 4.99.0 and renders through v16. Prior evidence remains unless superseded; no new renderer, Docker or browser probe."
|
|
204
|
+
"notes": "Cratis/AI#975: reviewed every release v4.246.0 through v5.1.0. Standalone 5.1.0 and its byte-identical contract pinned; the onboarding/environment contract exceptions are gone. v5.0.0: objects and lists are indented blocks (`member = value`, `item`, `none`, `empty`), inline JSON is PLAY0833, and every skill example uses the block form. v4.246.0 (decision 0115): a specification runs only its own slice; command specifications state their own events, automations state cross-slice hand-overs with `then invokes` (ESM v34), and every cross-slice expectation in the examples moved to the producing slice. v4.248.0: action subjects `for item`/`for screen` with PLAY0817-PLAY0821; every example action states its subject by intent. v4.250.0 (decision 0117): attached handlers beside unconditional produces with a resolved body bind as the v23 result contract; PLAY0800 only for the remaining shapes; PLAY0035 retired. v4.254.0: `$eventContext.occurred` runs in scoped projections for facts appended under `given clock` (probed on the 5.1.0 tool; a `given` fact carries none). v4.257.0: PLAY0824/PLAY0825 preferred-syntax rows. v5.1.0: `statemachine` and `workflow` (ESM v36) taught with a compiled, passing example; Stage 4.214.0 refuses v36. Cratis.Orleans engine hosting remains Cratis/AI#972. Editor-only, host-provider and board releases need no teaching change. Prior: Cratis/AI#820: reviewed v4.245.0 release; protected-read constraint precedence preserved. Review correction: removed unsupported parser-repair and inbound-public refusal release attributions and the incorrect PLAY0136 event-key claim, restoring prior teaching. Published contract asset is byte-identical to the previous snapshot; pin and compatibility entry advanced together. Prior: Cratis/AI#779: reference-runner capability refusals taught as scoped per specification (introduced in v4.213.2, Cratis/Screenplay#897) from the v4.216.0 tool and MCP documentation and plan source: an unadmitted projection (UnsupportedEventContext, UnsupportedProjectionBlock) marks unsupported only the specifications that reach it or its read model, the others run and planIssues lists deferred issues; application-level issues still block every selected specification; no new render/runtime probe. Prior: Cratis/AI#776: PLAY0802 ReservedStoredName (introduced in v4.213.3, Cratis/Screenplay#893) taught from the v4.216.0 compilers and documentation: stored event source `Default` and stored event stream `All` (ordinal, name or `id` pin) refused at authoring time, a pin away from the reserved name valid, PLAY0273 kept as the binding backstop; no new render/runtime probe. Prior: Cratis/AI#784: standalone Screenplay 4.216.0 pinned; compiler contract replaced by the v4.216.0 release asset (adds the propose-repair destinationIntent v1 schema and PLAY0802 ReservedStoredName). Source-checked decision 0096 and the MCP reference for the explicit author-intent PLAY0470 repair: repair-intents discovery, intentActions feature detection, complete per-production selections, retained production-destination report and identity views, explicit apply and refusals. No new render/runtime probe. Prior: Cratis/AI#771: standalone Screenplay 4.213.0 pinned; regenerated compiler contract is byte-identical to the v4.213.0 release asset and unchanged from 4.212.4. Reviewed the full v4.212.4-v4.213.0 delta against tagged decision 0093 and MCP reference: pre-binding container identities and stable binding/migration continuity, own-slice member substitutions, containerIdentities completeness/ambiguity/collision refusals, retained ambiguous notes, explicit semanticRenames/retirements, binding fixes through MCP, exact reopen exception, notes/identity rollback and exact-ID re-add anchoring. No grammar, binder, ESM or diagnostic-code changes; no new render/runtime probe. Prior: Cratis/AI#772: standalone Screenplay 4.212.4 pinned; regenerated compiler contract is byte-identical to the v4.212.4 release asset. Source-checked joined-event automap/no automap overrides and level fallback in executable binding; PLAY0380 covers only all inside children/nested. No new render/runtime probe. Prior: Cratis/AI#769: standalone Screenplay 4.212.3 pinned; regenerated compiler contract is byte-identical to the v4.212.3 release asset. Source-checked both compilers and projection documentation for PLAY0801 DuplicateEventInProjectionScope: shared from/removal/clear set, separate join set, fresh sets per children/nested/variant level, and no two-row update through repeated from blocks with different keys. No new render/runtime probe. Prior: Cratis/AI#768: standalone Screenplay 4.212.2 pinned; regenerated compiler contract is byte-identical to the v4.212.2 release asset (unchanged from the previous contract). Source-checked v4.212.0 split-model dotted note targets, open-workspace applicationIdentity and complete add/reanchor substitutions; unbound container identities are not claimed. v4.212.1 aligns PLAY0535 collection fields, optional parameters and single-result identity inference. v4.212.2 counts read-only query denials for SPEC004, not SPEC006. No new render/runtime probe. Prior: Cratis/AI#762 and #761: source-checked v4.210.0 and v4.211.0 contracts for PLAY0800 CommandHandlerRequiresAttachment (required typed subject, permanent code-attachment requirement, other PLAY0268 families unchanged), independent reference remove/add batches, located same-text ambiguity conflicts and string MCP conflict/move-report document fields. v4.211.1 mapping changes inspected but excluded from this guidance update at the user's request; no typed PLAY0273 property/type arguments are claimed. Standalone Screenplay 4.211.1 and its compiler contract pinned; the contract is a byte-identical copy of the v4.211.1 release asset. No new render/runtime probe. Prior: Standalone 4.205.0 and byte-identical compiler contract pinned. Cratis/AI#746: Uuid ==/!= in command require and produces when (ESM v28): same-concept rule, bare Uuid against a concept, canonical literals, protected read paths in require only; PLAY0268 (different concepts, ordering, Uuid validation and concept rules, read paths in produces when) and PLAY0273 (non-canonical literal) checked against the 4.205.0 compiler, v28 selection read from the MCP executable-model view; Stage admits exact v1-v21 and v23-v26 pairs so v28 is refused STAGE-ESM-016, not probed against a Stage image; CLI 3.74.0 renders through v26. Prior: Standalone 4.204.0 and byte-identical compiler contract pinned. Cratis/AI#702 and #691: PLAY0690 reducer identity (Screenplay 4.170.0, native compiler only) and the screenplay.json validation gate (Screenplay 4.165.0; cratis screenplay validate reads it from CLI 3.65.0) are taught and probed against the 4.204.0 compiler. Cratis/AI#743: flat composite read-model keys (ESM v27): untyped projection key blocks on root from and remove with, equality-filter lists, single-instance by blocks and per-part fixtures, with PLAY0661/PLAY0662/PLAY0268 refusals checked against the 4.204.0 compiler; Stage origin/main still refuses v27 with STAGE-ESM-016 (stage-rendering.md); Stage v4.135.0 v26 admission (Host and executor run date comparisons; renderer STAGE-ESM-046) was source-checked for this sync; no render or runtime probe. Prior: Standalone 4.201.0 and byte-identical compiler contract pinned. Cratis/AI#733: the ui profile root template, shell options, appearance and new screens default (PLAY0788-PLAY0799, quick fix for the legacy layout line, ui-profiles MCP tool, 44 tools). Cratis/AI#735: chronological Date/DateTime ordering in command conditions and command/property literal validation (ESM v26), UTC tick precision and pre-rule offset validation; then matching remains ordinal. Source-checked Screenplay v4.199.0 commands, diagnostics, interoperability and specifications documentation plus decision 0087. Stage v4.127.1 still refuses v26 with STAGE-ESM-016 (stage-rendering.md and SemanticVersionFeatures.Supports); no render/runtime probe. Cratis/AI#576: prior mechanical compiler catch-up. Language batch #717/#722/#723/#724/#720/#728/#734 teaches atomic reaction batches (v22), described payload handlers (v23), portable linear matching, ordinal text rules (v24), protected command reads (v25), diagnostic arguments and event-source invokes mappings. Facts read at Screenplay v4.198.0 and introducing tags; Stage v4.127.0 admits exact v1-v21 and v23-v25 pairs but refuses v22/v26 and mixed pairs (STAGE-ESM-016), protected reads (044), atomic mode (043) and described handlers (STAGE-IMPL-002), even Stub mode. Stage text rules execute/render; no new renderer/runtime probe or Stage pin uplift. Cratis/AI#706: application navigation regions (module inherit, extend or override), toolbar slice buttons, blueprint template references and sample data packs in cratis-screenplay-ui-composition (references/application-shell.md), with the canonical shell vector and the rejection codes PLAY0710-PLAY0722 and PLAY0740-PLAY0765. Examples moved to the executable-state rules since 4.164: translator reactions in an Automation slice beside the Translate slice (PLAY0694) and the first record of a capture key appended with `when added`. Earlier: Standalone 4.164.0 and byte-identical compiler contract pinned. Cratis/AI#663: one origin per capture (PLAY0687). #668: executable no-event/redelivery v17. #684: concept query-argument validation in every version and query-error assertions v18. #681: executable refusal branches and refusal values v19. #666: proposal summary/severity counts and exact structural source proposals. Generated-concept rules select v20 with PLAY0688/0689 proofs and derived-matches repair; generated secrets and preview strategies remain refused. Release-baseline from-esm admission reads storedName. Standalone binding is not renderer admission: Stage 4.103.0 admits v1-v17 and v19; CLI 3.62.0 bundles Screenplay 4.159.0 / Stage 4.99.0 and renders through v16. Prior evidence remains unless superseded; no new renderer, Docker or browser probe."
|
|
205
205
|
},
|
|
206
206
|
{
|
|
207
207
|
"id": "scene",
|
|
@@ -44,7 +44,7 @@ This skill is a method: it names no API of its own. When the Screenplay skills a
|
|
|
44
44
|
| --- | --- |
|
|
45
45
|
| Where each rule lives (validator, `Provide()`, handler result, constraint, exception) | `rules/vertical-slices.md` "The decision matrix" |
|
|
46
46
|
| A customization never makes a rejected model renderable; managed output is never hand-edited | Stage (`Customizations/` is the unmanaged seam; managed output is regenerated) |
|
|
47
|
-
| Attached file or inline command handlers
|
|
47
|
+
| Attached file or inline command handlers bind beside unconditional `produces` with a resolved body (Screenplay 4.250.0) and are otherwise refused with PLAY0800 (4.210.0 to 4.249.x refuse every attached handler; older binders report PLAY0268); pending handlers with unconditional productions bind v23 as described commands, but reached bodies are Unsupported ImplementationBody and Stage refuses STAGE-IMPL-002 even in Stub mode | Screenplay and Stage; use the model as the gap-fill contract |
|
|
48
48
|
|
|
49
49
|
## Procedure
|
|
50
50
|
|
|
@@ -83,9 +83,9 @@ module Marina
|
|
|
83
83
|
screen BerthListScreen
|
|
84
84
|
title "Berths"
|
|
85
85
|
data BerthListView[] via query ListBerths
|
|
86
|
-
action BookBerth
|
|
86
|
+
action BookBerth for screen
|
|
87
87
|
label "Book a berth"
|
|
88
|
-
action CancelBerth
|
|
88
|
+
action CancelBerth for item
|
|
89
89
|
table BerthListView
|
|
90
90
|
column boatName label "Boat"
|
|
91
91
|
on row-click navigate to BerthDetailsScreen by berthId
|
|
@@ -94,7 +94,7 @@ module Marina
|
|
|
94
94
|
data BerthListView via query GetBerth by berthId
|
|
95
95
|
summary BerthListView
|
|
96
96
|
field boatName label "Boat"
|
|
97
|
-
action CancelBerth
|
|
97
|
+
action CancelBerth for item
|
|
98
98
|
navigate to BerthListScreen
|
|
99
99
|
|
|
100
100
|
form BookBerthForm for BookBerth
|
|
@@ -119,8 +119,8 @@ field because `berthId` is the identifier, not something the user types.
|
|
|
119
119
|
| `table BerthListView` with `column boatName label "Boat"` | `<DataPage.Columns><Column field='boatName' header='Boat' /></DataPage.Columns>`; one `Column` per modeled `column`, no extras | Verified |
|
|
120
120
|
| A second `table` on one screen | `DataTableForQuery` / `DataTableForObservableQuery` ([data-tables.md](data-tables.md)) | Verified |
|
|
121
121
|
| `summary BerthListView` with `field boatName label "Boat"` | Plain markup in the page or in `detailsComponent` (`{ item }`), one labelled line per modeled `field` | Gap: this skill's verified sources name no summary component |
|
|
122
|
-
| `action BookBerth` with `label "Book a berth"` | `<MenuItem label='Book a berth' icon={...} command={() => showBookBerth()} />` plus `CommandDialog` and `useDialog
|
|
123
|
-
| `action CancelBerth` on a list with a table | `MenuItem` with `disableOnUnselected`; the selected row supplies the identifier | Verified prop |
|
|
122
|
+
| `action BookBerth for screen` with `label "Book a berth"` | `<MenuItem label='Book a berth' icon={...} command={() => showBookBerth()} />` plus `CommandDialog` and `useDialog`; no row fills its inputs | Verified |
|
|
123
|
+
| `action CancelBerth for item` on a list with a table | `MenuItem` with `disableOnUnselected`; the selected row supplies the identifier | Verified prop |
|
|
124
124
|
| `action` with no `label` | The model gives no text. Use the command name, spaced, and report it | Gap |
|
|
125
125
|
| `action X` with `navigate to S [by p]` | Navigate to the page for `S` after the command succeeds, in `onSuccess`; pass `p` from the response or the row | Assumption: `screens.md` does not say when it navigates. The form's `on submit` is defined as "after a successful submit"; confirm with the model owner |
|
|
126
126
|
| `on row-click navigate to S by p` | `DataPage` and `DataTableForQuery` forward no row-click prop (only `DataTableCore` has `onRowClick`, and it takes rows, not a query). Use controlled `selection` and `onSelectionChange` to navigate, or a link in a `Column` `body` | Gap: selection is not a click; report which you chose |
|
|
@@ -13,7 +13,7 @@ that read one contract, produced from the model and a Cratis environment:
|
|
|
13
13
|
|---|---|---|
|
|
14
14
|
| **AuthProxy** | The only public entry point; signs people in with the model's providers. | `Cratis:AuthProxy:Application` (see the AuthProxy reference of `cratis-arc-authentication-authorization-and-identity`). |
|
|
15
15
|
| **Ante** | **One per application.** Signs invitation tokens, serves the lobby, records acceptance and legal terms, publishes to its outbox. | `Ante:Onboarding:*`. |
|
|
16
|
-
| **Herald** | Sends the invitation and welcome emails from the application (the declined
|
|
16
|
+
| **Herald** | Sends the invitation and welcome emails from the application (including the declined sign-up email). | `cratis-showrunner-herald`. |
|
|
17
17
|
|
|
18
18
|
Nobody writes the equivalent `Ante:*` or `Cratis:AuthProxy:*` keys by hand for a Screenplay
|
|
19
19
|
application. The model supplies structure (providers, personas, invitation types, legal files);
|
|
@@ -29,7 +29,7 @@ persona and invitation-type checks. The **application** owns the persona list (t
|
|
|
29
29
|
invited, link delivery, membership and provisioning. Ante sends no email: the application sends
|
|
30
30
|
the invitation link through Herald using the `InvitationTokenIssued` token. Every accepted fact
|
|
31
31
|
(`InvitationToJoinTenantAccepted`, `InvitationToCreateTenantAccepted`,
|
|
32
|
-
`OrganizationRegistrationCompleted`, `LegalTermsAccepted`) means **published to Ante's outbox, not
|
|
32
|
+
`OrganizationRegistrationCompleted`, `OrganizationRegistrationDeclined`, `LegalTermsAccepted`) means **published to Ante's outbox, not
|
|
33
33
|
provisioned**: make provisioning idempotent by event source id and event kind. Ante does not know
|
|
34
34
|
what a persona may do; it validates grantable personas against the configured list only.
|
|
35
35
|
|
|
@@ -46,6 +46,12 @@ for the table before configuring anything.
|
|
|
46
46
|
- Legal terms are files in a mounted folder (`terms.md`, `privacy.md`). The version is a content hash, so editing either file requires everyone onboarding afterwards to accept again. Archive each version for consent audit; the bodies live in your files.
|
|
47
47
|
- **Secrets** (the signing private key, pinned attestation public keys) arrive only as mounted files or standard configuration, never on the command line; Ante logs no value.
|
|
48
48
|
|
|
49
|
+
## Sign-up review and the default offering
|
|
50
|
+
|
|
51
|
+
- **Sign-up review** is opt-in (`Ante:Registration:Review`, off by default): Ante holds each sign-up until the host decides. Read [sign-up review](references/sign-up-review.md) before turning it on or handling `OrganizationRegistrationAwaitingReview`.
|
|
52
|
+
- **The default offering** starts each new tenant on the offer the product declared, through Box Office. Read [default offering](references/default-offering.md) before wiring `IDefaultOffering` or diagnosing a tenant without seats or modules.
|
|
53
|
+
- `InvitationRejected` is a host configuration problem, never a message to the invitee; only `OrganizationRegistrationDeclined` says a person was turned down.
|
|
54
|
+
|
|
49
55
|
## Development mode is for local runs only
|
|
50
56
|
|
|
51
57
|
`Ante:Onboarding:Development:Enabled=true` generates a 2048-bit RSA signing key per data volume and
|
|
@@ -76,6 +82,7 @@ with its AuthProxy when the application has `authentication` and its own Ante wh
|
|
|
76
82
|
- Treating `Accepted` as provisioned: provisioning is the application's, and must be idempotent.
|
|
77
83
|
- Setting a signing key or provider secret as an environment variable in a manifest: use the mounted files.
|
|
78
84
|
- Two Ante instances for one application, or one Ante shared by several Performances: one Ante per Performance, with its own event store (`ante-<name>` by default).
|
|
85
|
+
- Answering `InvitationRejected` with a message to the invitee: fix the invitation or host configuration instead.
|
|
79
86
|
- Using development mode in a shared cluster: Ante refuses; do not work around the guard.
|
|
80
87
|
|
|
81
88
|
## Verify
|
|
@@ -90,5 +97,6 @@ with its AuthProxy when the application has `authentication` and its own Ante wh
|
|
|
90
97
|
- The model's `onboarding` block and environment keys: `cratis-screenplay-authentication-and-onboarding`.
|
|
91
98
|
- Environment commands and secrets providers: `cratis-environments-and-secrets`.
|
|
92
99
|
- Sending the emails: `cratis-showrunner-herald`.
|
|
100
|
+
- Box Office offers, seats and entitlements beyond the default offering: Showrunner's Box Office documentation; this corpus covers only starting a tenant on the default offering.
|
|
93
101
|
- Ante used by a host product, not a Screenplay application: Ante's own documentation; this corpus does not cover it.
|
|
94
102
|
- Chronicle itself in a cluster: `cratis-chronicle-hosting`.
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# Default offering
|
|
2
|
+
|
|
3
|
+
Requires Showrunner 1.13.0 or later (`Cratis.Showrunner.BoxOffice`) for `DefaultOffering`,
|
|
4
|
+
`IDefaultOffering` and an event store taken from the host. Older releases have neither.
|
|
5
|
+
|
|
6
|
+
A product that sells itself starts a new tenant on its default offering without waiting for the
|
|
7
|
+
operator. The product decides, the operator is told, and a later operator decision replaces it.
|
|
8
|
+
|
|
9
|
+
## Declare it
|
|
10
|
+
|
|
11
|
+
```csharp
|
|
12
|
+
builder.Services.AddBoxOfficeOffering(offering => offering
|
|
13
|
+
.Product(productId)
|
|
14
|
+
.Seats(SeatLicensing.PerUser)
|
|
15
|
+
.DefaultOffering("Starter"));
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
The name is the offer in the operator's catalog. The declaration is reported once per change as
|
|
19
|
+
`DefaultOfferingDeclared`, so the operator knows which offer new tenants start on. A declaration
|
|
20
|
+
that cannot be sold throws `InvalidOffering` at startup, one sentence per problem.
|
|
21
|
+
|
|
22
|
+
## Start a tenant
|
|
23
|
+
|
|
24
|
+
Call `IDefaultOffering.StartTenant(tenant, organization)` when the product has created the tenant.
|
|
25
|
+
It finds the named offer among the offers the operator published and does two things:
|
|
26
|
+
|
|
27
|
+
- records `TenantStartedOnDefaultOffering` in the tenant's own stream, so the tenant has the offer's
|
|
28
|
+
included seats and modules at once, with no trial;
|
|
29
|
+
- publishes `TenantStartedOnOffer` to the operator, with the offer's name, included seats and
|
|
30
|
+
modules.
|
|
31
|
+
|
|
32
|
+
A later operator decision such as `SeatCapacitySet` or `ModuleRevoked` supersedes what the tenant
|
|
33
|
+
started with: the newest decision wins.
|
|
34
|
+
|
|
35
|
+
## Failures
|
|
36
|
+
|
|
37
|
+
| Failure | Meaning | Action |
|
|
38
|
+
|---|---|---|
|
|
39
|
+
| `DefaultOfferingNotDeclared` | The product declared no default offering. | Add `DefaultOffering(...)`. |
|
|
40
|
+
| `DefaultOfferingNotPublished` | The operator has not published an offer with that name, or withdrew it. The name compares ignoring case. | Publish the offer; retry. |
|
|
41
|
+
| `TenantNotStarted` | The tenant could not be started. | Read the reason; retry. |
|
|
42
|
+
|
|
43
|
+
The catalog arrives after the product starts, so a name is checked when a tenant starts, not at
|
|
44
|
+
startup. Nothing is published on a failure. Starting the same tenant again, also from another
|
|
45
|
+
instance, returns `TenantStart.AlreadyStarted` and publishes nothing; if the product stopped
|
|
46
|
+
between the two facts, starting again completes what is missing. A different default later does
|
|
47
|
+
not restart a tenant.
|
|
48
|
+
|
|
49
|
+
## Event store
|
|
50
|
+
|
|
51
|
+
Herald, Box Office and the offering record in the host application's own event store in a host set
|
|
52
|
+
up with `AddCratis` or `AddCratisChronicle`; nothing needs naming. Set `HeraldOptions.EventStore`,
|
|
53
|
+
`BoxOfficeOptions.EventStore` or `OfferingOptions.EventStore` only to use another store. A host that
|
|
54
|
+
registers only the Chronicle client uses the name in `ChronicleClientOptions.EventStore`.
|
|
55
|
+
|
|
56
|
+
## Verify
|
|
57
|
+
|
|
58
|
+
1. After the operator publishes the offer, `StartTenant` for a new tenant publishes
|
|
59
|
+
`TenantStartedOnOffer`; a second call returns `TenantStart.AlreadyStarted`.
|
|
60
|
+
2. Before the offer is published, `StartTenant` throws `DefaultOfferingNotPublished` and publishes
|
|
61
|
+
nothing.
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# Sign-up review
|
|
2
|
+
|
|
3
|
+
Requires Ante 1.6.0 or later (`Ante:Registration:Review`, `RegistrationReview` in the onboarding
|
|
4
|
+
contract). Older releases complete every sign-up without a decision and publish neither event
|
|
5
|
+
below.
|
|
6
|
+
|
|
7
|
+
Review is off by default and changes nothing while off. Turn it on when a person must be approved
|
|
8
|
+
before an organization is created.
|
|
9
|
+
|
|
10
|
+
## Flow
|
|
11
|
+
|
|
12
|
+
1. A person finishes the sign-up. With review on, Ante accepts it but holds it: no
|
|
13
|
+
`OrganizationRegistrationCompleted` is published and the registration is not complete.
|
|
14
|
+
2. Ante publishes `OrganizationRegistrationAwaitingReview` to its outbox, once per registration, on
|
|
15
|
+
the registration id. It carries the same details `OrganizationRegistrationCompleted` would carry:
|
|
16
|
+
the organization name asked for, the contact address (can be empty, never verified), the names,
|
|
17
|
+
the sign-in subject and provider, and the untrusted sign-up context.
|
|
18
|
+
3. The host shows the sign-up to its reviewers. Ante has no administrator screen and takes no
|
|
19
|
+
decision itself.
|
|
20
|
+
4. The host appends one of these to **its own store's outbox**, with the registration id as the
|
|
21
|
+
event source id:
|
|
22
|
+
- `OrganizationRegistrationApproved`: Ante completes the registration as it would have without
|
|
23
|
+
review and publishes `OrganizationRegistrationCompleted`.
|
|
24
|
+
- `OrganizationRegistrationDeclineRequested(Message)`: Ante publishes
|
|
25
|
+
`OrganizationRegistrationDeclined` with the contact address, the name the person gave and the
|
|
26
|
+
reviewer's message. `Message` is required; a blank one is refused and nothing is published.
|
|
27
|
+
|
|
28
|
+
## Rules
|
|
29
|
+
|
|
30
|
+
- A registration is decided once. A decision for a registration that was completed, was already
|
|
31
|
+
declined or was never held is ignored, so redelivery is safe and a completed registration is
|
|
32
|
+
never declined afterwards.
|
|
33
|
+
- Deduplicate `OrganizationRegistrationAwaitingReview` by registration id, like every Ante outcome:
|
|
34
|
+
delivery is at least once.
|
|
35
|
+
- If an approved registration's organization name was claimed by someone else while it waited, it
|
|
36
|
+
stays held and Ante logs a warning. Decline it with a message instead.
|
|
37
|
+
- While a sign-up is held the lobby tells the person it is waiting for review; after a decline it
|
|
38
|
+
says the sign-up was not approved, stops polling and offers no second submission.
|
|
39
|
+
- Ante emails no one. The host sends the person the declined message from
|
|
40
|
+
`OrganizationRegistrationDeclined` (Herald, `signupDeclined` template with `decline.message`).
|
|
41
|
+
- `OrganizationRegistrationDeclined` is the only outcome that says a person was turned down.
|
|
42
|
+
`InvitationRejected` says an invitation did not match what the host allows; treat it as a
|
|
43
|
+
configuration problem for whoever issued the invitation.
|
|
44
|
+
|
|
45
|
+
## Verify
|
|
46
|
+
|
|
47
|
+
1. With review on, a sign-up produces `OrganizationRegistrationAwaitingReview` and no
|
|
48
|
+
`OrganizationRegistrationCompleted`.
|
|
49
|
+
2. Appending `OrganizationRegistrationApproved` on the registration id produces
|
|
50
|
+
`OrganizationRegistrationCompleted`; appending it again produces nothing.
|
|
51
|
+
3. A decline request with a blank message publishes nothing; with a message it publishes
|
|
52
|
+
`OrganizationRegistrationDeclined` once.
|
|
@@ -69,7 +69,7 @@ block. The diagnostics for each rule are in that reference. The rules that decid
|
|
|
69
69
|
`signup open creates tenant` makes a signup create a tenant, `signup open joins tenant` asks to join an existing one.
|
|
70
70
|
- Every persona in `as`, `by` and `grant` must be declared with `persona`; there are no free-text roles.
|
|
71
71
|
- `emails` names only `invitation`, `welcome` and `signupDeclined`. The sender and mail server are not in the model.
|
|
72
|
-
- `file` paths are repository-relative, like handler files. `offering` is
|
|
72
|
+
- `file` paths are repository-relative, like handler files. `offering` is the name of an offer the operator publishes in Box Office; a rendered application starts each new tenant on it. `signupDeclined` is sent when the host declines a held sign-up (review is not modeled; see `cratis-onboarding-runtime`).
|
|
73
73
|
|
|
74
74
|
## Environment keys
|
|
75
75
|
|
|
@@ -66,7 +66,7 @@ Syntax and meaning of each line of the `onboarding` block. All lines are optiona
|
|
|
66
66
|
| `invite tenant` | `invite tenant as <Persona>` | An invitation that creates a tenant; the invitee becomes the persona in it. One line, no body. |
|
|
67
67
|
| `invite member` | body with `by <Persona>, ...` and `grant <Persona>, ...` | An invitation into an existing tenant. `by` lists who may send it, `grant` what the invitee is given. Both are required. |
|
|
68
68
|
| `legal terms` | body of `file <path>` lines | Documents a newcomer must accept. Present means acceptance is required. |
|
|
69
|
-
| `offering` | `offering <Id>` | The
|
|
69
|
+
| `offering` | `offering <Id>` | The Box Office offer a new tenant starts on. Absent means no licensing. |
|
|
70
70
|
| `emails` | body of `<email> file <path>` lines and `images <folder>` | Templates for `invitation`, `welcome` and `signupDeclined`, and the folder they take images from. |
|
|
71
71
|
|
|
72
72
|
## What the block deliberately lacks
|
|
@@ -95,7 +95,12 @@ another version behaves the same.
|
|
|
95
95
|
|
|
96
96
|
## When / when not
|
|
97
97
|
- Use: "when X happens, then ...", schedules, retries, work queues, notifications, webhooks, APIs,
|
|
98
|
-
files or message feeds, events imported from another context, legacy sync
|
|
98
|
+
files or message feeds, events imported from another context, legacy sync, lifecycles and
|
|
99
|
+
longer processes.
|
|
100
|
+
- A lifecycle (where one thing is and what moves it on) is a `statemachine`; a process that
|
|
101
|
+
sends several commands, waits, asks for approval or gives up after a deadline is a
|
|
102
|
+
`workflow` (ESM v36). Read
|
|
103
|
+
[state machines and workflows](references/statemachines-and-workflows.md) before modeling either.
|
|
99
104
|
- Not for: reaction, trigger or CDL grammar (`cratis-screenplay-captures-and-reactions`); stream
|
|
100
105
|
identity and invariants (`cratis-screenplay-streams-and-consistency`); UI interactions such as
|
|
101
106
|
`on click` (`cratis-screenplay-ui-composition`); hand-written reactors (`cratis-chronicle-reactor`).
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
- 9. Fan-out
|
|
14
14
|
- 10. Long-running process shapes
|
|
15
15
|
|
|
16
|
-
Complete compiled example: `todo-list-example.md` (binds as ESM
|
|
16
|
+
Complete compiled example: `todo-list-example.md` (binds as ESM v34 for `then invokes`; the list query
|
|
17
17
|
excerpt binds too, and the retry sweep that needs code is shown as a marked excerpt).
|
|
18
18
|
|
|
19
19
|
## 1. Deciding whether it is an automation
|
|
@@ -63,11 +63,11 @@ One spec in the slice does not cover the others.
|
|
|
63
63
|
- Current admitted Automation/Translate specifications run through standalone
|
|
64
64
|
`screenplay test` or MCP `run-specifications`. Validate/render alone is not V4;
|
|
65
65
|
report unsupported/unbound separately from passing scenarios.
|
|
66
|
-
- A
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
then
|
|
70
|
-
(
|
|
66
|
+
- A specification runs only its own slice (Screenplay decision 0115). A command spec
|
|
67
|
+
states the command's own events; the Automation states what its reaction appends in
|
|
68
|
+
its own `when append <Trigger>` spec, and a command it invokes in another slice with
|
|
69
|
+
`then invokes <Command>` (ESM v34). Another slice's event in a spec is PLAY0285
|
|
70
|
+
(unreachable). See `cratis-screenplay-scenario-coverage`.
|
|
71
71
|
- `given capture` never persists between specs: state the baseline in each record
|
|
72
72
|
update spec. First records (root, child, nested) are added only; field-change
|
|
73
73
|
`and`/`or` and transitions need previous state. Expressions/maps/unguarded record
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
# State machines and workflows (ESM v36)
|
|
2
|
+
|
|
3
|
+
## Contents
|
|
4
|
+
|
|
5
|
+
- Which construct
|
|
6
|
+
- Complete example
|
|
7
|
+
- Specifications
|
|
8
|
+
- Diagnostics and targets
|
|
9
|
+
|
|
10
|
+
Requires Screenplay 5.1.0 or later (`screenplay --version`). Sources: Screenplay
|
|
11
|
+
`Documentation/screenplay/statemachines.md`, `workflows.md` and decision 0124.
|
|
12
|
+
|
|
13
|
+
## Which construct
|
|
14
|
+
|
|
15
|
+
| The domain says | Model |
|
|
16
|
+
| --- | --- |
|
|
17
|
+
| "When X happens, do Y", one step | An `Automation` slice with a reaction |
|
|
18
|
+
| Where one thing is in its lifecycle, and what moves it on | A `statemachine` that follows the thing's read model |
|
|
19
|
+
| A longer process: several commands, a choice, a wait for a fact or a person, a deadline, a fan-out | A `workflow` with one run per subject |
|
|
20
|
+
|
|
21
|
+
A state machine never decides on commands: it follows facts that already happened. Entering
|
|
22
|
+
a state may `send` a command or `start` a workflow; both may run again on redelivery, so the
|
|
23
|
+
command or workflow must be safe to repeat. A workflow is how a process waits, retries, asks
|
|
24
|
+
for approval and gives up; do not chain reactions across slices to imitate one.
|
|
25
|
+
|
|
26
|
+
Both are top-level declarations, siblings of `trigger` and `policy`. They name commands,
|
|
27
|
+
events, read models and personas declared in slices of any module. A model that declares one
|
|
28
|
+
selects ESM v36.
|
|
29
|
+
|
|
30
|
+
## Complete example
|
|
31
|
+
|
|
32
|
+
This model compiles with `--warnaserror` and its three specifications pass with
|
|
33
|
+
`screenplay test`:
|
|
34
|
+
|
|
35
|
+
```screenplay
|
|
36
|
+
concept InvoiceId : Uuid
|
|
37
|
+
persona FinanceController
|
|
38
|
+
module Billing
|
|
39
|
+
feature Invoices
|
|
40
|
+
slice StateChange SendInvoice
|
|
41
|
+
command SendInvoice
|
|
42
|
+
invoiceId InvoiceId identifier
|
|
43
|
+
produces event InvoiceSent
|
|
44
|
+
slice StateChange MarkOverdue
|
|
45
|
+
command MarkOverdue
|
|
46
|
+
invoiceId InvoiceId identifier
|
|
47
|
+
produces event InvoiceMarkedOverdue
|
|
48
|
+
slice StateChange PayInvoice
|
|
49
|
+
command PayInvoice
|
|
50
|
+
invoiceId InvoiceId identifier
|
|
51
|
+
produces event InvoicePaid
|
|
52
|
+
slice StateChange SendReminder
|
|
53
|
+
command SendReminder
|
|
54
|
+
invoiceId InvoiceId identifier
|
|
55
|
+
produces event ReminderSent
|
|
56
|
+
slice StateChange WriteOffInvoice
|
|
57
|
+
command WriteOffInvoice
|
|
58
|
+
invoiceId InvoiceId identifier
|
|
59
|
+
produces event InvoiceWrittenOff
|
|
60
|
+
slice StateView InvoiceStatus
|
|
61
|
+
readmodel Invoice
|
|
62
|
+
invoiceId InvoiceId key
|
|
63
|
+
status String
|
|
64
|
+
projection Invoices => Invoice
|
|
65
|
+
from InvoiceSent
|
|
66
|
+
invoiceId = $eventSourceId
|
|
67
|
+
status = "sent"
|
|
68
|
+
from InvoiceMarkedOverdue
|
|
69
|
+
status = "overdue"
|
|
70
|
+
from InvoicePaid
|
|
71
|
+
status = "paid"
|
|
72
|
+
query InvoiceById => Invoice optional
|
|
73
|
+
by invoiceId InvoiceId
|
|
74
|
+
|
|
75
|
+
statemachine InvoiceLifecycle
|
|
76
|
+
description "Where an invoice is, from sent to settled"
|
|
77
|
+
follows Invoice
|
|
78
|
+
state Sent initial
|
|
79
|
+
on InvoiceMarkedOverdue -> Overdue
|
|
80
|
+
on InvoicePaid -> Paid
|
|
81
|
+
state Overdue
|
|
82
|
+
entering start CollectOverdue
|
|
83
|
+
on InvoicePaid -> Paid
|
|
84
|
+
on InvoiceWrittenOff -> WrittenOff
|
|
85
|
+
state Paid final
|
|
86
|
+
state WrittenOff final
|
|
87
|
+
|
|
88
|
+
specification GoingOverdueStartsCollection
|
|
89
|
+
given InvoiceSent
|
|
90
|
+
for "9c858901-8a57-4791-81fe-4c455b099bc9"
|
|
91
|
+
when append InvoiceMarkedOverdue
|
|
92
|
+
for "9c858901-8a57-4791-81fe-4c455b099bc9"
|
|
93
|
+
then is Overdue
|
|
94
|
+
then starts CollectOverdue
|
|
95
|
+
|
|
96
|
+
workflow CollectOverdue
|
|
97
|
+
description "Reminds the customer, waits for payment and asks finance before writing off"
|
|
98
|
+
for Invoice
|
|
99
|
+
trigger when InvoiceLifecycle enters Overdue
|
|
100
|
+
-> Remind
|
|
101
|
+
action Remind sends SendReminder
|
|
102
|
+
next -> AwaitPayment
|
|
103
|
+
wait AwaitPayment for InvoicePaid expires after 14 days
|
|
104
|
+
expired -> ApproveWriteOff
|
|
105
|
+
approval ApproveWriteOff by FinanceController expires after 7 days
|
|
106
|
+
approved -> WriteOff
|
|
107
|
+
action WriteOff sends WriteOffInvoice
|
|
108
|
+
|
|
109
|
+
specification AnUnpaidInvoiceIsWrittenOff
|
|
110
|
+
given InvoiceSent
|
|
111
|
+
for "9c858901-8a57-4791-81fe-4c455b099bc9"
|
|
112
|
+
when append InvoiceMarkedOverdue
|
|
113
|
+
for "9c858901-8a57-4791-81fe-4c455b099bc9"
|
|
114
|
+
outcome AwaitPayment expired
|
|
115
|
+
outcome ApproveWriteOff approved
|
|
116
|
+
then sends SendReminder
|
|
117
|
+
then sends WriteOffInvoice
|
|
118
|
+
then completes
|
|
119
|
+
|
|
120
|
+
specification TheRunWaitsForPayment
|
|
121
|
+
given InvoiceSent
|
|
122
|
+
for "9c858901-8a57-4791-81fe-4c455b099bc9"
|
|
123
|
+
when append InvoiceMarkedOverdue
|
|
124
|
+
for "9c858901-8a57-4791-81fe-4c455b099bc9"
|
|
125
|
+
then sends SendReminder
|
|
126
|
+
then waits at AwaitPayment
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
- `follows Invoice` / `for Invoice`: the read model whose key is one instance (one run per
|
|
130
|
+
invoice). A transition condition (`on E when <condition> -> S`) reads that read model after
|
|
131
|
+
the event; a condition over an optional property is refused at binding.
|
|
132
|
+
- Exactly one `initial` state; a `final` state has no transitions. An event takes the first
|
|
133
|
+
transition on it, in declaration order across the whole machine, whose condition holds and
|
|
134
|
+
whose target the current state allows. Anything else is ignored, not an error.
|
|
135
|
+
- Workflow nodes: `trigger` (`on <Event>`, `when <StateMachine> enters <State>`, `every`,
|
|
136
|
+
`at`, `manual`), `action <Name> sends <Command> [attempts n] [timeout] [retry after]`,
|
|
137
|
+
`decide <Name> when <condition>` with exactly two outlets, `wait` for an event or a
|
|
138
|
+
duration, `approval <Name> by <Persona or Policy>`, `foreach <Name> over <collection>` and
|
|
139
|
+
`join all|any|at least n`. Edges are `<outlet> -> <Node>` under their node.
|
|
140
|
+
- An unconnected negative outlet (`failed`, `rejected`, `expired`) fails the run; an
|
|
141
|
+
unconnected positive outlet ends that branch. Give every event wait and approval an
|
|
142
|
+
`expires after` (PLAY0849 warns otherwise).
|
|
143
|
+
|
|
144
|
+
## Specifications
|
|
145
|
+
|
|
146
|
+
| Construct | Lines |
|
|
147
|
+
| --- | --- |
|
|
148
|
+
| `statemachine` | `given <Event>`, `when append <Event>`, `then is <State>`, `then sends <Command>`, `then starts <Workflow>` (every command and workflow, in order) |
|
|
149
|
+
| `workflow` | `given <Event>`, `when append <Event>` or `when start <key>`, `outcome <Node> <outlet>`, `then sends <Command>` (every one, in order), `then completes`, `then fails at <Node>`, `then waits at <Node>` |
|
|
150
|
+
|
|
151
|
+
The reference evaluator steps the run deterministically. A wait or approval with no stated
|
|
152
|
+
`outcome` suspends the run (`then waits at`); an action defaults to `next`; a wait for a
|
|
153
|
+
duration resumes at once.
|
|
154
|
+
|
|
155
|
+
## Diagnostics and targets
|
|
156
|
+
|
|
157
|
+
- State machines: PLAY0834-PLAY0842 (missing or duplicate `initial` is PLAY0835, an
|
|
158
|
+
unreachable state warns PLAY0836, an undeclared reference is PLAY0840).
|
|
159
|
+
- Workflows: PLAY0843-PLAY0851 (no trigger is PLAY0844, a bad outlet PLAY0847, a decision
|
|
160
|
+
without exactly two outlets PLAY0848, an undeclared reference PLAY0851); PLAY0839 and
|
|
161
|
+
PLAY0841 are shared.
|
|
162
|
+
- Stage refuses ESM v36 models with `STAGE-ESM-016`; every other model renders as
|
|
163
|
+
before. The durable engine is Cratis.Orleans; its hosting and adapters are outside this
|
|
164
|
+
reference.
|
|
@@ -5,14 +5,15 @@
|
|
|
5
5
|
- Design-only additions
|
|
6
6
|
|
|
7
7
|
A complete model: a result opens a work item, a reaction invokes a command, the command's fact
|
|
8
|
-
closes the item.
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
`
|
|
15
|
-
|
|
8
|
+
closes the item. `then invokes` selects ESM v34 (`executableReady: true` from Screenplay 4.246.0),
|
|
9
|
+
standalone and through `cratis screenplay mcp`. The Stage spec runner compares `then invokes`, but the
|
|
10
|
+
Cratis renderer refuses models after v33 with `STAGE-ESM-016`; keep the specifications intact. A compiler
|
|
11
|
+
that stops before v34 refuses `then invokes`. Versions: `cratis-screenplay-toolchain` `SKILL.md`.
|
|
12
|
+
|
|
13
|
+
Each specification states only its own slice (Screenplay decision 0115): `RecordingAPass`
|
|
14
|
+
states `CoursePassed`, `SendingAfterAPass` states the hand-over with `then invokes
|
|
15
|
+
SendCertificate` (ESM v34), and `SendingACertificate` states `CertificateSent`. `given clock`
|
|
16
|
+
supplies the instant that `$context.occurred` needs.
|
|
16
17
|
Current admitted scenarios can be run with
|
|
17
18
|
standalone `screenplay test` or MCP `run-specifications`.
|
|
18
19
|
|
|
@@ -58,7 +59,7 @@ module Courses
|
|
|
58
59
|
CoursePassed
|
|
59
60
|
for enrolmentId
|
|
60
61
|
enrolmentId = enrolmentId // copied on purpose: the reaction selects it as a value
|
|
61
|
-
completedAt = $context.occurred // carried on the fact
|
|
62
|
+
completedAt = $context.occurred // carried on the fact, so every reader sees the same instant
|
|
62
63
|
produces when passed == false
|
|
63
64
|
CourseFailed
|
|
64
65
|
for enrolmentId
|
|
@@ -81,9 +82,6 @@ module Courses
|
|
|
81
82
|
for "0d3b9e2a-6c4f-4f1e-8b7a-5e2d1c3b4a01"
|
|
82
83
|
enrolmentId = "0d3b9e2a-6c4f-4f1e-8b7a-5e2d1c3b4a01"
|
|
83
84
|
completedAt = "2026-10-05T08:00:00Z"
|
|
84
|
-
then CertificateSent
|
|
85
|
-
for "0d3b9e2a-6c4f-4f1e-8b7a-5e2d1c3b4a01"
|
|
86
|
-
sentAt = "2026-10-05T08:00:00Z"
|
|
87
85
|
specification RefusingANonCoordinator
|
|
88
86
|
given caller
|
|
89
87
|
authenticated
|
|
@@ -180,9 +178,8 @@ module Certification
|
|
|
180
178
|
for "0d3b9e2a-6c4f-4f1e-8b7a-5e2d1c3b4a01"
|
|
181
179
|
enrolmentId = "0d3b9e2a-6c4f-4f1e-8b7a-5e2d1c3b4a01"
|
|
182
180
|
completedAt = "2026-10-05T08:00:00Z"
|
|
183
|
-
then
|
|
184
|
-
|
|
185
|
-
sentAt = "2026-10-05T08:00:00Z"
|
|
181
|
+
then invokes SendCertificate
|
|
182
|
+
enrolmentId = "0d3b9e2a-6c4f-4f1e-8b7a-5e2d1c3b4a01"
|
|
186
183
|
```
|
|
187
184
|
|
|
188
185
|
## Design-only additions
|
|
@@ -93,9 +93,6 @@ module Exams
|
|
|
93
93
|
for "7e9d1c2b-4a3f-4e5d-8c6b-1a2b3c4d5e06"
|
|
94
94
|
outcome = "passed"
|
|
95
95
|
score = 87
|
|
96
|
-
then ExamPassed
|
|
97
|
-
for "7e9d1c2b-4a3f-4e5d-8c6b-1a2b3c4d5e06"
|
|
98
|
-
score = 87
|
|
99
96
|
slice Automation RecordExamResult
|
|
100
97
|
reaction PassTranslator
|
|
101
98
|
when ProctorResultReceived
|
|
@@ -115,6 +112,14 @@ module Exams
|
|
|
115
112
|
constraint OneResultPerAttempt
|
|
116
113
|
unique event ExamPassed
|
|
117
114
|
unique event ExamFailed
|
|
115
|
+
specification RecordingAPass
|
|
116
|
+
when append ProctorResultReceived
|
|
117
|
+
for "7e9d1c2b-4a3f-4e5d-8c6b-1a2b3c4d5e06"
|
|
118
|
+
outcome = "passed"
|
|
119
|
+
score = 87
|
|
120
|
+
then ExamPassed
|
|
121
|
+
for "7e9d1c2b-4a3f-4e5d-8c6b-1a2b3c4d5e06"
|
|
122
|
+
score = 87
|
|
118
123
|
specification RefusingASecondResult
|
|
119
124
|
given ExamPassed
|
|
120
125
|
for "7e9d1c2b-4a3f-4e5d-8c6b-1a2b3c4d5e06"
|
|
@@ -131,7 +136,8 @@ module Exams
|
|
|
131
136
|
- Keep the capture and its appended event in Translate; put reactions to that local
|
|
132
137
|
event in a separate Automation. Co-location in a directionless Translate warns
|
|
133
138
|
PLAY0694 and fails `--warnaserror`; explicit inbound refuses it with PLAY0616.
|
|
134
|
-
|
|
139
|
+
A specification runs only its own slice (Screenplay decision 0115), so `TranslatingAPass`
|
|
140
|
+
states the Translate slice's fact and `RecordingAPass` states the Automation's result.
|
|
135
141
|
- `when added` records first sight; the separate `when outcome` append handles
|
|
136
142
|
later changes. For an update spec, seed the same reference with `given capture`.
|
|
137
143
|
Requires Screenplay 4.175.0 or later (`screenplay --version`); older evaluators
|
|
@@ -289,8 +289,8 @@ module Collections
|
|
|
289
289
|
when trigger PaymentFileArrived
|
|
290
290
|
invoiceId = "9c858901-8a57-4791-81fe-4c455b099bc9"
|
|
291
291
|
amount = 120
|
|
292
|
-
then
|
|
293
|
-
|
|
292
|
+
then invokes CloseInvoice
|
|
293
|
+
invoiceId = "9c858901-8a57-4791-81fe-4c455b099bc9"
|
|
294
294
|
reason = "paid"
|
|
295
295
|
specification IssuingTheWeeklyDigest
|
|
296
296
|
given clock "2026-10-05T07:00:00Z"
|
|
@@ -54,10 +54,16 @@ module Work
|
|
|
54
54
|
specification ProcessingRequestedWork
|
|
55
55
|
when append WorkRequested
|
|
56
56
|
workId = "work-1"
|
|
57
|
-
then
|
|
58
|
-
|
|
57
|
+
then invokes RecordWork
|
|
58
|
+
workId = "work-1"
|
|
59
59
|
```
|
|
60
60
|
|
|
61
|
+
The automation states the hand-over with `then invokes` (ESM v34). `RecordWork` is
|
|
62
|
+
decided under the declared system identity, so a denial would reach the reaction's
|
|
63
|
+
refusal branches, but `WorkRecorded` belongs to the `RecordWork` slice and is not kept
|
|
64
|
+
in this specification (Screenplay decision 0115). `RecordWork`'s own slice proves the
|
|
65
|
+
event with a `when RecordWork` specification.
|
|
66
|
+
|
|
61
67
|
## Diagnostics and target boundaries
|
|
62
68
|
|
|
63
69
|
- PLAY0647: malformed, repeated or misplaced identity, including duplicate/empty roles.
|