@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.
Files changed (68) hide show
  1. package/package/corpus/product-sync.json +4 -4
  2. package/package/corpus/skills/cratis-application-slice-conformance/SKILL.md +1 -1
  3. package/package/corpus/skills/cratis-arc-react-page/references/from-screenplay.md +5 -5
  4. package/package/corpus/skills/cratis-onboarding-runtime/SKILL.md +10 -2
  5. package/package/corpus/skills/cratis-onboarding-runtime/references/default-offering.md +61 -0
  6. package/package/corpus/skills/cratis-onboarding-runtime/references/sign-up-review.md +52 -0
  7. package/package/corpus/skills/cratis-screenplay-authentication-and-onboarding/SKILL.md +1 -1
  8. package/package/corpus/skills/cratis-screenplay-authentication-and-onboarding/references/onboarding-directives.md +1 -1
  9. package/package/corpus/skills/cratis-screenplay-automations-and-translations/SKILL.md +6 -1
  10. package/package/corpus/skills/cratis-screenplay-automations-and-translations/references/automation-patterns.md +1 -1
  11. package/package/corpus/skills/cratis-screenplay-automations-and-translations/references/cases-to-specify.md +5 -5
  12. package/package/corpus/skills/cratis-screenplay-automations-and-translations/references/statemachines-and-workflows.md +164 -0
  13. package/package/corpus/skills/cratis-screenplay-automations-and-translations/references/todo-list-example.md +12 -15
  14. package/package/corpus/skills/cratis-screenplay-automations-and-translations/references/translate-example.md +10 -4
  15. package/package/corpus/skills/cratis-screenplay-captures-and-reactions/references/complete-examples.md +2 -2
  16. package/package/corpus/skills/cratis-screenplay-captures-and-reactions/references/invocation-identity.md +8 -2
  17. package/package/corpus/skills/cratis-screenplay-command-surface/SKILL.md +5 -4
  18. package/package/corpus/skills/cratis-screenplay-command-surface/references/described-handlers.md +12 -8
  19. package/package/corpus/skills/cratis-screenplay-command-surface/references/validate-rules.md +5 -5
  20. package/package/corpus/skills/cratis-screenplay-command-surface/verification.json +1 -1
  21. package/package/corpus/skills/cratis-screenplay-event-modeling/references/nine-steps.md +6 -3
  22. package/package/corpus/skills/cratis-screenplay-legacy-extraction/references/generated-recovery.md +4 -4
  23. package/package/corpus/skills/cratis-screenplay-model-authoring/references/language-reference.md +2 -2
  24. package/package/corpus/skills/cratis-screenplay-read-surface/references/named-keys.md +3 -1
  25. package/package/corpus/skills/cratis-screenplay-read-surface/references/screen-patterns.md +2 -2
  26. package/package/corpus/skills/cratis-screenplay-render-and-gap-fill/SKILL.md +4 -4
  27. package/package/corpus/skills/cratis-screenplay-render-and-gap-fill/references/renderability-gate.md +6 -5
  28. package/package/corpus/skills/cratis-screenplay-scenario-coverage/SKILL.md +2 -2
  29. package/package/corpus/skills/cratis-screenplay-scenario-coverage/references/invoicing-dues-design.md +0 -3
  30. package/package/corpus/skills/cratis-screenplay-scenario-coverage/references/invoicing-dues-example.md +8 -3
  31. package/package/corpus/skills/cratis-screenplay-scenario-coverage/references/scenario-examples.md +17 -9
  32. package/package/corpus/skills/cratis-screenplay-scenario-coverage/references/spec-forms-by-mode.md +4 -3
  33. package/package/corpus/skills/cratis-screenplay-scenario-coverage/references/version-skew.md +25 -14
  34. package/package/corpus/skills/cratis-screenplay-scenario-coverage/references/view-and-story-specs.md +7 -6
  35. package/package/corpus/skills/cratis-screenplay-scenario-coverage/verification.json +1 -1
  36. package/package/corpus/skills/cratis-screenplay-slice-design/references/read-model-design.md +1 -1
  37. package/package/corpus/skills/cratis-screenplay-slice-design/references/slicing.md +1 -1
  38. package/package/corpus/skills/cratis-screenplay-slice-design/references/worked-example.md +3 -3
  39. package/package/corpus/skills/cratis-screenplay-specifications/SKILL.md +4 -2
  40. package/package/corpus/skills/cratis-screenplay-specifications/references/actions-beyond-commands.md +4 -2
  41. package/package/corpus/skills/cratis-screenplay-specifications/references/child-ordering.md +12 -3
  42. package/package/corpus/skills/cratis-screenplay-specifications/references/reactions-and-cascades.md +70 -21
  43. package/package/corpus/skills/cratis-screenplay-specifications/references/vocabulary.md +3 -2
  44. package/package/corpus/skills/cratis-screenplay-specifications/verification.json +2 -2
  45. package/package/corpus/skills/cratis-screenplay-toolchain/SKILL.md +3 -3
  46. package/package/corpus/skills/cratis-screenplay-toolchain/references/automation-translate-example.md +5 -8
  47. package/package/corpus/skills/cratis-screenplay-toolchain/references/cheat-sheet-example.md +12 -11
  48. package/package/corpus/skills/cratis-screenplay-toolchain/references/cheat-sheet.md +1 -1
  49. package/package/corpus/skills/cratis-screenplay-toolchain/references/diagnostic-arguments.md +1 -1
  50. package/package/corpus/skills/cratis-screenplay-toolchain/references/diagnostics.md +2 -2
  51. package/package/corpus/skills/cratis-screenplay-toolchain/references/executable-subset.md +10 -7
  52. package/package/corpus/skills/cratis-screenplay-toolchain/references/language-admission.md +4 -1
  53. package/package/corpus/skills/cratis-screenplay-toolchain/references/preferred-syntax.md +4 -1
  54. package/package/corpus/skills/cratis-screenplay-toolchain/references/renderable-subset.md +4 -4
  55. package/package/corpus/skills/cratis-screenplay-toolchain/references/screenplay-contract-exceptions.json +0 -70
  56. package/package/corpus/skills/cratis-screenplay-toolchain/references/screenplay-contract.json +4743 -623
  57. package/package/corpus/skills/cratis-screenplay-toolchain/references/screenplay-contract.version +1 -1
  58. package/package/corpus/skills/cratis-screenplay-toolchain/references/traps.md +1 -1
  59. package/package/corpus/skills/cratis-screenplay-ui-composition/SKILL.md +6 -0
  60. package/package/corpus/skills/cratis-screenplay-ui-composition/references/action-subjects.md +73 -0
  61. package/package/corpus/skills/cratis-screenplay-ui-composition/references/file-references.md +4 -3
  62. package/package/corpus/skills/cratis-screenplay-ui-composition/references/response-continuations.md +1 -1
  63. package/package/corpus/skills/cratis-screenplay-ui-composition/references/worked-flow.md +1 -1
  64. package/package/corpus/skills/cratis-showrunner-herald/SKILL.md +5 -0
  65. package/package/corpus/skills/cratis-stage-rendering-and-sandbox/SKILL.md +6 -5
  66. package/package/corpus/skills/cratis-stage-rendering-and-sandbox/references/admission.md +8 -5
  67. package/package/corpus/skills/cratis-stage-rendering-and-sandbox/references/rendered-application.md +14 -5
  68. package/package.json +1 -1
@@ -171,9 +171,9 @@
171
171
  }
172
172
  ],
173
173
  "synced": {
174
- "version": "4.245.0",
175
- "date": "2026-10-25",
176
- "by": "Cratis/AI#820"
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 are refused with PLAY0800, a permanent requirement for a code implementation attachment (Requires Screenplay 4.210.0; 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 |
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` | Verified |
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 template waits for an Ante outcome). | `cratis-showrunner-herald`. |
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 an opaque name resolved where the application is provisioned.
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 offering a new tenant starts on. Opaque; absent means no licensing. |
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 v6; the list query
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 command spec lists the cascade (v6 semantics: after
67
- `when <Command>`, `then` lists every new fact, including reaction appends). Only when the V1
68
- tool's compiler stops before v6 does it report a false PLAY0285 on a cascade:
69
- then keep the cascade out of the command spec, specify it in the Automation slice
70
- (`when append <Trigger>`) and record the expectation. See `cratis-screenplay-scenario-coverage`.
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. It binds as ESM v6 (`executableReady: true`), standalone and through `cratis screenplay mcp`.
9
- Stage renders supported event reactions, but this model's clock/cascade specs remain
10
- refused (`-024`/`-011`); keep them intact. A compiler that stops before v6 rejects the
11
- Automation slice at binding with PLAY0285 or PLAY0268. Versions: `cratis-screenplay-toolchain` `SKILL.md`.
12
-
13
- The first spec lists the whole cascade (`then` names every new fact: `CoursePassed`, and
14
- `CertificateSent` through the reaction), and `given clock` supplies the instant that
15
- `$context.occurred` needs. Both tools accept that cascade when they admit v6; an older compiler reports a false PLAY0285 on it.
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: a projection cannot read $eventContext.occurred
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 CertificateSent
184
- for "0d3b9e2a-6c4f-4f1e-8b7a-5e2d1c3b4a01"
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
- `then` lists every new fact, so `TranslatingAPass` includes the Automation result.
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 InvoiceClosed
293
- for "9c858901-8a57-4791-81fe-4c455b099bc9"
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 WorkRecorded
58
- for "work-1"
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.