@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.
- package/package/corpus/harnesses/copilot/instructions/application-profile.instructions.md +1 -1
- package/package/corpus/harnesses/copilot/instructions/orleans.instructions.md +10 -2
- package/package/corpus/harnesses/copilot/instructions/pull-requests.instructions.md +7 -0
- package/package/corpus/harnesses/copilot/instructions/specs.csharp.instructions.md +4 -4
- package/package/corpus/harnesses/copilot/instructions/vertical-slices.instructions.md +1 -1
- package/package/corpus/hooks/scripts/cratis-store-mutations.json +4 -0
- package/package/corpus/product-sync.json +88 -88
- package/package/corpus/rules/application-profile.md +1 -1
- package/package/corpus/rules/orleans.md +10 -2
- package/package/corpus/rules/pull-requests.md +7 -0
- package/package/corpus/rules/specs.csharp.md +4 -4
- package/package/corpus/rules/vertical-slices.md +1 -1
- package/package/corpus/skills/cratis-application-slice-specifications/references/query-and-decision-scenarios.md +19 -0
- package/package/corpus/skills/cratis-arc-authentication-authorization-and-identity/SKILL.md +8 -0
- package/package/corpus/skills/cratis-arc-authentication-authorization-and-identity/references/authproxy.md +26 -0
- package/package/corpus/skills/cratis-arc-command/references/proxy-generation.md +10 -1
- package/package/corpus/skills/cratis-arc-command-execution/SKILL.md +3 -2
- package/package/corpus/skills/cratis-arc-command-execution/references/occurrence-commands.md +7 -6
- package/package/corpus/skills/cratis-arc-command-validation/SKILL.md +5 -0
- package/package/corpus/skills/cratis-arc-command-validation/references/input-binding.md +17 -0
- package/package/corpus/skills/cratis-arc-command-validation/references/protected-validator-construction.md +94 -0
- package/package/corpus/skills/cratis-arc-ef-core-migration/SKILL.md +18 -0
- package/package/corpus/skills/cratis-arc-query-paging/SKILL.md +11 -4
- package/package/corpus/skills/cratis-arc-query-paging/references/live-query-processing.md +71 -0
- package/package/corpus/skills/cratis-arc-react-page/SKILL.md +11 -0
- package/package/corpus/skills/cratis-arc-validation-kotlin/SKILL.md +20 -3
- package/package/corpus/skills/cratis-chronicle-cli-operations/SKILL.md +11 -2
- package/package/corpus/skills/cratis-chronicle-cli-operations/references/command-effects.md +7 -0
- package/package/corpus/skills/cratis-chronicle-cli-operations/references/project-tooling.md +91 -0
- package/package/corpus/skills/cratis-chronicle-cli-operations/references/recovery-and-comparison.md +68 -0
- package/package/corpus/skills/cratis-chronicle-client-elixir/SKILL.md +12 -0
- package/package/corpus/skills/cratis-chronicle-client-elixir/references/decision-reads.md +10 -0
- package/package/corpus/skills/cratis-chronicle-client-go/SKILL.md +12 -2
- package/package/corpus/skills/cratis-chronicle-client-kotlin/SKILL.md +4 -0
- package/package/corpus/skills/cratis-chronicle-client-kotlin/references/annotations-and-handlers.md +6 -1
- package/package/corpus/skills/cratis-chronicle-client-kotlin/references/fundamentals-migration.md +48 -0
- package/package/corpus/skills/cratis-chronicle-client-typescript/SKILL.md +18 -0
- package/package/corpus/skills/cratis-chronicle-client-typescript/references/lifecycle.md +7 -0
- package/package/corpus/skills/cratis-chronicle-read-model/references/queries.md +5 -3
- package/package/corpus/skills/cratis-cli-terminal-workbench/SKILL.md +5 -1
- package/package/corpus/skills/cratis-components-common-controls/SKILL.md +11 -0
- package/package/corpus/skills/cratis-components-data-surfaces/SKILL.md +5 -0
- package/package/corpus/skills/cratis-components-data-surfaces/references/query-table-updates.md +51 -0
- package/package/corpus/skills/cratis-components-schema-editor/references/tree-layout.md +18 -0
- package/package/corpus/skills/cratis-components-stepper-command-dialog/SKILL.md +11 -0
- package/package/corpus/skills/cratis-fundamentals-type-discovery/SKILL.md +13 -0
- package/package/corpus/skills/cratis-orleans-jobs/SKILL.md +39 -51
- package/package/corpus/skills/cratis-orleans-jobs/references/lifecycle-and-placement.md +52 -0
- package/package/corpus/skills/cratis-orleans-jobs/references/state-machines.md +3 -1
- package/package/corpus/skills/cratis-release-notes/SKILL.md +23 -0
- package/package/corpus/skills/cratis-screenplay-command-surface/references/protected-reads.md +3 -2
- package/package/corpus/skills/cratis-screenplay-legacy-extraction/references/prologue-safety.md +14 -0
- package/package/corpus/skills/cratis-screenplay-toolchain/references/screenplay-contract.version +1 -1
- package/package/corpus/skills/cratis-specifications-csharp/SKILL.md +14 -2
- package/package/corpus/skills/cratis-specifications-csharp/references/running-specs.md +8 -1
- package/package/corpus/skills/cratis-specifications-csharp/references/shared-lifecycle.md +19 -2
- package/package.json +1 -1
|
@@ -0,0 +1,52 @@
|
|
|
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
|
+
# Lifecycle, recovery and placement
|
|
5
|
+
|
|
6
|
+
## Stop, drain and admission
|
|
7
|
+
|
|
8
|
+
Requires Cratis.Orleans 1.20.0 for `IJobs.StopAndDrain(key, jobId, timeout)` and the grain protocols `IJobDrain` / `IJobStepDrain`. Unlike ordinary stop acceptance, `Drained` means no step code can run, final outcomes/checkpoints are durable and completion/stop hooks finished. Other outcomes are `TimedOut` (call again), `Completed`, `NotFound` and `UnknownJobType`. `TimeSpan.Zero` polls. Add the method to hand-written `IJobs` implementations. Enable only after every silo supports it. A pending drain survives reactivation and refuses resume; a timeout is not proof of quiescence. Hooks can repeat or be missed after a crash, so keep them idempotent rather than collecting results only there.
|
|
9
|
+
|
|
10
|
+
Requires 1.21.0 for owner admission: implement `IJobAdmission.MayRun(JobAdmissionRequest, CancellationToken)` and register with `siloBuilder.AddJobAdmission<T>()` on every silo that hosts those job types. Every admission must allow; none means allow. It runs before start, every resume and each later stage. Refusals return `StartJobError.NotAdmitted` / `CannotResumeJobError.NotAdmitted`; manager resume returns false. A refused running job is stopped/drained, and a refused later stage stops the job. Exceptions/timeouts are failures, not refusals; a later stage retries an unanswered admission on a timer.
|
|
11
|
+
|
|
12
|
+
`MayRun` runs in the job's turn: never call the job, its steps, or a non-interleaving grain that could be waiting on this start/resume. To change what existing work may do, the owner calls `StopAndDrain` **before** changing the admission answer. Older silos do not ask, so admission guarantees require every silo to run the supporting version. Admission does not by itself serialize arbitrary host-owned mutual-exclusion rules.
|
|
13
|
+
|
|
14
|
+
## Bounded delivery and retries
|
|
15
|
+
|
|
16
|
+
Requires 1.23.0 for these opt-in execution controls. Defaults preserve unbounded dispatch, one execution attempt and no lease timeout:
|
|
17
|
+
|
|
18
|
+
| Option | Default / meaning |
|
|
19
|
+
| --- | --- |
|
|
20
|
+
| `MaxActiveStepsPerJob` | `null` (all); a positive limit fills a dispatch window within a stage |
|
|
21
|
+
| `MaxStepAttempts` | `1`, including first attempt; failed work can retry when increased |
|
|
22
|
+
| `StepRetryBackoff`, `MaxStepRetryBackoff` | `5 seconds`, `5 minutes`; capped exponential delay |
|
|
23
|
+
| `JobWatchdogInterval` | `1 minute`; probes stalled delivery/progress |
|
|
24
|
+
| `StepLeaseTimeout` | `TimeSpan.Zero` disables heartbeat lease enforcement |
|
|
25
|
+
| `StepDeliveryMaxAttempts` | `10` |
|
|
26
|
+
| `StepDeliveryRetryDelay`, `MaxStepDeliveryRetryDelay` | `1 second`, `30 seconds` |
|
|
27
|
+
|
|
28
|
+
The watchdog restarts a leased step only after its owner silo left the cluster **and** its lease expired. Steps saved by older releases get one lease period. `Job.ShouldRetryStep` decides which failures retry, and `Job.MaxActiveSteps` can override the window. Persist optional `Attempt` and `Lease` on custom step state; old records default to attempt 1 and no lease. `IJobStepStorage.CountByStatus(jobId)` has a default implementation. A step persists its terminal state before retrying outcome delivery; exhausted delivery does not turn that completed step into a new failed execution. The watchdog reconciles stored outcomes if reports never arrive. Keep work idempotent: leases and delivery deduplication do not make external effects exactly-once.
|
|
29
|
+
|
|
30
|
+
`IJobsManager.RetryFailedSteps(jobId)` is opt-in through `Job.CanRetryFailedSteps` and runs failed steps of a job completed with failures again. Ordinary resume is unchanged. It is not a general rerun of a successful job.
|
|
31
|
+
|
|
32
|
+
## Step test runs
|
|
33
|
+
|
|
34
|
+
Requires 1.22.0 for `step.BeginTestRun()` and `JobStepTestRun<TState>.Perform(state)` in a specification host. `Perform` runs `PerformStep` off activation with the supplied state and returns its `Catch<JobStepResult>`; `TryInvokeOnActivation` callbacks run serially on a stand-in scheduler. `IsOnActivation` tests that state changes happen in callbacks. `Stop()` cancels work while admission remains open; `CloseAdmission()` refuses callbacks. A run performs once and records/delivers nothing to a job. Cover `JobStepAlreadyHasALiveRun` and `JobStepTestRunWasSuperseded` misuse. This does not isolate external effects: use safe substitutes, not a live job/store.
|
|
35
|
+
|
|
36
|
+
## Custom storage and rolling upgrades
|
|
37
|
+
|
|
38
|
+
Persist the complete `JobState`, including `StopFinalized`, `StoppedStepsCounted` and `CompletedStepsCounted`. Missing lists read as empty for old records; do not project these fields away when storing state. The completion list tracks outcomes in executions begun by resume/retry, not jobs never resumed, and warns at 100,000 entries. Cross-version code that does not persist the list can lose duplicate protection, so keep mixed-version windows short.
|
|
39
|
+
|
|
40
|
+
A completed stop sets `StopFinalized` after all required notifications have succeeded. Unfinalized stops are retried; finalized stops are excluded from recovery through `IJobStorage.GetJobsExcludingFinalizedStops`. Custom providers can override its default in-memory filtering to filter in storage. MongoDB and SQL filter there; MongoDB adds `status_stopFinalized`. SQLite, PostgreSQL and SQL Server jobs storage are supported; MySQL/MariaDB is not. Removing jobs likewise retries unacknowledged notifications; acceptance of removal is not quiescence or immediate physical deletion.
|
|
41
|
+
|
|
42
|
+
## Independent controller and worker placement
|
|
43
|
+
|
|
44
|
+
Requires 1.30.0 for `Cratis.Orleans.Hosting` extensions on `ISiloBuilder`:
|
|
45
|
+
|
|
46
|
+
- `AddJobPlacement()` or `AddJobPlacement<TDirector>()` opts controllers into `JobsPlacementStrategy`.
|
|
47
|
+
- `AddJobStepPlacement()` or `AddJobStepPlacement<TDirector>()` opts workers into `JobStepsPlacementStrategy`, including recovered steps.
|
|
48
|
+
- Directors implement Orleans `IPlacementDirector`. Host directors decide eligibility; throw `NoEligibleJobWorker` when no silo is eligible. Orleans does not retry that exception; the job's failure handling applies.
|
|
49
|
+
- Without an opt-in, controller placement remains resource-optimized and workers use the cluster default. The built-in directors preserve those defaults when an opt-in has no custom director.
|
|
50
|
+
- **Wait until every silo runs the supporting version**, then register each strategy identically on every silo. Do not introduce the strategy during a mixed-version rollout.
|
|
51
|
+
|
|
52
|
+
`UseJobStepParallelismFromSiloMetadata()` independently sizes each silo's throttle from the positive integer `cratis.jobs.max-parallel-steps` metadata value (or the supplied metadata key). Missing, nonnumeric or nonpositive values fall back to `JobsOptions.MaxParallelSteps` and its processor-count default. Publish with Orleans `UseSiloMetadata`. This is a startup value, not live resizing, authorization or admission. Keep controller placement, worker eligibility, execution throttling and job admission as separate choices.
|
|
@@ -44,7 +44,9 @@ public class Finished : State<ProcessState>;
|
|
|
44
44
|
|
|
45
45
|
Split types into their house-style files in the consumer; the block collects declarations to show the API. Do not copy the `processes` provider name into Chronicle's kernel; use its registered constants.
|
|
46
46
|
|
|
47
|
-
A refused transition is a **no-op**, not an exception or a successful change. An unknown target throws `UnknownStateTypeInStateMachine`. The machine runs leaving hooks, `OnLeave`, entering hooks, `OnEnter`, then persistence (`StateMachine.cs`).
|
|
47
|
+
A refused transition is a **no-op**, not an exception or a successful change. An unknown target throws `UnknownStateTypeInStateMachine`. The machine runs leaving hooks, `OnLeave`, entering hooks, `OnEnter`, then persistence (`StateMachine.cs`).
|
|
48
|
+
|
|
49
|
+
Requires 1.22.3 for transitions admitted during entry to queue FIFO rather than be dropped. Their request tasks complete on admission, **before** the queued transition executes. If another state has been entered, the target is rechecked and silently skipped when refused; a failed drain discards pending targets and fails its owning task. Transitions while leaving still throw `TransitioningDuringOnLeaveIsNotSupported`.
|
|
48
50
|
|
|
49
51
|
When stored state derives `StateMachineState`, `CurrentState` stores the state's full type name; activation resolves it, enters it again, and can repeat enter effects. Renames need a stored-value migration; an unknown recorded name throws `UnknownCurrentState` (`StateMachine.cs`). A self-transition with the **same state instance** skips persistence: return a new stored-state instance when a self-transition must write.
|
|
50
52
|
|
|
@@ -111,6 +111,29 @@ Only when asked to fix a release that violates the contract:
|
|
|
111
111
|
only when the request covers closing issues; otherwise list the issues as a
|
|
112
112
|
proposal. Leave an issue open when the release only partly delivered it.
|
|
113
113
|
|
|
114
|
+
## Release-action batching and recovery
|
|
115
|
+
|
|
116
|
+
Requires release-action 1.5.1 for corrected pending-major hotfix handling; check the workflow's `uses` pin, or keep immediate releases on the older contract.
|
|
117
|
+
|
|
118
|
+
`release-window` defaults to `0` (one
|
|
119
|
+
release per PR); a positive minute window batches pending merges once the oldest
|
|
120
|
+
is old enough. The highest intent wins, notes merge by section with one combined
|
|
121
|
+
`## Summary`, and delivered `(#n)` issues still close. Reference definitions are
|
|
122
|
+
preserved; duplicate labels keep the first definition and warn. Missing intent
|
|
123
|
+
labels warn but are not permission to omit required PR labels.
|
|
124
|
+
|
|
125
|
+
`hotfix-labels` defaults to `hotfix` and bypasses the window. With a pending major,
|
|
126
|
+
only the merge run for the hotfix fails; scheduled/other merge runs warn and leave
|
|
127
|
+
the batch pending. A manual run without a version releases everything pending;
|
|
128
|
+
obtain the required human major confirmation first. Inspect `pull-requests` and
|
|
129
|
+
`reason` (`batched` or `nothing-pending`) rather than assuming every successful
|
|
130
|
+
run released. Never turn on batching just to clear a queue without authorization.
|
|
131
|
+
|
|
132
|
+
A release-creation 403 caused by workflow drift names the recovery:
|
|
133
|
+
dispatch the publish workflow from the current default branch with the PR's
|
|
134
|
+
release notes. Re-running the stale commit does not fix this. Other 403s keep
|
|
135
|
+
their original cause; do not treat every permission failure as workflow drift.
|
|
136
|
+
|
|
114
137
|
## Verify before handing over
|
|
115
138
|
|
|
116
139
|
1. Reconcile every version, affected range, capability and API against the
|
package/package/corpus/skills/cratis-screenplay-command-surface/references/protected-reads.md
CHANGED
|
@@ -117,8 +117,9 @@ which is one more reason to keep refused shapes out of read keys.
|
|
|
117
117
|
|
|
118
118
|
Decide records the unfiltered fact-log boundary, read key and handled event types.
|
|
119
119
|
A matching fact after that boundary makes commit return Conflict /
|
|
120
|
-
DecisionStateChanged with no command facts, including publications.
|
|
121
|
-
|
|
120
|
+
DecisionStateChanged with no command facts, including publications. Append constraints
|
|
121
|
+
are checked first: if the same candidate violates a constraint and a protected read,
|
|
122
|
+
the constraint rejection wins. Irrelevant facts do not conflict and remain in the committed world. Even a no-fact command is
|
|
122
123
|
checked. Race cases are evaluator vectors, not a new `.play` specification construct.
|
|
123
124
|
|
|
124
125
|
Specify present/absent state, rule refusal and denial. Assert no new facts and
|
package/package/corpus/skills/cratis-screenplay-legacy-extraction/references/prologue-safety.md
CHANGED
|
@@ -151,6 +151,20 @@ Record in the evidence table: who ran which statements, when, and the verificati
|
|
|
151
151
|
summary.
|
|
152
152
|
|
|
153
153
|
## 5. Capture verification before interpreting
|
|
154
|
+
|
|
155
|
+
Requires Prologue 2.0.5 for the emission/image behavior below; check pinned package/image versions and `cratis --version` against its bundle, or upgrade before relying on it.
|
|
156
|
+
|
|
157
|
+
Upgrade older Extractor installations for the PKCS denial-of-service dependency
|
|
158
|
+
fixes. Extractor, Interpreter and Receiver images support linux/amd64 and
|
|
159
|
+
linux/arm64; Apple Silicon does not need a forced amd64 platform.
|
|
160
|
+
|
|
161
|
+
Heuristics-only interpretation retains each command's own correlated events
|
|
162
|
+
when routes merge, declares shared events once, treats insert-plus-update in one
|
|
163
|
+
transaction as creation, omits text-only `not empty` rules for required numbers
|
|
164
|
+
and declares/key-identifies referenced read models. Do not retain manual
|
|
165
|
+
workarounds for old emitter defects. These repairs do not prove intent or compile
|
|
166
|
+
the output for you: still run executable validation on the emitted model, not
|
|
167
|
+
only parsing, and record remaining diagnostics.
|
|
154
168
|
- Capture files exist for every enabled source.
|
|
155
169
|
- Commands per route match the scenario script; status-code mix matches expected rejections.
|
|
156
170
|
- Fraction of DB transactions correlated to a command (low: concurrency or jobs).
|
package/package/corpus/skills/cratis-screenplay-toolchain/references/screenplay-contract.version
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
4.
|
|
1
|
+
4.245.0
|
|
@@ -44,6 +44,17 @@ Requires `Cratis.Arc.Testing` 22.67.0 for generated-value scenario pinning.
|
|
|
44
44
|
Check the owning product repository before claiming support for
|
|
45
45
|
another version. Never translate an assertion or helper name from memory.
|
|
46
46
|
|
|
47
|
+
Requires Specifications 4.4.0 for Given/When lifecycle aliases across framework packages; check `dotnet list package`, or keep Establish/Because on older packages.
|
|
48
|
+
|
|
49
|
+
`Given`/`When` are lifecycle aliases, but house style remains `Establish`/`Because`;
|
|
50
|
+
declaring both forms of a phase produces CRSPEC0009. Inherited phases execute
|
|
51
|
+
once and preserve the original exception; `ValueTask` is awaited. The native
|
|
52
|
+
runner remains experimental: CRSPEC0010 rejects `async void`, CRSPEC0011 warns
|
|
53
|
+
about trim/AOT-unsafe reflective lifecycle calls. Shared resources/leases, phase
|
|
54
|
+
timings, runtime defaults and parallel NUnit fixtures are opt-ins, not blanket
|
|
55
|
+
recommendations to parallelize a stateful suite. Read the product upgrade guide
|
|
56
|
+
before changing runner or package family.
|
|
57
|
+
|
|
47
58
|
## Route near misses
|
|
48
59
|
|
|
49
60
|
- The specification is TypeScript, React, or a view model: use
|
|
@@ -202,8 +213,9 @@ public class when_<behavior> : Specification
|
|
|
202
213
|
leave no blank line between `should_` methods.
|
|
203
214
|
- Fields are `private` in a concrete specification and `protected` in a `given/`
|
|
204
215
|
context, named `_camelCase`.
|
|
205
|
-
- Any phase may
|
|
206
|
-
once per eligible class by default
|
|
216
|
+
- Any phase may return `Task` or `ValueTask`; both are awaited. Never use `async void`.
|
|
217
|
+
`void Destroy()` is optional teardown, once per eligible class by default
|
|
218
|
+
(shared lifecycle); after each fact in a
|
|
207
219
|
`[PerFactSpecificationLifecycle]` class.
|
|
208
220
|
|
|
209
221
|
`Cratis.Specifications.XUnit.v3` discovers `Establish`, `Because`, and `Destroy` by
|
|
@@ -82,7 +82,14 @@ and record the spec count and outcomes first.
|
|
|
82
82
|
Specifications.
|
|
83
83
|
5. Fix each `CRSPEC0008` error by moving the change into `Establish` or `Because`; use
|
|
84
84
|
`[PerFactSpecificationLifecycle]` only when the fact genuinely needs a fresh instance.
|
|
85
|
-
6.
|
|
85
|
+
6. Change assertion delegates typed as `Predicate<T>` to `Func<T, bool>`; for
|
|
86
|
+
NUnit 4 comparisons that relied on unordered `ShouldEqual(params)`, use
|
|
87
|
+
`ShouldEqualInAnyOrder`. Null actual values now fail, including nullable
|
|
88
|
+
`ShouldNotContain` strings. Assertions live in core with forwarded types;
|
|
89
|
+
rebuild with warnings as errors and fix new nullable warnings. Delete
|
|
90
|
+
`CratisSpecificationsWarnOnSharedContextMutation` (it has no effect in 5).
|
|
91
|
+
Native-runner `async void` facts/phases must return `Task` or `ValueTask`
|
|
92
|
+
instead (CRSPEC0010 is an error).
|
|
86
93
|
7. Run the executable and require the same total, the same passed count and the same
|
|
87
94
|
classes and methods as the baseline (display names may become more readable),
|
|
88
95
|
with no new skips. A different count means a spec was
|
|
@@ -32,18 +32,35 @@ implementations, custom fact test cases and plain xUnit classes keep the per-fac
|
|
|
32
32
|
|
|
33
33
|
Requires Cratis.Specifications 4.4.0 or later for `IDisposable` specifications to share
|
|
34
34
|
the lifecycle; earlier versions use per-fact construction. With shared lifecycle enabled,
|
|
35
|
-
construction happens once and `
|
|
35
|
+
construction happens once, and `Destroy` runs followed by
|
|
36
|
+
one `Dispose` after the last fact, even when `Destroy` fails. Class/collection fixtures remain owned by xUnit,
|
|
37
|
+
with assembly fixtures also supported on v3. Use
|
|
36
38
|
`[PerFactSpecificationLifecycle]` when a fresh instance per fact is needed.
|
|
37
39
|
|
|
38
40
|
`Specification.InitializeAsync()` is idempotent for a single instance. It does not make
|
|
39
41
|
an ineligible class shared or cache instances across classes.
|
|
40
42
|
|
|
43
|
+
## Native runner teardown outcomes
|
|
44
|
+
|
|
45
|
+
Requires Cratis.Specifications.Runner 5.0.3 for separate class teardown results; check `dotnet list package`, or expect the older runner to mark every fact failed after teardown fails.
|
|
46
|
+
|
|
47
|
+
A failing `Destroy`, disposal or scope end produces one separate failed result
|
|
48
|
+
for the specification class and fails the run. Completed facts keep their own
|
|
49
|
+
outcomes, as on xUnit/NUnit. Select the teardown result to rerun its class; passing
|
|
50
|
+
facts do not imply the class or run passed.
|
|
51
|
+
|
|
41
52
|
## CRSPEC0008
|
|
42
53
|
|
|
43
54
|
`CRSPEC0008` is an error by default: a `should_` fact that assigns to or increments an
|
|
44
55
|
instance field or property of the specification, or calls `Add`, `AddRange`, `Remove`,
|
|
45
56
|
`RemoveAt`, `Clear` or `Insert` on one, would make the result depend on fact order.
|
|
46
|
-
|
|
57
|
+
Requires Specifications 5.0.2 for Received.InOrder verification recognition; check `dotnet list package`, or upgrade before relying on this diagnostic exception.
|
|
58
|
+
|
|
59
|
+
Calls inside NSubstitute `Received.InOrder(...)` delegates are recognized as
|
|
60
|
+
verification, but assignments and increments there still mutate state and are
|
|
61
|
+
reported. Theories, per-fact classes/assemblies, immutable collection calls and
|
|
62
|
+
collection calls whose return value is used are excluded. Move actual mutations
|
|
63
|
+
into `Establish` or `Because`:
|
|
47
64
|
|
|
48
65
|
```csharp
|
|
49
66
|
public class when_registering : Specification
|