@cratis/pi 7.112.0 → 7.114.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 (57) hide show
  1. package/package/corpus/harnesses/copilot/instructions/application-profile.instructions.md +1 -1
  2. package/package/corpus/harnesses/copilot/instructions/orleans.instructions.md +10 -2
  3. package/package/corpus/harnesses/copilot/instructions/pull-requests.instructions.md +7 -0
  4. package/package/corpus/harnesses/copilot/instructions/specs.csharp.instructions.md +4 -4
  5. package/package/corpus/harnesses/copilot/instructions/vertical-slices.instructions.md +1 -1
  6. package/package/corpus/hooks/scripts/cratis-store-mutations.json +4 -0
  7. package/package/corpus/product-sync.json +88 -88
  8. package/package/corpus/rules/application-profile.md +1 -1
  9. package/package/corpus/rules/orleans.md +10 -2
  10. package/package/corpus/rules/pull-requests.md +7 -0
  11. package/package/corpus/rules/specs.csharp.md +4 -4
  12. package/package/corpus/rules/vertical-slices.md +1 -1
  13. package/package/corpus/skills/cratis-application-slice-specifications/references/query-and-decision-scenarios.md +19 -0
  14. package/package/corpus/skills/cratis-arc-authentication-authorization-and-identity/SKILL.md +8 -0
  15. package/package/corpus/skills/cratis-arc-authentication-authorization-and-identity/references/authproxy.md +26 -0
  16. package/package/corpus/skills/cratis-arc-command/references/proxy-generation.md +10 -1
  17. package/package/corpus/skills/cratis-arc-command-execution/SKILL.md +3 -2
  18. package/package/corpus/skills/cratis-arc-command-execution/references/occurrence-commands.md +7 -6
  19. package/package/corpus/skills/cratis-arc-command-validation/SKILL.md +5 -0
  20. package/package/corpus/skills/cratis-arc-command-validation/references/input-binding.md +17 -0
  21. package/package/corpus/skills/cratis-arc-command-validation/references/protected-validator-construction.md +94 -0
  22. package/package/corpus/skills/cratis-arc-ef-core-migration/SKILL.md +18 -0
  23. package/package/corpus/skills/cratis-arc-query-paging/SKILL.md +11 -4
  24. package/package/corpus/skills/cratis-arc-query-paging/references/live-query-processing.md +71 -0
  25. package/package/corpus/skills/cratis-arc-react-page/SKILL.md +11 -0
  26. package/package/corpus/skills/cratis-arc-validation-kotlin/SKILL.md +20 -3
  27. package/package/corpus/skills/cratis-chronicle-cli-operations/SKILL.md +11 -2
  28. package/package/corpus/skills/cratis-chronicle-cli-operations/references/command-effects.md +7 -0
  29. package/package/corpus/skills/cratis-chronicle-cli-operations/references/project-tooling.md +91 -0
  30. package/package/corpus/skills/cratis-chronicle-cli-operations/references/recovery-and-comparison.md +68 -0
  31. package/package/corpus/skills/cratis-chronicle-client-elixir/SKILL.md +12 -0
  32. package/package/corpus/skills/cratis-chronicle-client-elixir/references/decision-reads.md +10 -0
  33. package/package/corpus/skills/cratis-chronicle-client-go/SKILL.md +12 -2
  34. package/package/corpus/skills/cratis-chronicle-client-kotlin/SKILL.md +4 -0
  35. package/package/corpus/skills/cratis-chronicle-client-kotlin/references/annotations-and-handlers.md +6 -1
  36. package/package/corpus/skills/cratis-chronicle-client-kotlin/references/fundamentals-migration.md +48 -0
  37. package/package/corpus/skills/cratis-chronicle-client-typescript/SKILL.md +18 -0
  38. package/package/corpus/skills/cratis-chronicle-client-typescript/references/lifecycle.md +7 -0
  39. package/package/corpus/skills/cratis-chronicle-read-model/references/queries.md +5 -3
  40. package/package/corpus/skills/cratis-cli-terminal-workbench/SKILL.md +5 -1
  41. package/package/corpus/skills/cratis-components-common-controls/SKILL.md +11 -0
  42. package/package/corpus/skills/cratis-components-data-surfaces/SKILL.md +5 -0
  43. package/package/corpus/skills/cratis-components-data-surfaces/references/query-table-updates.md +51 -0
  44. package/package/corpus/skills/cratis-components-schema-editor/references/tree-layout.md +18 -0
  45. package/package/corpus/skills/cratis-components-stepper-command-dialog/SKILL.md +11 -0
  46. package/package/corpus/skills/cratis-fundamentals-type-discovery/SKILL.md +13 -0
  47. package/package/corpus/skills/cratis-orleans-jobs/SKILL.md +39 -51
  48. package/package/corpus/skills/cratis-orleans-jobs/references/lifecycle-and-placement.md +52 -0
  49. package/package/corpus/skills/cratis-orleans-jobs/references/state-machines.md +3 -1
  50. package/package/corpus/skills/cratis-release-notes/SKILL.md +23 -0
  51. package/package/corpus/skills/cratis-screenplay-command-surface/references/protected-reads.md +3 -2
  52. package/package/corpus/skills/cratis-screenplay-legacy-extraction/references/prologue-safety.md +14 -0
  53. package/package/corpus/skills/cratis-screenplay-toolchain/references/screenplay-contract.version +1 -1
  54. package/package/corpus/skills/cratis-specifications-csharp/SKILL.md +14 -2
  55. package/package/corpus/skills/cratis-specifications-csharp/references/running-specs.md +8 -1
  56. package/package/corpus/skills/cratis-specifications-csharp/references/shared-lifecycle.md +19 -2
  57. package/package.json +1 -1
@@ -67,7 +67,7 @@ Tagged **[contract]** (framework-enforced) or **[convention]** (house default).
67
67
 
68
68
  ## Implementation Workflow
69
69
 
70
- - **Starting a brand-new application:** scaffold it instead of hand-writing the skeleton: `dotnet new install Cratis.Templates`, then `dotnet new cratis -n MyApp -o MyApp` (`--language Kotlin|Java`, `--Database MongoDB|PostgreSQL|MsSql|SQLite`; `cratis-aspire` for Aspire; `cratis-chronicle-console` or `cratis-chronicle-web` for a Chronicle client only). Non-interactive runs need `--allow-scripts yes`; the .NET templates target `net10.0`. The template writes `.cratis/ai.json`; run `cratis ai update` afterwards. Its `SomeModule/SomeFeature/Registration/` slice is the house shape. There is no Go, Python or Elixir template (verified at Cratis.Templates `v1.7.4`).
70
+ - **Starting a brand-new application:** scaffold it instead of hand-writing the skeleton: `dotnet new install Cratis.Templates`, then `dotnet new cratis -n MyApp -o MyApp` (`--language Kotlin|Java`, `--Database MongoDB|PostgreSQL|MsSql|SQLite`; `cratis-aspire` for Aspire; `cratis-chronicle-console` or `cratis-chronicle-web` for a Chronicle client only). Non-interactive runs need `--allow-scripts yes`; the .NET templates target `net10.0`. The template writes `.cratis/ai.json`; run `cratis ai update` afterwards. Its `SomeModule/SomeFeature/Registration/` slice is the house shape. There is no Go, Python or Elixir template (verified at Cratis.Templates `v1.8.1`). Since 1.8.0 the `cratis` and `cratis-aspire` .NET app projects emit `<CratisReadProtection>On</CratisReadProtection>`: read models supplied to commands and validators guard the append. Existing apps are not changed by reinstalling the templates.
71
71
  - **Phase 0 — Find the contract / choose the level.** Before writing slice code, find what the code must match, and choose the level once for the whole scope.
72
72
  1. **Look for a Screenplay model** under the model root (opted in per `general.md` "Model first"; where `cratis-screenplay-modeling-lifecycle` is installed, run its `scripts/model-first-status.mjs` for the decision, root and drafts) for the slice, command, event and read-model names.
73
73
  2. **Model level** — an accepted model under the root covers the scope, or the repository is opted in and this scope has no model yet. The `.play` slice and its specs are the contract: change the model first (new behavior starts in discovery), verify it (V1–V3), get an independent review, then render with Stage or gap-fill by hand only what the renderer rejects. Hand-written code stays checked against the model (**cratis-application-slice-conformance**). Never edit Stage-managed output, never implement behavior the model does not state, never change the model to match existing code, never weaken protection to make it compile or render. Start with **cratis-screenplay-event-modeling** (decision rule), then **cratis-screenplay-modeling-lifecycle**. If the Screenplay skills are not installed, say so; do not author `.play` from memory.
@@ -11,7 +11,7 @@ paths:
11
11
  > **⚠️ APPLIES ONLY TO PROJECTS USING MICROSOFT ORLEANS**
12
12
  > If your project does not reference `Microsoft.Orleans` or any Orleans packages, **ignore this entire file**. These rules are irrelevant outside of Orleans contexts.
13
13
 
14
- In the Cratis organization, Orleans is the Chronicle kernel's actor runtime (`Source/Kernel/`). The kernel conventions below are verified against `Cratis/Chronicle` **v19.50.0**. Shared hosting and jobs come from `Cratis/Orleans` **v1.16.3**; use its setup for other services that co-host a silo.
14
+ In the Cratis organization, Orleans is the Chronicle kernel's actor runtime (`Source/Kernel/`). The kernel conventions below are verified against `Cratis/Chronicle` **v19.50.0**. Shared hosting and jobs come from `Cratis/Orleans` **v1.30.0**; use its setup for other services that co-host a silo.
15
15
 
16
16
  ## General
17
17
 
@@ -50,7 +50,7 @@ framework/service guidance; they do not impose application slice architecture.
50
50
 
51
51
  For service authors, `Cratis.Orleans` supplies hosting, grain serializers, and the
52
52
  shared job system without requiring Chronicle. With `Cratis.Orleans` and
53
- `Cratis.Orleans.Storage.MongoDB` 1.16.3, this host uses durable MongoDB membership
53
+ `Cratis.Orleans.Storage.MongoDB` 1.30.0, this host uses durable MongoDB membership
54
54
  and jobs storage (a local MongoDB server is required):
55
55
 
56
56
  ```csharp
@@ -81,6 +81,14 @@ app.Run();
81
81
  - Register jobs storage separately: `AddCratisOrleansMongoDBJobsStorage`,
82
82
  `AddCratisOrleansSqlJobsStorage` (`Cratis.Orleans.Setup`), or
83
83
  `AddCratisOrleansInMemoryJobsStorage` (`Cratis.Orleans.Storage`).
84
+ - Use the local `IJobs` service to start/stop/delete typed jobs during rolling
85
+ upgrades; generic manager calls can land on a release that does not know the
86
+ type. Provide singleton `IJobsManagerKeys` on every silo for all host-owned
87
+ scope/namespace pairs; process-local discovery is not a recovery catalog.
88
+ - Controller and worker placement are separate opt-ins through `AddJobPlacement`
89
+ and `AddJobStepPlacement`. Enable them only after every silo supports the
90
+ strategies and register them identically. Worker throttling is not admission;
91
+ see **cratis-orleans-jobs** for drain-before-replacement and metadata limits.
84
92
  - Give grain implementations a unique `[GrainType("unique-name")]`. Orleans'
85
93
  default type name derives from the class name alone; a collision across
86
94
  assemblies prevents silo startup.
@@ -155,6 +155,13 @@ The test is **outward-facing effect, not file location**. A change under `Source
155
155
 
156
156
  A non-release pull request must satisfy the relevant required checks like any other. Confirm label acceptance and publication suppression against the current workflow contract; do not assume external CI or API state.
157
157
 
158
+ ### Release-action windows and workflow drift
159
+
160
+ Batching is opt-in; success with `batched` or `nothing-pending` is not publication.
161
+ Read **cratis-release-notes** before configuring windows, handling a pending-major
162
+ hotfix, or recovering a workflow-drift 403. Major confirmation remains required;
163
+ a workflow-drift recovery differs from the concurrent-tag retry above.
164
+
158
165
  ### Group small related changes into one pull request
159
166
 
160
167
  Do not open a pull request per task when the tasks belong to the same body of work. Several small merged PRs become several releases, and a stream of near-empty patch releases makes the release history useless for the people it is written for. Collect related work — a set of CI gates, a group of fixes in one area, the steps of one refactor — onto **one branch, as separate commits**, and open **one** pull request. Commits stay one-logical-unit-each; the pull request is the release boundary, and the release boundary should be a coherent, describable change. Joining an open candidate, folding superseded PRs and the cut are in `cratis-engineering-release-trains`.
@@ -46,13 +46,13 @@ public class when_combining_parts : Specification
46
46
  | `void Establish()` | setup, before `Because()` | each class in the chain has its own, run base-first — never call `base.Establish()` |
47
47
  | `void Because()` | the single action under test | only in concrete spec files, never in a reusable context |
48
48
  | `[Fact] void should_*()` | one assertion per fact | use the `ShouldXxx()` extension methods |
49
- | `void Destroy()` | teardown after each fact by default | once per eligible class with shared lifecycle opt-in |
49
+ | `void Destroy()` | teardown once per eligible class by default | after each fact when per-fact lifecycle is selected |
50
50
 
51
- The shared lifecycle is the default on xUnit v2 and v3 since 5.0; the package registers the framework, so delete any hand-written `[assembly: Xunit.TestFramework(...)]` (it fails with `CS0579`). Eligible classes derive from `Specification`, have one public parameterless constructor and contain only plain facts. Construction, Establish/Because and Destroy run once; all facts share the instance and must not mutate it. `IDisposable` specifications also share the lifecycle since Cratis.Specifications 4.4.0: one construction and one `Dispose` after the last fact. Initialization failure fails every fact. Theories and `ITestOutputHelper` constructors keep per-fact execution; `[PerFactSpecificationLifecycle]` opts a class out. `CRSPEC0008` (a fact modifies the shared context) is an error by default: move the change into `Establish` or `Because`. See the **cratis-specifications-csharp** skill's shared-lifecycle reference.
51
+ The shared lifecycle is the default on xUnit v2 and v3 since 5.0; the package registers the framework, so delete any hand-written `[assembly: Xunit.TestFramework(...)]` (it fails with `CS0579`). Eligible classes derive from `Specification`, have one public constructor with no arguments or only framework-managed fixture arguments, and contain only plain facts. Construction, Establish/Because and Destroy run once; all facts share the instance and must not mutate it. `IDisposable` specifications also share the lifecycle since Cratis.Specifications 4.4.0: one construction and one `Dispose` after the last fact. Initialization failure fails every fact. Theories and `ITestOutputHelper` constructors keep per-fact execution; `[PerFactSpecificationLifecycle]` opts a class out. `CRSPEC0008` (a fact modifies the shared context) is an error by default: move the change into `Establish` or `Because`. See the **cratis-specifications-csharp** skill's shared-lifecycle reference.
52
52
 
53
53
  Run specifications as the built executable, not `dotnet test`: restore and build once, then run `bin/<Config>/net10.0/<Project>.Specs`. In a solution that mixes Microsoft.Testing.Platform and VSTest projects, run each project on its own; `dotnet test` on the whole solution does not work there. Filters and the 4.x → 5.0 checklist are in the **cratis-specifications-csharp** skill's [running-specs reference](../../../skills/cratis-specifications-csharp/references/running-specs.md).
54
54
 
55
- CRSPEC0001–CRSPEC0007 are warnings bundled in `.Specifications`, `.XUnit`, `.XUnit.v3`, and `.NUnit`. With warnings as errors, a non-`should_` fact, multiple specs per file (given contexts exempt), a fact on a given context, a `should_` without a test attribute, explicit base lifecycle calls, non-public specs with facts, or `Because` on a given context fail the build. Follow **cratis-specification-by-example**; do not suppress these diagnostics.
55
+ CRSPEC0001–CRSPEC0007 are warnings. Since 4.5 the analyzers ship only in `Cratis.Specifications`, transitively used by the framework packages; excluding analyzers on a framework package does not remove them. Derived xUnit/NUnit test attributes are recognized since 4.1.2. `Given`/`When` are aliases since 4.4 (declaring both aliases for one phase is CRSPEC0009), but house style stays `Establish`/`Because`. With warnings as errors, a non-`should_` fact, multiple specs per file (given contexts exempt), a fact on a given context, a `should_` without a test attribute, explicit base lifecycle calls, non-public specs with facts, or `Because` on a given context fail the build. Follow **cratis-specification-by-example**; do not suppress these diagnostics.
56
56
 
57
57
  ## Reusable layered contexts
58
58
 
@@ -95,7 +95,7 @@ async Task Because() => _error = await Catch.Exception(_sut.DoSomething);
95
95
 
96
96
  ## Assertion extension methods
97
97
 
98
- From the `Cratis.Specifications.XUnit` package (namespace `Cratis.Specifications`): `.ShouldEqual(expected)`, `.ShouldBeTrue()`, `.ShouldBeFalse()`, `.ShouldBeNull()`, `.ShouldNotBeNull()`, `.ShouldBeEmpty()`, `.ShouldNotBeEmpty()`, `.ShouldContain(item)`, `.ShouldNotContain(item)`, `.ShouldContainOnly(items)`, `.ShouldBeOfExactType<T>()`, `.ShouldBeGreaterThan(n)`, `.ShouldBeLessThan(n)`.
98
+ Since 5.0 assertions live in `Cratis.Specifications`, with types forwarded by each framework package (namespace `Cratis.Specifications`); recompile and keep core/framework packages on the same version: `.ShouldEqual(expected)`, `.ShouldBeTrue()`, `.ShouldBeFalse()`, `.ShouldBeNull()`, `.ShouldNotBeNull()`, `.ShouldBeEmpty()`, `.ShouldNotBeEmpty()`, `.ShouldContain(item)`, `.ShouldNotContain(item)`, `.ShouldContainOnly(items)`, `.ShouldBeOfExactType<T>()`, `.ShouldBeGreaterThan(n)`, `.ShouldBeLessThan(n)`.
99
99
 
100
100
  Additional helpers include `ShouldNotEqual`, `ShouldBeSame`/`ShouldNotBeSame`, `ShouldMatch(Func<T, bool>)`, `ShouldBeInRange`, inclusive comparisons `ShouldBeGreaterThanOrEqual`/`ShouldBeLessThanOrEqual`, `ShouldContainSingleItem`, `ShouldEachConformTo`, ordered collection `ShouldEqual(IEnumerable<T>)`, collection `ShouldContain(Predicate<T>)`, `ShouldBeAssignableFrom<T>`, and string `ShouldContain(substring, StringComparison)`. `Catch.Exception` accepts `Action` or `Func<Task>`; `Catch.Exception<T>(Action)` catches only T.
101
101
 
@@ -258,7 +258,7 @@ public record AuthorRegistered(AuthorName Name);
258
258
 
259
259
  ## Read Models and Queries
260
260
 
261
- **[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
+ **[contract]** `[ReadModel]` records expose eligible public static methods as queries. Requires Arc 22.121.0 for non-public methods to be excluded even with `[Query]` (ARC0029 warns); older versions also expose eligible internal statics. Keep helpers outside the read model when supporting those versions. 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.
262
262
 
263
263
  Use `[ReadModel(RequireQueryAttribute = true)]` with `[Query]` on intended
264
264
  endpoints when folds exist (ARC0026/ARCCHR0019). `[Query]` alone does not hide
@@ -61,6 +61,7 @@
61
61
  { "command": "read-models occurrences", "reason": "lists a read model's replay history" },
62
62
  { "command": "read-models snapshots", "reason": "reads snapshots of one read model instance" },
63
63
  { "command": "recommendations list", "reason": "lists active recommendations" },
64
+ { "command": "streams closed list", "reason": "lists closed stream scopes and their closure metadata without changing them" },
64
65
  { "command": "subscriptions list", "reason": "lists event store subscriptions" },
65
66
  { "command": "users list", "reason": "lists registered users" }
66
67
  ],
@@ -68,13 +69,16 @@
68
69
  { "command": "observers replay", "effect": "replays an observer from the beginning of the event log, resetting all state it has built" },
69
70
  { "command": "observers replay-partition", "effect": "replays one partition of an observer from the beginning, resetting that partition's state" },
70
71
  { "command": "observers retry-partition", "effect": "retries a failed partition from the sequence number where it failed" },
72
+ { "command": "observers retry-failed-partitions", "effect": "starts bounded-batch recovery of every failed partition of an observer; acceptance does not mean recovery finished" },
71
73
  { "command": "observers clear-quarantine", "effect": "clears observer-level quarantine only, not a partition's quarantine" },
72
74
  { "command": "observers clear-partition-quarantine", "effect": "clears a failed partition's quarantine and resets its retry budget; retries the handler unless --no-retry is given" },
73
75
  { "command": "observers remove", "effect": "deletes an observer's definition, state, handled counts, failed partitions and projection definition across every namespace of the event store; leaves read model data" },
74
76
  { "command": "jobs stop", "effect": "stops a running background job" },
75
77
  { "command": "jobs resume", "effect": "resumes a stopped background job" },
78
+ { "command": "jobs delete", "effect": "requests irreversible deletion of a job and its retained state; acceptance does not confirm completed removal" },
76
79
  { "command": "recommendations perform", "effect": "executes a server recommendation, such as a schema or replay maintenance action" },
77
80
  { "command": "recommendations ignore", "effect": "marks a recommendation as ignored so it no longer appears" },
81
+ { "command": "streams closed reopen", "effect": "reopens one exact manual stream closure and records the authenticated actor and repair reason in a StreamScopeReopened system event; event-driven closures are refused" },
78
82
  { "command": "subscriptions add", "effect": "adds an event store subscription to a target event store" },
79
83
  { "command": "subscriptions remove", "effect": "removes an event store subscription from a target event store" },
80
84
  { "command": "users add", "effect": "adds a user to the server's user store" },