@cratis/pi 7.21.0 → 7.23.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 (81) hide show
  1. package/package/corpus/skills/cratis-screenplay-automations-and-translations/SKILL.md +31 -15
  2. package/package/corpus/skills/cratis-screenplay-automations-and-translations/references/audit-format.md +4 -3
  3. package/package/corpus/skills/cratis-screenplay-automations-and-translations/references/automation-patterns.md +13 -15
  4. package/package/corpus/skills/cratis-screenplay-automations-and-translations/references/cases-to-specify.md +4 -4
  5. package/package/corpus/skills/cratis-screenplay-automations-and-translations/references/effects-and-idempotency.md +21 -0
  6. package/package/corpus/skills/cratis-screenplay-automations-and-translations/references/provenance.md +4 -2
  7. package/package/corpus/skills/cratis-screenplay-automations-and-translations/references/todo-list-example.md +7 -4
  8. package/package/corpus/skills/cratis-screenplay-automations-and-translations/verification.json +4 -4
  9. package/package/corpus/skills/cratis-screenplay-captures-and-reactions/SKILL.md +41 -38
  10. package/package/corpus/skills/cratis-screenplay-captures-and-reactions/references/complete-examples.md +1 -1
  11. package/package/corpus/skills/cratis-screenplay-captures-and-reactions/references/invocation-identity.md +84 -0
  12. package/package/corpus/skills/cratis-screenplay-captures-and-reactions/references/refusals-and-redelivery.md +102 -0
  13. package/package/corpus/skills/cratis-screenplay-captures-and-reactions/references/specifying-triggers-and-clock.md +4 -2
  14. package/package/corpus/skills/cratis-screenplay-captures-and-reactions/verification.json +1 -1
  15. package/package/corpus/skills/cratis-screenplay-command-surface/SKILL.md +57 -44
  16. package/package/corpus/skills/cratis-screenplay-command-surface/references/compliance.md +154 -0
  17. package/package/corpus/skills/cratis-screenplay-command-surface/references/context.md +57 -0
  18. package/package/corpus/skills/cratis-screenplay-command-surface/references/generated-values-and-responses.md +15 -13
  19. package/package/corpus/skills/cratis-screenplay-command-surface/references/operations.md +80 -0
  20. package/package/corpus/skills/cratis-screenplay-command-surface/references/policy-persona-seed.md +23 -1
  21. package/package/corpus/skills/cratis-screenplay-command-surface/verification.json +8 -2
  22. package/package/corpus/skills/cratis-screenplay-discovery/SKILL.md +19 -9
  23. package/package/corpus/skills/cratis-screenplay-discovery/references/interview-questions.md +1 -1
  24. package/package/corpus/skills/cratis-screenplay-discovery/references/storming-loop.md +6 -5
  25. package/package/corpus/skills/cratis-screenplay-event-modeling/SKILL.md +10 -8
  26. package/package/corpus/skills/cratis-screenplay-event-modeling/references/naming-primitives.md +5 -3
  27. package/package/corpus/skills/cratis-screenplay-event-modeling/references/nine-steps.md +6 -5
  28. package/package/corpus/skills/cratis-screenplay-event-modeling/references/parsed-not-runnable.md +41 -49
  29. package/package/corpus/skills/cratis-screenplay-legacy-extraction/SKILL.md +15 -5
  30. package/package/corpus/skills/cratis-screenplay-legacy-extraction/references/generate-notes.md +48 -8
  31. package/package/corpus/skills/cratis-screenplay-model-authoring/SKILL.md +47 -42
  32. package/package/corpus/skills/cratis-screenplay-model-authoring/references/language-reference.md +79 -15
  33. package/package/corpus/skills/cratis-screenplay-model-authoring/references/mcp-loop.md +49 -11
  34. package/package/corpus/skills/cratis-screenplay-model-authoring/references/mcp-tools.md +155 -14
  35. package/package/corpus/skills/cratis-screenplay-model-authoring/verification.json +3 -3
  36. package/package/corpus/skills/cratis-screenplay-model-review/SKILL.md +19 -7
  37. package/package/corpus/skills/cratis-screenplay-model-review/references/anti-patterns.md +1 -1
  38. package/package/corpus/skills/cratis-screenplay-model-review/references/checklist.md +11 -2
  39. package/package/corpus/skills/cratis-screenplay-modeling-lifecycle/SKILL.md +3 -3
  40. package/package/corpus/skills/cratis-screenplay-modeling-lifecycle/references/completeness-self-check.md +1 -1
  41. package/package/corpus/skills/cratis-screenplay-modeling-lifecycle/references/verdicts-and-modes.md +1 -1
  42. package/package/corpus/skills/cratis-screenplay-read-surface/SKILL.md +17 -0
  43. package/package/corpus/skills/cratis-screenplay-read-surface/references/guarded-actions.md +79 -0
  44. package/package/corpus/skills/cratis-screenplay-render-and-gap-fill/SKILL.md +11 -9
  45. package/package/corpus/skills/cratis-screenplay-render-and-gap-fill/references/gap-fill-handoff.md +6 -3
  46. package/package/corpus/skills/cratis-screenplay-render-and-gap-fill/references/renderability-gate.md +1 -1
  47. package/package/corpus/skills/cratis-screenplay-render-and-gap-fill/verification.json +2 -2
  48. package/package/corpus/skills/cratis-screenplay-scenario-coverage/SKILL.md +3 -2
  49. package/package/corpus/skills/cratis-screenplay-scenario-coverage/references/spec-forms-by-mode.md +13 -2
  50. package/package/corpus/skills/cratis-screenplay-slice-design/SKILL.md +13 -3
  51. package/package/corpus/skills/cratis-screenplay-slice-design/references/command-inventory.md +5 -3
  52. package/package/corpus/skills/cratis-screenplay-slice-design/references/review-questions.md +2 -1
  53. package/package/corpus/skills/cratis-screenplay-slice-design/references/rule-layers.md +4 -3
  54. package/package/corpus/skills/cratis-screenplay-slice-design/references/slicing.md +40 -0
  55. package/package/corpus/skills/cratis-screenplay-specifications/SKILL.md +24 -16
  56. package/package/corpus/skills/cratis-screenplay-specifications/references/examples-and-routes.md +111 -0
  57. package/package/corpus/skills/cratis-screenplay-specifications/references/reactions-and-cascades.md +5 -6
  58. package/package/corpus/skills/cratis-screenplay-streams-and-consistency/SKILL.md +22 -8
  59. package/package/corpus/skills/cratis-screenplay-streams-and-consistency/references/chronicle-boundaries.md +8 -4
  60. package/package/corpus/skills/cratis-screenplay-streams-and-consistency/references/consistency-and-concurrency.md +10 -0
  61. package/package/corpus/skills/cratis-screenplay-streams-and-consistency/references/stream-patterns.md +13 -2
  62. package/package/corpus/skills/cratis-screenplay-streams-and-consistency/references/streams-example.md +3 -3
  63. package/package/corpus/skills/cratis-screenplay-streams-and-consistency/verification.json +2 -2
  64. package/package/corpus/skills/cratis-screenplay-toolchain/SKILL.md +44 -35
  65. package/package/corpus/skills/cratis-screenplay-toolchain/references/cheat-sheet-example.md +3 -3
  66. package/package/corpus/skills/cratis-screenplay-toolchain/references/cheat-sheet.md +58 -2
  67. package/package/corpus/skills/cratis-screenplay-toolchain/references/diagnostics.md +128 -10
  68. package/package/corpus/skills/cratis-screenplay-toolchain/references/doc-contradictions.md +13 -1
  69. package/package/corpus/skills/cratis-screenplay-toolchain/references/executable-subset.md +37 -13
  70. package/package/corpus/skills/cratis-screenplay-toolchain/references/provenance.md +10 -2
  71. package/package/corpus/skills/cratis-screenplay-toolchain/references/renderable-subset.md +23 -1
  72. package/package/corpus/skills/cratis-screenplay-toolchain/references/sources-and-streams.md +111 -27
  73. package/package/corpus/skills/cratis-screenplay-toolchain/references/traps.md +27 -6
  74. package/package/corpus/skills/cratis-screenplay-toolchain/references/verdicts.md +34 -16
  75. package/package/corpus/skills/cratis-screenplay-toolchain/references/versions.md +98 -136
  76. package/package/corpus/skills/cratis-screenplay-toolchain/verification.json +13 -5
  77. package/package/corpus/skills/cratis-screenplay-ui-composition/references/screen-composition-contract.md +20 -0
  78. package/package/corpus/skills/cratis-stage-rendering-and-sandbox/SKILL.md +10 -6
  79. package/package/corpus/skills/cratis-stage-rendering-and-sandbox/references/admission.md +8 -1
  80. package/package/corpus/skills/cratis-stage-rendering-and-sandbox/verification.json +2 -2
  81. package/package.json +1 -1
@@ -28,10 +28,15 @@ identity, effect and pending-work contract at that point; do not postpone it to
28
28
  4.66.0). Probed on 3.28.2: the complete examples are `executableReady`. A cratis bundle before 3.28.2
29
29
  (4.60.1) reports PLAY0268 at binding: report "V3 blocked: PLAY0268 (ESM v6)" and
30
30
  name the tool, never remove them.
31
- - No MCP tool, `validate` or render runs Automation or Translate specs. V4 is "not run: no route".
32
- - Stage 4.24.2 (bundled in cratis 3.28.3) renders no Automation or Translate slice (Stage#79); `cratis render` refuses the whole v6 model with STAGE-ESM-016: the whole automation is
33
- gap-fill or hand-written delivery with the model as contract (`references/realization-and-gap-fill.md`).
34
- - Invoked commands run with no caller; `.play` cannot name an actor (Screenplay#383).
31
+ - Standalone 4.125.0 runs admitted scenarios through `screenplay test` or MCP
32
+ `run-specifications`; source validation and render publication do not run V4.
33
+ - Stage 4.51.3 refuses Automation/Translate members with STAGE-ESM-024; its direct
34
+ planner audits through v7. Deliver that scope as authorized gap-fill
35
+ (`references/realization-and-gap-fill.md`).
36
+ - Reaction `runs as system role "<Role>"` declares an invocation actor (ESM v10).
37
+ Without it the invoke has no caller. CLI 3.41.0's 4.114.0 compiler rejects the
38
+ new syntax (PLAY0137). Checked model/diagnostics: captures-and-reactions
39
+ `references/invocation-identity.md`.
35
40
 
36
41
  ## Effect guarantees and recovery traps
37
42
  | Guarantee | What it promises | What can show it |
@@ -54,7 +59,8 @@ sends again.
54
59
  A field left out of `map` still passes through the capture's working record: omission is not
55
60
  redaction. Check the append mappings and every resulting event property, and record whether
56
61
  the target stores raw or last-seen source records and how they are minimized.
57
- Personal data kept in events needs `@pii` on its concept and a purpose; keep the annotation
62
+ Personal data kept in events needs bare `pii` on its concept and a declared purpose
63
+ (see command-surface `references/compliance.md`); keep the marker
58
64
  even when it blocks binding. Never record bearer tokens, magic links or signed URLs as facts
59
65
  (a keyed hash or reference at most), and never put PII on the event-source id.
60
66
 
@@ -113,12 +119,20 @@ or actor that nobody confirmed. Read `references/worked-integration.md` when you
113
119
  supersession), the work-item key and the recovery path. Direct reaction only for an immediate,
114
120
  internal, always-possible effect; say why no pending state is needed. A translation is not
115
121
  automatically infallible.
116
- 4. **Effect and actor.** `produces <Fact>` when nothing should refuse the fact. `invokes <Command>`
117
- when the step is a decision that may reject; it carries **no caller**, so gated commands reject it.
118
- Record one actor decision: internal ungated command (only when safe and unreachable), direct
119
- `produces`, or gated command with a trusted actor and the capability gap (Screenplay#383). The code
120
- realization of the actor is a reactor with `[ExecuteCommandsAsSystem("<role>")]` and a policy
121
- requiring that role; never invent `runs as`. Never strip authorization to pass a tool.
122
+ 4. **Effect and actor.** `produces <Fact>` records a decided fact; `invokes <Command>`
123
+ requests a decision. Keep its gate and declare the trusted role with reaction
124
+ `runs as system role "<Role>"` (ESM v10). An undeclared actor remains caller-less.
125
+ CLI/Stage realization is a separate gap; a returned-command reactor uses
126
+ `[ExecuteCommandsAsSystem("<role>")]` and the matching policy. Never strip a
127
+ gate or supply `given caller` as a fictional reaction identity. Arc supplies a
128
+ system principal only to reactors marked `[ExecuteCommandsAsSystem]`; without
129
+ it there is no principal and `[Authorize]`/`[Roles]` deny. `runs as` covers returned
130
+ or invoked commands, not imperative pipeline calls, reads, productions or causation.
131
+ On Screenplay 4.127.0 run `--check privilege --warnaserror` (PLAY0652) for
132
+ confused-deputy paths: every trigger-event producer must require **all** declared
133
+ system roles. Ungated commands/captures/reaction productions warn; opaque gates
134
+ are information, not proven safe. An OR alternative does not require a role.
135
+ Clock/application triggers have no producer and are silent; still review trust.
122
136
  5. **Trace inputs.** Every trigger value, command input, event property and destination needs a
123
137
  supported source; every filter a business reason. Gaps are questions, not invented mappings.
124
138
  6. **Repetition and termination.** Identify one logical work occurrence and what a retry is. Guard the
@@ -135,12 +149,13 @@ or actor that nobody confirmed. Read `references/worked-integration.md` when you
135
149
  ## Rules
136
150
  **Compiler contracts** (diagnostics at 4.66.0)
137
151
  - No inline `produces event` in a reaction (PLAY0474); declare reaction-produced events in the slice.
138
- - Effects sit under a trigger; only `description` and `where` are reaction-level; one `where` per
152
+ - Effects sit under a trigger; `description`, `where` and current `runs as` are reaction-level; one `where` per
139
153
  reaction (PLAY0252); a trigger may not repeat (PLAY0253).
140
154
  - Clock triggers take no values (PLAY0450) and no `by` on reads (PLAY0443). `for each <View>` is
141
155
  reserved, not available.
142
156
  - Capture `when` cannot mix `and` and `or` (PLAY0089). A capture without `key` does not bind.
143
- - Undeclared events in capture `append` and `remove with` pass V1 and fail only at binding (V3, PLAY0273): run V3.
157
+ - Current V1 warns on undeclared capture/removal events (PLAY0166); V3 remains a
158
+ separate binder check.
144
159
  - A trigger with `reads` that `produces` directly fails binding: decide in a command. `reads` never protects.
145
160
  - An authorized command exercised in a spec without `given caller` is PLAY0389 at binding.
146
161
  - A list query (`=> Item[]`) and a clock sweep that iterates items do not bind; show them only as marked
@@ -155,7 +170,7 @@ or actor that nobody confirmed. Read `references/worked-integration.md` when you
155
170
  record. A fan-out records one outcome per item; partial success is failure at an effect boundary
156
171
  (`cratis-engineering-effect-boundaries`), never a batch "done" while members failed.
157
172
  - Infrastructure (logging, caching, retries, outbox plumbing) is never a Translate slice.
158
- - Personal data kept in events needs `@pii` on its concept; keep it even when it blocks binding or render.
173
+ - Personal data kept in events needs `pii` on its concept; keep it even when it blocks binding or render.
159
174
  - Code bodies (`file`, inline fences) document realization; no local engine runs them.
160
175
 
161
176
  **Review questions**
@@ -175,7 +190,8 @@ Never report a verdict without the tool and version that produced it.
175
190
 
176
191
  ## Verify
177
192
  - V1 and V3 per `cratis-screenplay-toolchain`, each with tool and version. On a cratis before 3.28.2
178
- bundle report "V3 blocked: PLAY0268 (ESM v6)"; on 4.66.0 (standalone or cratis 3.28.2) these slices bind. V4 is "not run: no route" for these slices.
193
+ bundle report "V3 blocked: PLAY0268 (ESM v6)". Current admitted scenarios use
194
+ standalone `screenplay test`/MCP for V4; unsupported or unbound is not passed.
179
195
  - For each external source and type: its translation, or an explicit out-of-scope reason; check
180
196
  target-field completeness as well as source-field dispositions.
181
197
  - One happy path is not coverage: cite the spec or the missing case for each branch, denial, competing
@@ -11,8 +11,8 @@ technique: partial work stays visible and nothing is skipped because it looked r
11
11
 
12
12
  Result is `complete` only when every column is filled or says why it does not apply (for example
13
13
  "direct effect: immediate, internal, cannot fail"). `open` names the unresolved decision and who
14
- answers. `blocked` names the capability gap (for example Screenplay#383 for the actor, or a
15
- list query that does not bind) with the intended behaviour.
14
+ answers. `blocked` names the actual capability gap (for example CLI 3.41.0's
15
+ older compiler cannot parse a declared ESM v10 reaction actor) with intended behavior.
16
16
 
17
17
  ## Per translation (capture or translator reaction)
18
18
  | Source and type | Location | Correlation | Field dispositions | Target fields traced | Dedup and ordering | Trust boundary | Recovery owner | Named cases | Result |
@@ -45,4 +45,5 @@ never skip it silently or call the chain complete.
45
45
  | Unreviewed | `RecordCompletion` denial for a non-coordinator is specified; query authorization not in scope | stated |
46
46
 
47
47
  Then the verdict line per `cratis-screenplay-toolchain`: tool and version on each of V1 to V4
48
- (V4 for these slices: "not run: no route").
48
+ (V4 uses standalone `screenplay test` or MCP `run-specifications`; report the
49
+ actual result, or a specific host/input limitation if not run).
@@ -65,16 +65,17 @@ When a todo list is not needed: the effect is immediate, internal and cannot fai
65
65
  | can it be refused? | only by append-time constraints | authorization, validation, `require`, constraints |
66
66
  | destination | `for` value; without `for`, the trigger fact's source | the command's identifier |
67
67
  | with trigger `reads` | fails binding (unprotected decision) | allowed; protection is the command's job |
68
- | caller | n/a | **none**: gated commands reject |
68
+ | caller | n/a | declared reaction `runs as` actor (ESM v10), otherwise none |
69
69
 
70
70
  ## 4. The actor behind an invoke
71
- On Screenplay 4.66.0 there is no caller: the invoked command runs its full pipeline (authorization, validation,
72
- requirements, constraints) with no caller, a command that needs one rejects, and the rejection
73
- ends the scenario. Screenplay has no syntax for an identity (Screenplay#383, open); never invent
74
- `runs as` or a caller line. At code level the realization is a Chronicle reactor whose returned
75
- commands run as a trusted system actor: `[ExecuteCommandsAsSystem("<role>")]` (Arc, since
76
- v20.56.0; also in a Stage-rendered app, whose Arc is 22.25.0) with a policy that requires that
77
- role. Record the intended actor in the model; the attribute lives in gap-fill code.
71
+ Screenplay 4.125.0 declares the actor with reaction-level `runs as system role
72
+ "<Role>"` (ESM v10); without it a gated invocation has no caller and denies.
73
+ `given caller` is not an invocation actor. Role requirements remain enforced;
74
+ claim conditions for this system principal remain unknown. CLI 3.41.0's older
75
+ compiler rejects the syntax (PLAY0137), and Stage 4.51.3 admits through v7 only.
76
+ Use the checked model in captures-and-reactions `references/invocation-identity.md`.
77
+ Arc gap-fill uses `[ExecuteCommandsAsSystem("<role>")]` for returned commands,
78
+ not identity inferred from prose or an imperative pipeline call.
78
79
 
79
80
  Decide and record one of:
80
81
  1. **Internal ungated command** - only if the security design supports it: not reachable by
@@ -84,13 +85,10 @@ Decide and record one of:
84
85
  requirement in `STATE.md`.
85
86
  2. **Direct `produces`** - when no decision is left (the fact is already decided) and nothing
86
87
  should refuse it.
87
- 3. **Gated command + trusted actor + recorded gap** - when the command must stay protected.
88
- Keep the gate (a policy requiring the service role), name the role as the intended actor,
89
- and record that Screenplay 4.66.0 cannot declare it. The reference rejects the caller-less invoke,
90
- so the automation spec cannot pass: do not write a fake passing spec. Report V4 as "not run:
91
- no route" (no available route executes these specs) and record the expected rejection and
92
- the trusted-actor gap separately, citing the reaction semantics (a command that requires a
93
- caller rejects the reaction).
88
+ 3. **Gated command + declared trusted actor** - keep the service-role policy and
89
+ declare matching `runs as system role` on the reaction. Reference-test the
90
+ scenario with standalone 4.125.0; separately record CLI/Stage target refusal.
91
+ A missing actor must not be excused by removing the gate or inventing a caller.
94
92
  Never remove an existing gate only to make a reaction spec pass.
95
93
  Omitting an HTTP route is not an authorization proof: the exposure requirement stays a target
96
94
  requirement with its negative case (an outside caller is refused).
@@ -16,7 +16,7 @@ One spec in the slice does not cover the others.
16
16
  | queue opens / closes | item appears, item disappears | `then query …ById`; `when append <Closing>` + `then no readmodel … for` |
17
17
  | already done | trigger re-delivered after the result exists | `given <Result>` + `when <Command>` -> `then error "<fixed constraint message>"` |
18
18
  | invoked command rejects | validation or constraint refuses | command spec in its StateChange slice; record what the queue shows afterwards |
19
- | no caller | invoked command is gated | record the expected rejection and the actor decision (`automation-patterns.md` §4); V4 is "not run: no route" |
19
+ | no declared actor | invoked command is gated | specify its denial; for the trusted path declare reaction `runs as system role` and reference-test with standalone 4.125.0 |
20
20
  | clock boundary | due exactly at the instant, just before, just after | `given clock` + `when clock`; boundary semantics are contested in the docs, mark the expectation as an assumption |
21
21
  | each branch | does every filter and conditional production have both outcomes? | concrete triggering and non-triggering values; assert the resulting facts or view |
22
22
  | denied actor | every command and query under an inherited module/feature `authorize` needs its own denial; also, can an unauthorized caller reach a gated invoked command by another origin? | command spec with otherwise-valid inputs, `given caller` carrying the wrong role/claim (or no caller) and `then denied`; separate from the caller-less reaction gap |
@@ -58,9 +58,9 @@ One spec in the slice does not cover the others.
58
58
  The decision must not depend on it (it is not protected).
59
59
 
60
60
  ## Spec limits (tool differences: `cratis-screenplay-toolchain` `references/versions.md`)
61
- - These Automation/Translate specs parse and bind (V3) on Screenplay 4.66.0, but no MCP tool,
62
- `validate` or Stage render runs them (Stage renders no Automation or Translate slice). Report
63
- V4 as "not run: no route"; never as passed.
61
+ - Current admitted Automation/Translate specifications run through standalone
62
+ `screenplay test` or MCP `run-specifications`. Validate/render alone is not V4;
63
+ report unsupported/unbound separately from passing scenarios.
64
64
  - With Screenplay 4.66.0 (standalone or cratis 3.28.2), a command spec lists the cascade (v6 semantics: after
65
65
  `when <Command>`, `then` lists every new fact, including reaction appends). Only when a
66
66
  cratis before 3.28.2 bundle (4.60.1) is the V1 tool does it report a false PLAY0285 on a cascade (cli#242):
@@ -25,6 +25,27 @@ or reaction. Choose and record one of:
25
25
  Payments, legal notices and anything costly or irreversible: prefer 2 or 3 and an idempotency
26
26
  key; write a reconciliation case.
27
27
 
28
+ ## Refusal disposition and redelivery
29
+
30
+ At Screenplay 4.125.0 an invocation can state ordered `on refused` selectors for
31
+ validation, constraint (optionally named) or explicit authorization denial.
32
+ Bare refusal does not include authorization. A matching branch declares a fact
33
+ or leaf `acknowledge`; `$refusal.reason`/`.message` are String details and
34
+ `.constraint` belongs only to constraint selectors. This is **authoring-only**
35
+ (PLAY0268), not evidence that a duplicate was safely acknowledged at runtime.
36
+
37
+ Recovery syntax `when redelivered <Event> to <Reaction>` selects exactly one
38
+ existing given occurrence; it is not append or replay. `then no events` makes a
39
+ no-new-facts contract explicit but remains unadmitted too. Full selectors,
40
+ occurrence matching and checked source examples: captures-and-reactions
41
+ `references/refusals-and-redelivery.md`.
42
+
43
+ Infrastructure/contract errors, Unsupported and concurrency are never domain
44
+ refusals. No `by concurrency` exists: fail/retry transient contention. Record the
45
+ actual target's disposition, trusted actor, durable delivery identity and external
46
+ idempotency/reconciliation owner. A branch or observer receipt alone proves no
47
+ cascade transaction or exactly-once external effect.
48
+
28
49
  ## Retry identity
29
50
  - The retry must carry the same identity as the first attempt: the stream id chosen before
30
51
  the first try (never a fresh id per attempt), and the same idempotency key outward.
@@ -40,5 +40,7 @@ Changes in this version: the examples are complete fenced documents that compile
40
40
  example's anonymous-booking spec gained the `given caller` PLAY0389 requires; the todo-list
41
41
  example's list query, `reads` and retry sweep moved to marked design-only excerpts so the core
42
42
  binds); tool-qualified verdict text; the trusted-actor text now names `[ExecuteCommandsAsSystem]`
43
- (Arc v20.56.0, available in a rendered app's Arc 22.25.0) and Screenplay#383; Stage renders no
44
- Automation or Translate slice (Stage#79).
43
+ (Arc v20.56.0). Current actor syntax was reverified at Screenplay v4.125.0
44
+ `reactions.md`, `ReactionIdentityParser.cs`, `ReactionRefusalValidator.cs` and the
45
+ binder's v10 selection; the checked scenario passes reference execution. CLI
46
+ 3.41.0's older parser and Stage 4.51.3's v7 planner remain target limits.
@@ -13,7 +13,8 @@ The first spec lists the whole cascade (`then` names every new fact: `CoursePass
13
13
  `CertificateSent` through the reaction), and `given clock` supplies the instant that
14
14
  `$context.occurred` needs. Both 4.66.0 tools accept that cascade; the cratis 3.27.1 bundle reported a false PLAY0285 on it
15
15
  (cli#242). These specs were not
16
- run (V4: not run, no route); the expectations follow the v4.66.0 reference semantics.
16
+ run in that historical probe; current admitted scenarios can be run with
17
+ standalone `screenplay test` or MCP `run-specifications`.
17
18
 
18
19
  What the model proves and what it does not:
19
20
 
@@ -22,8 +23,10 @@ What the model proves and what it does not:
22
23
  - Not proven: that the certificate email reaches the person once. See
23
24
  `references/effects-and-idempotency.md`.
24
25
  - The actor behind `SendCertificate` is a recorded security decision in the `Certification`
25
- module `description`, because reaction invocations carry no caller on Screenplay 4.66.0 (Screenplay#383).
26
- - No local engine runs Automation specifications: report them as authored, not as run.
26
+ module `description`: this example declares no reaction identity, so its
27
+ invocations remain caller-less. A gated trusted path can instead declare
28
+ `runs as system role` on 4.125.0 (ESM v10), with separate CLI/Stage refusal.
29
+ - Report reference outcomes only after executing the selected scenarios.
27
30
 
28
31
  ```screenplay
29
32
  // Todo-list automation. Shape: CoursePassed opens an item -> CertificateSender invokes
@@ -101,7 +104,7 @@ module Courses
101
104
  for "0d3b9e2a-6c4f-4f1e-8b7a-5e2d1c3b4a01"
102
105
 
103
106
  module Certification
104
- description "Trusted background boundary. No persona or screen issues SendCertificate; only the CertificateSender reaction invokes it, and reaction invocations carry no caller. Leaving the command ungated is a SECURITY DECISION, accepted only because: (1) it appends a fact keyed to one enrolment, (2) a repeat is rejected by IssueOnce, (3) the realization must not expose it to external callers (requirement to verify in the target). If (3) cannot hold, gate it with a service-actor policy and record the capability gap instead (reaction invocations carry no caller: Screenplay#383)."
107
+ description "Trusted background boundary. No persona or screen issues SendCertificate; only the CertificateSender reaction invokes it, and reaction invocations carry no caller. Leaving the command ungated is a SECURITY DECISION, accepted only because: (1) it appends a fact keyed to one enrolment, (2) a repeat is rejected by IssueOnce, (3) the realization must not expose it to external callers (requirement to verify in the target). If (3) cannot hold, gate it with a service-actor policy and declare runs as system role on the reaction (ESM v10), retaining the CLI/Stage realization gap."
105
108
  feature Certificates
106
109
  slice StateView CertificatesToSend
107
110
  description "Work queue: membership means 'still to send'; there is no status flag"
@@ -4,13 +4,13 @@
4
4
  "fixtures": [],
5
5
  "assertions": [
6
6
  { "kind": "skill-contains", "value": "`[ExecuteCommandsAsSystem(\"<role>\")]`" },
7
- { "kind": "skill-contains", "value": "Screenplay#383" },
8
- { "kind": "skill-contains", "value": "renders no Automation or Translate slice" },
9
- { "kind": "skill-contains", "value": "never invent `runs as`" },
7
+ { "kind": "skill-contains", "value": "ESM v10" },
8
+ { "kind": "skill-contains", "value": "STAGE-ESM-024" },
9
+ { "kind": "skill-contains", "value": "runs as system role" },
10
10
  { "kind": "skill-contains", "value": "**One meaning of Translation:**" },
11
11
  { "kind": "skill-contains", "value": "complete, open or blocked" },
12
12
  { "kind": "skill-contains", "value": "never write a mapping" },
13
- { "kind": "skill-contains", "value": "V4 is \"not run: no route\"" },
13
+ { "kind": "skill-contains", "value": "run-specifications" },
14
14
  { "kind": "skill-contains", "value": "never skipped silently" },
15
15
  { "kind": "skill-contains", "value": "not applicable: no queue" }
16
16
  ]
@@ -32,16 +32,10 @@ source is the single flow model.
32
32
  | `Cratis.Screenplay` | main `fd18129` | Command-only inline event boundary |
33
33
  | `Cratis.Screenplay` | `4.66.0` (`c89198b`) | ESM v6: reactions, clock, trigger and capture specifications bind; `invokes` caller rule; probed with the standalone tool and its MCP server |
34
34
 
35
- The update follows `commands.md`, `events.md` and `diagnostics.md` at that main
36
- commit (after v4.52.0).
37
-
38
- Historical baseline evidence: the original examples were checked against the Screenplay repository at tag `v4.31.0` (commit `355dffb`):
39
- `Documentation/screenplay/{captures,captures/grammar,reactions,triggers,interactions,file-references,grammar,diagnostics}.md`
40
- and decisions 0003, 0006 and 0009; those original examples compiled with that
41
- version's compiler. The specification actions and ESM v6 text were checked at
42
- `v4.66.0` (see its row above), and the complete examples here and in
43
- `references/complete-examples.md` compile with the standalone 4.68.0 compiler.
44
- Reverify before claiming another version behaves the same.
35
+ The table records historical examples/probes; they are not reclassified as
36
+ current execution evidence. Refusal/redelivery guidance follows released
37
+ v4.125.0 `reactions.md`/`specifications.md`. Current pins are in toolchain
38
+ `references/versions.md`; reverify before promoting an old probe to that version.
45
39
 
46
40
  ⚠️ **Which tool admits them depends on its Screenplay version.** The ESM level
47
41
  decides, not the slice type:
@@ -50,14 +44,10 @@ decides, not the slice type:
50
44
  `Translate` slices, reactions, declared triggers and captures bind, and the
51
45
  reference runner executes them. Probed: the complete example below is
52
46
  `executableReady` over `screenplay mcp`.
53
- - **`cratis` 3.28.2 (bundles Screenplay 4.66.0, ESM v1-v6):** the same as the standalone
54
- tool. Probed: the complete examples validate with warnings as errors and are
55
- `executableReady` over `cratis screenplay mcp`. `cratis` before 3.28.2 (Screenplay
56
- 4.60.1, ESM v1-v5) failed an `Automation` or `Translate` slice at binding with `PLAY0268`
57
- (*Slice '<name>' of type '<type>' is not admitted by ESM v1*), reported reactions as
58
- *requires portable occurrence and effect semantics* and captures as *require a portable
59
- compiled CDL plan*, and gave a false `PLAY0285` on a specification that follows a reaction
60
- cascade (Cratis/cli#242).
47
+ - **Historical CLI 3.28.2 / Screenplay 4.66.0 probe:** complete examples validated
48
+ and were executableReady through MCP. Earlier 4.60.1 bundles refused v6 at
49
+ binding and falsely reported PLAY0285 on cascades. Toolchain `references/versions.md`
50
+ separates that history from current pins.
61
51
  - **Stage 4.24.2** admits ESM v1-v4 and renders no `Automation` or `Translate`
62
52
  slice. The automation is gap-fill, with the `.play` slice and its specifications
63
53
  as the contract: `cratis-screenplay-render-and-gap-fill`.
@@ -69,25 +59,27 @@ Method (the four-part automation test, loops, translations versus automations):
69
59
 
70
60
  ## Specify what sets them off
71
61
 
72
- A specification names what sets the automation off: `when clock`, `when trigger` or `when capture`. No command runs these specifications; report one as authored, not executed.
62
+ A specification names what sets the automation off: `when clock`, `when trigger`
63
+ or `when capture`. Execute admitted scenarios through `screenplay test` or MCP
64
+ `run-specifications`; source compilation alone is only authored evidence.
73
65
 
74
66
  Read [references/specifying-triggers-and-clock.md](references/specifying-triggers-and-clock.md) when writing a specification for a reaction, trigger or capture, or when the clock, occurrence or limit rules matter.
75
67
 
76
68
  ## Caller-less invokes and unprotected reads
77
69
 
78
- **Who is the caller of an `invokes`?** Nobody. In the reference execution the invoked
79
- command runs its full pipeline - authorization, validation, requirements,
80
- constraints - **with no caller**; a command that needs one rejects, and the
81
- rejection ends the scenario. Each invoked command is atomic, but the cascade is not,
82
- so facts accepted earlier remain. There is no syntax for a trusted identity in the verified Screenplay versions
83
- (Screenplay#383, open): never invent `runs as` or a `given caller` for a reaction.
84
- Say so in the model: a `description` on the reaction that names the trusted actor
85
- the target must use. At code level a rendered or hand-written target runs such a
86
- command as the system with `[ExecuteCommandsAsSystem]` (Arc 20.56.0 and later, so
87
- also in a rendered application's Arc 22.25.0). An authorized command a reaction
88
- invokes needs that decision made explicit, in the model's description and in the
89
- gap-fill code, not left to a rejection nobody expected. Cascades and their
90
- specification limits: `cratis-screenplay-specifications`.
70
+ **Who is the caller of an `invokes`?** Without a declared actor, nobody.
71
+ Screenplay 4.125.0 supports reaction-level `runs as system role "<Role>"`
72
+ (optional roles, joined with `and role`). It selects ESM v10 and supplies the
73
+ reference invocation's authenticated system principal with exactly those roles;
74
+ `given caller` does not supply it. Keep gates and declare the least-privilege actor.
75
+ Read [invocation identity](references/invocation-identity.md) for the checked
76
+ scenario, claim/unknown semantics and PLAY0647–0652/0557 diagnostics.
77
+
78
+ CLI 3.41.0's 4.114.0 compiler rejects this source with PLAY0137; its version gate
79
+ and Stage 4.51.3 planner admit only through v7. Target realization is gap-fill,
80
+ using Arc `[ExecuteCommandsAsSystem]` for returned commands. Without that attribute
81
+ Arc supplies no principal and `[Authorize]`/`[Roles]` deny. Each invoked command
82
+ is atomic, not the whole cascade; earlier accepted facts remain after a later refusal.
91
83
 
92
84
  ⚠️ **Declared, not enforced.** A trigger `reads` gives no runtime protection. From
93
85
  ESM v6 the binder refuses to treat it as one: a trigger with `reads` that **produces
@@ -101,9 +93,19 @@ the input selection or not; nested paths and read aliases fail binding): keep th
101
93
  the invoked command or the implementation. Under `cratis` before 3.28.2 none of this
102
94
  bound at all (`PLAY0268`); `cratis` 3.28.2 binds it like the standalone tool.
103
95
 
96
+ ## Refusals and recovery redelivery
97
+
98
+ At 4.125.0, invocation refusal selectors, `$refusal` branch values,
99
+ `acknowledge`, `when redelivered ... to ...` and `then no events` are valid
100
+ authoring intent but refuse binding with PLAY0268. Read
101
+ [refusals and redelivery](references/refusals-and-redelivery.md) for first-match
102
+ selectors, typed values, occurrence matching, diagnostics and the checked
103
+ unbound example. Never acknowledge infrastructure or concurrency failures.
104
+
104
105
  ## Complete example (ESM v6)
105
106
 
106
- One document with every construct (application trigger, reactions on an event, a trigger, a view read and the clock, and a capture with specifications) is kept in the reference file.
107
+ The reference document covers v6 triggers, event/clock reactions, view reads and
108
+ capture specifications. Refusal/redelivery forms use their separate checked reference.
107
109
 
108
110
  Read [references/complete-examples.md](references/complete-examples.md) when you need a complete, compiling parent document for an excerpt or want to check the authoring and binding prerequisites.
109
111
 
@@ -176,7 +178,7 @@ optional.
176
178
 
177
179
  ⚠️ **Indentation decides what is a trigger and what is an effect.** `produces`,
178
180
  `invokes`, `file` and inline code belong **inside** the trigger block, indented
179
- under `when`/`every`/`at`. Only `description` and `where` sit at reaction level.
181
+ under `when`/`every`/`at`. `description`, `where` and `runs as` sit at reaction level.
180
182
  Outdenting an effect gives *Expected a trigger in reaction body, got 'invokes …'*
181
183
  (`PLAY0137`) — the compiler is looking for another trigger where the effect is.
182
184
 
@@ -238,7 +240,7 @@ append-time constraints. `invokes` asks for a command, which additionally runs t
238
240
  command's authorization, validation and requirements, and may reject.
239
241
  Using `produces` for both would say those are the same kind of consequence.
240
242
 
241
- **Who is the caller of an `invokes`?** Nobody; see *Caller-less invokes and unprotected reads* above before writing one.
243
+ **Who is the caller of an `invokes`?** Nobody unless `runs as` declares the actor; see *Caller-less invokes and unprotected reads* above before writing one.
242
244
 
243
245
  Both are declarations of *what happens*, not of how — a trigger can state its
244
246
  consequences **and** carry a `file` or an inline block in a tagged fence
@@ -338,7 +340,8 @@ something is reported. `Startup` and `Shutdown` are registered the second way.
338
340
  `PLAY0268` at binding and a false `PLAY0285` on cascade specifications, and report them
339
341
  as tool skew.
340
342
  - [ ] The tool that bound the model is named (Screenplay 4.61 or later, so standalone or
341
- `cratis` 3.28.2 or later, for ESM v6 constructs); no tool runs the specifications.
343
+ `cratis` 3.28.2 or later, for ESM v6 constructs); reference scenarios use
344
+ `screenplay test`/MCP. Unadmitted refusal/redelivery is not executed evidence.
342
345
  - [ ] Each automation has all four components — occurrence, state consulted,
343
346
  conditional logic, resulting command or event. If it always fires
344
347
  unconditionally it is co-production, not an automation.
@@ -351,8 +354,8 @@ something is reported. `Startup` and `Shutdown` are registered the second way.
351
354
  value the trigger takes, and clock triggers read without `by`.
352
355
  - [ ] Nobody reports trigger or command `reads` as protected; UI clicks are
353
356
  interactions, not triggers.
354
- - [ ] Every `invokes` of an authorized command names the trusted actor in a
355
- description; no caller is invented for a reaction.
357
+ - [ ] Every gated invocation declares its trusted actor with reaction `runs as`
358
+ (ESM v10) or records the target gap explicitly; `given caller` is not that actor.
356
359
 
357
360
  ## Route near misses
358
361
 
@@ -97,7 +97,7 @@ module Delivery
97
97
 
98
98
  ## Reaction with `produces` and `invokes`
99
99
 
100
- Parent of the `Provisioner` excerpt. The invoked command runs with no caller in the
100
+ Parent of the `Provisioner` excerpt. The reaction declares no `runs as system`, so the invoked command runs with no caller in the
101
101
  reference execution.
102
102
 
103
103
  ```screenplay
@@ -0,0 +1,84 @@
1
+ <!-- Copyright (c) Cratis. All rights reserved. -->
2
+ <!-- Licensed under the MIT license. See LICENSE file in the project root for full license information. -->
3
+
4
+ # Declare the actor behind a reaction invocation
5
+
6
+ ## Contents
7
+
8
+ - Trusted system identity
9
+ - Checked example
10
+ - Diagnostics and target boundaries
11
+
12
+ ## Trusted system identity
13
+
14
+ Screenplay 4.125.0 supports one reaction-level line
15
+ `runs as system [role "<Role>" and role "<Role>"]`. Roles are optional, nonempty,
16
+ distinct quoted literals; personas and expressions are not accepted. Put it
17
+ under the reaction, not its trigger or invocation. The declaration selects
18
+ **ESM v10**. Without it, invocations remain caller-less; `given caller` never
19
+ supplies an actor to a reaction.
20
+
21
+ The reference evaluator authenticates a system principal with exactly the stated
22
+ roles. Claim conditions remain unknown, including under not; a satisfied role
23
+ alternative may allow, but final unknown denies. This is not the caller's audit
24
+ identity and does not invent Arc's system subject claims. The identity covers
25
+ invoked/returned commands across that reaction's triggers, not imperative
26
+ pipeline calls in bodies, direct productions, reads, refusal productions or
27
+ causation. Record the actual least-privilege role, not a prose-only actor or an
28
+ ungated command substituted to make the scenario pass.
29
+
30
+ ## Checked example
31
+
32
+ This complete model compiled with warnings as errors and its reference scenario
33
+ passed on standalone Screenplay 4.125.0:
34
+
35
+ ```screenplay
36
+ policy Worker
37
+ require role "Worker"
38
+ module Work
39
+ feature Processing
40
+ slice StateChange RecordWork
41
+ command RecordWork
42
+ workId String identifier
43
+ authorize Worker
44
+ produces event WorkRecorded
45
+ slice Automation ProcessWork
46
+ event WorkRequested
47
+ workId String
48
+ reaction Processor
49
+ runs as system role "Worker"
50
+ when WorkRequested
51
+ workId
52
+ invokes RecordWork
53
+ workId = workId
54
+ specification ProcessingRequestedWork
55
+ when append WorkRequested
56
+ workId = "work-1"
57
+ then WorkRecorded
58
+ for "work-1"
59
+ ```
60
+
61
+ ## Diagnostics and target boundaries
62
+
63
+ - PLAY0647: malformed, repeated or misplaced identity, including duplicate/empty roles.
64
+ - PLAY0648: gated invocation without declared identity and without an authorization
65
+ refusal branch. PLAY0557 instead warns on that refusal branch; it cannot turn
66
+ an always-denied caller-less invocation into a trusted path.
67
+ - PLAY0649: identity with neither invocations nor an implementation body.
68
+ - C# binding PLAY0650/0651 warns about unused roles or definite authorization
69
+ denial; opaque/unknown cases are not guessed. `--check privilege` (PLAY0652)
70
+ reviews whether event producers require every elevated role, not runtime safety.
71
+
72
+ CLI 3.41.0 bundles Screenplay 4.114.0, which does not parse `runs as`: the example's
73
+ `cratis screenplay validate --executable --warnings-as-errors` returns PLAY0137,
74
+ exit 5. It cannot render this source. Its render version gate separately admits
75
+ only through v7 (CLI-RENDER-004 for newer admitted compiler output), while Stage
76
+ 4.51.3's direct planner audits through v7 and refuses v10 with STAGE-ESM-016.
77
+ Clock/application-trigger identities have no Stage Arc realization either.
78
+ Use authorized gap-fill with the model as contract; returned-command Arc identity
79
+ uses `[ExecuteCommandsAsSystem]`, never permission inferred from a model header.
80
+ Refusal/redelivery syntax remains unadmitted even when identity itself runs.
81
+
82
+ Authority: Screenplay v4.125.0 `reactions.md`, `ReactionIdentityParser.cs`,
83
+ `ReactionRefusalValidator.cs`, `SemanticModelBinder.cs`; CLI v3.41.0
84
+ `RenderedSemanticVersions.cs`; Stage v4.51.3 `SemanticCratisAdmission.cs`.