@cratis/pi 7.75.0 → 7.76.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 (70) hide show
  1. package/package/corpus/harnesses/copilot/instructions/vertical-slices.instructions.md +6 -4
  2. package/package/corpus/product-sync.json +14 -14
  3. package/package/corpus/rules/vertical-slices.md +6 -4
  4. package/package/corpus/skills/cratis-arc-authentication-authorization-and-identity/references/authorization.md +9 -0
  5. package/package/corpus/skills/cratis-arc-authentication-authorization-and-identity/references/observable-emission-guards.md +12 -3
  6. package/package/corpus/skills/cratis-arc-command/references/decisions-and-routing.md +11 -0
  7. package/package/corpus/skills/cratis-arc-command-execution/SKILL.md +3 -0
  8. package/package/corpus/skills/cratis-arc-command-execution/references/occurrence-commands.md +78 -0
  9. package/package/corpus/skills/cratis-arc-command-validation/SKILL.md +10 -36
  10. package/package/corpus/skills/cratis-arc-command-validation/references/input-binding.md +49 -0
  11. package/package/corpus/skills/cratis-arc-command-validation/references/read-model-resolution.md +25 -0
  12. package/package/corpus/skills/cratis-arc-command-validation/references/validation-severity.md +21 -0
  13. package/package/corpus/skills/cratis-arc-ef-core-migration/SKILL.md +7 -1
  14. package/package/corpus/skills/cratis-arc-hosting/SKILL.md +3 -0
  15. package/package/corpus/skills/cratis-arc-hosting/references/connection-resolution.md +61 -0
  16. package/package/corpus/skills/cratis-arc-query-paging/SKILL.md +4 -2
  17. package/package/corpus/skills/cratis-arc-react-page/references/queries-and-commands.md +14 -1
  18. package/package/corpus/skills/cratis-chronicle-client-dotnet/SKILL.md +5 -0
  19. package/package/corpus/skills/cratis-chronicle-client-dotnet/references/immediate-append-refusal.md +40 -0
  20. package/package/corpus/skills/cratis-chronicle-client-dotnet/references/lifecycle.md +4 -0
  21. package/package/corpus/skills/cratis-chronicle-client-dotnet/references/occurrences.md +89 -0
  22. package/package/corpus/skills/cratis-chronicle-client-dotnet/references/pinned-generation-delivery.md +33 -3
  23. package/package/corpus/skills/cratis-chronicle-decision-reads/SKILL.md +5 -2
  24. package/package/corpus/skills/cratis-chronicle-decision-reads/references/admission-and-ownership.md +18 -1
  25. package/package/corpus/skills/cratis-chronicle-event-type-migration/references/pinned-generations.md +6 -0
  26. package/package/corpus/skills/cratis-chronicle-hosting/SKILL.md +3 -0
  27. package/package/corpus/skills/cratis-chronicle-hosting/references/operations.md +26 -0
  28. package/package/corpus/skills/cratis-chronicle-hosting/references/storage-resolution.md +55 -0
  29. package/package/corpus/skills/cratis-chronicle-multi-tenancy/SKILL.md +3 -0
  30. package/package/corpus/skills/cratis-chronicle-multi-tenancy/references/remove-namespace.md +38 -0
  31. package/package/corpus/skills/cratis-chronicle-projection/references/definition-changes.md +26 -0
  32. package/package/corpus/skills/cratis-chronicle-projection/references/model-bound-attributes.md +8 -0
  33. package/package/corpus/skills/cratis-chronicle-reactor/SKILL.md +5 -22
  34. package/package/corpus/skills/cratis-chronicle-reactor/references/starting-and-replaying.md +33 -0
  35. package/package/corpus/skills/cratis-chronicle-read-model/SKILL.md +9 -2
  36. package/package/corpus/skills/cratis-chronicle-read-model/references/queries.md +9 -4
  37. package/package/corpus/skills/cratis-chronicle-reducer/SKILL.md +4 -0
  38. package/package/corpus/skills/cratis-multi-service-architecture/SKILL.md +9 -3
  39. package/package/corpus/skills/cratis-performance-review/SKILL.md +4 -1
  40. package/package/corpus/skills/cratis-screenplay-automations-and-translations/SKILL.md +2 -2
  41. package/package/corpus/skills/cratis-screenplay-automations-and-translations/references/realization-and-gap-fill.md +10 -2
  42. package/package/corpus/skills/cratis-screenplay-captures-and-reactions/SKILL.md +9 -9
  43. package/package/corpus/skills/cratis-screenplay-captures-and-reactions/references/atomic-batches-and-source-mappings.md +2 -2
  44. package/package/corpus/skills/cratis-screenplay-model-authoring/SKILL.md +11 -11
  45. package/package/corpus/skills/cratis-screenplay-model-authoring/references/mcp-tools.md +9 -0
  46. package/package/corpus/skills/cratis-screenplay-model-authoring/references/model-notes.md +41 -23
  47. package/package/corpus/skills/cratis-screenplay-model-authoring/verification.json +8 -3
  48. package/package/corpus/skills/cratis-screenplay-projections/SKILL.md +19 -12
  49. package/package/corpus/skills/cratis-screenplay-projections/references/pdl-grammar.md +37 -2
  50. package/package/corpus/skills/cratis-screenplay-projections/verification.json +11 -0
  51. package/package/corpus/skills/cratis-screenplay-render-and-gap-fill/SKILL.md +37 -40
  52. package/package/corpus/skills/cratis-screenplay-render-and-gap-fill/references/gap-fill-handoff.md +3 -2
  53. package/package/corpus/skills/cratis-screenplay-render-and-gap-fill/references/renderability-gate.md +1 -1
  54. package/package/corpus/skills/cratis-screenplay-render-and-gap-fill/verification.json +4 -2
  55. package/package/corpus/skills/cratis-screenplay-scenario-coverage/references/coverage-matrix.md +9 -0
  56. package/package/corpus/skills/cratis-screenplay-toolchain/SKILL.md +13 -30
  57. package/package/corpus/skills/cratis-screenplay-toolchain/references/diagnostics.md +39 -6
  58. package/package/corpus/skills/cratis-screenplay-toolchain/references/executable-subset.md +5 -2
  59. package/package/corpus/skills/cratis-screenplay-toolchain/references/language-admission.md +15 -5
  60. package/package/corpus/skills/cratis-screenplay-toolchain/references/renderable-subset.md +7 -4
  61. package/package/corpus/skills/cratis-screenplay-toolchain/references/screenplay-contract.json +12 -1
  62. package/package/corpus/skills/cratis-screenplay-toolchain/references/screenplay-contract.version +1 -1
  63. package/package/corpus/skills/cratis-screenplay-toolchain/verification.json +9 -2
  64. package/package/corpus/skills/cratis-stage-rendering-and-sandbox/SKILL.md +38 -56
  65. package/package/corpus/skills/cratis-stage-rendering-and-sandbox/references/admission.md +23 -13
  66. package/package/corpus/skills/cratis-stage-rendering-and-sandbox/references/date-comparisons.md +44 -0
  67. package/package/corpus/skills/cratis-stage-rendering-and-sandbox/references/rendered-application.md +8 -2
  68. package/package/corpus/skills/cratis-stage-rendering-and-sandbox/references/sandbox-and-specrunner.md +59 -8
  69. package/package/corpus/skills/cratis-stage-rendering-and-sandbox/verification.json +7 -3
  70. package/package.json +1 -1
@@ -234,6 +234,10 @@ event means no observer subscription; assembly membership alone is not event
234
234
  membership. Types implementing `IReducer` stay classic even with a self-shaped
235
235
  static helper.
236
236
 
237
+ Requires Chronicle 19.72.0 for CHR0065 to warn on fold-like methods that are
238
+ misnamed (`Reducer`/`reduce`) or not static and therefore never discovered.
239
+ Check `dotnet list package`; older analyzers can leave those methods silent.
240
+
237
241
  Use the existing generic or Type `RegisterReducer` API for explicit self-model
238
242
  nomination too; there is no special self API. A self model cannot share ownership
239
243
  with a separate reducer, fluent projection or genuine model-bound mappings in the
@@ -154,9 +154,15 @@ of tags, and export only the fields consumers need. Read
154
154
  ## Versioning contracts
155
155
 
156
156
  A public event type follows the same generation and migration rules as a private
157
- one (`cratis-chronicle-event-type-migration`). Kernel subscriptions name event
158
- types by id and register them as generation 1, and the CLI's `subscriptions add`
159
- takes ids only. Prefer additive, optional changes to a contract; publish a new
157
+ one (`cratis-chronicle-event-type-migration`). Requires Chronicle 19.66.0 for
158
+ subscription-builder `WithGenerationDelivery(EventGenerationDelivery.Pinned)`
159
+ with typed `WithEventType<TEvent>()` or `WithEventType(id, generation)` to pin
160
+ forwarding into the target inbox. Both stores must register that generation;
161
+ Compatibility remains the default. Read
162
+ ../cratis-chronicle-client-dotnet/references/pinned-generation-delivery.md when
163
+ configuring subscription pins and failure behavior. The CLI's `subscriptions add`
164
+ takes ids only; do not invent a generation flag. Prefer additive, optional changes
165
+ to a contract; publish a new
160
166
  event type for a breaking change and keep publishing the old one until every
161
167
  consumer has moved, rather than adding a generation consumers may not handle.
162
168
  Version the contracts package with the contract, and never move a type between
@@ -80,7 +80,10 @@ behavior this file does not already state.
80
80
  - Preserve reducer admission and ordering guards when proposing a projection
81
81
  conversion; an unconditional setter may resurrect or prematurely create state.
82
82
  - Count passive models as inventory, not a smell. Assess history length and read
83
- frequency against consistency/security needs. `IMongoCollection<T>` cannot
83
+ frequency against consistency/security needs. Requires Chronicle 19.77.3 for
84
+ per-key strongly consistent projection reads to fold from the start each time;
85
+ repeated reads are O(key history), not incremental cache hits. Prefer a
86
+ materialized projection for frequent long-history reads when freshness permits. `IMongoCollection<T>` cannot
84
87
  read passive computed state; never materialize secrets to make that query work.
85
88
  - Distinguish retained `Observe` state and in-memory emissions from explicit
86
89
  recompute queries. Narrow source filters and inspect page-refill/membership
@@ -42,8 +42,8 @@ Start new models with application-root `reaction batches atomic` (ESM v22 or lat
42
42
  Each trigger occurrence's direct productions and each selected refusal branch are
43
43
  separate all-or-none batches; invoked commands remain independent. Absence retains
44
44
  legacy per-fact behavior even at later versions. Assert no failed-batch facts and
45
- unchanged views, not only `then error`. Stage refuses v22 (STAGE-ESM-016) and
46
- atomic mode in admitted v23/v24 models (STAGE-ESM-043); keep the semantics as gap-fill.
45
+ unchanged views, not only `then error`. Requires Stage 4.139.0 for v22 admission
46
+ (older: -016); atomic mode stays STAGE-ESM-043. Keep as gap-fill.
47
47
  Read [atomic batches and source mappings](../cratis-screenplay-captures-and-reactions/references/atomic-batches-and-source-mappings.md)
48
48
  when choosing these boundaries or mapping an invoked identifier from `$eventSourceId`
49
49
  (or `$eventContext.eventSourceId`) instead of copying it into event payload.
@@ -22,11 +22,19 @@ recovery behavior rather than assuming this handler supplies all-or-nothing sett
22
22
  rejected model renderable, and never claim a whole-application V5 from a subset. Choose the route
23
23
  with `cratis-screenplay-render-and-gap-fill`.
24
24
 
25
- Application-root `reaction batches atomic` also blocks Stage delivery: v22
26
- refuses STAGE-ESM-016; mode in admitted v23–v27 refuses STAGE-ESM-043. Preserve the
25
+ Application-root `reaction batches atomic` also blocks Stage delivery with
26
+ STAGE-ESM-043. Requires Stage 4.139.0 for v22 admission; older Stage reports -016. Preserve the
27
27
  per-occurrence/selected-branch batch boundary and independent invoked commands.
28
28
  Atomic appends do not prove redelivery deduplication or external exactly-once effects.
29
29
 
30
+ Requires Stage 4.141.1 for independent event-reaction specifications with `given clock`;
31
+ older executors refuse clocks beside reactions. This supplies `$context.occurred`
32
+ through cascades, invocation arguments and refusal branches, not a scheduler.
33
+ Clock/non-event triggers still refuse `STAGE-ESM-024`. Generated append/redelivery
34
+ clock fixtures retain -024 and context-dependent generated reaction specs retain -011.
35
+ Read [sandbox occurrence boundaries](../../cratis-stage-rendering-and-sandbox/references/sandbox-and-specrunner.md)
36
+ when verifying reaction time in Stage rather than reference execution.
37
+
30
38
  ## Where the pieces go (hand-written)
31
39
  | Model element | Realization | Skill |
32
40
  |---|---|---|
@@ -29,11 +29,11 @@ Language claims follow Screenplay `reactions.md`, `triggers.md`, `captures.md` a
29
29
  The compiler's ESM admission decides, not the slice type. Reactions, triggers and
30
30
  captures bind/reference-execute from v6; older compilers refuse them. Read toolchain
31
31
  `references/diagnostics.md` when diagnosing skew or false PLAY0285 cascades.
32
- - **The CLI and Stage** render supported event-triggered Automation, not
33
- Translate/captures, non-event triggers or opaque bodies (`-024`). Role/authenticated `runs as`
34
- and semantic `from` render; claim/opaque gates, mixed effects and unsupported mappings remain refused;
35
- cascade specs remain `-011`. Keep refused scope as gap-fill. Full boundary and source
36
- citations: `cratis-stage-rendering-and-sandbox` `references/admission.md`.
32
+ - **Stage realization:** read `cratis-stage-rendering-and-sandbox` `references/admission.md`
33
+ before claiming rendering. Supported event-triggered Automation renders; captures,
34
+ Translate, clocks and opaque bodies remain gap-fill (`-024`).
35
+ Read [sandbox boundaries](../cratis-stage-rendering-and-sandbox/references/sandbox-and-specrunner.md)
36
+ when checking authored occurrence versus generated-spec limits; a clock fixture is not scheduling.
37
37
 
38
38
  Name the binding tool. For the automation test, loops and translation boundaries,
39
39
  read `cratis-screenplay-automations-and-translations`.
@@ -74,7 +74,7 @@ Start new models with application-root `reaction batches atomic`. One trigger's
74
74
  productions, or one selected refusal branch, append all-or-none; invoked commands stay
75
75
  separate. Legacy models without opt-in retain per-fact appends even at newer versions.
76
76
  Read [atomic batches and source mappings](references/atomic-batches-and-source-mappings.md)
77
- for batch failure assertions, PLAY0693, Stage STAGE-ESM-016/043 refusals and
77
+ for batch failure assertions, PLAY0693, Stage atomic-mode refusals and
78
78
  `invokes` mappings from `$eventSourceId` / `$eventContext.eventSourceId`.
79
79
 
80
80
  ## Caller-less invokes and unprotected reads
@@ -104,9 +104,9 @@ binding, because its decision dependency cannot be protected. A reaction that on
104
104
  command's own reads. Eligible command reads protect under application-root
105
105
  `command reads protected` (ESM v25); legacy reads retain PLAY0271. Read command-surface
106
106
  [protected reads](../cratis-screenplay-command-surface/references/protected-reads.md)
107
- for admission and absence/conflict behavior. Stage admits v25 and, from 4.138.0, renders protected reads as Arc read protection (CLI 3.75.0 refuses them with STAGE-ESM-044).
108
- Semantic Host/executor support is separate; non-Error protected requirements refuse -045,
109
- including reaction-invoked commands.
107
+ for admission and absence/conflict behavior. Requires Stage 4.138.0 to render
108
+ protected reads; older bundles refuse -044. Semantic Host/executor non-Error
109
+ protected requirements refuse -045.
110
110
  `where` over read paths out of scope, and `where` needs
111
111
  every operand to resolve from the trigger's declared scalar occurrence shape (listed in
112
112
  the input selection or not; nested paths and read aliases fail binding): keep the logic that uses the state in
@@ -36,8 +36,8 @@ batch and unchanged read models with evaluator world/read-model assertions; earl
36
36
  accepted work can remain. `then no events` means accepted zero outcomes and cannot
37
37
  accompany `then error`. Do not invent a mixed success/error specification form.
38
38
 
39
- Stage refuses ESM v22 with STAGE-ESM-016. Even an admitted v23–v27 model carrying
40
- atomic mode is refused with STAGE-ESM-043 by renderer, Host and specification executor.
39
+ Requires Stage 4.139.0 for ESM v22 admission; older Stage refuses STAGE-ESM-016.
40
+ Atomic mode is still refused with STAGE-ESM-043 by renderer, Host and specification executor.
41
41
  Keep the declaration and report authorized gap-fill; do not promise a render date or
42
42
  strip atomicity to lower the version.
43
43
 
@@ -26,6 +26,9 @@ Record open modeling questions as `question` notes in committed
26
26
  personal data in notes. Read [model notes](references/model-notes.md) when
27
27
  listing, recording or resolving questions: `list-model-notes`,
28
28
  `propose-model-notes`, `read-proposal view=notes`, refs and orphan review.
29
+ Prefer dotted split-model targets; inspect `substitutions`, also for reanchor,
30
+ and disclose broader owners. The reference covers typed `parts` targets from
31
+ `open-workspace.applicationIdentity`.
29
32
 
30
33
  ## Choosing a strategy
31
34
 
@@ -45,8 +48,7 @@ Use the declared `screenplay` MCP server (for example `open-workspace`).
45
48
  Never ask the user which folder to use before trying `open-workspace` without
46
49
  arguments; do not invent a root. Read [MCP loop](references/mcp-loop.md) when connecting or switching roots;
47
50
  it owns fallback discovery, fixed-root limits and the initialization protocol.
48
- Discover `tools/list` schemas rather than relying on a remembered count.
49
-
51
+ Discover `tools/list` schemas.
50
52
 
51
53
  Look first for the project's existing `.play` files: their folder is the model.
52
54
  New models go in `Source/` or `src/`, else root `Screenplay/`, never `.cratis/`
@@ -104,9 +106,8 @@ for handler views: `executableReady` means binding, not an implemented body.
104
106
 
105
107
  ## Compare models
106
108
 
107
- For a `main` comparison, pass a worktree `path` to `semantic-diff`, not two
108
- exports. Read [comparison sources](references/mcp-tools.md#semantic-revision-comparison)
109
- for paging and proposal review.
109
+ Compare with `main` through `semantic-diff` worktree `path`, not two exports.
110
+ Read [comparison sources](references/mcp-tools.md#semantic-revision-comparison) for paging.
110
111
 
111
112
  ## Make one coherent proposal
112
113
 
@@ -191,11 +192,10 @@ Commit `.screenplay/identities.json` with the model; only `apply` writes it. Nev
191
192
 
192
193
  ## Code attachments
193
194
 
194
- Code bodies and `file` constraints are opaque attachments. Screenplay never compiles or runs them.
195
- A screen's `file` realizes UI, not an attachment. Read
196
- [MCP code attachments](references/mcp-tools.md#code-attachments) when resolving
197
- paths or diagnosing `PLAY0430`-`PLAY0434`; `read-workspace`/`read-proposal`
198
- `view: "implementation-requirements"` hashes/maps are not behavioral evidence.
195
+ Screenplay never compiles/runs opaque code attachments or `file` constraints;
196
+ a screen's `file` realizes UI instead. Read [MCP code attachments](references/mcp-tools.md#code-attachments)
197
+ for paths, PLAY0430–PLAY0434 and implementation-requirements views; hashes/maps
198
+ are not behavioral evidence.
199
199
 
200
200
  ## Verify and report honestly
201
201
 
@@ -225,7 +225,7 @@ Record screen MCP transcripts in `.ai-work/`; render/runtime checks must use the
225
225
  same source, never an app that silently drops authored UI. Use the Screenplay-owned canonical
226
226
  corpus fixture path instead of copying available `.play` fixtures here.
227
227
 
228
- Never invent commands, parameters, syntax nodes or downstream capabilities.
228
+ Never invent syntax or capabilities.
229
229
 
230
230
  ## Route near misses
231
231
 
@@ -555,6 +555,15 @@ row is authored presence, not full coverage, causation or a passing specificatio
555
555
  Bare rejections cannot distinguish message-specific rules; syntax-only owners
556
556
  retain information-level readiness reasons. Never invent rules from opaque code.
557
557
 
558
+ A query's SPEC004 denial matches either `when query <Query>` with `then denied`,
559
+ or a read-only specification with no `when`, exactly one `then query <Query>`
560
+ with `arguments` and no `result`, followed by `then denied`. That read-only denial
561
+ does not meet the returned read model's SPEC006 assertion obligation; add a
562
+ separate state, absence or query-result specification.
563
+ Requires Screenplay 4.212.2 (`screenplay --version`) for this obligation matching;
564
+ older servers miss the read-only denial for SPEC004 and count it for SPEC006.
565
+ Upgrade before treating those rows as a coverage gate.
566
+
558
567
  `find-modeling-smells` asks information-level questions, never changes compilation
559
568
  or `--warnaserror`: SMELL001 generic event endings, SMELL002 generic command verbs,
560
569
  SMELL003 duplicate nonempty event shapes from different commands, SMELL004 event
@@ -5,7 +5,6 @@
5
5
 
6
6
  ## Contents
7
7
 
8
- - Verified product sources
9
8
  - Choose the artifact
10
9
  - Anchors and independent state
11
10
  - List with bounded, pinned reads
@@ -14,25 +13,8 @@
14
13
  - Source proposals can orphan notes
15
14
  - Question gate is independent of compilation
16
15
 
17
- ## Verified product sources
18
-
19
16
  Requires Screenplay 4.144.0 or later (`screenplay --version`) for model notes; the CLI-bundled MCP can be older.
20
17
 
21
- Sources in `Cratis/Screenplay`:
22
-
23
- | Contract | Path |
24
- | --- | --- |
25
- | Purpose, anchors, decisions and privacy | `Documentation/screenplay/model-notes.md` |
26
- | Filters, operations, review and orphan disclosure | `Documentation/screenplay/mcp/reference.md`; `Source/DotNET/Screenplay.Mcp/McpNotesSchemas.cs` |
27
- | Retained proposals, revision guards and notes review | `Source/DotNET/Screenplay.Mcp/McpWorkspaces.Notes.cs` |
28
- | Operation fields and resolution evidence | `Source/DotNET/Screenplay.Mcp/McpNotesOperations.cs` |
29
- | Sidecar bytes, absence and canonical revision | `Source/DotNET/Screenplay/Workspaces/ModelNotesStore.cs` |
30
- | Standalone question gate | `Source/DotNET/Tool/ModelOpenQuestions.cs`; `Documentation/screenplay/model-notes.md` |
31
-
32
- The source-edit and authoring guides remain useful for the ordinary proposal loop:
33
- `Documentation/screenplay/mcp/edit.md` and `authoring-tools.md`.
34
- The notes-specific arguments are in the reference and sources above.
35
-
36
18
  ## Choose the artifact
37
19
 
38
20
  Record an unresolved modeling choice as a `question` note on the affected element,
@@ -60,10 +42,45 @@ Notes live beside the model in committed `.screenplay/notes.json`. An anchor is
60
42
  do not derive them from names. Renames and moves keep notes without rewriting the
61
43
  sidecar. `lastAddress` is a display hint, never an anchor.
62
44
 
63
- For a syntax-only construct, select its current source handle or address and kind.
64
- The server substitutes its nearest identified slice, feature, module or application;
65
- inspect `substitutions` and name the particular construct in the note text.
66
- Document and authoring-key anchors are unsupported.
45
+ Prefer dotted `{ address, kind }` targets for Module, Feature and Slice notes,
46
+ including split models. Repeated Module/Feature headers at the same logical
47
+ address merge across import placements and explicit headers; genuinely ambiguous
48
+ leaf declarations still refuse. A folder is one application, not a separate note
49
+ namespace per file.
50
+
51
+ For a typed `{ kind, parts }` target, copy an address from `read-ast` or
52
+ `read-workspace view=semantics`, or build it from names and the exact
53
+ `applicationIdentity` returned by `open-workspace`. This argument template targets
54
+ a Module (replace the Application key with that response's value):
55
+
56
+ ```json
57
+ {
58
+ "kind": "Module",
59
+ "parts": [
60
+ { "kind": "Application", "key": "<applicationIdentity from open-workspace>" },
61
+ { "kind": "Module", "key": "Library" }
62
+ ]
63
+ }
64
+ ```
65
+
66
+ A typed address needs an existing catalog identity; it refuses when none exists.
67
+ Use the construct's current source handle instead. A target without an identity
68
+ lands on the nearest identified slice, feature, module or application. On an
69
+ unbound model, even a Slice can lack an identity and fall back to Application;
70
+ opening the workspace does not guarantee container identities.
71
+
72
+ Always inspect `substitutions` for both `add` and `reanchor`, even when reanchor
73
+ leaves the note unchanged. Each entry has the requested `target`, resolved
74
+ `anchor`, resolved `address` and `reason`. If the note lands on a broader owner,
75
+ say so to the user and name the intended construct in its text; reanchor once
76
+ the intended owner has an identity. Never report the requested anchor as applied
77
+ without checking the actual owner. Document and authoring-key anchors refuse.
78
+
79
+ Requires Screenplay 4.212.0 (`screenplay --version`) for split dotted-target
80
+ resolution, `open-workspace.applicationIdentity` and complete substitution
81
+ reporting. Older servers can refuse split targets, omit that field or silently
82
+ broaden the anchor; use a catalog address/current handle and inspect the notes
83
+ review's actual anchor, or upgrade before relying on these responses.
67
84
 
68
85
  Notes do not change source, workspace/catalog/semantic revisions, executable
69
86
  model bytes or compiler verdicts. Their own `notesRevision` is `nrev1:` plus the
@@ -141,7 +158,8 @@ revisions just read and an actual declaration address before calling it.
141
158
  ```
142
159
 
143
160
  1. Retain `proposalId`, `afterNotesRevision`, server `addedNotes` IDs and inspect
144
- `substitutions`. `changeCount: 0` means no source changes, not no notes change.
161
+ every `substitutions` entry for the actual owner, also for reanchor.
162
+ `changeCount: 0` means no source changes, not no notes change.
145
163
  2. Read `read-proposal` with `view: "notes"`: before/after notes revisions and
146
164
  paged `{ id, before, after }` pairs. On continuation pin **afterNotesRevision**
147
165
  as `expectedNotesRevision`, not the disk revision. Review the entire batch.
@@ -37,6 +37,11 @@
37
37
  { "kind": "skill-contains", "value": "never hand-edit `generate` text", "file": "references/mcp-loop.md" },
38
38
  { "kind": "skill-contains", "value": "Record open modeling questions as `question` notes" },
39
39
  { "kind": "skill-contains", "value": "list-model-notes", "file": "references/model-notes.md" },
40
+ { "kind": "skill-contains", "value": "`applicationIdentity` returned by `open-workspace`", "file": "references/model-notes.md" },
41
+ { "kind": "skill-contains", "value": "Repeated Module/Feature headers", "file": "references/model-notes.md" },
42
+ { "kind": "skill-contains", "value": "Always inspect `substitutions` for both `add` and `reanchor`", "file": "references/model-notes.md" },
43
+ { "kind": "skill-contains", "value": "even a Slice can lack an identity", "file": "references/model-notes.md" },
44
+ { "kind": "skill-contains", "value": "older servers miss the read-only denial for SPEC004 and count it for SPEC006", "file": "references/mcp-tools.md" },
40
45
  { "kind": "skill-contains", "value": "`anchor`", "file": "references/model-notes.md" },
41
46
  { "kind": "skill-contains", "value": "`scope`", "file": "references/model-notes.md" },
42
47
  { "kind": "skill-contains", "value": "`state`", "file": "references/model-notes.md" },
@@ -163,11 +168,11 @@
163
168
  },
164
169
  {
165
170
  "kind": "skill-contains",
166
- "value": "`view: \"implementation-requirements\"`"
171
+ "value": "implementation-requirements views"
167
172
  },
168
173
  {
169
174
  "kind": "skill-contains",
170
- "value": "Screenplay never compiles or runs them"
175
+ "value": "Screenplay never compiles/runs opaque code attachments"
171
176
  },
172
177
  {
173
178
  "kind": "skill-contains",
@@ -180,7 +185,7 @@
180
185
  },
181
186
  {
182
187
  "kind": "skill-contains",
183
- "value": "schemas rather than relying on a remembered count"
188
+ "value": "Discover `tools/list` schemas"
184
189
  },
185
190
  {
186
191
  "kind": "skill-contains",
@@ -28,11 +28,9 @@ source is the single flow model.
28
28
 
29
29
  ## Product sources
30
30
 
31
- Screenplay `Documentation/screenplay/projections/` (including `semantic-model.md`, `keys.md`
32
- and `variants.md`), `readmodels.md`, `diagnostics.md`, `commands.md`, `events.md` and
33
- `mcp/authoring-tools.md` describe the PDL parser, validator, diagnostics, semantic binder and
34
- reducer-body binding (`Semantics/`). Every example below compiles with the standalone compiler.
35
- Reverify before claiming another version behaves the same.
31
+ Consult Screenplay `Documentation/screenplay/projections/` for grammar and semantics,
32
+ `readmodels.md` for targets and `diagnostics.md` for errors. Verify examples with
33
+ the standalone compiler before claiming another version behaves the same.
36
34
 
37
35
  **Chronicle decides what a projection means.**
38
36
  Screenplay owns the grammar; which instance an event affects, what a join may
@@ -81,11 +79,8 @@ Read [observer filters](../cratis-screenplay-toolchain/references/production-rou
81
79
 
82
80
  ## Projection-level directives
83
81
 
84
- `description "..."` (or a fenced text block) on the projection header (report-only `PLAY0270`; variants
85
- and nested blocks take none), `no automap`, `sequence <name>`, `file <path>`. `sequence` is a realization
86
- concern and does not bind to the executable model. A mapping target may end in a dynamic dictionary
87
- key, `count eventCountByType.$eventContext.eventType.id` (one entry per distinct value); only
88
- `$eventContext` resolves there, any other `$` text is a literal key with warning `PLAY0299`.
82
+ Read [projection-level directives](references/pdl-grammar.md#projection-level-directives)
83
+ when using descriptions, `sequence`, `file` or dynamic dictionary-key targets.
89
84
 
90
85
  ⚠️ **Do not write `key` on the projection.** It parses, but neither Chronicle nor
91
86
  the executable model routes any event by it, and it is not a default for the
@@ -148,14 +143,26 @@ subscribe to every event type: `all` inside `children` or `nested` behaves as
148
143
  `lastUpdatedAt`. The `every` block **inside** a `children` block does not accept
149
144
  it — it is already in a children context.
150
145
 
146
+ ## One event per level
147
+
148
+ One event type is used once per projection level (`PLAY0801`): two `from` blocks
149
+ cannot update two rows at that level, even with different keys. Combine mappings
150
+ for one row; model a genuine second domain fact as its own event. Never invent
151
+ events only to satisfy the read side. Joins use a separate set; each children,
152
+ nested and variant block starts fresh sets. Read [event scope](references/pdl-grammar.md#event-scope)
153
+ for grouped events, removals and compiler compatibility.
154
+
151
155
  ## Property mapping and AutoMap
152
156
 
153
157
  ⚠️ **AutoMap is on by default.** Matching property names are copied before your
154
158
  explicit mappings run, and explicit mappings win. Turn it off with `no automap` at
155
159
  **projection**, `every`/`all`, `join`, `children` or `nested` level — it
156
160
  **cannot** be toggled inside an individual `from` block. An `automap`/`no automap`
157
- under a joined event (`with …`) parses but Chronicle replaces it with the auto-map
158
- of the level the join sits in (`PLAY0380`).
161
+ under a joined event (`with …`) decides auto-mapping for that event alone;
162
+ without one, the joined event follows its level's auto-map.
163
+
164
+ Requires Screenplay 4.212.4 (`screenplay --version`) for joined-event auto-map
165
+ overrides in executable binding; older binders replace the setting with the level's.
159
166
 
160
167
  Mapping sources: a property path (`name`, `contactInfo.email`), a literal
161
168
  (`true`, `"Pending"`, `42`, `null`), `$eventSourceId`, and
@@ -5,6 +5,8 @@
5
5
  - Grammar
6
6
  - Parser regexes
7
7
  - Diagnostics
8
+ - Event scope
9
+ - Projection-level directives
8
10
  - Syntax that parses but means something else
9
11
  - Flat composite read-model keys
10
12
  - Worked examples
@@ -147,20 +149,53 @@ LiteralKeyword = "literal", " ", Literal ; (* parsed at the Expr level *)
147
149
  | `PLAY0191` | A read model is built by more than one projection or reducer |
148
150
  | `PLAY0192` | A read model is declared more than once |
149
151
  | `PLAY0295`–`PLAY0299` | An `$eventContext` path the event-context catalog does not have; `PLAY0299` also warns when a dynamic dictionary key uses a `$` source other than `$eventContext` |
150
- | `PLAY0380` | Chronicle drops part of a construct: `all` below the top level, or `automap` on a joined event |
152
+ | `PLAY0380` | Only `all` inside `children`/`nested`: loses its subscription to every event type and behaves as `every` |
151
153
  | `PLAY0381` | A projection-level `key` routes no event |
152
154
  | `PLAY0382`–`PLAY0385` | Variant errors: no `enters on`, shared mapping missing on a variant, duplicate variant name, entering event claimed twice |
153
155
  | `PLAY0397` | Inline code uses a language line instead of a tagged fence |
154
156
  | `PLAY0398` / `PLAY0399` | A reducer mixes bodied and body-less rules / observes one event twice |
155
157
 
158
+ ## Event scope
159
+
160
+ Requires Screenplay 4.212.3 (`screenplay --version`) for the ordinary compilation
161
+ error `PLAY0801` (`DuplicateEventInProjectionScope`) in both compilers; older
162
+ executable binding rejected duplicate uses later with `PLAY0273`.
163
+
164
+ A level is the projection root, one `children` block, one `nested` block or one
165
+ variant. Within that level, `from` (including each event in `from A, B` lists),
166
+ `remove with`, `remove via join` and `clear with` share one set of event names.
167
+ All `join` events at that level share a separate set: an event may occur once in
168
+ `from` and once in a join, but not twice in either set. Each children, nested and
169
+ variant block starts fresh sets; separate projections are independent.
170
+
171
+ The check compares authored event names ordinally, without resolving
172
+ qualifications or generations. It reports the second and each later reference;
173
+ identical or different keys do not change the rule. One event cannot update two
174
+ rows of the same level through two `from` blocks with different keys. Combine
175
+ mappings for the same row into one block. Only a genuinely second domain fact
176
+ warrants another event; never invent events only to satisfy the read side.
177
+ These scope checks do not establish executable or renderer admission.
178
+
179
+ ## Projection-level directives
180
+
181
+ `description "..."` (or a fenced text block) on the projection header (report-only `PLAY0270`; variants
182
+ and nested blocks take none), `no automap`, `sequence <name>`, `file <path>`. `sequence` is a realization
183
+ concern and does not bind to the executable model. A mapping target may end in a dynamic dictionary
184
+ key, `count eventCountByType.$eventContext.eventType.id` (one entry per distinct value); only
185
+ `$eventContext` resolves there, any other `$` text is a literal key with warning `PLAY0299`.
186
+
156
187
  ## Syntax that parses but means something else
157
188
 
189
+ An `automap` / `no automap` under a joined event (`with …`) is honored for that
190
+ event alone; without one, it follows its level's auto-map. Requires Screenplay
191
+ 4.212.4 (`screenplay --version`) for executable binding; older binders replace the
192
+ joined event's setting with the level's. It does not report `PLAY0380`.
193
+
158
194
  | Syntax | What Chronicle and the executable model do |
159
195
  | --- | --- |
160
196
  | `key` on the projection | Nothing: events route by the `from` key, then the event source id (`PLAY0381`) |
161
197
  | `from X` with no key | Routes by the event source id, never by another `from`'s key |
162
198
  | `join … on …` | Updates existing instances only; never creates one; the name after `join` is discarded |
163
- | `automap` under a joined event | Replaced by the auto-map of the join's level (`PLAY0380`) |
164
199
  | `all` inside `children`/`nested` | Behaves as `every` (`PLAY0380`) |
165
200
  | `$causedBy.<x>` | Does not bind; use `$eventContext.causedBy.<x>` |
166
201
  | Templates in mappings or keys | Do not bind |
@@ -9,7 +9,18 @@
9
9
  { "kind": "skill-contains", "value": "Look first for the project's existing `.play` files" },
10
10
  { "kind": "skill-contains", "value": "`cratis ai install` manages `.cratis/ai/`, never model files" },
11
11
  { "kind": "skill-contains", "value": "AutoMap is on by default" },
12
+ { "kind": "skill-contains", "value": "decides auto-mapping for that event alone" },
13
+ { "kind": "skill-contains", "value": "without one, the joined event follows its level's auto-map" },
14
+ { "kind": "skill-contains", "value": "Requires Screenplay 4.212.4" },
15
+ { "kind": "skill-contains", "value": "| `PLAY0380` | Only `all` inside `children`/`nested`:", "file": "references/pdl-grammar.md" },
16
+ { "kind": "skill-contains", "value": "It does not report `PLAY0380`.", "file": "references/pdl-grammar.md" },
12
17
  { "kind": "skill-contains", "value": "PLAY0191" },
18
+ { "kind": "skill-contains", "value": "One event type is used once per projection level (`PLAY0801`)" },
19
+ { "kind": "skill-contains", "value": "cannot update two rows at that level, even with different keys" },
20
+ { "kind": "skill-contains", "value": "events only to satisfy the read side" },
21
+ { "kind": "skill-contains", "value": "`clear with` share one set of event names", "file": "references/pdl-grammar.md" },
22
+ { "kind": "skill-contains", "value": "Each children, nested and\nvariant block starts fresh sets", "file": "references/pdl-grammar.md" },
23
+ { "kind": "skill-contains", "value": "older\nexecutable binding rejected duplicate uses later with `PLAY0273`", "file": "references/pdl-grammar.md" },
13
24
  { "kind": "skill-contains", "value": "every event type in the system" },
14
25
  { "kind": "skill-contains", "value": "references/pdl-grammar.md" },
15
26
  { "kind": "skill-contains", "value": "Do not write `key` on the projection." },
@@ -36,24 +36,21 @@ Tool versions are covered in `cratis-screenplay-toolchain` `SKILL.md`; read it b
36
36
 
37
37
  Read [language admission](../cratis-screenplay-toolchain/references/language-admission.md)
38
38
  for v22–v25: Stage rendering refuses atomic batches, described bodies (even Stub mode)
39
- and protected reads. Semantic Host/executor support is not generated-app protection.
39
+ but renders admitted protected reads in a supporting bundle. Semantic Host/executor
40
+ support is not generated-app protection.
40
41
  Preserve contracts; reference success is not target realization.
41
42
 
42
- File/inline command handlers refuse PLAY0800 (`CommandHandlerRequiresAttachment`):
43
- a permanent requirement for a constrained implementation attachment. Gap-fill the
44
- slice in code rather than wait for a new ESM version. Hosts identify the command
45
- through the required typed `arguments.subject`, not message text. Requires
46
- Screenplay 4.210.0 (`screenplay --version`); older binders use PLAY0268 for these
47
- handlers. Other PLAY0268 families still mean not representable in a supported ESM
48
- version yet; triage details: [renderability gate](references/renderability-gate.md).
43
+ File/inline command handlers permanently require constrained attachments: gap-fill
44
+ in code, not by waiting for ESM admission. Requires Screenplay 4.210.0
45
+ (`screenplay --version`) for PLAY0800 and required typed `arguments.subject`;
46
+ older binders use PLAY0268. Read [renderability gate](references/renderability-gate.md)
47
+ when classifying a handler or other binding refusal; never parse message text.
49
48
 
50
49
  ## Interview phase
51
- **Skip if** the request names the model root, the application name, the destination and the
52
- decision on non-renderable scope. Otherwise ask only what is missing:
53
- Ask only what is missing: the model and accepted version, the application name for `--name` (identical on every re-render), the destination, the decision if admission fails (the three cases below), and the seams (`Customizations/`). Read [references/delivery-protocol.md](references/delivery-protocol.md) ("Interview batch for render delivery") for the defaults.
54
-
55
- Unattended: assume visibly (probe destination, default name from the model root folder), never
56
- assume an answer to 4, and record it as `blocked` for the user.
50
+ Ask only for missing inputs: accepted model/root, stable `--name`, destination,
51
+ non-renderable-scope decision and seams. Read [references/delivery-protocol.md](references/delivery-protocol.md)
52
+ when selecting defaults. Unattended, state probe-name/destination assumptions;
53
+ never assume the non-renderable-scope decision: record it as blocked.
57
54
 
58
55
  ## The three cases (decide first, say which one applies)
59
56
 
@@ -63,36 +60,33 @@ assume an answer to 4, and record it as `blocked` for the user.
63
60
  | **B. Generated base plus authorized gap-fill** | an admitted render (whole, or a `--scope` of the admitted slices) exists and the user separately authorized hand-written scope, or a seam the model names needs an adapter | the generated output stays managed and untouched; hand-written code lives in `Customizations/` or a separate project (seam adapters by this skill, business gap-fill by `slice-implementer`), serves named model elements only, never claims render admission, and V5 is reported for the generated base **with its scope stated** |
64
61
  | **C. Fully hand-written delivery** | the scope cannot render and no generated base is wanted | `slice-implementer` delivers it with the model as the contract (`references/gap-fill-handoff.md`); V5 is `not run: no render` |
65
62
 
66
- Evolved events are gap-fill too: Stage still refuses any evolved event and its dependent scope with `STAGE-ESM-026`, because it cannot render Chronicle event-type migrations yet (Stage#204). Events at their initial revision still render. Hand-write the evolved events and their migrations per `cratis-chronicle-event-type-migration`, with the model as the contract.
63
+ Evolved events and dependent scope refuse `STAGE-ESM-026`; initial revisions render.
64
+ Gap-fill migrations per `cratis-chronicle-event-type-migration`, preserving the model contract.
67
65
 
68
- Supported UUID/String generation strategies, v15 freshness and scalar/named `returns`
69
- responses, fixtures and `then returns` render with the CLI and Stage. Unsupported generated
66
+ Supported UUID/String generation, v15 freshness, responses, fixtures and
67
+ `then returns` render. Unsupported generated
70
68
  types (`STAGE-ESM-028`) and result combinations (`-038`) still require case A or C:
71
69
  preserve the model and its specifications. See Stage's `references/admission.md`.
72
70
  Supported event-triggered Automation slices also render as managed Chronicle reactors;
73
- refused reactions, captures and Translate slices remain gap-fill.
74
-
75
- Models with event sources, streams or command routes bind and reference-execute as ESM v8 on the standalone
76
- tool, so report V3 and V4 from that tool. The CLI/Stage pair
77
- (`cratis-screenplay-toolchain/references/renderable-subset.md`) reaches v8 route checks
78
- and construct admission through v27 (Requires Cratis CLI 3.75.0; older bundles stop earlier, v28 is `CLI-RENDER-004`). Public/foreign events and production overrides
79
- still refuse; semantic reaction/reducer filters and role/authenticated `runs as` render.
80
- Claim-reading/opaque system gates, legacy actor/filter paths and mixed effects still refuse. Keep refused scope as case A/C,
81
- never infer target support from binding. Read Stage's `references/admission.md` and
82
- toolchain `references/sources-and-streams.md`.
83
-
84
- **Mixed reaction effects.** A reaction that both `produces` events and `invokes` commands is refused by
85
- Stage (`STAGE-ESM-037`) although Arc runs one reactor returning events
86
- and commands (events appended first as one batch, then commands in order, no cross-effect
87
- transaction; a retry can repeat the events). The scaffold now includes the mixed-result handler,
88
- but Stage still refuses it because redelivery can duplicate events. `[OnceOnly]` excludes replay,
89
- not retries. Keep the modeled reaction whole; gap-fill needs a proven retry-safe realization,
90
- not splitting or dropping effects to get a render. Source: Stage
91
- `Documentation/reference/reaction-rendering.md`.
92
-
93
- Read Stage's `references/admission.md` when checking v17/v19 or query validation:
94
- primitive query arguments still answer absence, not Screenplay's Validation.
95
- Query errors need v18 admission; do not delete rules or claim parity.
71
+ refused reactions, captures and Translate slices remain gap-fill. A `given clock` fixture
72
+ in the semantic executor is not support for rendering clock triggers.
73
+ Requires Stage 4.141.0 to render v26 Date/DateTime command comparisons; older renderers
74
+ refuse `STAGE-ESM-046`. Read [rendered date comparisons](../cratis-stage-rendering-and-sandbox/references/date-comparisons.md)
75
+ when delivering dates for remaining refusals and input-binding differences.
76
+
77
+ Source/stream routes bind and reference-execute as v8; target admission is separate.
78
+ Requires Cratis CLI 3.75.0 for v27 admission; older bundles stop earlier, v28 is
79
+ `CLI-RENDER-004`. Read toolchain `references/renderable-subset.md` and
80
+ `references/sources-and-streams.md` when delivering routes, actor gates or filters.
81
+ Preserve refused public/foreign events, production overrides and opaque gates as A/C.
82
+
83
+ **Mixed effects (`STAGE-ESM-037`).** Keep the reaction whole: returned events append
84
+ before commands and redelivery can duplicate them. `[OnceOnly]` excludes replay,
85
+ not retries. Read Stage's [admission](../cratis-stage-rendering-and-sandbox/references/admission.md)
86
+ when gap-filling a mixed reaction; prove retry safety, never split or drop effects.
87
+
88
+ Read Stage's `references/admission.md` when checking v17/v19 or query validation;
89
+ query errors need v18 admission. Preserve rules and test rejection separately from absence.
96
90
 
97
91
  Two rules hold in every case: a customization never makes a rejected model renderable, and
98
92
  a whole-application V5 is never claimed from a subset. `--scope` renders an admitted part (the whole
@@ -114,6 +108,9 @@ model still compiles and binds) and its V5 states the scope.
114
108
  (repeatable) to render an admitted part. Classify every
115
109
  diagnostic with `references/renderability-gate.md`: model fix in the chosen mode,
116
110
  capability gap, permanent implementation-attachment requirement, tool skew or environment. Group by code and count; do not paste the list.
111
+ Requires Stage 4.146.0 for collecting independent admission refusals in one plan;
112
+ earlier renderers reveal later batches after earlier fixes. Profile/version failures
113
+ still stop first. Classify all returned refusals before the next probe.
117
114
  3. **When admission fails** (case A) present the options, the user decides:
118
115
  (a) keep design mode and record the gaps; (b) narrow to renderable mode, where the modeler
119
116
  changes the model for business reasons and **without** removing protection (`pii`,
@@ -107,8 +107,9 @@ reaction or drop an effect to dodge rendering.
107
107
 
108
108
  Preserve declared `reaction batches atomic` boundaries: each trigger occurrence's
109
109
  direct productions and each selected refusal branch are separate batches, with
110
- invoked commands independent. Stage refuses v22 (STAGE-ESM-016) and atomic mode
111
- in admitted v23–v27 (STAGE-ESM-043); the declaration is not external-effect deduplication.
110
+ invoked commands independent. Atomic mode refuses STAGE-ESM-043.
111
+ Requires Stage 4.139.0 for v22 admission; older Stage reports -016.
112
+ The declaration is not external-effect deduplication.
112
113
  For described handlers, hand off only payload computation under the v23 result
113
114
  contract; Stage STAGE-IMPL-002 means no stubs, even Stub mode. Protected v25 reads
114
115
  render from Stage 4.138.0 (STAGE-ESM-044 from older bundles, or for shapes it cannot