@cratis/pi 7.75.0 → 7.77.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 (88) hide show
  1. package/package/corpus/harnesses/copilot/instructions/authoring-skills.instructions.md +2 -0
  2. package/package/corpus/harnesses/copilot/instructions/capability-is-not-authority.instructions.md +4 -0
  3. package/package/corpus/harnesses/copilot/instructions/efcore.instructions.md +2 -0
  4. package/package/corpus/harnesses/copilot/instructions/vertical-slices.instructions.md +6 -4
  5. package/package/corpus/product-sync.json +14 -14
  6. package/package/corpus/rules/authoring-skills.md +2 -0
  7. package/package/corpus/rules/capability-is-not-authority.md +4 -0
  8. package/package/corpus/rules/efcore.md +2 -0
  9. package/package/corpus/rules/general.md +1 -0
  10. package/package/corpus/rules/vertical-slices.md +6 -4
  11. package/package/corpus/skills/cratis-application-react-specifications/SKILL.md +4 -4
  12. package/package/corpus/skills/cratis-application-slice-specifications/SKILL.md +1 -1
  13. package/package/corpus/skills/cratis-arc-authentication-authorization-and-identity/references/authorization.md +9 -0
  14. package/package/corpus/skills/cratis-arc-authentication-authorization-and-identity/references/observable-emission-guards.md +12 -3
  15. package/package/corpus/skills/cratis-arc-command/references/decisions-and-routing.md +11 -0
  16. package/package/corpus/skills/cratis-arc-command-execution/SKILL.md +3 -0
  17. package/package/corpus/skills/cratis-arc-command-execution/references/occurrence-commands.md +78 -0
  18. package/package/corpus/skills/cratis-arc-command-validation/SKILL.md +11 -37
  19. package/package/corpus/skills/cratis-arc-command-validation/references/input-binding.md +49 -0
  20. package/package/corpus/skills/cratis-arc-command-validation/references/read-model-resolution.md +25 -0
  21. package/package/corpus/skills/cratis-arc-command-validation/references/validation-severity.md +21 -0
  22. package/package/corpus/skills/cratis-arc-ef-core-migration/SKILL.md +7 -1
  23. package/package/corpus/skills/cratis-arc-hosting/SKILL.md +3 -0
  24. package/package/corpus/skills/cratis-arc-hosting/references/connection-resolution.md +61 -0
  25. package/package/corpus/skills/cratis-arc-query-kotlin/SKILL.md +1 -1
  26. package/package/corpus/skills/cratis-arc-query-paging/SKILL.md +4 -2
  27. package/package/corpus/skills/cratis-arc-query-typescript/SKILL.md +1 -1
  28. package/package/corpus/skills/cratis-arc-react-page/references/queries-and-commands.md +14 -1
  29. package/package/corpus/skills/cratis-arc-validation-kotlin/SKILL.md +1 -1
  30. package/package/corpus/skills/cratis-arc-validation-typescript/SKILL.md +1 -1
  31. package/package/corpus/skills/cratis-chronicle-client-dotnet/SKILL.md +5 -0
  32. package/package/corpus/skills/cratis-chronicle-client-dotnet/references/immediate-append-refusal.md +40 -0
  33. package/package/corpus/skills/cratis-chronicle-client-dotnet/references/lifecycle.md +4 -0
  34. package/package/corpus/skills/cratis-chronicle-client-dotnet/references/occurrences.md +89 -0
  35. package/package/corpus/skills/cratis-chronicle-client-dotnet/references/pinned-generation-delivery.md +33 -3
  36. package/package/corpus/skills/cratis-chronicle-client-elixir/SKILL.md +1 -1
  37. package/package/corpus/skills/cratis-chronicle-client-kotlin/SKILL.md +1 -1
  38. package/package/corpus/skills/cratis-chronicle-client-typescript/SKILL.md +1 -1
  39. package/package/corpus/skills/cratis-chronicle-decision-reads/SKILL.md +5 -2
  40. package/package/corpus/skills/cratis-chronicle-decision-reads/references/admission-and-ownership.md +18 -1
  41. package/package/corpus/skills/cratis-chronicle-event-type-migration/references/pinned-generations.md +6 -0
  42. package/package/corpus/skills/cratis-chronicle-hosting/SKILL.md +3 -0
  43. package/package/corpus/skills/cratis-chronicle-hosting/references/operations.md +26 -0
  44. package/package/corpus/skills/cratis-chronicle-hosting/references/storage-resolution.md +55 -0
  45. package/package/corpus/skills/cratis-chronicle-multi-tenancy/SKILL.md +3 -0
  46. package/package/corpus/skills/cratis-chronicle-multi-tenancy/references/remove-namespace.md +38 -0
  47. package/package/corpus/skills/cratis-chronicle-projection/references/definition-changes.md +26 -0
  48. package/package/corpus/skills/cratis-chronicle-projection/references/model-bound-attributes.md +8 -0
  49. package/package/corpus/skills/cratis-chronicle-reactor/SKILL.md +5 -22
  50. package/package/corpus/skills/cratis-chronicle-reactor/references/starting-and-replaying.md +33 -0
  51. package/package/corpus/skills/cratis-chronicle-read-model/SKILL.md +9 -2
  52. package/package/corpus/skills/cratis-chronicle-read-model/references/queries.md +9 -4
  53. package/package/corpus/skills/cratis-chronicle-reducer/SKILL.md +4 -0
  54. package/package/corpus/skills/cratis-multi-service-architecture/SKILL.md +9 -3
  55. package/package/corpus/skills/cratis-performance-review/SKILL.md +4 -1
  56. package/package/corpus/skills/cratis-screenplay-automations-and-translations/SKILL.md +2 -2
  57. package/package/corpus/skills/cratis-screenplay-automations-and-translations/references/realization-and-gap-fill.md +10 -2
  58. package/package/corpus/skills/cratis-screenplay-captures-and-reactions/SKILL.md +9 -9
  59. package/package/corpus/skills/cratis-screenplay-captures-and-reactions/references/atomic-batches-and-source-mappings.md +2 -2
  60. package/package/corpus/skills/cratis-screenplay-model-authoring/SKILL.md +11 -11
  61. package/package/corpus/skills/cratis-screenplay-model-authoring/references/mcp-tools.md +9 -0
  62. package/package/corpus/skills/cratis-screenplay-model-authoring/references/model-notes.md +41 -23
  63. package/package/corpus/skills/cratis-screenplay-model-authoring/verification.json +8 -3
  64. package/package/corpus/skills/cratis-screenplay-projections/SKILL.md +19 -12
  65. package/package/corpus/skills/cratis-screenplay-projections/references/pdl-grammar.md +37 -2
  66. package/package/corpus/skills/cratis-screenplay-projections/verification.json +11 -0
  67. package/package/corpus/skills/cratis-screenplay-render-and-gap-fill/SKILL.md +37 -40
  68. package/package/corpus/skills/cratis-screenplay-render-and-gap-fill/references/gap-fill-handoff.md +3 -2
  69. package/package/corpus/skills/cratis-screenplay-render-and-gap-fill/references/renderability-gate.md +1 -1
  70. package/package/corpus/skills/cratis-screenplay-render-and-gap-fill/verification.json +4 -2
  71. package/package/corpus/skills/cratis-screenplay-scenario-coverage/references/coverage-matrix.md +9 -0
  72. package/package/corpus/skills/cratis-screenplay-toolchain/SKILL.md +13 -30
  73. package/package/corpus/skills/cratis-screenplay-toolchain/references/diagnostics.md +39 -6
  74. package/package/corpus/skills/cratis-screenplay-toolchain/references/executable-subset.md +5 -2
  75. package/package/corpus/skills/cratis-screenplay-toolchain/references/language-admission.md +15 -5
  76. package/package/corpus/skills/cratis-screenplay-toolchain/references/renderable-subset.md +7 -4
  77. package/package/corpus/skills/cratis-screenplay-toolchain/references/screenplay-contract.json +12 -1
  78. package/package/corpus/skills/cratis-screenplay-toolchain/references/screenplay-contract.version +1 -1
  79. package/package/corpus/skills/cratis-screenplay-toolchain/verification.json +9 -2
  80. package/package/corpus/skills/cratis-stage-rendering-and-sandbox/SKILL.md +38 -56
  81. package/package/corpus/skills/cratis-stage-rendering-and-sandbox/references/admission.md +23 -13
  82. package/package/corpus/skills/cratis-stage-rendering-and-sandbox/references/date-comparisons.md +44 -0
  83. package/package/corpus/skills/cratis-stage-rendering-and-sandbox/references/rendered-application.md +8 -2
  84. package/package/corpus/skills/cratis-stage-rendering-and-sandbox/references/sandbox-and-specrunner.md +59 -8
  85. package/package/corpus/skills/cratis-stage-rendering-and-sandbox/verification.json +7 -3
  86. package/package/corpus/skills/guiding-refactoring-with-code-health/SKILL.md +1 -1
  87. package/package/corpus/skills/safeguarding-ai-generated-code/SKILL.md +1 -1
  88. package/package.json +1 -1
@@ -0,0 +1,38 @@
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
+ # Remove a namespace
5
+
6
+ Requires Chronicle 19.73.0 for `IEventStore.RemoveNamespace`.
7
+ Requires Chronicle 19.75.1 for reminder cleanup.
8
+ Requires Chronicle 19.76.1 for concurrent re-subscription recovery.
9
+ Requires client 19.77.1 for forgetting a removed namespace on reconnect. Check
10
+ with `dotnet list package` and the kernel image tag; older pairs can recreate
11
+ an apparently removed namespace.
12
+
13
+ This is destructive tenant removal, not a way to hide a tenant in the UI.
14
+ Before calling it, confirm the named event store and namespace, the authorized
15
+ scope, backups and application-owned storage disposition. Never target the
16
+ default namespace: its removal is refused. Removing an unknown namespace is a
17
+ no-op, and an interrupted removal can be repeated.
18
+
19
+ Removal first stops listing the namespace, unsubscribes and removes its
20
+ observers and their persistent reminders, then drops provider-owned namespace
21
+ storage and forgets the namespace. Forwarding and pattern observers with no
22
+ saved state are included through their reminders. Re-subscriptions already in
23
+ flight are handled by bounded unsubscribe/remove retries.
24
+
25
+ MongoDB drops its namespace database. SQL and in-memory providers retain their
26
+ namespace data; do not claim removal is erasure in those providers. Application
27
+ read-model databases are not dropped: the application owns that data and its
28
+ separately authorized cleanup.
29
+
30
+ On reconnect a non-default store asks whether its namespace still exists. If
31
+ absent, it releases that store instead of re-registering it; if the kernel
32
+ cannot answer, registration follows the older behavior. Explicitly using the
33
+ namespace again can create it anew. Stop or reroute writers when removal must
34
+ remain final.
35
+
36
+ Verify removal with a matching kernel and provider, including restart and
37
+ reconnect, and separately inspect the disposition of application-owned data.
38
+ Do not create or delete a live tenant merely to test this workflow.
@@ -23,5 +23,31 @@ history. Sources: `Documentation/projections/registration-lifecycle.md`,
23
23
  `Documentation/concepts/observers.mdx`, `Observation/Jobs/{CatchUpObserver,ReplayObserver}.cs`
24
24
  and `Observation/States/Routing.cs` (under `Source/Kernel/Core/`).
25
25
 
26
+ ## Rolling deployment versions
27
+
28
+ Requires Chronicle 19.79.0 on client and kernel for projection registration's
29
+ `ChronicleOptions.SoftwareVersion`. It defaults to the entry assembly's informational version;
30
+ `Cratis:Chronicle:SoftwareVersion` overrides it, and startup warns on `1.0.0`.
31
+ Check `dotnet list package` and the kernel image tag; older kernels ignore it.
32
+
33
+ The kernel compares semantic-version precedence, including prerelease labels.
34
+ An older definition cannot overwrite a newer stored version, and an older
35
+ full-set registration cannot retire newer projections. Equal, missing or
36
+ unparseable versions retain ordinary registration behavior. An intentional
37
+ rollback must give the older code a software version higher than the stored
38
+ one. Changing only software version does not request a replay; definition
39
+ evolution policy still determines that.
40
+
41
+ ## Namespace reconciliation
42
+
43
+ Requires Chronicle 19.81.1 for projections and captures to reconcile subscriptions
44
+ in every namespace, including runtime-created namespaces. Explicit ensure waits
45
+ for healthy subscriptions; implicit first-append creation is reconciled within
46
+ a watchdog interval. A broken definition does not block healthy ones or creation.
47
+ A lost subscription is repaired, but reconciliation never lifts quarantine,
48
+ revives a retired observer, or restarts a stopped/deleted capture. A kernel
49
+ restart or a newly added namespace still ends projection quarantine through a
50
+ fresh subscription; do not interpret ordinary watchdog repair as operator clear.
51
+
26
52
  Closing a stream does not erase its events or prevent a projection replay.
27
53
  Keep the closing fact as history; see **cratis-chronicle-event-constraints**.
@@ -59,6 +59,14 @@ pair it with `[NotRewindable]`. `[NotProjected]` excludes a query-assembled memb
59
59
  from AutoMap and CHR0024. Sources: `Projections/ModelBound/NotProjectedAttribute.cs`,
60
60
  `Projections/FromEveryBuilder.cs`, and `Documentation/projections/model-bound/`.
61
61
 
62
+ Requires Chronicle 19.78.1 for `[FromAll]`/`[FromEvery]` properties under
63
+ `[ChildrenFrom<T>]` or `[Nested]` to be declared on the child itself, including
64
+ the event creating it. Parent all-event mappings are not copied into children.
65
+ Older client definitions with root-declared child mappings work only when the
66
+ root has no property with the same name; otherwise the mapping stays on the
67
+ root until the client is upgraded. Check client/kernel versions and replay
68
+ affected projections to rebuild already materialized child values.
69
+
62
70
  ## Setting values
63
71
 
64
72
  | Attribute | Arity | Parameters | Targets |
@@ -133,32 +133,15 @@ re-delivers the event as an ordinary observation, and a `[OnceOnly]` handler run
133
133
  again. Catch-up and crash redelivery are not replay either; every ordinary
134
134
  matching event can run, even on the same source. Keep effects idempotent.
135
135
 
136
- **A reactor new to a store catches up the whole history on first registration, and
137
- `[OnceOnly]` does not cover that.** For a side-effect reactor (jobs, AI or external
138
- calls), start the observer at the tail or have the handler ignore facts that
139
- predate its registration, and specify that history causes nothing. A
140
- reconciliation sweep that decides from a read model must not run while that model's
141
- observer is replaying or behind: a rebuilding model looks like "never processed".
142
- Decide from the events or a `[Passive]` model, and specify the replaying case.
136
+ **A new reactor catches up history; `[OnceOnly]` does not stop that.**
137
+ Requires Chronicle 19.70.0 for `[StartAtTail]` to start only its first registration
138
+ at the tail; existing positions remain. Upgrade the server first: older kernels
139
+ ignore it. Read references/starting-and-replaying.md when avoiding pre-registration
140
+ side effects or choosing alternate replay behavior.
143
141
 
144
142
  Analyzer **CHR0022** (warning) requires `[OnceOnly]` on a handler that returns
145
143
  event side effects, because a replay would otherwise append duplicates.
146
144
 
147
- `Cratis.Chronicle.Reactors.ReplayAttribute` (`[Replay]`) is the other half, and
148
- targets a method only. Mark a **second** handler for the same event type with it
149
- when replay needs to do something *different* rather than nothing:
150
-
151
- ```csharp
152
- public Task <MethodName>(<EventName> @event) => <serviceName>.<Operation>(@event.<Property>);
153
-
154
- [Replay]
155
- public Task <MethodName>DuringReplay(<EventName> @event) => Task.CompletedTask;
156
- ```
157
-
158
- With a `[Replay]` handler present, only it runs during replay. Without one, the
159
- ordinary handler runs during replay as before. An event type handled *only* by a
160
- `[Replay]` handler is still subscribed to.
161
-
162
145
  ## Identity and event sequence
163
146
 
164
147
  `Cratis.Chronicle.Reactors.ReactorAttribute` takes two optional arguments:
@@ -0,0 +1,33 @@
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
+ # Start at the tail and distinguish replay
5
+
6
+ Requires Chronicle 19.70.0 for `[StartAtTail]` in
7
+ `Cratis.Chronicle.Reactors`. Upgrade the server before the client: an older
8
+ server ignores the field and catches up from the beginning. Check with
9
+ `dotnet list package` and the kernel image tag.
10
+
11
+ Put `[StartAtTail]` on a side-effect reactor that should observe only future
12
+ events. It changes the **first registration**: an observer already holding a
13
+ position keeps it. Leaving the attribute in place is safe, but adding it is not
14
+ a command to fast-forward an existing observer. Specify that historical facts
15
+ cause no effect on first registration.
16
+
17
+ `[OnceOnly]` excludes replay, not initial catch-up, failed-partition recovery
18
+ or crash redelivery. Keep side effects idempotent. A reconciliation sweep must
19
+ not decide from a model that is replaying or behind: rebuilding state can look
20
+ like "never processed". Decide from events or a passive model and cover that case.
21
+
22
+ ## Alternate replay behavior
23
+
24
+ `Cratis.Chronicle.Reactors.ReplayAttribute` targets a method. Mark a second
25
+ handler for the same event type when replay must do different work. With that
26
+ handler present only it runs during replay; without one, the ordinary handler
27
+ runs unless excluded by `[OnceOnly]`. An event type handled only by a `[Replay]`
28
+ handler is still subscribed to.
29
+
30
+ Verify first registration, restart with an existing position, replay and
31
+ failed-partition redelivery separately. Assert the external effect count, not
32
+ only that the handler was invoked. Run `dotnet test` on the owning spec project;
33
+ server-first compatibility and durable positions also need kernel integration.
@@ -215,8 +215,8 @@ current rather than eventually consistent.
215
215
  **Passive is fresher, not safer.** A materialized read may lag the log; a passive
216
216
  read is current when read. Neither captures a position or enrolls a guard, so
217
217
  neither makes a rule hold when two requests race. To guard a decision use a decision
218
- read over a flat, event-source-keyed projection with an `Id` property (reducers and
219
- self-reducing models are refused), a constraint for uniqueness, or an aggregate;
218
+ read over an admitted projection or unfiltered dependency-free reducer, a
219
+ constraint for uniqueness, or an aggregate;
220
220
  see [choosing how a rule holds](../cratis-chronicle-decision-reads/references/choosing-how-a-rule-holds.md).
221
221
 
222
222
  **`IMongoCollection<T>` reads only the sink.** It cannot compute passive state:
@@ -227,6 +227,13 @@ read-model parameter injection) when you need its computed state. Do not remove
227
227
  Keep secret-bearing state on the protected access path; project only safe
228
228
  metadata into a separate list/search model.
229
229
 
230
+ Requires Chronicle 19.77.3 for strongly consistent per-key projections to fold
231
+ from the start on every read: passive, stream-scoped, wildcard-key and session
232
+ reads immediately reflect revisions, redactions and joined-subject erasure.
233
+ Earlier warm reads can retain old content. Each read costs O(key history), not
234
+ an incremental suffix; prefer materialization for frequent long-history reads.
235
+ Check the deployed kernel tag before relying on this freshness.
236
+
230
237
  The number of passive types is not itself a performance smell. Review event
231
238
  history length, invocation frequency, and the consistency/security requirement;
232
239
  repeated reconstruction of large histories on a hot path is the concern.
@@ -32,10 +32,15 @@ Chronicle extensions — Chronicle declares no `Observe` on `IMongoCollection<T>
32
32
 
33
33
  ## Discovery rules
34
34
 
35
- Arc discovers **public static** methods; private and compiler-generated methods
36
- are never queries. Use `[ReadModel(RequireQueryAttribute = true)]` and `[Query]`
37
- on intended endpoints when the type also has folds (`Create`/`Reduce`) or public
38
- helpers. `[Query]` alone does not hide siblings. ARC0026 checks invalid/ambiguous
35
+ Arc discovers eligible **public and internal static** methods on `[ReadModel]`
36
+ types. Internal visibility is not an endpoint privacy boundary. Keep helpers
37
+ outside the read model, regardless of their visibility. Use
38
+ `[ReadModel(RequireQueryAttribute = true)]` and `[Query]` on intended endpoints
39
+ when the type also has folds (`Create`/`Reduce`); `[Query]` alone does not hide
40
+ siblings. Requires Arc 22.27.1 for exclusion of private, protected, special-name
41
+ and compiler-generated methods; older versions can expose private statics too.
42
+ Check with `dotnet list package`; on older versions move helpers out rather
43
+ than relying on visibility. ARC0026 checks invalid/ambiguous
39
44
  query declarations; ARCCHR0019 warns about fold-like statics exposed by convention.
40
45
  Requires Arc 22.90.0 for automatic exclusion of methods taking the model itself,
41
46
  including `Reduce(event, current)`; `[Query]` cannot force such a method into an
@@ -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