@cratis/pi 7.129.0 → 7.130.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/agents/coordinator.md +1 -1
- package/package/corpus/agents/orchestrator.md +1 -1
- package/package/corpus/agents/planner.md +1 -1
- package/package/corpus/harnesses/copilot/instructions/csharp.instructions.md +2 -2
- package/package/corpus/harnesses/copilot/instructions/framework.instructions.md +1 -1
- package/package/corpus/harnesses/copilot/instructions/orleans.instructions.md +2 -1
- package/package/corpus/harnesses/copilot/instructions/pull-requests.instructions.md +1 -1
- package/package/corpus/harnesses/copilot/instructions/specs.csharp.instructions.md +1 -1
- package/package/corpus/harnesses/pi/agents/coordinator.md +1 -1
- package/package/corpus/harnesses/pi/agents/orchestrator.md +1 -1
- package/package/corpus/harnesses/pi/agents/planner.md +1 -1
- package/package/corpus/harnesses/pi/extensions/cratis-hooks/index.ts +1 -1
- package/package/corpus/hooks/README.md +17 -5
- package/package/corpus/hooks/pre-commit.md +2 -2
- package/package/corpus/hooks/scripts/cratis-quality-gate.sh +1 -0
- package/package/corpus/hooks/scripts/cratis-run-specs.sh +147 -0
- package/package/corpus/hooks/scripts/quality-gates.json +5 -7
- package/package/corpus/rules/csharp.md +2 -2
- package/package/corpus/rules/framework.md +1 -1
- package/package/corpus/rules/orleans.md +2 -1
- package/package/corpus/rules/pull-requests.md +1 -1
- package/package/corpus/rules/specs.csharp.md +1 -1
- package/package/corpus/skills/binlog-generation/SKILL.md +1 -1
- package/package/corpus/skills/coverage-analysis/references/setup-discovery.md +1 -1
- package/package/corpus/skills/cratis-application-slice-specifications/SKILL.md +1 -1
- package/package/corpus/skills/cratis-arc-command-execution/references/command-refusals.md +1 -1
- package/package/corpus/skills/cratis-arc-command-execution/references/occurrence-commands.md +1 -1
- package/package/corpus/skills/cratis-arc-command-operation/references/testing.md +1 -1
- package/package/corpus/skills/cratis-arc-command-validation/references/input-binding.md +1 -1
- package/package/corpus/skills/cratis-arc-command-validation/references/validation-severity.md +1 -1
- package/package/corpus/skills/cratis-chronicle-client-dotnet/references/immediate-append-refusal.md +1 -1
- package/package/corpus/skills/cratis-chronicle-client-dotnet/references/occurrences.md +1 -1
- package/package/corpus/skills/cratis-chronicle-event-constraints/references/storage-uniqueness.md +1 -1
- package/package/corpus/skills/cratis-chronicle-event-specifications/SKILL.md +1 -1
- package/package/corpus/skills/cratis-chronicle-event-type-migration/references/explicit-migrations.md +1 -1
- package/package/corpus/skills/cratis-chronicle-reactor/references/starting-and-replaying.md +1 -1
- package/package/corpus/skills/cratis-chronicle-read-model/references/collection-observation.md +1 -1
- package/package/corpus/skills/cratis-chronicle-read-model-specifications/SKILL.md +1 -1
- package/package/corpus/skills/cratis-ci-pipeline-performance/SKILL.md +1 -1
- package/package/corpus/skills/cratis-ci-pipeline-performance/references/build-once-and-shard.md +7 -3
- package/package/corpus/skills/cratis-ci-pipeline-performance/references/flaky-and-hung-jobs.md +1 -1
- package/package/corpus/skills/cratis-ci-pipeline-performance/references/test-setup-cost.md +1 -1
- package/package/corpus/skills/cratis-commits-and-pull-requests/references/pr-labels-and-release.md +1 -1
- package/package/corpus/skills/cratis-engineering-ci-gates/SKILL.md +3 -2
- package/package/corpus/skills/cratis-engineering-local-cross-repo-verification/SKILL.md +5 -1
- package/package/corpus/skills/cratis-engineering-local-cross-repo-verification/references/worked-examples.md +17 -8
- package/package/corpus/skills/cratis-orchestration-lanes/references/context-handoff.md +1 -1
- package/package/corpus/skills/cratis-orchestration-lanes/references/lane-brief.md +2 -2
- package/package/corpus/skills/cratis-screenplay-render-and-gap-fill/references/delivery-protocol.md +2 -2
- package/package/corpus/skills/cratis-screenplay-specifications/SKILL.md +4 -3
- package/package/corpus/skills/cratis-screenplay-toolchain/references/fast-path.md +1 -1
- package/package/corpus/skills/cratis-screenplay-toolchain/references/verdicts.md +1 -1
- package/package/corpus/skills/cratis-specifications-csharp/references/running-specs.md +7 -3
- package/package/corpus/skills/cratis-stage-rendering-and-sandbox/SKILL.md +2 -1
- package/package/corpus/skills/cratis-stage-rendering-and-sandbox/references/render-example.md +1 -1
- package/package/corpus/skills/csharp-refactoring/SKILL.md +2 -2
- package/package/corpus/skills/eliminate-redundant-restores/SKILL.md +2 -1
- package/package/corpus/skills/filter-syntax/SKILL.md +1 -1
- package/package/corpus/skills/msbuild/references/build-perf-baseline.md +4 -1
- package/package/corpus/skills/run-tests/SKILL.md +9 -0
- package/package.json +1 -1
|
@@ -139,7 +139,7 @@ When handing off to a specialist agent:
|
|
|
139
139
|
For implementation, the applicable changed-lane gates must pass. Mark unrelated entries not applicable; this list is not a full-repository command mandate:
|
|
140
140
|
|
|
141
141
|
- [ ] `dotnet build` — zero errors, zero warnings
|
|
142
|
-
- [ ] `dotnet test`
|
|
142
|
+
- [ ] Built C# spec executables — all specs pass; `dotnet test <project> --no-build` only for VSTest (see specs.csharp)
|
|
143
143
|
- [ ] `yarn lint` — zero errors (if frontend present)
|
|
144
144
|
- [ ] `npx tsc -b` — zero TypeScript errors (if frontend present)
|
|
145
145
|
- [ ] Public-facing changes (clients, SDKs, public APIs) include associated documentation updates
|
|
@@ -165,7 +165,7 @@ When handing off to any agent or sub-orchestrator:
|
|
|
165
165
|
For implementation, the applicable changed-lane gates must pass. Mark unrelated entries not applicable; this list is not a full-repository command mandate:
|
|
166
166
|
|
|
167
167
|
- [ ] `dotnet build` — zero errors, zero warnings
|
|
168
|
-
- [ ] `dotnet test`
|
|
168
|
+
- [ ] Built C# spec executables — all specs pass; `dotnet test <project> --no-build` only for VSTest (see specs.csharp)
|
|
169
169
|
- [ ] `yarn lint` — zero errors (if frontend present)
|
|
170
170
|
- [ ] `npx tsc -b` — zero TypeScript errors (if frontend present)
|
|
171
171
|
- [ ] Public-facing changes (clients, SDKs, public APIs) include associated documentation updates
|
|
@@ -133,7 +133,7 @@ For an implemented application slice, require the applicable changed-lane gates
|
|
|
133
133
|
- [ ] `dotnet build` succeeds with zero errors and zero warnings
|
|
134
134
|
- [ ] `yarn lint` passes with zero errors (if frontend is present)
|
|
135
135
|
- [ ] `npx tsc -b` passes with zero errors (if frontend is present)
|
|
136
|
-
- [ ] All integration specs pass (`dotnet test`)
|
|
136
|
+
- [ ] All integration specs pass (built C# spec executables; `dotnet test <project> --no-build` only for VSTest; see specs.csharp)
|
|
137
137
|
- [ ] All TypeScript specs pass (`yarn test`) if applicable
|
|
138
138
|
- [ ] Public-facing changes (clients, SDKs, public APIs) include associated documentation updates
|
|
139
139
|
- [ ] `Documentation/verify-markdown.sh` passes when documentation is added or changed
|
|
@@ -13,8 +13,8 @@ The goal is minimal ceremony, maximum clarity. Modern C# (13+) gives us records,
|
|
|
13
13
|
## Building
|
|
14
14
|
|
|
15
15
|
- Use `dotnet build` from the command line.
|
|
16
|
-
-
|
|
17
|
-
-
|
|
16
|
+
- Follow `.editorconfig`; run `dotnet format` only when CI requires it.
|
|
17
|
+
- Run affected spec executables; use `dotnet test <project> --no-build` only for VSTest (see `specs.csharp.md`).
|
|
18
18
|
|
|
19
19
|
## Formatting
|
|
20
20
|
|
|
@@ -60,7 +60,7 @@ Repo conventions follow from this: `Source/DotNET` + `Source/JavaScript` for dua
|
|
|
60
60
|
## Quality gates (framework)
|
|
61
61
|
|
|
62
62
|
- Build clean (Debug and Release) with **zero warnings, zero errors**.
|
|
63
|
-
- Specs pass for affected projects (C#
|
|
63
|
+
- Specs pass for affected projects (C# spec executables (VSTest only: `dotnet test <project> --no-build`); TS packages via their test command; Components also `build-storybook`).
|
|
64
64
|
- For public-facing changes (APIs, attributes, generated output, component props): update the product documentation and verify it.
|
|
65
65
|
- Match the repo's existing patterns; when a deep architectural question isn't answered by the universal rules or this file, consult the **repo's own docs/CONTRIBUTING** or ask — do not infer framework internals from a single call site.
|
|
66
66
|
|
|
@@ -63,7 +63,8 @@ using Microsoft.AspNetCore.Builder;
|
|
|
63
63
|
using MongoDB.Driver;
|
|
64
64
|
|
|
65
65
|
var builder = WebApplication.CreateBuilder(args);
|
|
66
|
-
|
|
66
|
+
var connectionString = builder.Configuration.GetConnectionString("Mongo")
|
|
67
|
+
?? throw new InvalidOperationException("Configure the Mongo connection string.");
|
|
67
68
|
builder.AddCratisOrleans(new CratisOrleansOptions
|
|
68
69
|
{
|
|
69
70
|
ClusterId = "my-service",
|
|
@@ -32,6 +32,6 @@ applyTo: "**/*"
|
|
|
32
32
|
## Before you create or edit a PR
|
|
33
33
|
|
|
34
34
|
- Run `node .cratis/ai/hooks/scripts/cratis-check-pr.mjs --body-file <file> --label <intent>`; it applies the exact `policy / verify` release-note rules and the Bash hook runs it on `gh pr create` and `gh pr edit`. If it fails, fix the description, not the code. Before every body edit, run `git diff --stat origin/main...HEAD` and delete bullets the diff no longer supports.
|
|
35
|
-
- Run the affected-project gates before marking work ready (
|
|
35
|
+
- Run the affected-project gates before marking work ready (build, built specs, lint and type-check; zero warnings), and the repository's required CI checks after an authorized push. `no-release` and documentation-only PRs still satisfy every required check; none is a blanket exemption from red CI.
|
|
36
36
|
- Group small related changes into one branch and one PR; see the skill for consolidation and the release-action windows.
|
|
37
37
|
- Open the PR once, when verified: each push starts CI. One PR per body of work, opened by the orchestrator (`cratis-engineering-release-trains`), with `--assignee @me`.
|
|
@@ -50,7 +50,7 @@ public class when_combining_parts : Specification
|
|
|
50
50
|
|
|
51
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. Keep shared lifecycle on; `[PerFactSpecificationLifecycle]` opts out only the class whose facts genuinely mutate shared state and cannot move the mutation into `Because`. `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
|
-
Run specifications as
|
|
53
|
+
Run xUnit v3, TUnit and native-runner specifications as each project's built executable: restore and build once, then run its matching configuration/TFM output. Only identified VSTest projects use `dotnet test <project> --no-build`. Never default to solution-wide `dotnet test` in a mixed suite. 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
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
|
|
|
@@ -135,7 +135,7 @@ When handing off to a specialist agent:
|
|
|
135
135
|
For implementation, the applicable changed-lane gates must pass. Mark unrelated entries not applicable; this list is not a full-repository command mandate:
|
|
136
136
|
|
|
137
137
|
- [ ] `dotnet build` — zero errors, zero warnings
|
|
138
|
-
- [ ] `dotnet test`
|
|
138
|
+
- [ ] Built C# spec executables — all specs pass; `dotnet test <project> --no-build` only for VSTest (see specs.csharp)
|
|
139
139
|
- [ ] `yarn lint` — zero errors (if frontend present)
|
|
140
140
|
- [ ] `npx tsc -b` — zero TypeScript errors (if frontend present)
|
|
141
141
|
- [ ] Public-facing changes (clients, SDKs, public APIs) include associated documentation updates
|
|
@@ -161,7 +161,7 @@ When handing off to any agent or sub-orchestrator:
|
|
|
161
161
|
For implementation, the applicable changed-lane gates must pass. Mark unrelated entries not applicable; this list is not a full-repository command mandate:
|
|
162
162
|
|
|
163
163
|
- [ ] `dotnet build` — zero errors, zero warnings
|
|
164
|
-
- [ ] `dotnet test`
|
|
164
|
+
- [ ] Built C# spec executables — all specs pass; `dotnet test <project> --no-build` only for VSTest (see specs.csharp)
|
|
165
165
|
- [ ] `yarn lint` — zero errors (if frontend present)
|
|
166
166
|
- [ ] `npx tsc -b` — zero TypeScript errors (if frontend present)
|
|
167
167
|
- [ ] Public-facing changes (clients, SDKs, public APIs) include associated documentation updates
|
|
@@ -129,7 +129,7 @@ For an implemented application slice, require the applicable changed-lane gates
|
|
|
129
129
|
- [ ] `dotnet build` succeeds with zero errors and zero warnings
|
|
130
130
|
- [ ] `yarn lint` passes with zero errors (if frontend is present)
|
|
131
131
|
- [ ] `npx tsc -b` passes with zero errors (if frontend is present)
|
|
132
|
-
- [ ] All integration specs pass (`dotnet test`)
|
|
132
|
+
- [ ] All integration specs pass (built C# spec executables; `dotnet test <project> --no-build` only for VSTest; see specs.csharp)
|
|
133
133
|
- [ ] All TypeScript specs pass (`yarn test`) if applicable
|
|
134
134
|
- [ ] Public-facing changes (clients, SDKs, public APIs) include associated documentation updates
|
|
135
135
|
- [ ] `Documentation/verify-markdown.sh` passes when documentation is added or changed
|
|
@@ -394,7 +394,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
394
394
|
const last = latestGateLog(gateLogDirectory(sessionId), started);
|
|
395
395
|
const tail = last ? tailLines(last.file, TAIL_LINES) : "";
|
|
396
396
|
throw new Error(`The Cratis quality gate TIMED OUT after ${duration(timeoutSeconds * 1000)}${last ? ` while running '${last.gate}'${last.cwd ? ` (cwd: ${last.cwd})` : ""}` : ""}. This is not a pass: nothing was verified.` +
|
|
397
|
-
(last ? `\nRun a narrower command instead: ${last.gate === "backend-specs" ? "dotnet test <
|
|
397
|
+
(last ? `\nRun a narrower command instead: ${last.gate === "backend-specs" ? "./<affected-project-dir>/bin/Debug/<TFM>/<AssemblyName> (or dotnet <TargetPath.dll> without apphost); dotnet test <project> --configuration Debug --no-build only for VSTest. Repeat for affected dependents." : "run the affected project alone using this gate's configured command."}\nConfigure it in .cratis/ai/quality-gates.project.json.\n\nGate log: ${last.file}` : "") +
|
|
398
398
|
(tail ? `\n\n--- last ${TAIL_LINES} lines ---\n${tail}\n--- end ---` : ""));
|
|
399
399
|
};
|
|
400
400
|
const reportInterrupted = () => {
|
|
@@ -636,17 +636,29 @@ the script stops the command's process group (TERM, then KILL after one second),
|
|
|
636
636
|
reports **NOT VERIFIED**, the gate, its directory, log tail, and `timeoutHint` (advice, never executed).
|
|
637
637
|
Commands that create separate sessions/process groups can escape this cleanup; this is not a sandbox.
|
|
638
638
|
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
639
|
+
The default runs `cratis-run-specs.sh` through the absolute `CRATIS_HOOKS_SCRIPTS_DIR`
|
|
640
|
+
exported by the gate, including nested solutions and bundled Pi installations. The runner
|
|
641
|
+
requires Node, Bash and Git, the same prerequisites as the hooks (not an additional runtime). It evaluates
|
|
642
|
+
MSBuild metadata without building, runs supported built xUnit v3/TUnit/native executables
|
|
643
|
+
(or `dotnet <TargetPath.dll>` without apphost), and uses project-scoped `dotnet test --no-build`
|
|
644
|
+
only for identified VSTest projects. Restore/build matching Debug outputs first. Missing or
|
|
645
|
+
ambiguous metadata/output, custom application entrypoints, failed suites and zero-selected
|
|
646
|
+
suites are not passes; unsupported runners need a repository-owned invocation override.
|
|
647
|
+
|
|
648
|
+
For a large solution, replace the placeholder below with the affected project directory,
|
|
649
|
+
TFM and AssemblyName and repeat for affected dependents. Use that executable's filter/report
|
|
650
|
+
flags (see [running-specs](../skills/cratis-specifications-csharp/references/running-specs.md)),
|
|
651
|
+
not VSTest logger switches. Override `command` rather than raising a timeout without diagnosis:
|
|
642
652
|
|
|
643
653
|
```json
|
|
644
|
-
{ "gates": [{ "id": "backend-specs", "command": ["
|
|
654
|
+
{ "gates": [{ "id": "backend-specs", "command": ["./<project-dir>/bin/Debug/<TFM>/<AssemblyName>"], "timeoutSeconds": 120, "timeoutHint": "Run each affected project's built spec executable separately; dotnet test <project> --configuration Debug --no-build only for VSTest." }] }
|
|
645
655
|
```
|
|
646
656
|
|
|
647
657
|
This is not automatic affected-project selection: imported/conditional MSBuild references and
|
|
648
658
|
linked or shared sources require evaluation to establish coverage safely. The default retains
|
|
649
|
-
solution
|
|
659
|
+
all solution projects, executing each test project independently rather than silently missing
|
|
660
|
+
dependents. Non-test projects are explicitly skipped; a solution with none reports no verified
|
|
661
|
+
specifications. A timeout is never a pass. Reports are local under `.ai-work/spec-runs/`.
|
|
650
662
|
|
|
651
663
|
**Profile note.** The C# patterns are application-profile and scoped to `Source/**/*.cs`, which is
|
|
652
664
|
the application source root [`../rules/general.md`](../rules/general.md) documents. A
|
|
@@ -26,9 +26,9 @@ Apply before an authorized `git commit`, including `rtk git commit` or `rtk prox
|
|
|
26
26
|
|
|
27
27
|
3. **Run specs for each affected .NET project**:
|
|
28
28
|
```
|
|
29
|
-
|
|
29
|
+
./<project-dir>/bin/<Config>/<TFM>/<AssemblyName>
|
|
30
30
|
```
|
|
31
|
-
Use
|
|
31
|
+
Use the project's verified built spec executable (or `dotnet <TargetPath.dll>` without apphost; see [running-specs](../skills/cratis-specifications-csharp/references/running-specs.md)). Only VSTest uses `dotnet test <project> --no-build`. Require current matching outputs; otherwise incrementally build the affected specs project first. If the owning specs project cannot be identified, inspect project references or report the uncertainty; do not default to a root-wide test run.
|
|
32
32
|
|
|
33
33
|
4. **Run specs for each affected TypeScript project**:
|
|
34
34
|
```
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Copyright (c) Cratis. All rights reserved.
|
|
3
|
+
# Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
4
|
+
|
|
5
|
+
# Read-only MSBuild evaluation followed by built runners. Children inherit the gate's process group.
|
|
6
|
+
exec node --input-type=module - "$@" <<'NODE'
|
|
7
|
+
import { spawnSync } from 'node:child_process';
|
|
8
|
+
import { existsSync, mkdirSync, mkdtempSync, readFileSync, readdirSync } from 'node:fs';
|
|
9
|
+
import { dirname, isAbsolute, join, resolve } from 'node:path';
|
|
10
|
+
import { parseArgs } from 'node:util';
|
|
11
|
+
|
|
12
|
+
function refuse(message) {
|
|
13
|
+
console.error(`cratis-run-specs: ${message}`);
|
|
14
|
+
process.exit(1);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const { values } = parseArgs({ args: process.argv.slice(2), options: {
|
|
18
|
+
project: { type: 'string' }, solution: { type: 'string' }, configuration: { type: 'string', default: 'Debug' },
|
|
19
|
+
framework: { type: 'string' }, 'no-build': { type: 'boolean' },
|
|
20
|
+
} });
|
|
21
|
+
if (!values['no-build']) refuse('--no-build is required; restore and build once before running specs.');
|
|
22
|
+
if (values.project && values.solution) refuse('Select either --project or --solution, not both.');
|
|
23
|
+
|
|
24
|
+
function dotnet(arguments_) {
|
|
25
|
+
const result = spawnSync('dotnet', arguments_, { encoding: 'utf8', maxBuffer: 32 * 1024 * 1024 });
|
|
26
|
+
if (result.error || result.status !== 0) refuse(`Metadata evaluation failed: dotnet ${arguments_.join(' ')}\n${result.error?.message ?? result.stderr}`);
|
|
27
|
+
return result.stdout;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const properties = 'IsTestProject,IsTestingPlatformApplication,UseMicrosoftTestingPlatformRunner,OutputType,TargetPath,TargetFramework,TargetFrameworks,AssemblyName,XunitAutoGeneratedEntryPoint';
|
|
31
|
+
function evaluate(project, framework) {
|
|
32
|
+
const arguments_ = ['msbuild', project, '-nologo', `-p:Configuration=${values.configuration}`];
|
|
33
|
+
if (framework) arguments_.push(`-p:TargetFramework=${framework}`);
|
|
34
|
+
arguments_.push(`-getProperty:${properties}`, '-getItem:PackageReference');
|
|
35
|
+
try {
|
|
36
|
+
const metadata = JSON.parse(dotnet(arguments_));
|
|
37
|
+
if (!metadata.Properties || !Array.isArray(metadata.Items?.PackageReference)) throw new Error('Missing evaluated Properties or PackageReference items');
|
|
38
|
+
return metadata;
|
|
39
|
+
} catch (error) {
|
|
40
|
+
refuse(`Cannot evaluate ${project}: ${error.message}. Restore/build the matching configuration first; configure a repository-owned gate override for unsupported projects.`);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
let projects;
|
|
45
|
+
if (values.project) projects = [resolve(values.project)];
|
|
46
|
+
else {
|
|
47
|
+
const solutions = values.solution ? [values.solution] : readdirSync('.').filter(name => /\.slnx?$/.test(name));
|
|
48
|
+
if (solutions.length !== 1) refuse('Expected one solution in the working directory; select --solution or --project explicitly in a gate override.');
|
|
49
|
+
const solution = resolve(solutions[0]);
|
|
50
|
+
// Ignore localized headings; accept only actual project entries, relative to the selected solution.
|
|
51
|
+
projects = dotnet(['sln', solution, 'list']).split(/\r?\n/).map(line => line.trim())
|
|
52
|
+
.filter(line => /\.(?:cs|fs|vb)proj$/i.test(line)).map(line => resolve(dirname(solution), line.replaceAll('\\', '/')));
|
|
53
|
+
if (!projects.length) refuse(`No project entries could be established for ${solution}; no specifications verified.`);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function classify(metadata, project) {
|
|
57
|
+
const properties = metadata.Properties;
|
|
58
|
+
const packages = new Set(metadata.Items.PackageReference.map(item => String(item.Identity).toLowerCase()));
|
|
59
|
+
const platform = properties.IsTestingPlatformApplication?.toLowerCase() === 'true';
|
|
60
|
+
const xunit = ['xunit.v3', 'xunit.v3.core', 'xunit.v3.mtp-off', 'xunit.v3.core.mtp-off',
|
|
61
|
+
'xunit.v3.mtp-v1', 'xunit.v3.core.mtp-v1', 'xunit.v3.mtp-v2', 'xunit.v3.core.mtp-v2']
|
|
62
|
+
.some(name => packages.has(name));
|
|
63
|
+
const native = packages.has('cratis.specifications.runner');
|
|
64
|
+
const tunit = packages.has('tunit');
|
|
65
|
+
const legacy = ['xunit', 'nunit', 'mstest.testframework'].some(name => packages.has(name));
|
|
66
|
+
const test = properties.IsTestProject?.toLowerCase() === 'true' || platform || xunit || native || tunit || legacy;
|
|
67
|
+
if (!test) return 'non-test';
|
|
68
|
+
if (properties.XunitAutoGeneratedEntryPoint?.toLowerCase() === 'false') refuse(`${project}: custom application entrypoint; configure a repository-owned spec invocation override (do not start the server).`);
|
|
69
|
+
if (['exe', 'winexe'].includes(properties.OutputType?.toLowerCase())) {
|
|
70
|
+
if (xunit && (packages.has('xunit.v3.mtp-off') || packages.has('xunit.v3.core.mtp-off')
|
|
71
|
+
|| properties.UseMicrosoftTestingPlatformRunner?.toLowerCase() !== 'true')) return 'xunit-mtp-off';
|
|
72
|
+
if (platform || xunit || native || tunit) return 'mtp';
|
|
73
|
+
}
|
|
74
|
+
// Test.Sdk can generate an Exe entrypoint for legacy VSTest projects too.
|
|
75
|
+
if (properties.IsTestProject?.toLowerCase() === 'true' && !platform && !xunit && !native && !tunit && legacy && packages.has('microsoft.net.test.sdk')) return 'vstest';
|
|
76
|
+
refuse(`${project}: unsupported/unknown test runner; configure a repository-owned backend-specs override instead of falling back to dotnet test.`);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
let reportRoot;
|
|
80
|
+
function reportPath() {
|
|
81
|
+
if (!reportRoot) {
|
|
82
|
+
const repository = spawnSync('git', ['rev-parse', '--show-toplevel'], { encoding: 'utf8' });
|
|
83
|
+
const root = repository.status === 0 ? repository.stdout.trim() : process.cwd();
|
|
84
|
+
const artifacts = join(root, '.ai-work', 'spec-runs');
|
|
85
|
+
mkdirSync(artifacts, { recursive: true });
|
|
86
|
+
reportRoot = mkdtempSync(join(artifacts, 'run-'));
|
|
87
|
+
}
|
|
88
|
+
return join(reportRoot, `${executed}.trx`);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function verifyCounts(runner, output, report, project) {
|
|
92
|
+
let total;
|
|
93
|
+
let passed;
|
|
94
|
+
let failed;
|
|
95
|
+
let skipped;
|
|
96
|
+
if (runner === 'xunit-mtp-off' && existsSync(report)) {
|
|
97
|
+
const counters = /<(?:\w+:)?Counters\b([^>]*)\/?\s*>/.exec(readFileSync(report, 'utf8'))?.[1];
|
|
98
|
+
const count = name => { const value = new RegExp(`\\b${name}="(\\d+)"`).exec(counters ?? ''); return value ? Number(value[1]) : undefined; };
|
|
99
|
+
total = count('total'); passed = count('passed'); failed = count('failed'); skipped = count('notExecuted') ?? 0;
|
|
100
|
+
} else if (runner !== 'xunit-mtp-off') {
|
|
101
|
+
const count = expression => { const match = expression.exec(output); return match ? Number(match[1]) : undefined; };
|
|
102
|
+
total = count(/\btotal:\s*(\d+)/i);
|
|
103
|
+
passed = count(/\b(?:succeeded|passed):\s*(\d+)/i);
|
|
104
|
+
failed = count(/\bfailed:\s*(\d+)/i);
|
|
105
|
+
skipped = count(/\bskipped:\s*(\d+)/i) ?? 0;
|
|
106
|
+
}
|
|
107
|
+
if (total === 0) refuse(`${project}: zero tests executed; no specifications verified.`);
|
|
108
|
+
if (total === undefined || passed === undefined || failed === undefined) refuse(`${project}: UNVERIFIED — runner count evidence unavailable. Configure a repository-owned invocation with verified reports.`);
|
|
109
|
+
if (failed !== 0 || passed + skipped !== total || passed === 0) refuse(`${project}: not all specifications passed (total=${total}, passed=${passed}, failed=${failed}).`);
|
|
110
|
+
console.log(`cratis-run-specs: verified total=${total}, passed=${passed}, failed=${failed}`);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
let executed = 0;
|
|
114
|
+
for (const project of projects) {
|
|
115
|
+
if (!existsSync(project)) refuse(`Solution project does not exist: ${project}`);
|
|
116
|
+
const initial = evaluate(project);
|
|
117
|
+
const frameworks = (initial.Properties.TargetFrameworks || initial.Properties.TargetFramework || '').split(';').filter(Boolean);
|
|
118
|
+
const runner = classify(initial, project);
|
|
119
|
+
if (runner === 'non-test') { console.log(`cratis-run-specs: SKIP non-test ${project}`); continue; }
|
|
120
|
+
if (!frameworks.length) refuse(`${project}: target framework unavailable; evaluate the restored project or supply an override.`);
|
|
121
|
+
if (values.framework && !frameworks.includes(values.framework)) refuse(`${project}: requested framework ${values.framework} not in ${frameworks.join(', ')}.`);
|
|
122
|
+
for (const framework of values.framework ? [values.framework] : frameworks) {
|
|
123
|
+
const metadata = initial.Properties.TargetFrameworks ? evaluate(project, framework) : initial;
|
|
124
|
+
const selectedRunner = classify(metadata, project);
|
|
125
|
+
if (selectedRunner === 'non-test') refuse(`${project} (${framework}): inconsistent test metadata; no suite may be omitted.`);
|
|
126
|
+
const target = metadata.Properties.TargetPath;
|
|
127
|
+
if (!target || !isAbsolute(target)) refuse(`${project}: evaluated TargetPath unavailable; perform the matching ${values.configuration}/${framework} build first.`);
|
|
128
|
+
const apphost = target.replace(/\.dll$/i, process.platform === 'win32' ? '.exe' : '');
|
|
129
|
+
const useApphost = apphost !== target && existsSync(apphost);
|
|
130
|
+
if (!useApphost && !existsSync(target)) refuse(`${project}: missing built output ${target}; perform the matching ${values.configuration}/${framework} build first.`);
|
|
131
|
+
const report = selectedRunner === 'xunit-mtp-off' ? reportPath() : undefined;
|
|
132
|
+
const command = selectedRunner === 'vstest' || !useApphost ? 'dotnet' : apphost;
|
|
133
|
+
const arguments_ = selectedRunner === 'vstest'
|
|
134
|
+
? ['test', project, '--configuration', values.configuration, '--no-build', '--framework', framework]
|
|
135
|
+
: [...(useApphost ? [] : [target]), ...(report ? ['-trx', report] : [])];
|
|
136
|
+
console.log(`cratis-run-specs: RUN ${project} runner=${selectedRunner} framework=${framework} configuration=${values.configuration}`);
|
|
137
|
+
const result = spawnSync(command, arguments_, { encoding: 'utf8', maxBuffer: 32 * 1024 * 1024 });
|
|
138
|
+
process.stdout.write(result.stdout ?? '');
|
|
139
|
+
process.stderr.write(result.stderr ?? '');
|
|
140
|
+
if (result.error) refuse(`${project}: ${result.error.message}`);
|
|
141
|
+
if (result.status !== 0) process.exit(result.status ?? 1);
|
|
142
|
+
verifyCounts(selectedRunner, (result.stdout ?? '') + (result.stderr ?? ''), report, project);
|
|
143
|
+
executed++;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
console.log(executed ? `cratis-run-specs: verified ${executed} project/framework suite(s).` : 'cratis-run-specs: NO-OP — no test projects; no specifications verified.');
|
|
147
|
+
NODE
|
|
@@ -117,9 +117,9 @@
|
|
|
117
117
|
},
|
|
118
118
|
{
|
|
119
119
|
"id": "backend-specs",
|
|
120
|
-
"description": "
|
|
120
|
+
"description": "Built C# spec executables (Debug, no rebuild); VSTest-only fallback \u2014 zero failures",
|
|
121
121
|
"timeoutSeconds": 120,
|
|
122
|
-
"timeoutHint": "dotnet test <
|
|
122
|
+
"timeoutHint": "./<affected-project-dir>/bin/Debug/<TFM>/<AssemblyName> (or dotnet <TargetPath.dll> without apphost); only VSTest: dotnet test <project> --configuration Debug --no-build. Repeat for affected dependents.",
|
|
123
123
|
"changed": [
|
|
124
124
|
"**/*.cs",
|
|
125
125
|
"**/*.csproj",
|
|
@@ -145,11 +145,9 @@
|
|
|
145
145
|
"**/*.sln"
|
|
146
146
|
],
|
|
147
147
|
"command": [
|
|
148
|
-
"
|
|
149
|
-
"
|
|
150
|
-
"--configuration"
|
|
151
|
-
"Debug",
|
|
152
|
-
"--no-build"
|
|
148
|
+
"bash",
|
|
149
|
+
"-c",
|
|
150
|
+
"exec bash \"$CRATIS_HOOKS_SCRIPTS_DIR/cratis-run-specs.sh\" --configuration Debug --no-build"
|
|
153
151
|
]
|
|
154
152
|
},
|
|
155
153
|
{
|
|
@@ -12,8 +12,8 @@ The goal is minimal ceremony, maximum clarity. Modern C# (13+) gives us records,
|
|
|
12
12
|
## Building
|
|
13
13
|
|
|
14
14
|
- Use `dotnet build` from the command line.
|
|
15
|
-
-
|
|
16
|
-
-
|
|
15
|
+
- Follow `.editorconfig`; run `dotnet format` only when CI requires it.
|
|
16
|
+
- Run affected spec executables; use `dotnet test <project> --no-build` only for VSTest (see `specs.csharp.md`).
|
|
17
17
|
|
|
18
18
|
## Formatting
|
|
19
19
|
|
|
@@ -59,7 +59,7 @@ Repo conventions follow from this: `Source/DotNET` + `Source/JavaScript` for dua
|
|
|
59
59
|
## Quality gates (framework)
|
|
60
60
|
|
|
61
61
|
- Build clean (Debug and Release) with **zero warnings, zero errors**.
|
|
62
|
-
- Specs pass for affected projects (C#
|
|
62
|
+
- Specs pass for affected projects (C# spec executables (VSTest only: `dotnet test <project> --no-build`); TS packages via their test command; Components also `build-storybook`).
|
|
63
63
|
- For public-facing changes (APIs, attributes, generated output, component props): update the product documentation and verify it.
|
|
64
64
|
- Match the repo's existing patterns; when a deep architectural question isn't answered by the universal rules or this file, consult the **repo's own docs/CONTRIBUTING** or ask — do not infer framework internals from a single call site.
|
|
65
65
|
|
|
@@ -62,7 +62,8 @@ using Microsoft.AspNetCore.Builder;
|
|
|
62
62
|
using MongoDB.Driver;
|
|
63
63
|
|
|
64
64
|
var builder = WebApplication.CreateBuilder(args);
|
|
65
|
-
|
|
65
|
+
var connectionString = builder.Configuration.GetConnectionString("Mongo")
|
|
66
|
+
?? throw new InvalidOperationException("Configure the Mongo connection string.");
|
|
66
67
|
builder.AddCratisOrleans(new CratisOrleansOptions
|
|
67
68
|
{
|
|
68
69
|
ClusterId = "my-service",
|
|
@@ -31,6 +31,6 @@ applyTo: "**/*"
|
|
|
31
31
|
## Before you create or edit a PR
|
|
32
32
|
|
|
33
33
|
- Run `node .cratis/ai/hooks/scripts/cratis-check-pr.mjs --body-file <file> --label <intent>`; it applies the exact `policy / verify` release-note rules and the Bash hook runs it on `gh pr create` and `gh pr edit`. If it fails, fix the description, not the code. Before every body edit, run `git diff --stat origin/main...HEAD` and delete bullets the diff no longer supports.
|
|
34
|
-
- Run the affected-project gates before marking work ready (
|
|
34
|
+
- Run the affected-project gates before marking work ready (build, built specs, lint and type-check; zero warnings), and the repository's required CI checks after an authorized push. `no-release` and documentation-only PRs still satisfy every required check; none is a blanket exemption from red CI.
|
|
35
35
|
- Group small related changes into one branch and one PR; see the skill for consolidation and the release-action windows.
|
|
36
36
|
- Open the PR once, when verified: each push starts CI. One PR per body of work, opened by the orchestrator (`cratis-engineering-release-trains`), with `--assignee @me`.
|
|
@@ -49,7 +49,7 @@ public class when_combining_parts : Specification
|
|
|
49
49
|
|
|
50
50
|
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. Keep shared lifecycle on; `[PerFactSpecificationLifecycle]` opts out only the class whose facts genuinely mutate shared state and cannot move the mutation into `Because`. `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
51
|
|
|
52
|
-
Run specifications as
|
|
52
|
+
Run xUnit v3, TUnit and native-runner specifications as each project's built executable: restore and build once, then run its matching configuration/TFM output. Only identified VSTest projects use `dotnet test <project> --no-build`. Never default to solution-wide `dotnet test` in a mixed suite. 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).
|
|
53
53
|
|
|
54
54
|
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.
|
|
55
55
|
|
|
@@ -16,7 +16,7 @@ Cratis rules in `.cratis/ai/rules/` (including `csharp.md`, `specs.csharp.md`, a
|
|
|
16
16
|
|
|
17
17
|
You MUST add the `/bl:{}` flag to:
|
|
18
18
|
- `dotnet build`
|
|
19
|
-
- `dotnet test`
|
|
19
|
+
- `dotnet test` when it is the selected VSTest runner; built spec executables do not produce MSBuild binlogs
|
|
20
20
|
- `dotnet pack`
|
|
21
21
|
- `dotnet publish`
|
|
22
22
|
- `dotnet restore`
|
|
@@ -202,7 +202,7 @@ if ($testProjects.Count -eq 0) {
|
|
|
202
202
|
Write-Host "TEST_OUTPUT_ROOT:$testOutputRoot"
|
|
203
203
|
```
|
|
204
204
|
|
|
205
|
-
- If `ENTRY_TYPE:NotFound` and SDK-style test projects were found →
|
|
205
|
+
- If `ENTRY_TYPE:NotFound` and SDK-style test projects were found → pass the selected projects to `run-tests` discovery: supported executable suites use their built runners; only VSTest uses `dotnet test <project> --no-build`.
|
|
206
206
|
- If `ENTRY_TYPE:NotFound` and classic test projects were found → use only the repository's documented coverage command; do not infer `dotnet test`.
|
|
207
207
|
- If `ENTRY_TYPE:NotFound` and no test projects found → stop: `No .sln, .slnx, or test projects found under <path>. Provide the path to your .NET solution, filter, or project.`
|
|
208
208
|
- A missing/unreadable requested path, failed lookup, or ambiguous entry point is a discovery blocker, not measured zero coverage or evidence of an empty suite. Do not continue collection after a discovery error.
|
|
@@ -302,6 +302,6 @@ ideas recorded in `references/provenance.md`. Read `references/provenance.md` wh
|
|
|
302
302
|
## How it is proven
|
|
303
303
|
|
|
304
304
|
`dotnet build -c Debug` — it compiles the `#if DEBUG` specification code — then
|
|
305
|
-
|
|
305
|
+
the owning project's built spec executable (see [specs.csharp](../../rules/specs.csharp.md)), both clean, with a specification for the happy path and one per
|
|
306
306
|
rejection. Before trusting a rejection specification green, remove the condition
|
|
307
307
|
that causes the rejection once and confirm it goes red.
|
|
@@ -59,7 +59,7 @@ These non-refusal failures and unhandled refusals fail the observer for recovery
|
|
|
59
59
|
## Verify
|
|
60
60
|
|
|
61
61
|
Run `dotnet build -c Debug` and the affected specification project with
|
|
62
|
-
|
|
62
|
+
the owning project's built spec executable (see [specs.csharp](../../../rules/specs.csharp.md)). Cover selector ordering, each handled refusal, unchanged
|
|
63
63
|
remaining-command collaborators, branch append failure, and a concurrency or
|
|
64
64
|
exception failure that must not be acknowledged. Assert earlier committed effects
|
|
65
65
|
separately; a failed result does not prove rollback.
|
package/package/corpus/skills/cratis-arc-command-execution/references/occurrence-commands.md
CHANGED
|
@@ -76,4 +76,4 @@ append behavior. Deliver the same occurrence twice under the same effect name:
|
|
|
76
76
|
assert one committed effect and a recorded result on the second delivery. Cover
|
|
77
77
|
a terminal refusal, a retryable concurrency conflict, insufficient capability,
|
|
78
78
|
and commit-then-lost-reply recovery. Run the owning specification project with
|
|
79
|
-
|
|
79
|
+
the owning project's built spec executable (see [specs.csharp](../../../rules/specs.csharp.md)); passing means those assertions ran, not just that compilation succeeded.
|
|
@@ -237,7 +237,7 @@ not uncertain remote acknowledgments or the external provider's durability.
|
|
|
237
237
|
`UncompensatedCount`/`FailedCompensationCount`, and remaining callbacks attempted.
|
|
238
238
|
|
|
239
239
|
Arc's [failure recipes](https://github.com/Cratis/Arc/blob/main/Documentation/backend/csharp/testing/command-operation-failures.md)
|
|
240
|
-
contain the full cases. Run
|
|
240
|
+
contain the full cases. Run the owning project's built spec executable (see [specs.csharp](../../../rules/specs.csharp.md)); assert behavior,
|
|
241
241
|
not just command success. These corpus excerpts are source-checked, not compiled
|
|
242
242
|
by the corpus text-verification gate. Test provider ownership, repeated finalized
|
|
243
243
|
requests, conflicting keys, and delayed creates at the provider integration boundary.
|
|
@@ -61,6 +61,6 @@ Arc can fail to bind such results to the matching form field.
|
|
|
61
61
|
|
|
62
62
|
Add specs for offset-less rejection, an accepted offset, malformed input under
|
|
63
63
|
both authorized and denied callers, and nested/indexed member paths. Assert
|
|
64
|
-
server `Members` using camelCase and run
|
|
64
|
+
server `Members` using camelCase and run the owning spec project's built executable (see [specs.csharp](../../../rules/specs.csharp.md)).
|
|
65
65
|
For form behavior, assert the rejection appears on its intended field, not only
|
|
66
66
|
in a command-wide error list.
|
package/package/corpus/skills/cratis-arc-command-validation/references/validation-severity.md
CHANGED
|
@@ -18,4 +18,4 @@ remove the floor, and an explicit attribute wins. Check with
|
|
|
18
18
|
|
|
19
19
|
Specify both the default refusal and a caller sending a permissive severity.
|
|
20
20
|
Assert the command did not write events; a displayed message alone is not proof
|
|
21
|
-
that validation blocked execution. Run
|
|
21
|
+
that validation blocked execution. Run the owning spec project's built executable (see [specs.csharp](../../../rules/specs.csharp.md)).
|
package/package/corpus/skills/cratis-chronicle-client-dotnet/references/immediate-append-refusal.md
CHANGED
|
@@ -36,5 +36,5 @@ In a spec, attempt an immediate append through both the current event log and a
|
|
|
36
36
|
previously captured reference; assert that neither reaches transport. Assert
|
|
37
37
|
that transactional work commits with its receipt, that an unsupported kernel
|
|
38
38
|
fails closed, and that borrowed frames cannot complete another owner's unit.
|
|
39
|
-
Run
|
|
39
|
+
Run the owning project's built spec executable (see [specs.csharp](../../../rules/specs.csharp.md)). In-process proof is not a substitute for
|
|
40
40
|
integration coverage of the storage provider's transaction boundary.
|
|
@@ -81,7 +81,7 @@ a handler through in-process ingress, claims, receipts and completion:
|
|
|
81
81
|
|
|
82
82
|
There are no background workers, automatic lease renewals or reminders in this
|
|
83
83
|
scenario; it does not prove behavior in a real multi-node cluster. Run
|
|
84
|
-
|
|
84
|
+
the owning spec project's built executable (see [specs.csharp](../../../rules/specs.csharp.md)) and assert duplicate ingress, redelivery,
|
|
85
85
|
terminal refusal, lost reply and unsupported-capability paths.
|
|
86
86
|
|
|
87
87
|
Requires Chronicle 19.78.0 for `Defaults` and `EventStoreForTesting` constructors
|
package/package/corpus/skills/cratis-chronicle-event-constraints/references/storage-uniqueness.md
CHANGED
|
@@ -22,7 +22,7 @@ complete: the first claimant in event-log order retains the value, later duplica
|
|
|
22
22
|
claims are logged and skipped. Reindexing does not retract their stored events.
|
|
23
23
|
Older kernels can fail the reindex instead.
|
|
24
24
|
|
|
25
|
-
Run the affected specifications with
|
|
25
|
+
Run the affected specifications with the owning project's built spec executable (see [specs.csharp](../../../rules/specs.csharp.md)), asserting a second source's
|
|
26
26
|
rejection, unchanged original claim after a failed move, and successful reuse
|
|
27
27
|
after release. Real SQL integration must prove two competing claims cannot both
|
|
28
28
|
succeed; an in-memory pass does not prove the SQL index was upgraded.
|
|
@@ -229,6 +229,6 @@ assert the value can be claimed again.
|
|
|
229
229
|
## How it is proven
|
|
230
230
|
|
|
231
231
|
`dotnet build` in Debug (which compiles the `#if DEBUG` specification code) and
|
|
232
|
-
|
|
232
|
+
the owning project's built spec executable (see [specs.csharp](../../rules/specs.csharp.md)), both clean. A constraint specification is only meaningful if it
|
|
233
233
|
has been seen to fail: remove the seeding `Given` once and confirm the
|
|
234
234
|
specification goes red before trusting it green.
|
|
@@ -41,6 +41,6 @@ the store-local alias. Custom schema generators resolving explicit compensation
|
|
|
41
41
|
targets need the registry-aware overloads or throw
|
|
42
42
|
`RegistryAwareEventTypeSchemasNotSupported`.
|
|
43
43
|
|
|
44
|
-
Run `dotnet build -c Debug` and migration
|
|
44
|
+
Run `dotnet build -c Debug` and migration spec executables (see [specs.csharp](../../../rules/specs.csharp.md)); assert both
|
|
45
45
|
directions and real observer delivery where pinning or protected-value release
|
|
46
46
|
matters. A successful nomination alone does not prove a generation can be read.
|
|
@@ -29,5 +29,5 @@ handler is still subscribed to.
|
|
|
29
29
|
|
|
30
30
|
Verify first registration, restart with an existing position, replay and
|
|
31
31
|
failed-partition redelivery separately. Assert the external effect count, not
|
|
32
|
-
only that the handler was invoked. Run
|
|
32
|
+
only that the handler was invoked. Run the owning spec project's built executable (see [specs.csharp](../../../rules/specs.csharp.md));
|
|
33
33
|
server-first compatibility and durable positions also need kernel integration.
|
package/package/corpus/skills/cratis-chronicle-read-model/references/collection-observation.md
CHANGED
|
@@ -41,7 +41,7 @@ pretending observation succeeded.
|
|
|
41
41
|
|
|
42
42
|
## Verify
|
|
43
43
|
|
|
44
|
-
Run `dotnet build -c Debug` and
|
|
44
|
+
Run `dotnet build -c Debug` and the owning query spec executable (see [specs.csharp](../../../rules/specs.csharp.md)). Cover
|
|
45
45
|
empty, add, update, remove, filter exit and disposal.
|
|
46
46
|
Requires Arc 22.87.0 for Chronicle observations in `QueryScenario`.
|
|
47
47
|
Requires Arc 22.91.1 with Chronicle 19.59.1 for default-mode children/joins/reducers. Scenario rebuilds do
|
|
@@ -283,6 +283,6 @@ Read `references/view-lifecycle-checks.md` when delivering a read model from a c
|
|
|
283
283
|
|
|
284
284
|
## How it is proven
|
|
285
285
|
|
|
286
|
-
`dotnet build` in Debug and
|
|
286
|
+
`dotnet build` in Debug and the owning project's built spec executable (see [specs.csharp](../../rules/specs.csharp.md)), both clean. A projection
|
|
287
287
|
specification is only meaningful once it has been seen to fail: drop one seeded
|
|
288
288
|
event and confirm the assertion goes red before trusting it green.
|
|
@@ -75,7 +75,7 @@ named reference before applying one.
|
|
|
75
75
|
**Build once, shard the tests.** Fits execution-bound workflows where build and
|
|
76
76
|
tests run serially or several jobs each rebuild. Default: one job builds in
|
|
77
77
|
`Release`, uploads the output with `actions/upload-artifact`, and a matrix of shard jobs downloads it and runs
|
|
78
|
-
`dotnet test --no-build`. Pitfall: a shard whose filter matches nothing still
|
|
78
|
+
each built spec executable; only VSTest projects use `dotnet test <project> --no-build`. Pitfall: a shard whose filter matches nothing still
|
|
79
79
|
passes, so assert that every shard ran tests. Read
|
|
80
80
|
`references/build-once-and-shard.md` when applying or reviewing this.
|
|
81
81
|
|
package/package/corpus/skills/cratis-ci-pipeline-performance/references/build-once-and-shard.md
CHANGED
|
@@ -75,15 +75,19 @@ jobs:
|
|
|
75
75
|
with:
|
|
76
76
|
name: build-output
|
|
77
77
|
- run: tar --zstd -xf build-output.tar.zst
|
|
78
|
+
# Example assumes each xUnit v3 mtp-off AssemblyName matches its directory.
|
|
79
|
+
# Use evaluated TargetPath for custom outputs; TUnit/native runners need their own report flags.
|
|
80
|
+
# Only VSTest uses dotnet test <project> --no-build --configuration Release with --logger/--results-directory.
|
|
78
81
|
- name: Test the shard's projects
|
|
79
82
|
env:
|
|
80
83
|
PROJECTS: ${{ matrix.projects }}
|
|
81
84
|
run: |
|
|
82
85
|
failed=0
|
|
83
86
|
for project in $PROJECTS; do
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
+
mkdir -p "$RUNNER_TEMP/test-results"
|
|
88
|
+
# xUnit v3 mtp-off example: resolve each project's actual AssemblyName/TFM.
|
|
89
|
+
"$project/bin/Release/net10.0/$(basename "$project")" \
|
|
90
|
+
-trx "$RUNNER_TEMP/test-results/$(basename "$project").trx" || failed=1
|
|
87
91
|
done
|
|
88
92
|
exit "$failed"
|
|
89
93
|
- name: Verify every project ran tests
|
package/package/corpus/skills/cratis-ci-pipeline-performance/references/flaky-and-hung-jobs.md
CHANGED
|
@@ -24,7 +24,7 @@ cost runner-minutes and developer trust; diagnose before retrying.
|
|
|
24
24
|
## Find hangs and crashes in .NET
|
|
25
25
|
|
|
26
26
|
```bash
|
|
27
|
-
dotnet test
|
|
27
|
+
dotnet test VSTest.Specs.csproj --configuration Release --no-build \
|
|
28
28
|
--blame-hang --blame-hang-timeout 5m --blame-hang-dump-type mini \
|
|
29
29
|
--blame-crash --blame-crash-dump-type mini \
|
|
30
30
|
--results-directory TestResults
|
|
@@ -32,7 +32,7 @@ Measure before guessing, with the language's profiler on the test process:
|
|
|
32
32
|
|
|
33
33
|
```bash
|
|
34
34
|
dotnet tool install --global dotnet-trace
|
|
35
|
-
dotnet-trace collect --format speedscope --
|
|
35
|
+
dotnet-trace collect --format speedscope -- ./<project-dir>/bin/Release/<TFM>/<AssemblyName>
|
|
36
36
|
```
|
|
37
37
|
|
|
38
38
|
Read the inclusive time of the setup methods. Pass means the profile names the
|
package/package/corpus/skills/cratis-commits-and-pull-requests/references/pr-labels-and-release.md
CHANGED
|
@@ -81,7 +81,7 @@ Documentation-only changes use repository-supported non-release intent, ordinari
|
|
|
81
81
|
Before marking code/automation work ready, select the affected-project gates that apply from the following list; run wider checks for cross-cutting changes and repository-required merge/release gates:
|
|
82
82
|
|
|
83
83
|
- `dotnet build`: zero errors, zero warnings
|
|
84
|
-
- `dotnet test
|
|
84
|
+
- Built C# spec executables: all specs pass; `dotnet test <project> --no-build` only for VSTest (see specs.csharp)
|
|
85
85
|
- `yarn lint`: zero errors
|
|
86
86
|
- `npx tsc -b`: zero TypeScript errors
|
|
87
87
|
- Code follows all project coding standards and conventions
|
|
@@ -81,8 +81,9 @@ a red run to discover the next failure.
|
|
|
81
81
|
|
|
82
82
|
Several agents, worktrees or builds often share one machine. Keep it responsive:
|
|
83
83
|
|
|
84
|
-
- Cap parallelism, for example `dotnet build -m:2`,
|
|
85
|
-
|
|
84
|
+
- Cap parallelism, for example `dotnet build -m:2`, built spec executables with their
|
|
85
|
+
runner-specific thread limit, and `vitest run --maxWorkers=2`. Do not pass MSBuild
|
|
86
|
+
`-m` to executables; `dotnet test <project> --no-build -m:2` is VSTest-only.
|
|
86
87
|
- Run one heavy phase at a time (build, then specs, then frontend lint and
|
|
87
88
|
tests), never several at once.
|
|
88
89
|
- Do not start a heavy phase while another agent's runs in the same machine's
|
|
@@ -162,9 +162,13 @@ From the consumer root, with the printed NuGet environment sourced:
|
|
|
162
162
|
|
|
163
163
|
```bash
|
|
164
164
|
dotnet build path/to/consumer.slnx -c Release -warnaserror
|
|
165
|
-
|
|
165
|
+
./<integration-project-dir>/bin/Release/<TFM>/<AssemblyName> <runner-specific-filter>
|
|
166
166
|
```
|
|
167
167
|
|
|
168
|
+
Resolve the integration project's actual built spec entrypoint and filter syntax with
|
|
169
|
+
[running-specs](../cratis-specifications-csharp/references/running-specs.md); without
|
|
170
|
+
apphost use `dotnet <TargetPath.dll>`. Only VSTest uses `dotnet test <project> -c Release
|
|
171
|
+
--no-build --filter '<regression>'`. Keep the sourced local NuGet environment.
|
|
168
172
|
Substitute the repository's actual commands; for frontend fixes run build, lint,
|
|
169
173
|
specs and the previously broken UI action. Pass: the reproducing spec/action now
|
|
170
174
|
succeeds, at least one intended filtered spec actually ran, and the consumer's
|
|
@@ -50,10 +50,14 @@ step. Apply the entry point's check/restore/cleanup sequence to both repositorie
|
|
|
50
50
|
export CHRONICLE_KERNEL_VERSION="$stamp"
|
|
51
51
|
cd "$consumer"
|
|
52
52
|
dotnet build path/to/Studio.slnx -c Release -p:StudioFullBuild=true -warnaserror
|
|
53
|
-
|
|
54
|
-
--filter '<regression>'
|
|
53
|
+
./<integration-project-dir>/bin/Release/<TFM>/<AssemblyName> <runner-specific-filter>
|
|
55
54
|
```
|
|
56
55
|
|
|
56
|
+
Resolve the actual output and filter for `Source/Integrations/Specs/Specs.csproj`
|
|
57
|
+
via [running-specs](../../cratis-specifications-csharp/references/running-specs.md).
|
|
58
|
+
Without apphost use `dotnet <TargetPath.dll>`; only VSTest uses
|
|
59
|
+
`dotnet test <project> -c Release --no-build --filter '<regression>'`.
|
|
60
|
+
Inspect the current consumer workflow before claiming CI equivalence.
|
|
57
61
|
Studio defaults kernel selection to the client version when the environment
|
|
58
62
|
override is absent. Ensure logs show the stamped local image. Local Debug
|
|
59
63
|
Studio builds skip analyzers; use `-p:StudioFullBuild=true` to match CI analyzer
|
|
@@ -83,9 +87,11 @@ bash "$local" use-nuget "$arc" "$stamp"
|
|
|
83
87
|
Gates (Arc `dotnet-build.yml`), run in this order after sourcing the printed env:
|
|
84
88
|
`yarn install --immutable`; in `Source/DotNET/Screenplay.Embedded`: `npm ci --workspaces=false`,
|
|
85
89
|
`npm run typecheck`, `npm test`, `npm run build`; `dotnet build --configuration Release
|
|
86
|
-
-p:CratisSpecsTargetFramework=net10.0`; then
|
|
87
|
-
|
|
88
|
-
--shard specs-N` prints.
|
|
90
|
+
-p:CratisSpecsTargetFramework=net10.0`; then each project's evaluated Release/net10.0
|
|
91
|
+
spec executable (or `dotnet <TargetPath.dll>` without apphost) for each project that
|
|
92
|
+
`python3 scripts/ci-test-shards.py projects --shard specs-N` prints. Only identified
|
|
93
|
+
VSTest projects use `dotnet test <project> --no-build --configuration Release --framework
|
|
94
|
+
net10.0`. Inspect the current consumer workflow before claiming equivalence. Finish by listing Arc's `obj/project.assets.json` files for the stamp.
|
|
89
95
|
|
|
90
96
|
- Pass: the Fundamentals IDs in `project.assets.json` are at the stamp, build has 0 warnings and 0 errors, 18 spec projects run and none fail.
|
|
91
97
|
- Time: pack about 4 min, build about 6 min, the spec projects about 18 min.
|
|
@@ -134,9 +140,12 @@ bash "$local" use-nuget "$direct" "$stamp"
|
|
|
134
140
|
```
|
|
135
141
|
|
|
136
142
|
Gates (Direct `build.yml`): `dotnet build Source/Direct/Direct.csproj -c Release
|
|
137
|
-
-p:DisableProxyGenerator=true`, the same in Debug with `-warnaserror`,
|
|
138
|
-
|
|
139
|
-
|
|
143
|
+
-p:DisableProxyGenerator=true`, the same in Debug with `-warnaserror`, then the project's
|
|
144
|
+
verified built Debug spec entrypoint. Build `Source/Assurance/Assurance.csproj` in the
|
|
145
|
+
matching configuration and run its verified spec entrypoint too; do not guess assembly
|
|
146
|
+
names or start an application server. See [running-specs](../../cratis-specifications-csharp/references/running-specs.md);
|
|
147
|
+
only VSTest uses `dotnet test <project> --no-build` in that configuration. Inspect the
|
|
148
|
+
current consumer workflow before claiming equivalence. Then check `project.assets.json`. Image-based specs also need the producer image tag.
|
|
140
149
|
|
|
141
150
|
- Pass for a consumer whose pins lag the producer: every Chronicle ID is in the feed at the
|
|
142
151
|
stamp, the Release build with the owner's floors passes, and `project.assets.json` shows every
|
|
@@ -59,7 +59,7 @@ Cap export retries at five and surface the final failure.
|
|
|
59
59
|
|
|
60
60
|
## Verified facts (with evidence)
|
|
61
61
|
- Cap and spec committed: `git log -1` shows the SHA above.
|
|
62
|
-
- Spec project passes:
|
|
62
|
+
- Spec project passes: `./Source/Export.Specs/bin/Debug/net10.0/Export.Specs` exit 0 at that SHA.
|
|
63
63
|
- Pull request is open: `gh pr list --head export-retry` shows one entry; CI run
|
|
64
64
|
`1234567890` is in progress.
|
|
65
65
|
|
|
@@ -60,12 +60,12 @@ C# rules.
|
|
|
60
60
|
**Decisions already made:** the cap is five and is a constant, not
|
|
61
61
|
configuration.
|
|
62
62
|
|
|
63
|
-
**Gate command:**
|
|
63
|
+
**Gate command:** `./Source/Export.Specs/bin/Debug/net10.0/Export.Specs`.
|
|
64
64
|
|
|
65
65
|
**Done =**
|
|
66
66
|
- [ ] A failing upload stops after five attempts and reports the error
|
|
67
67
|
- [ ] A spec covers the fifth failure and a success on the third attempt
|
|
68
|
-
- [ ]
|
|
68
|
+
- [ ] `./Source/Export.Specs/bin/Debug/net10.0/Export.Specs` exits 0
|
|
69
69
|
- [ ] `git diff --stat` shows only the owned files
|
|
70
70
|
|
|
71
71
|
**Stop and report if:** a public type must change, or another file needs edits.
|
package/package/corpus/skills/cratis-screenplay-render-and-gap-fill/references/delivery-protocol.md
CHANGED
|
@@ -33,8 +33,8 @@ per tool call and read each result from its exit status, never from a grep of th
|
|
|
33
33
|
| Drift or pending-change check | the same command plus `--check` (and `--scope`, `--force` as used) | no write, no recovery: exit 0 current, 6 `changes_pending`, 5 planning failure, refusal or pending recovery |
|
|
34
34
|
| Bundled-binder check | `cratis screenplay validate --executable <root>` | exit 5 with "does not bind into an executable semantic model" when it does not; never renders or writes. Uses the bundled compiler, not the standalone pin |
|
|
35
35
|
| Debug build | `dotnet build <dir>/<Project>.csproj -c Debug` | the build's exit status |
|
|
36
|
-
| Debug tests | `dotnet test <dir>/<Project>.csproj -c Debug --no-build` | the test runner's exit status plus per-test results |
|
|
37
|
-
| List the generated classes | `dotnet test <dir>/<Project>.csproj -c Debug --no-build --list-tests` | the names to map to specifications |
|
|
36
|
+
| Debug tests | `dotnet test <dir>/<Project>.csproj -c Debug --no-build` after the Debug build (Stage-rendered apps use VSTest) | the test runner's exit status plus per-test results |
|
|
37
|
+
| List the generated classes | `dotnet test <dir>/<Project>.csproj -c Debug --no-build --list-tests` | the names to map to specifications; listing is not execution |
|
|
38
38
|
|
|
39
39
|
`<Project>` is the project name the render used: the `--project-name` value when one was given,
|
|
40
40
|
otherwise the application name. Confirm it from the published `*.csproj` in the destination
|
|
@@ -284,8 +284,9 @@ For view specifications:
|
|
|
284
284
|
## Run the specs before calling the work done
|
|
285
285
|
|
|
286
286
|
Symptom: a model delivered with specifications that were never run. `screenplay test <root>` runs the
|
|
287
|
-
reference evaluator; after
|
|
288
|
-
specification classes.
|
|
287
|
+
reference evaluator; after rendering and building in Debug, run `dotnet test <destination>/<Project>.csproj -c Debug --no-build`
|
|
288
|
+
for the generated specification classes (Stage-rendered apps use VSTest). Run a built spec executable only where spec projects are executables
|
|
289
|
+
(see [specs.csharp](../../rules/specs.csharp.md)). Report both results separately (`cratis-screenplay-toolchain` V4 and V5.tests); a
|
|
289
290
|
build that succeeds is not a test run, and `unbound`/`unsupported` is not a pass.
|
|
290
291
|
|
|
291
292
|
## Verify
|
|
@@ -293,7 +294,7 @@ build that succeeds is not a test run, and `unbound`/`unsupported` is not a pass
|
|
|
293
294
|
- [ ] Validate the complete root with warnings as errors, naming tool/version.
|
|
294
295
|
Standalone tool version: `cratis-screenplay-toolchain/SKILL.md`. Run specification examples through
|
|
295
296
|
`screenplay test`; expected unadmitted syntax reports unbound, not passed.
|
|
296
|
-
- [ ] `screenplay test` and, after a render, `dotnet test` were run and their counts reported.
|
|
297
|
+
- [ ] `screenplay test` and, after a Debug render and build, the `dotnet test` above were run and their counts reported.
|
|
297
298
|
- [ ] Executable diagnostics are clean too: `PLAY0350`, `PLAY0352`, `PLAY0388`,
|
|
298
299
|
`PLAY0389` and `PLAY0273` are only reported at binding.
|
|
299
300
|
- [ ] Every slice has at least one boundary specification.
|
|
@@ -24,7 +24,7 @@ Run these in order and stop at the first failure; each step catches what the one
|
|
|
24
24
|
run one create command and one query, and read the console for errors. The check is the app, not the build:
|
|
25
25
|
a screen reported as `PLAY0269` (deferred from the backend profile, information only) is not evidence that
|
|
26
26
|
it was rendered. List any authored screen that is absent as not rendered; do not call it delivered.
|
|
27
|
-
10. **Specs:** `dotnet test
|
|
27
|
+
10. **Specs:** after the Debug build, `dotnet test <dir>/<Project>.csproj -c Debug --no-build` (Stage-rendered apps use VSTest) and `screenplay test <root>`; see
|
|
28
28
|
`cratis-screenplay-specifications`.
|
|
29
29
|
|
|
30
30
|
The rendered `README.md` repeats steps 6-8 for the pinned scaffold. Re-render and gap-fill rules:
|
|
@@ -227,7 +227,7 @@ results, plus runtime when it was exercised:
|
|
|
227
227
|
2. **Publication**: what was written, unchanged or refused (`.cratis-render.json`,
|
|
228
228
|
`.cratis-render/journal.json`; `recovered: true` means stop and reconcile).
|
|
229
229
|
3. **Build**: Debug build of the destination (`dotnet build`).
|
|
230
|
-
4. **Tests**:
|
|
230
|
+
4. **Tests**: After the Debug build, run `dotnet test <destination>/<Project>.csproj -c Debug --no-build` for Stage-rendered apps (VSTest). Use a built spec executable only in repositories whose spec projects really are executables (see [specs.csharp](../../../rules/specs.csharp.md)); never start the rendered app's web-server executable to run specs. Generated specifications are
|
|
231
231
|
compiled in Debug only; map results by generated spec class (`when_<snake>` in namespace
|
|
232
232
|
`<Slice ns>.when_<snake>`, `when_<snake>_is_queried`, `when_<snake>_is_projected`) back to
|
|
233
233
|
the `.play` specification, not by test counts.
|
|
@@ -11,9 +11,13 @@
|
|
|
11
11
|
- Filters
|
|
12
12
|
- Migrate from 4.x to 5.0
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
`
|
|
16
|
-
|
|
14
|
+
The xUnit examples and migration checklist require `Cratis.Specifications.XUnit.v3`
|
|
15
|
+
5.0 on `net10.0`. This is not a requirement to migrate frameworks: identify the
|
|
16
|
+
project's evaluated runner first. TUnit and `Cratis.Specifications.Runner` suites
|
|
17
|
+
also run their built executable, with their own help-confirmed flags, not xUnit
|
|
18
|
+
`-trx`/filter flags. Only legacy VSTest projects use `dotnet test <project> --no-build`.
|
|
19
|
+
Check package versions and the actual configuration/TFM; the 4.x migration checklist
|
|
20
|
+
below applies only when migrating, not as a prerequisite to running an existing suite.
|
|
17
21
|
|
|
18
22
|
Sources: [Running specifications fast](https://github.com/Cratis/Specifications/blob/main/Documentation/running-fast.md),
|
|
19
23
|
[The native runner](https://github.com/Cratis/Specifications/blob/main/Documentation/runner.md) and
|
|
@@ -241,7 +241,8 @@ to disk with no managed staging and no safe stale-file removal; a failure can le
|
|
|
241
241
|
result. State the scope in the V5 report.
|
|
242
242
|
- Report V5 as separate results, each a result or "not run": admission, publication,
|
|
243
243
|
Debug build (`dotnet build <destination>/<Project>.csproj -c Debug`), Debug tests
|
|
244
|
-
(`dotnet test`
|
|
244
|
+
(`dotnet test <destination>/<Project>.csproj -c Debug --no-build` after the build; Stage-rendered apps use VSTest) and runtime. Render alone is the first two.
|
|
245
|
+
Use a built spec executable only in repositories whose spec projects really are executables (see [specs.csharp](../../rules/specs.csharp.md)); the rendered app's executable starts its web server, not its specs.
|
|
245
246
|
- A refusal is kept verbatim as reported: `PLAY*` (compile or bind), `PLAN-*` (execution
|
|
246
247
|
plan), `STAGE-*` (admission), `CLI-RENDER-*`, or a plain ownership error for a managed
|
|
247
248
|
file. The fix is an intent-preserving model change or a recorded gap, never an edit of
|
package/package/corpus/skills/cratis-stage-rendering-and-sandbox/references/render-example.md
CHANGED
|
@@ -119,7 +119,7 @@ Why it is shaped this way:
|
|
|
119
119
|
| Forced | the same with `--force` | `written: 1`, the rest `unchanged` |
|
|
120
120
|
| Missing name | render without `--name` | exit 5: `A valid --name is required and must be a C# identifier` |
|
|
121
121
|
| Debug build | `dotnet build out/Marina.csproj -c Debug` | succeeds, 0 warnings, 0 errors |
|
|
122
|
-
| Debug tests | `dotnet test out/Marina.csproj -c Debug` | all specification classes pass |
|
|
122
|
+
| Debug tests | `dotnet test out/Marina.csproj -c Debug --no-build` after the Debug build (Stage-rendered apps use VSTest) | all specification classes pass |
|
|
123
123
|
|
|
124
124
|
Runtime (`docker compose up`, `/healthz`) and the frontend build are separate results.
|
|
125
125
|
|
|
@@ -132,8 +132,8 @@ Use the repo's own build/test workflow when it documents one (`README`/`CONTRIBU
|
|
|
132
132
|
|
|
133
133
|
Otherwise:
|
|
134
134
|
```bash
|
|
135
|
-
dotnet build # 0 errors
|
|
136
|
-
|
|
135
|
+
dotnet build # 0 errors; use dotnet test <project> --no-build only for VSTest (see specs.csharp)
|
|
136
|
+
./<project-dir>/bin/<Config>/<TFM>/<AssemblyName> # built spec executable; same discovered/passed counts
|
|
137
137
|
```
|
|
138
138
|
|
|
139
139
|
One operation per step; never mix a refactor and a behavior change in the same step. On red, stop and report the failure; repair only your edit without discarding unrelated worktree changes.
|
|
@@ -73,7 +73,8 @@ Keep the first restore. Skip a later one only when all four checks pass:
|
|
|
73
73
|
### Step 4: Apply the smallest change
|
|
74
74
|
|
|
75
75
|
- One explicit restore carrying every restore input, then `--no-restore`, `-restore:false` or `--no-build` on later steps.
|
|
76
|
-
-
|
|
76
|
+
- Supported executable suites run their built spec runner instead (see [running-specs](../cratis-specifications-csharp/references/running-specs.md)); the dotnet-test examples here are VSTest-only.
|
|
77
|
+
- Several `dotnet test` steps over one VSTest-only solution: build once, then `dotnet test --no-build` on each. Add `--no-restore -restore:false` if an rsp enables restore, including on .NET 8 and earlier. `--no-restore` alone still rebuilds.
|
|
77
78
|
- Keep self-contained publish settings. A `publish --no-build` still needs a prior build with matching configuration, framework, RID and self-contained output; restore compatibility does not prove that build outputs exist.
|
|
78
79
|
- Scope the change to CI and scripts. Leave `-restore` in `Directory.Build.rsp`, because developers rely on it; pass `-restore:false` per invocation instead.
|
|
79
80
|
- Never remove the first restore. If it is a `--locked-mode` gate, keep it there.
|
|
@@ -11,7 +11,7 @@ metadata:
|
|
|
11
11
|
|
|
12
12
|
# Test Filter Syntax Reference
|
|
13
13
|
|
|
14
|
-
Cratis rules in `.cratis/ai/rules/` (including `csharp.md`, `specs.csharp.md`, and `orleans.md`) and the `cratis-*` skills win where they differ. Specification authoring belongs to **cratis-specifications-csharp**;
|
|
14
|
+
Cratis rules in `.cratis/ai/rules/` (including `csharp.md`, `specs.csharp.md`, and `orleans.md`) and the `cratis-*` skills win where they differ. Specification authoring belongs to **cratis-specifications-csharp**; identify the actual runner rather than assuming xUnit v2/VSTest. Supported Cratis executable suites use direct runner flags first (see its [running-specs reference](../cratis-specifications-csharp/references/running-specs.md)). The dotnet-test forms below are technical syntax when that entrypoint is explicitly required, not the Cratis default.
|
|
15
15
|
|
|
16
16
|
Filter syntax depends on the **platform** and **test framework**.
|
|
17
17
|
|
|
@@ -408,9 +408,12 @@ dotnet restore
|
|
|
408
408
|
if ($LASTEXITCODE -ne 0) { throw "Restore failed; do not use stale assets." }
|
|
409
409
|
dotnet build --no-restore -m
|
|
410
410
|
if ($LASTEXITCODE -ne 0) { throw "Build failed; do not test stale outputs." }
|
|
411
|
-
|
|
411
|
+
./<project-dir>/bin/<Config>/<TFM>/<AssemblyName> # built spec executable
|
|
412
412
|
```
|
|
413
413
|
|
|
414
|
+
Use the evaluated output without rebuilding (see [running-specs](../../cratis-specifications-csharp/references/running-specs.md));
|
|
415
|
+
only VSTest uses `dotnet test <project> --no-build`. The executable step itself
|
|
416
|
+
produces no MSBuild binlog.
|
|
414
417
|
Use matching configuration/TFM/RID and restore-affecting properties in each stage.
|
|
415
418
|
`--no-restore` requires current assets; `--no-build` requires successfully built
|
|
416
419
|
matching test outputs. Keep restore-inclusive and build-only timings separate.
|
|
@@ -88,6 +88,15 @@ resolved. Route identification-only requests to `platform-detection`.
|
|
|
88
88
|
|
|
89
89
|
## Decision table
|
|
90
90
|
|
|
91
|
+
For supported Cratis xUnit v3, TUnit and native-runner suites, restore/build once
|
|
92
|
+
and run each project's built executable directly, or `dotnet <TargetPath.dll>`
|
|
93
|
+
when there is no apphost. Use the matching configuration/TFM and runner-specific
|
|
94
|
+
filter/report flags; see [running-specs](../cratis-specifications-csharp/references/running-specs.md).
|
|
95
|
+
Only identified VSTest projects default to `dotnet test <project> --no-build`.
|
|
96
|
+
Mixed suites run per project, never solution-wide `dotnet test`. The command-mode
|
|
97
|
+
forms below remain valid when the user explicitly requires dotnet-test syntax;
|
|
98
|
+
do not switch an executable suite to them as an automatic fallback.
|
|
99
|
+
|
|
91
100
|
| Detected mode / platform | Command shape | Never use |
|
|
92
101
|
|---|---|---|
|
|
93
102
|
| Classic non-SDK | Repository script, or full MSBuild followed by `vstest.console.exe` / `MSTest.exe` | Assuming `dotnet test` is compatible or migrating implicitly |
|