@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
@@ -30,6 +30,8 @@ Use portable fields: `name`, `description`, `license`, `compatibility`, `metadat
30
30
 
31
31
  An explicit trigger clause (`Use when`, `Load when`, `Read when` or an equivalent) and neutral voice are required even with `SKILL_AUTHORING_MODE=warn`. Negative routing and meta-language findings follow that switch; the 700-character target is guidance, not a gate.
32
32
 
33
+ The overlap lint warns when positive trigger token sets have Jaccard similarity (intersection / union) **>= 0.4**, compared before rounding. It lowercases ASCII word tokens, deduplicates them and removes routing boilerplate and common function words. Only the explicit `Use when` (or equivalent) clause counts, stopping at negative routing; empty triggers never match. The warning stays advisory even in strict mode: shared vocabulary is a review signal, not proof of competing scope. Sharpen the trigger and add a sibling pointer rather than padding it with unrelated words.
34
+
33
35
  ## 3. Budget and progressive disclosure
34
36
 
35
37
  Target at most 400 body lines and 16,000 characters; the hard limits remain 500 lines and 20,000 characters. A warning starts above the 16,000-character target, so a body that outgrows it is split before it nears the hard limit; characters only approximate tokens.
@@ -41,5 +41,9 @@ Levels of Authority in [`general.md`](../../../rules/general.md).
41
41
  - **[contract] Absent authority for a consequential effect, stop and ask about that
42
42
  effect in plain language.** State the exact target, action, consequence, and recovery;
43
43
  a missing answer is a blocker for that effect, not for unrelated in-scope work.
44
+ - **[contract] Never copy secrets or personal values into models, notes, state,
45
+ packets or briefs.** Never use real credentials or personal data in examples.
46
+ - **[contract] Legacy extraction uses Git read-only:** never checkout, reset or stash
47
+ the legacy repository; do not touch a live checkout the brief excludes.
44
48
  - **[convention] Prefer the narrowest capability that does the job.** Reaching for the
45
49
  broadest available grant makes the next reader assume it was authorized.
@@ -68,6 +68,8 @@ Migrations are created and applied with the **standard EF Core tooling** (`dotne
68
68
  | `table.JsonColumn<TProperty>(migrationBuilder, …)` | a `[Json]`-mapped property |
69
69
  | `migrationBuilder.Add{String,Guid,Number,Bool,DateTimeOffset,AutoIncrement,Json,Point,LineString,Polygon}Column(…)` | adding a column to an existing table |
70
70
 
71
+ A migration that is committed or applied to any database is append-only: never edit or delete it. Correct mistakes with a new migration. Only an unapplied, uncommitted migration may be removed with `dotnet ef migrations remove` and regenerated.
72
+
71
73
  Where a repository organizes its migrations (a dedicated project, a versioned file naming scheme, a table-name constants class) is its own convention: follow what the repository already does, and do not introduce one as if Arc required it.
72
74
 
73
75
  ## Concepts and JSON **[contract]**
@@ -257,15 +257,17 @@ public record AuthorRegistered(AuthorName Name);
257
257
 
258
258
  ## Read Models and Queries
259
259
 
260
- **[contract]** `[ReadModel]` records expose queries as `public static` methods; dependencies are plain method parameters (no `[FromServices]`). For application code, start with model-bound mappings, use fluent when the definition needs structure, and choose reducer code when transitions read better as code. For step-by-step creation, invoke the **cratis-chronicle-read-model** skill.
260
+ **[contract]** `[ReadModel]` records expose eligible public and internal static methods as queries; internal visibility does not hide an endpoint. Dependencies are plain method parameters (no `[FromServices]`). For application code, start with model-bound mappings, use fluent when the definition needs structure, and choose reducer code when transitions read better as code. For step-by-step creation, invoke the **cratis-chronicle-read-model** skill.
261
261
 
262
262
  Use `[ReadModel(RequireQueryAttribute = true)]` with `[Query]` on intended
263
- endpoints when public folds/helpers exist (ARC0026/ARCCHR0019). `[Query]` alone
264
- does not hide siblings; private/compiler-generated statics are never queries.
263
+ endpoints when folds exist (ARC0026/ARCCHR0019). `[Query]` alone does not hide
264
+ siblings. Keep helpers outside the read model regardless of visibility.
265
+ Requires Arc 22.27.1 for private/protected/compiler-generated methods to be
266
+ excluded; older versions can expose private statics too. Check `dotnet list package`.
265
267
  A `CancellationToken` is supplied by Arc; concept arguments come from the caller,
266
268
  not DI. Bad GET/QUERY argument conversions return 400. Single-instance MongoDB/EF
267
269
  observations emit `default` on absence/deletion/filter exit: guard `hasData` and
268
- `isReady` in React. Verified at Arc v22.75.0; see the read-model query reference.
270
+ `isReady` in React; see the read-model query reference.
269
271
 
270
272
  ### Query return shapes **[contract]**
271
273
 
@@ -27,9 +27,9 @@
27
27
  "repository": "Cratis/Stage",
28
28
  "packages": [],
29
29
  "synced": {
30
- "version": "4.138.0",
30
+ "version": "4.146.0",
31
31
  "date": "2026-10-17",
32
- "by": "Cratis/AI#752"
32
+ "by": "Cratis/AI#773"
33
33
  },
34
34
  "covers": {
35
35
  "skills": [
@@ -46,7 +46,7 @@
46
46
  ],
47
47
  "rules": []
48
48
  },
49
- "notes": "Source-checked Stage v4.103.0: exact ESM v1-v17 and v19, not v18 or v20 (v18 admitted from 4.106.0 and v20 from 4.109.0, taught with Requires lines; 4.104-4.108 not otherwise reviewed). Snapshot/live collection queries, identity-mapping all projections, stored event names, event-id publication checks, release-baseline warnings, command clock/receipt-time generation, conditional and multi-command slices, generated text constraints, no-event and bounded redelivery specs, refusal branches. Query concept validation still uses primitive workaround; Stage#370 released in 4.106.0. CLI v3.62.0 bundles Stage 4.99.0, not 4.103.0. Generated-values-only delta checked at v4.127.0: v21/all-Proven unpinned specs from 4.115.0, warning/info generated rules 4.117.0, checksum validation 4.118.0, pattern/random factories/Host/executor 4.119.0; generate rule still STAGE-ESM-028. Language admission reconciled at the same v4.127.0 tag: exact v1-v21 and v23-v25 pairs; v22/v26 and mixed pairs -016, protected reads -044, atomic mode -043, described bodies STAGE-IMPL-002 even Stub mode; v24 first admitted 4.124.0 (absent 4.123.0). Reviewed v4.128.0-v4.130.0 deltas for Cratis/AI#739: v4.128.0 new-application self-reducing Cratis C# profile (CreateNewApplicationProfile, ReducerConventionInput.Read, WithReducerConvention; existing callers classic); shared SemanticValidationRules.Check confirmed (already present in v4.127.1, so no new 4.128.0 minimum claimed); v4.129.0 semantic Host/executor protected reads, presence before requirements/generation, read-backed requirements/mappings, non-Error requirements STAGE-ESM-045 including reaction invocations, Host fault on any outside append (stricter than reference scoped conflict). Renderer/legacy Host/structural runner retain STAGE-ESM-044. v4.130.0 root-template shell, options/appearance and fail-closed startup/planning findings reviewed in stage-rendering.md, RootShell.cs and stageShell.ts. Exact pairs remain v1-v21 and v23-v25; v26 refused STAGE-ESM-016 and Stage#473 still open. Earlier unreviewed deltas remain as noted above, so synced stays at the last fully reviewed release. No new render/browser/Docker probe."
49
+ "notes": "Cratis/AI#773: release/tag delta v4.139.0-v4.146.0 (including v4.141.1). Exact ESM v1-v27 pairs admitted; v22 from 4.139.0, atomic mode still -043. Date comparisons render from 4.141.0 with remaining -046 shapes and named-policy binding differences. 4.141.1 supplies authored occurrence in independent event-reaction specs, not clock triggers or generated append/redelivery clock fixtures. 4.142.0 Host decide/commit absorbs unrelated outside facts, with dependency conflicts, guarded batch retries only without invocations and fail-closed unknown writes. 4.143.0 shared STAGE-PROFILE-001 through -006 findings; 4.144.0 scaffold pins follow Stage package inputs. 4.145.0 reached reducer/validation bodies use STAGE-IMPL-003 without refusing unrelated behavior; described handlers retain -002. 4.146.0 collects independent render refusals, preserving profile/version early exits. Scene template verification changes classified as internal; no new render/browser/Docker probe. Prior focused checks remain; v4.104-v4.108 were not otherwise fully reviewed."
50
50
  },
51
51
  {
52
52
  "id": "arc",
@@ -63,9 +63,9 @@
63
63
  }
64
64
  ],
65
65
  "synced": {
66
- "version": "22.100.0",
67
- "date": "2026-10-15",
68
- "by": "Cratis/AI#710"
66
+ "version": "22.117.0",
67
+ "date": "2026-10-17",
68
+ "by": "Cratis/AI#773"
69
69
  },
70
70
  "covers": {
71
71
  "skills": [
@@ -99,7 +99,7 @@
99
99
  "vertical-slices.md"
100
100
  ]
101
101
  },
102
- "notes": "Whole-product floor unchanged at 22.100.0. Focused read-protection coverage, Arc 22.106.0-22.108.0: ReadProtectionMode Off, Measure and On (MSBuild property, assembly and command attributes, runtime MaximumMode cap), read-model parameters of Handle and validator constructors guarded under On, [LookUpBy], [Unprotected(\"why\")], per-stream read models on routed commands, Measure report, ReadChanged and ReadIncomplete refusals, and CommandScenario selecting decision mode automatically. the caller severity threshold (X-Allowed-Severity, [BlockOnValidationSeverity]) and the Error floor for commands declared On (22.108.0). [ProtectedDecision] and DecisionRead<T> retained as the per-command opt-in. The other 22.101.0-22.108.0 changes were not reviewed. Prior notes: scoped completion and routing validation, generated-target freshness, observable scenarios, asynchronous execution scopes, read-model diagnostics, ordered reactor refusal handling and ICommandExceptionMapper. Generated-values-only delta checked at v22.107.1: 22.104.0 enforces every concept-rule severity and carries Fundamentals 7.25.0; 22.107.0 recovers pattern/random/checksum and self-contained String generation rules, with v21 caps and fixture validation. No new runtime probe."
102
+ "notes": "Reviewed releases 22.100.1-22.117.0 at tags: occurrence command receipts and retry classification, tenant/purpose storage resolution, explicit-offset binding and authorization of malformed bodies, camelCase validation members, conflict event details, hub fallback authorization and snapshot guards, and React query-key isolation/resubscription. Existing read-protection and generated-value guidance retained. Query discovery includes internal statics; public-only discovery in Arc#3368 is unreleased. Screenplay-generator deltas classified for the owning lane, not changed here. No new runtime probe."
103
103
  },
104
104
  {
105
105
  "id": "ai",
@@ -171,9 +171,9 @@
171
171
  }
172
172
  ],
173
173
  "synced": {
174
- "version": "4.211.1",
174
+ "version": "4.212.4",
175
175
  "date": "2026-10-17",
176
- "by": "Cratis/AI#762"
176
+ "by": "Cratis/AI#772"
177
177
  },
178
178
  "covers": {
179
179
  "skills": [
@@ -201,7 +201,7 @@
201
201
  ],
202
202
  "rules": []
203
203
  },
204
- "notes": "Cratis/AI#762 and #761: source-checked v4.210.0 and v4.211.0 contracts for PLAY0800 CommandHandlerRequiresAttachment (required typed subject, permanent code-attachment requirement, other PLAY0268 families unchanged), independent reference remove/add batches, located same-text ambiguity conflicts and string MCP conflict/move-report document fields. v4.211.1 mapping changes inspected but excluded from this guidance update at the user's request; no typed PLAY0273 property/type arguments are claimed. Standalone Screenplay 4.211.1 and its compiler contract pinned; the contract is a byte-identical copy of the v4.211.1 release asset. No new render/runtime probe. Prior: Standalone 4.205.0 and byte-identical compiler contract pinned. Cratis/AI#746: Uuid ==/!= in command require and produces when (ESM v28): same-concept rule, bare Uuid against a concept, canonical literals, protected read paths in require only; PLAY0268 (different concepts, ordering, Uuid validation and concept rules, read paths in produces when) and PLAY0273 (non-canonical literal) checked against the 4.205.0 compiler, v28 selection read from the MCP executable-model view; Stage admits exact v1-v21 and v23-v26 pairs so v28 is refused STAGE-ESM-016, not probed against a Stage image; CLI 3.74.0 renders through v26. Prior: Standalone 4.204.0 and byte-identical compiler contract pinned. Cratis/AI#702 and #691: PLAY0690 reducer identity (Screenplay 4.170.0, native compiler only) and the screenplay.json validation gate (Screenplay 4.165.0; cratis screenplay validate reads it from CLI 3.65.0) are taught and probed against the 4.204.0 compiler. Cratis/AI#743: flat composite read-model keys (ESM v27): untyped projection key blocks on root from and remove with, equality-filter lists, single-instance by blocks and per-part fixtures, with PLAY0661/PLAY0662/PLAY0268 refusals checked against the 4.204.0 compiler; Stage origin/main still refuses v27 with STAGE-ESM-016 (stage-rendering.md); Stage v4.135.0 v26 admission (Host and executor run date comparisons; renderer STAGE-ESM-046) was source-checked for this sync; no render or runtime probe. Prior: Standalone 4.201.0 and byte-identical compiler contract pinned. Cratis/AI#733: the ui profile root template, shell options, appearance and new screens default (PLAY0788-PLAY0799, quick fix for the legacy layout line, ui-profiles MCP tool, 44 tools). Cratis/AI#735: chronological Date/DateTime ordering in command conditions and command/property literal validation (ESM v26), UTC tick precision and pre-rule offset validation; then matching remains ordinal. Source-checked Screenplay v4.199.0 commands, diagnostics, interoperability and specifications documentation plus decision 0087. Stage v4.127.1 still refuses v26 with STAGE-ESM-016 (stage-rendering.md and SemanticVersionFeatures.Supports); no render/runtime probe. Cratis/AI#576: prior mechanical compiler catch-up. Language batch #717/#722/#723/#724/#720/#728/#734 teaches atomic reaction batches (v22), described payload handlers (v23), portable linear matching, ordinal text rules (v24), protected command reads (v25), diagnostic arguments and event-source invokes mappings. Facts read at Screenplay v4.198.0 and introducing tags; Stage v4.127.0 admits exact v1-v21 and v23-v25 pairs but refuses v22/v26 and mixed pairs (STAGE-ESM-016), protected reads (044), atomic mode (043) and described handlers (STAGE-IMPL-002), even Stub mode. Stage text rules execute/render; no new renderer/runtime probe or Stage pin uplift. Cratis/AI#706: application navigation regions (module inherit, extend or override), toolbar slice buttons, blueprint template references and sample data packs in cratis-screenplay-ui-composition (references/application-shell.md), with the canonical shell vector and the rejection codes PLAY0710-PLAY0722 and PLAY0740-PLAY0765. Examples moved to the executable-state rules since 4.164: translator reactions in an Automation slice beside the Translate slice (PLAY0694) and the first record of a capture key appended with `when added`. Earlier: Standalone 4.164.0 and byte-identical compiler contract pinned. Cratis/AI#663: one origin per capture (PLAY0687). #668: executable no-event/redelivery v17. #684: concept query-argument validation in every version and query-error assertions v18. #681: executable refusal branches and refusal values v19. #666: proposal summary/severity counts and exact structural source proposals. Generated-concept rules select v20 with PLAY0688/0689 proofs and derived-matches repair; generated secrets and preview strategies remain refused. Release-baseline from-esm admission reads storedName. Standalone binding is not renderer admission: Stage 4.103.0 admits v1-v17 and v19; CLI 3.62.0 bundles Screenplay 4.159.0 / Stage 4.99.0 and renders through v16. Prior evidence remains unless superseded; no new renderer, Docker or browser probe."
204
+ "notes": "Cratis/AI#772: standalone Screenplay 4.212.4 pinned; regenerated compiler contract is byte-identical to the v4.212.4 release asset. Source-checked joined-event automap/no automap overrides and level fallback in executable binding; PLAY0380 covers only all inside children/nested. No new render/runtime probe. Prior: Cratis/AI#769: standalone Screenplay 4.212.3 pinned; regenerated compiler contract is byte-identical to the v4.212.3 release asset. Source-checked both compilers and projection documentation for PLAY0801 DuplicateEventInProjectionScope: shared from/removal/clear set, separate join set, fresh sets per children/nested/variant level, and no two-row update through repeated from blocks with different keys. No new render/runtime probe. Prior: Cratis/AI#768: standalone Screenplay 4.212.2 pinned; regenerated compiler contract is byte-identical to the v4.212.2 release asset (unchanged from the previous contract). Source-checked v4.212.0 split-model dotted note targets, open-workspace applicationIdentity and complete add/reanchor substitutions; unbound container identities are not claimed. v4.212.1 aligns PLAY0535 collection fields, optional parameters and single-result identity inference. v4.212.2 counts read-only query denials for SPEC004, not SPEC006. No new render/runtime probe. Prior: Cratis/AI#762 and #761: source-checked v4.210.0 and v4.211.0 contracts for PLAY0800 CommandHandlerRequiresAttachment (required typed subject, permanent code-attachment requirement, other PLAY0268 families unchanged), independent reference remove/add batches, located same-text ambiguity conflicts and string MCP conflict/move-report document fields. v4.211.1 mapping changes inspected but excluded from this guidance update at the user's request; no typed PLAY0273 property/type arguments are claimed. Standalone Screenplay 4.211.1 and its compiler contract pinned; the contract is a byte-identical copy of the v4.211.1 release asset. No new render/runtime probe. Prior: Standalone 4.205.0 and byte-identical compiler contract pinned. Cratis/AI#746: Uuid ==/!= in command require and produces when (ESM v28): same-concept rule, bare Uuid against a concept, canonical literals, protected read paths in require only; PLAY0268 (different concepts, ordering, Uuid validation and concept rules, read paths in produces when) and PLAY0273 (non-canonical literal) checked against the 4.205.0 compiler, v28 selection read from the MCP executable-model view; Stage admits exact v1-v21 and v23-v26 pairs so v28 is refused STAGE-ESM-016, not probed against a Stage image; CLI 3.74.0 renders through v26. Prior: Standalone 4.204.0 and byte-identical compiler contract pinned. Cratis/AI#702 and #691: PLAY0690 reducer identity (Screenplay 4.170.0, native compiler only) and the screenplay.json validation gate (Screenplay 4.165.0; cratis screenplay validate reads it from CLI 3.65.0) are taught and probed against the 4.204.0 compiler. Cratis/AI#743: flat composite read-model keys (ESM v27): untyped projection key blocks on root from and remove with, equality-filter lists, single-instance by blocks and per-part fixtures, with PLAY0661/PLAY0662/PLAY0268 refusals checked against the 4.204.0 compiler; Stage origin/main still refuses v27 with STAGE-ESM-016 (stage-rendering.md); Stage v4.135.0 v26 admission (Host and executor run date comparisons; renderer STAGE-ESM-046) was source-checked for this sync; no render or runtime probe. Prior: Standalone 4.201.0 and byte-identical compiler contract pinned. Cratis/AI#733: the ui profile root template, shell options, appearance and new screens default (PLAY0788-PLAY0799, quick fix for the legacy layout line, ui-profiles MCP tool, 44 tools). Cratis/AI#735: chronological Date/DateTime ordering in command conditions and command/property literal validation (ESM v26), UTC tick precision and pre-rule offset validation; then matching remains ordinal. Source-checked Screenplay v4.199.0 commands, diagnostics, interoperability and specifications documentation plus decision 0087. Stage v4.127.1 still refuses v26 with STAGE-ESM-016 (stage-rendering.md and SemanticVersionFeatures.Supports); no render/runtime probe. Cratis/AI#576: prior mechanical compiler catch-up. Language batch #717/#722/#723/#724/#720/#728/#734 teaches atomic reaction batches (v22), described payload handlers (v23), portable linear matching, ordinal text rules (v24), protected command reads (v25), diagnostic arguments and event-source invokes mappings. Facts read at Screenplay v4.198.0 and introducing tags; Stage v4.127.0 admits exact v1-v21 and v23-v25 pairs but refuses v22/v26 and mixed pairs (STAGE-ESM-016), protected reads (044), atomic mode (043) and described handlers (STAGE-IMPL-002), even Stub mode. Stage text rules execute/render; no new renderer/runtime probe or Stage pin uplift. Cratis/AI#706: application navigation regions (module inherit, extend or override), toolbar slice buttons, blueprint template references and sample data packs in cratis-screenplay-ui-composition (references/application-shell.md), with the canonical shell vector and the rejection codes PLAY0710-PLAY0722 and PLAY0740-PLAY0765. Examples moved to the executable-state rules since 4.164: translator reactions in an Automation slice beside the Translate slice (PLAY0694) and the first record of a capture key appended with `when added`. Earlier: Standalone 4.164.0 and byte-identical compiler contract pinned. Cratis/AI#663: one origin per capture (PLAY0687). #668: executable no-event/redelivery v17. #684: concept query-argument validation in every version and query-error assertions v18. #681: executable refusal branches and refusal values v19. #666: proposal summary/severity counts and exact structural source proposals. Generated-concept rules select v20 with PLAY0688/0689 proofs and derived-matches repair; generated secrets and preview strategies remain refused. Release-baseline from-esm admission reads storedName. Standalone binding is not renderer admission: Stage 4.103.0 admits v1-v17 and v19; CLI 3.62.0 bundles Screenplay 4.159.0 / Stage 4.99.0 and renders through v16. Prior evidence remains unless superseded; no new renderer, Docker or browser probe."
205
205
  },
206
206
  {
207
207
  "id": "scene",
@@ -284,9 +284,9 @@
284
284
  }
285
285
  ],
286
286
  "synced": {
287
- "version": "19.65.0",
288
- "date": "2026-10-14",
289
- "by": "Cratis/AI#695"
287
+ "version": "19.81.1",
288
+ "date": "2026-10-17",
289
+ "by": "Cratis/AI#773"
290
290
  },
291
291
  "covers": {
292
292
  "skills": [
@@ -323,7 +323,7 @@
323
323
  ],
324
324
  "rules": []
325
325
  },
326
- "notes": "Whole-product floor unchanged at 19.65.0. Focused read-protection coverage, Chronicle 19.68.0-19.71.x: admitted reducers (unfiltered, no constructor dependencies, 19.68.0), per-stream read models with [EventStream<TSource>], IUnitOfWork.EnforceReadProtection, AllowReads and GetAppendConditions, CHR0062-CHR0064. The other 19.66.0-19.71.x changes were not reviewed. Prior notes: explicit artifacts, collection observation, redelivery scenarios, webhook generation pins, enrollment contributors, seed ownership, reconnect readiness and hosting/storage fixes. No new kernel/transport probe."
326
+ "notes": "Reviewed releases 19.65.1-19.81.1 at tags: subscription generation pins, StartAtTail, namespace removal/reconnect, storage connection resolution (deploy 19.74.2+), definition refusal recovery, conflict event fields, .NET occurrences/lifecycle/receipts and testing identities, full-history per-key reads, child all-event mapping repair, projection SoftwareVersion, bounded job acceptance/recovery, immediate-append refusal ownership and namespace subscription reconciliation. Existing protected-read guidance retained. Chronicle#5028 definition round-trip/restart-replay fix is unreleased and not taught as fixed. No new kernel/transport probe."
327
327
  },
328
328
  {
329
329
  "id": "arc-go",
@@ -29,6 +29,8 @@ Use portable fields: `name`, `description`, `license`, `compatibility`, `metadat
29
29
 
30
30
  An explicit trigger clause (`Use when`, `Load when`, `Read when` or an equivalent) and neutral voice are required even with `SKILL_AUTHORING_MODE=warn`. Negative routing and meta-language findings follow that switch; the 700-character target is guidance, not a gate.
31
31
 
32
+ The overlap lint warns when positive trigger token sets have Jaccard similarity (intersection / union) **>= 0.4**, compared before rounding. It lowercases ASCII word tokens, deduplicates them and removes routing boilerplate and common function words. Only the explicit `Use when` (or equivalent) clause counts, stopping at negative routing; empty triggers never match. The warning stays advisory even in strict mode: shared vocabulary is a review signal, not proof of competing scope. Sharpen the trigger and add a sibling pointer rather than padding it with unrelated words.
33
+
32
34
  ## 3. Budget and progressive disclosure
33
35
 
34
36
  Target at most 400 body lines and 16,000 characters; the hard limits remain 500 lines and 20,000 characters. A warning starts above the 16,000-character target, so a body that outgrows it is split before it nears the hard limit; characters only approximate tokens.
@@ -40,5 +40,9 @@ Levels of Authority in [`general.md`](./general.md).
40
40
  - **[contract] Absent authority for a consequential effect, stop and ask about that
41
41
  effect in plain language.** State the exact target, action, consequence, and recovery;
42
42
  a missing answer is a blocker for that effect, not for unrelated in-scope work.
43
+ - **[contract] Never copy secrets or personal values into models, notes, state,
44
+ packets or briefs.** Never use real credentials or personal data in examples.
45
+ - **[contract] Legacy extraction uses Git read-only:** never checkout, reset or stash
46
+ the legacy repository; do not touch a live checkout the brief excludes.
43
47
  - **[convention] Prefer the narrowest capability that does the job.** Reaching for the
44
48
  broadest available grant makes the next reader assume it was authorized.
@@ -67,6 +67,8 @@ Migrations are created and applied with the **standard EF Core tooling** (`dotne
67
67
  | `table.JsonColumn<TProperty>(migrationBuilder, …)` | a `[Json]`-mapped property |
68
68
  | `migrationBuilder.Add{String,Guid,Number,Bool,DateTimeOffset,AutoIncrement,Json,Point,LineString,Polygon}Column(…)` | adding a column to an existing table |
69
69
 
70
+ A migration that is committed or applied to any database is append-only: never edit or delete it. Correct mistakes with a new migration. Only an unapplied, uncommitted migration may be removed with `dotnet ef migrations remove` and regenerated.
71
+
70
72
  Where a repository organizes its migrations (a dedicated project, a versioned file naming scheme, a table-name constants class) is its own convention: follow what the repository already does, and do not introduce one as if Arc required it.
71
73
 
72
74
  ## Concepts and JSON **[contract]**
@@ -167,6 +167,7 @@ A claim is only as good as the signal behind it — a build result, a test run,
167
167
  ## Source-of-Truth Discipline
168
168
 
169
169
  - **Rules define invariants; skills define workflows.** A skill may refine how to apply a rule but must not contradict it. On conflict, follow the stricter invariant and fix the stale artifact.
170
+ - The user's instructions take precedence over guidelines provided in a skill. This does not override safety rules or hooks; skills must still follow rules.
170
171
  - **Skills and rules are the authoritative answer.** If not answered there, ask. Don't infer Cratis behavior from package internals.
171
172
  - Only make high-confidence suggestions.
172
173
  - When a user asks how to get help, has a question not answered by the docs, or wants to discuss design, point them to the [Cratis Discord](https://discord.gg/kt4AMpV8WV); direct confirmed bugs to GitHub issues.
@@ -256,15 +256,17 @@ public record AuthorRegistered(AuthorName Name);
256
256
 
257
257
  ## Read Models and Queries
258
258
 
259
- **[contract]** `[ReadModel]` records expose queries as `public static` methods; dependencies are plain method parameters (no `[FromServices]`). For application code, start with model-bound mappings, use fluent when the definition needs structure, and choose reducer code when transitions read better as code. For step-by-step creation, invoke the **cratis-chronicle-read-model** skill.
259
+ **[contract]** `[ReadModel]` records expose eligible public and internal static methods as queries; internal visibility does not hide an endpoint. Dependencies are plain method parameters (no `[FromServices]`). For application code, start with model-bound mappings, use fluent when the definition needs structure, and choose reducer code when transitions read better as code. For step-by-step creation, invoke the **cratis-chronicle-read-model** skill.
260
260
 
261
261
  Use `[ReadModel(RequireQueryAttribute = true)]` with `[Query]` on intended
262
- endpoints when public folds/helpers exist (ARC0026/ARCCHR0019). `[Query]` alone
263
- does not hide siblings; private/compiler-generated statics are never queries.
262
+ endpoints when folds exist (ARC0026/ARCCHR0019). `[Query]` alone does not hide
263
+ siblings. Keep helpers outside the read model regardless of visibility.
264
+ Requires Arc 22.27.1 for private/protected/compiler-generated methods to be
265
+ excluded; older versions can expose private statics too. Check `dotnet list package`.
264
266
  A `CancellationToken` is supplied by Arc; concept arguments come from the caller,
265
267
  not DI. Bad GET/QUERY argument conversions return 400. Single-instance MongoDB/EF
266
268
  observations emit `default` on absence/deletion/filter exit: guard `hasData` and
267
- `isReady` in React. Verified at Arc v22.75.0; see the read-model query reference.
269
+ `isReady` in React; see the read-model query reference.
268
270
 
269
271
  ### Query return shapes **[contract]**
270
272
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: cratis-application-react-specifications
3
- description: Write specifications for the React and TypeScript surface of a Cratis application slice — view models, helpers, command orchestration, and narrow component behavior — using Vitest with Mocha-style describe/it, Sinon, and the Chai should interface. Use when adding or changing frontend behavior in an application that consumes Cratis. Do not use for backend scenarios or for specifications inside a Cratis framework package.
3
+ description: Write specifications for the React and TypeScript surface of a Cratis application slice — view models, helpers, command orchestration, and narrow component behavior — using Vitest with Mocha-style describe/it, Sinon, and the Chai should interface. Use when specifying React view-model decisions, frontend command orchestration or narrow component interactions with Vitest, Sinon and Chai. Do not use for backend pipeline scenarios (use cratis-application-slice-specifications) or framework package specs (use cratis-specifications-typescript).
4
4
  license: MIT
5
5
  metadata:
6
6
  cratis-hint-paths: "**/for_*/**/*.ts **/for_*/**/*.tsx"
@@ -12,9 +12,9 @@ Frontend specifications are specifications, not tests. The `for_ / when_ / and_`
12
12
  shape is deliberately the same BDD language as the backend, so one subject, one
13
13
  context, clear setup, and small assertions read as sentences.
14
14
 
15
- This is the **application** frontend peer of the backend slice specification
16
- skill. Specifications for a Cratis framework package (`@cratis/*`) follow that
17
- repository's own TypeScript specification conventions instead.
15
+ This is the **application** frontend peer of `cratis-application-slice-specifications`
16
+ for backend pipeline scenarios. Framework package (`@cratis/*`) specifications
17
+ use `cratis-specifications-typescript` and the repository's conventions instead.
18
18
 
19
19
  ## Stack
20
20
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: cratis-application-slice-specifications
3
- description: Specify the backend behavior of an event-sourced Cratis application slice — plain-call specs for pure decisions, plus CommandScenario, EventScenario, ReadModelScenario and ReactorScenario where the pipeline, validation, constraints or projections matter — including what to cover for each slice type and where the specification files live. Use when adding or changing backend behavior in an application built on Cratis. Do not use for framework library specifications and do not use for frontend behavior.
3
+ description: Specify the backend behavior of an event-sourced Cratis application slice — plain-call specs for pure decisions, plus CommandScenario, EventScenario, ReadModelScenario and ReactorScenario where the pipeline, validation, constraints or projections matter — including what to cover for each slice type and where the specification files live. Use when choosing backend plain-call coverage versus CommandScenario, EventScenario, ReadModelScenario or ReactorScenario for an event-sourced slice. Do not use for frontend interactions (use cratis-application-react-specifications) or framework unit-spec mechanics (use cratis-specifications-csharp).
4
4
  license: MIT
5
5
  metadata:
6
6
  cratis-hint-paths: "**/when_*/**/*.cs **/for_*/**/*.cs"
@@ -217,6 +217,15 @@ MVC actions). Configure both: the evaluator for the Arc pipeline, `FallbackPolic
217
217
  for MVC. Neither protects an endpoint that is mapped explicitly anonymous (see the
218
218
  discovery endpoints in the skill).
219
219
 
220
+ Requires Arc 22.116.0 for hub subscriptions to apply the host's endpoint fallback
221
+ before running an unannotated query: ASP.NET Core evaluates `FallbackPolicy`,
222
+ and Arc Core requires authentication when authentication handlers are registered.
223
+ `IEndpointFallbackAuthorization` supplies this host check; it is separate from
224
+ `IFallbackAuthorizationEvaluator`. `[AllowAnonymous]` and guest-policy queries
225
+ remain exempt. Denial sends an Unauthorized frame; SSE subscribe returns 401.
226
+ Check with `dotnet list package`; on older Arc do not rely on host fallback alone
227
+ to secure the hub path.
228
+
220
229
  ## Default access by hosting model
221
230
 
222
231
  There is no `ArcOptions` switch for a default requirement. What you get depends
@@ -44,7 +44,15 @@ Arc API, and never an always-true stub.
44
44
  It runs on **every emission** of **every subscription**, on **every transport**:
45
45
  the multiplexed hub, WebSocket and SSE.
46
46
 
47
- Requires Arc 22.69.1 for guards and read-model interceptors on plain HTTP snapshots, waits and long polls; on an older Arc those requests are not guarded.
47
+ Requires Arc 22.69.1 for guards and read-model interceptors on plain HTTP snapshots
48
+ of observable queries, waits and long polls; on an older Arc those requests are not guarded.
49
+
50
+ Requires Arc 22.116.0 for **non-observable** query results performed through the
51
+ hub to run emission guards. Such a result has `IsSnapshot = true` and
52
+ `IsFirstEmission = true`. `Suppress` withholds the result (SSE subscribe still
53
+ returns 200); denial sends Unauthorized (SSE subscribe returns 401). Ordinary
54
+ non-observable direct HTTP queries do not run these guards. Check with
55
+ `dotnet list package`; on older Arc secure hub snapshots without relying on a guard.
48
56
 
49
57
  Source: [ObservableQueryHttp.cs](https://github.com/Cratis/Arc/blob/main/Source/DotNET/Arc.Core/Queries/ObservableQueryHttp.cs).
50
58
 
@@ -63,7 +71,7 @@ Several guards: every guard is asked, the **most restrictive** verdict wins
63
71
  ## The context
64
72
 
65
73
  `ObservableQueryEmissionContext` carries `QueryName`, `Arguments`,
66
- `SubscriptionScope`, `Principal`, `CorrelationId`, `IsFirstEmission`,
74
+ `SubscriptionScope`, `Principal`, `CorrelationId`, `IsFirstEmission`, `IsSnapshot`,
67
75
  `CancellationToken` and the `ServiceProvider` to resolve from. Each guard gets its
68
76
  own copy of the scope and arguments.
69
77
 
@@ -108,7 +116,8 @@ a failure.
108
116
 
109
117
  ## What a guard does not protect
110
118
 
111
- - Plain HTTP **is** guarded (Requires Arc 22.69.1; older versions leave it unguarded): suppression returns 202 until an allowed
119
+ - Plain HTTP **observable-query** snapshots are guarded (Requires Arc 22.69.1;
120
+ older versions leave them unguarded): suppression returns 202 until an allowed
112
121
  emission (or the wait deadline), denial returns unauthorized with no data.
113
122
  Keep safe data selection and initial
114
123
  authorization on every query regardless of transport.
@@ -61,6 +61,17 @@ Requires Arc 22.106.0 for read protection. Older Arc has only the per-command
61
61
  `[Unprotected("why")]` (`Cratis.Arc.Chronicle.ReadModels`; on a method it covers
62
62
  the body, not injected parameters), or repair with a reactor.
63
63
 
64
+ Requires Arc 22.113.0 with Chronicle 19.76.0 for `ReadChanged` validation state
65
+ to include the conflicting event type/id and sequence number when the kernel
66
+ reports them. Older kernels can leave those details absent. Outside-decision
67
+ read-model injection (for example a custom command filter) is refused under
68
+ `On`; explicitly unprotected models stay advisory. Check `dotnet list package`
69
+ before asserting conflict detail fields.
70
+
71
+ Requires Arc 22.116.2 for aggregate application, rehydration and append to resolve
72
+ events from registrations, including explicitly registered types without an
73
+ `[EventType]` attribute. Unregistered events still fail; do not omit registration.
74
+
64
75
  Under `On`, `IReadModels`, `IMongoCollection`, detached reads and immediate appends
65
76
  through an injected `IEventLog` are refused; take the model as a parameter and
66
77
  return the events. Admitted models: event-source-keyed model-bound or declarative
@@ -23,6 +23,9 @@ Operation execution,
23
23
  nesting restrictions, and backend recovery members below are described in
24
24
  `cratis-arc-command-operation`, which lists sources and limits.
25
25
 
26
+ Read references/occurrence-commands.md when an occurrence handler must execute a
27
+ command under a stable effect name with an atomic receipt and retry classification.
28
+
26
29
  ## When this is the wrong tool
27
30
 
28
31
  `ICommandPipeline` is for **command-shaped** work that needs authorization and
@@ -0,0 +1,78 @@
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
+ # Execute a command for an occurrence
5
+
6
+ Requires Arc 22.117.0 and Chronicle client 19.77.2, plus a kernel advertising
7
+ `effect-receipts`. Check with `dotnet list package`; older Arc has no occurrence
8
+ executor. Do not substitute an ordinary pipeline call and claim durable deduplication.
9
+
10
+ ## Choose the executor
11
+
12
+ Inject `IOccurrenceCommandExecutor` from `Cratis.Arc.Chronicle.Occurrences` into
13
+ an occurrence handler. Its overloads are:
14
+
15
+ ```csharp
16
+ Task<OccurrenceCommandResult> Execute(
17
+ object command, OccurrenceContext occurrence, EffectName effectName,
18
+ CancellationToken cancellationToken = default);
19
+
20
+ Task<OccurrenceCommandResult> Execute(
21
+ object command, OccurrenceContext occurrence, EffectName effectName,
22
+ IEnumerable<string> systemRoles, CancellationToken cancellationToken = default);
23
+ ```
24
+
25
+ `OccurrenceContext` and `EffectName` are Chronicle occurrence types. Read
26
+ **cratis-chronicle-client-dotnet** for recording triggers and handling lifecycle
27
+ occurrences. Do not call the executor from inside another command.
28
+
29
+ The executor supplies a system principal; no caller roles are inherited. Supply
30
+ only the explicit roles the automation needs. The occurrence namespace must
31
+ match the resolved command tenant; a mismatch throws. Authorization still runs.
32
+
33
+ Give each logical effect a stable, unique name within the occurrence. Retrying
34
+ uses the same name. Reusing it for a different command returns the earlier
35
+ receipt, not the new command's result. A deliberately new attempt at a terminal
36
+ business refusal needs a new effect name.
37
+
38
+ ## Outcomes and retry
39
+
40
+ The executor checks for an existing receipt before running the pipeline. Its
41
+ receipt is committed atomically with the command's transactional events.
42
+
43
+ - `Recorded` and `AlreadyRecorded` are settled results. Their outcomes are
44
+ `Appended`, `NoEvents` or `Refused`.
45
+ - Validation, business-rule and append-constraint refusals are terminal and
46
+ recorded. Redelivery does not re-run the handler to reconsider them.
47
+ - Authorization failures, concurrency conflicts and exceptions are `Failed`
48
+ without a receipt, so a later delivery can retry. Reread and re-decide rather
49
+ than replaying stale events.
50
+ - The stored response is a minimal result, not a raw command response. It does
51
+ not preserve command values or validation messages. Never depend on a receipt
52
+ returning secret data or the original response object.
53
+
54
+ A receipt settles Chronicle effects, not arbitrary I/O. Two concurrent attempts
55
+ can both reach the handler before one wins the atomic commit. Use
56
+ `occurrence.EffectKey(effectName).Value` as the external service's idempotency
57
+ key where that service supports it; otherwise an external effect can repeat.
58
+
59
+ ## Keep all appends inside the boundary
60
+
61
+ Return events from the command, or use transactional appends. Do not complete a
62
+ stream or commit an aggregate early inside the executor's command.
63
+
64
+ An immediate append can commit **before** the executor detects it and reports
65
+ `OccurrenceCommandAppendedImmediately`. No receipt is recorded for that failed
66
+ attempt, so retry can duplicate the escaped append. The executor does not
67
+ implicitly provide Chronicle's `RefuseImmediateAppends()` guard. Read
68
+ **cratis-chronicle-client-dotnet**'s immediate-append refusal reference when
69
+ building a custom boundary that needs prevention before transport.
70
+
71
+ ## Verify
72
+
73
+ Use an in-process occurrence scenario with the command's real validation and
74
+ append behavior. Deliver the same occurrence twice under the same effect name:
75
+ assert one committed effect and a recorded result on the second delivery. Cover
76
+ a terminal refusal, a retryable concurrency conflict, insufficient capability,
77
+ and commit-then-lost-reply recovery. Run the owning specification project with
78
+ `dotnet test`; passing means those assertions ran, not just that compilation succeeded.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: cratis-arc-command-validation
3
- description: Add a rejection rule to an existing Arc command — choosing between ConceptValidator, CommandValidator, a short-circuiting Provide, and a read-model-injected Handle returning a Result of either the event or a ValidationResult. Use when a command must refuse work under some condition. Do not use to define a new command, and do not use for append-time Chronicle constraints.
3
+ description: Add a rejection rule to an existing Arc command — choosing between ConceptValidator, CommandValidator, a short-circuiting Provide, and a read-model-injected Handle returning a Result of either the event or a ValidationResult. Use when placing a C# business rejection in ConceptValidator, CommandValidator, Provide() or a Handle() result containing ValidationResult. Do not use for JVM validators (use cratis-arc-validation-kotlin), Node.js ruleFor (use cratis-arc-validation-typescript), new commands (use cratis-arc-command), or append-time uniqueness (use cratis-chronicle-event-constraints).
4
4
  license: MIT
5
5
  ---
6
6
 
@@ -130,17 +130,11 @@ public class TransferFundsValidator : CommandValidator<TransferFunds>
130
130
  instance validators are refused. Under `[ProtectedDecision]` without `On`, a
131
131
  discoverable validator needs exactly one public parameterless constructor
132
132
  (otherwise HTTP 500).
133
- - **The caller can lower the severity threshold.** Model-bound commands accept
134
- `X-Allowed-Severity` (`allowedSeverity`). Under `Off` and `Measure`, a caller
135
- sending `3` (Error) removes Error results from validators, command filters and
136
- `Provide()`, so `Handle()` runs and a validator's state rule can be skipped
137
- unless the command declares
138
- `[BlockOnValidationSeverity(ValidationResultSeverity.Error)]`
139
- (`Cratis.Arc.Commands.ModelBound`). Requires Arc 22.108.0 for the `On` floor: a
140
- command declared `On` blocks `Error` and `Unknown` whatever the caller sends; the
141
- caller can relax only `Warning` and `Information`. Lowering
142
- `ReadProtection:MaximumMode` at runtime does not remove the floor, and an explicit
143
- attribute wins. Severity is not authorization.
133
+ - **The caller can lower the severity threshold.** Under `Off`/`Measure`, pin
134
+ `[BlockOnValidationSeverity(ValidationResultSeverity.Error)]` when Error rules
135
+ must block. Requires Arc 22.108.0 for commands declared `On` to keep an Error
136
+ floor. Read references/validation-severity.md when choosing that threshold;
137
+ severity is not authorization.
144
138
  - **Omit the validator entirely when there are no rules.** An empty subclass is
145
139
  noise the reader has to check.
146
140
  - Single-property intrinsic rules belong on `ConceptValidator<T>` instead, so
@@ -258,32 +252,12 @@ public Result<ItemAddedToCart, ValidationResult> Handle(CartSummary? cart) =>
258
252
  - Keep the fetch for a *computed* key in `Provide()` with `IDecisionReads.Get`;
259
253
  under `On`, `IReadModels` there is refused.
260
254
 
261
- ⚠️ **Two things the resolution does *not* do.** It does not key off the
262
- `[ReadModel]` attribute — a read model becomes injectable because a Chronicle
263
- projection or reducer, an EF Core `DbSet<T>`, or a MongoDB collection backs it.
264
- And there is **no slice or feature restriction**: registration is global by
265
- type, so "the read model must be in the same slice" is a convention with nothing
266
- enforcing it.
255
+ Read references/read-model-resolution.md when choosing lookup keys, handling a
256
+ missing injected model, or distinguishing registration from slice conventions.
267
257
 
268
- The resolution is **by the command's resolved event-source id**, not by the
269
- read-model type and not by "the property that looks like its key". If the
270
- instance you need is keyed by anything else — a referenced other entity, a
271
- command with more than one candidate identity, or an id generated inside
272
- `Handle()` — direct injection hands you the wrong instance or none. Read by
273
- explicit key in `Provide()` instead:
274
-
275
- ```csharp
276
- var other = await readModels.GetInstanceById<Other>((EventSourceId)otherId);
277
- ```
278
-
279
- A missing instance resolves to `null`, never to a default object. A nullable
280
- parameter receives that `null`; a non-nullable one is **rejected as a validation
281
- failure (400)**, not crashed. `ARC0006` warns on a non-nullable command-scoped
282
- read-model parameter for exactly this reason. Handle a nullable parameter by rejecting (a validator,
283
- `Provide()`, or `Result<TEvent, ValidationResult>`), never by returning a
284
- nullable event from `Handle()`. `cratis-arc-command` carries the
285
- full resolution and nullability reference, including the passive-projection case
286
- where absence is *not* `null`.
258
+ Read references/input-binding.md when accepting date-time input or returning
259
+ member-bound validation results: offset requirements, malformed-body
260
+ authorization and camelCase member paths are separate contracts.
287
261
 
288
262
  ## Step 6 — Specify the rejection
289
263
 
@@ -0,0 +1,49 @@
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
+ # Command input binding and member paths
5
+
6
+ ## Explicit offsets
7
+
8
+ Requires Arc 22.110.0. Check with `dotnet list package`; older Arc has no
9
+ `[ExplicitOffset]` binding contract. Require an explicit offset at the input
10
+ boundary instead of accepting a server-local interpretation.
11
+
12
+ Use `[property: ExplicitOffset]` on a `DateTimeOffset` or `DateTime` command
13
+ property, nullable or not. It refuses date-time text without an offset or `Z`
14
+ with `DateTime command property '<member>' requires an explicit offset or Z.`
15
+ `DateTimeOffset` retains the input offset; `DateTime` becomes UTC. The attribute
16
+ is in `Cratis.Arc.Commands`.
17
+
18
+ ## Malformed bodies still authorize
19
+
20
+ Requires Arc 22.110.0 for authorization-before-binding-failure handling on
21
+ execute and `/validate`. An unauthorized caller gets 403 even if the body is
22
+ malformed; an authorized caller gets a `malformedRequest` validation result.
23
+ Its message is generic, and its member is a normalized field path such as
24
+ `from` or `items[2].when`, not parser or CLR type details.
25
+
26
+ A resource-dependent policy cannot run without a bound command; those policies
27
+ still produce a binding validation failure for an unbindable body. Requirements
28
+ that never read the resource may implement
29
+ `Cratis.Arc.Authorization.IResourceFreeRequirement` so their
30
+ policies can run; built-in role, claim, name and authenticated-user requirements
31
+ are already resource-free. Do not mark a requirement resource-free if it reads
32
+ the command.
33
+
34
+ ## Validation members are field paths
35
+
36
+ Requires Arc 22.115.0 for **all** `ValidationResult.Members` paths to be
37
+ camelCase, including data annotations and errors returned by `Provide()` or
38
+ `Handle()`. Use `name`, `address.street` and `items[0].name` in server assertions,
39
+ not `nameof(Property)` or PascalCase paths. Authors may still construct a result
40
+ with `[nameof(Property)]`; Arc normalizes it before clients receive it. Older
41
+ Arc can fail to bind such results to the matching form field.
42
+
43
+ ## Verify
44
+
45
+ Add specs for offset-less rejection, an accepted offset, malformed input under
46
+ both authorized and denied callers, and nested/indexed member paths. Assert
47
+ server `Members` using camelCase and run `dotnet test` on the owning spec project.
48
+ For form behavior, assert the rejection appears on its intended field, not only
49
+ in a command-wide error list.
@@ -0,0 +1,25 @@
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
+ # Read-model resolution for validation
5
+
6
+ Resolution does not key off `[ReadModel]`: a model becomes injectable because a
7
+ Chronicle projection or reducer, an EF Core `DbSet<T>`, or a MongoDB collection
8
+ backs it. Registration is global by type; keeping a model in the slice is a
9
+ convention, not a resolver restriction.
10
+
11
+ The default lookup uses the command's resolved event-source id. It does not
12
+ infer a key from the read-model type or an arbitrary similarly named property.
13
+ Use `[LookUpBy(nameof(Command.Property))]` for a command-property key; for a
14
+ computed key use `IDecisionReads.Get` in `Provide()` under read protection `On`.
15
+ An ordinary `IReadModels.GetInstanceById` there is refused under `On`; outside
16
+ protected work it is an advisory read, not a consistency guard.
17
+
18
+ A missing instance resolves to `null`, not a default object. A nullable parameter
19
+ receives that null; a non-nullable one produces a validation failure (400).
20
+ `ARC0006` warns on a non-nullable command-scoped read-model parameter. Reject a
21
+ missing nullable model through a validator, `Provide()` or
22
+ `Result<TEvent, ValidationResult>`; do not return a nullable event.
23
+
24
+ Read **cratis-arc-command** for the full resolution and nullability reference,
25
+ including passive projections where absence is not null.
@@ -0,0 +1,21 @@
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
+ # Choose which severities block
5
+
6
+ Model-bound commands accept `X-Allowed-Severity` (`allowedSeverity`). Under
7
+ read protection `Off` and `Measure`, a caller sending `3` (Error) removes Error
8
+ results from validators, command filters and `Provide()`, so `Handle()` runs
9
+ and a validator's state rule can be skipped unless the command declares
10
+ `[BlockOnValidationSeverity(ValidationResultSeverity.Error)]`
11
+ (`Cratis.Arc.Commands.ModelBound`). Severity is not authorization.
12
+
13
+ Requires Arc 22.108.0 for the `On` floor: a command declared `On` blocks `Error`
14
+ and `Unknown` whatever the caller sends; the caller can relax only `Warning`
15
+ and `Information`. Lowering `ReadProtection:MaximumMode` at runtime does not
16
+ remove the floor, and an explicit attribute wins. Check with
17
+ `dotnet list package`; on older Arc declare the blocking severity explicitly.
18
+
19
+ Specify both the default refusal and a caller sending a permissive severity.
20
+ Assert the command did not write events; a displayed message alone is not proof
21
+ that validation blocked execution. Run `dotnet test` on the owning spec project.