@cratis/pi 7.124.0 → 7.125.1
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/orchestrator.md +3 -1
- package/package/corpus/agents/spec-writer.md +1 -1
- package/package/corpus/harnesses/copilot/instructions/application-profile.instructions.md +1 -1
- package/package/corpus/harnesses/copilot/instructions/framework.instructions.md +1 -0
- package/package/corpus/harnesses/copilot/instructions/pull-requests.instructions.md +1 -0
- package/package/corpus/harnesses/copilot/instructions/specs.csharp.instructions.md +1 -1
- package/package/corpus/harnesses/copilot/instructions/specs.scenarios.csharp.instructions.md +4 -4
- package/package/corpus/harnesses/copilot/instructions/verification-discipline.instructions.md +2 -0
- package/package/corpus/harnesses/copilot/instructions/vertical-slices.instructions.md +1 -1
- package/package/corpus/harnesses/pi/agents/orchestrator.md +3 -1
- package/package/corpus/harnesses/pi/agents/spec-writer.md +1 -1
- package/package/corpus/prompts/ship-changes.prompt.md +7 -1
- package/package/corpus/rules/application-profile.md +1 -1
- package/package/corpus/rules/framework.md +1 -0
- package/package/corpus/rules/general.md +2 -1
- package/package/corpus/rules/issue-assignment.md +2 -0
- package/package/corpus/rules/pull-requests.md +1 -0
- package/package/corpus/rules/specs.csharp.md +1 -1
- package/package/corpus/rules/specs.scenarios.csharp.md +4 -4
- package/package/corpus/rules/verification-discipline.md +2 -0
- package/package/corpus/rules/vertical-slices.md +1 -1
- package/package/corpus/skills/cratis-application-slice-specifications/SKILL.md +5 -4
- package/package/corpus/skills/cratis-application-slice-specifications/references/query-and-decision-scenarios.md +14 -16
- package/package/corpus/skills/cratis-arc-command/SKILL.md +1 -1
- package/package/corpus/skills/cratis-arc-command/references/decisions-and-routing.md +13 -7
- package/package/corpus/skills/cratis-arc-command-validation/SKILL.md +3 -3
- package/package/corpus/skills/cratis-chronicle-decision-reads/SKILL.md +2 -2
- package/package/corpus/skills/cratis-chronicle-decision-reads/references/choosing-how-a-rule-holds.md +5 -6
- package/package/corpus/skills/cratis-ci-pipeline-performance/SKILL.md +8 -4
- package/package/corpus/skills/cratis-ci-pipeline-performance/references/test-setup-cost.md +15 -0
- 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 +17 -0
- package/package/corpus/skills/cratis-engineering-issue-hygiene/SKILL.md +3 -0
- package/package/corpus/skills/cratis-engineering-release-trains/SKILL.md +10 -0
- package/package/corpus/skills/cratis-specifications-csharp/SKILL.md +2 -3
- package/package/corpus/skills/cratis-specifications-csharp/references/application-scenarios.md +4 -4
- package/package/corpus/skills/cratis-specifications-csharp/references/running-specs.md +1 -1
- package/package.json +1 -1
|
@@ -97,7 +97,8 @@ When you receive a goal:
|
|
|
97
97
|
6. **Output a team plan** — always as a structured markdown checklist with agent assignments and phase labels.
|
|
98
98
|
7. **Return or execute the plan** — default to a parent handoff; delegate only under the explicit large-scope contract.
|
|
99
99
|
8. **Track overall progress** — after each phase, report what was completed and what remains.
|
|
100
|
-
9. **
|
|
100
|
+
9. **Open the PR yourself, once** — sub-agents deliver verified branches and never open or push to PRs. Verify locally first, then open one PR for the whole scope with `--assignee @me`; do not open it early or keep pushing to it (see `pull-requests.md`).
|
|
101
|
+
10. **Enforce scoped quality gates** — require relevant changed-lane evidence, not an unrelated full-code matrix.
|
|
101
102
|
|
|
102
103
|
---
|
|
103
104
|
|
|
@@ -107,6 +108,7 @@ When you receive a goal:
|
|
|
107
108
|
- **Implementation before documentation** — documentation of new features must wait until the implementation is complete and reviewed.
|
|
108
109
|
- **Build is a synchronisation point** — `dotnet build` must succeed before any frontend, spec, or documentation work that references generated proxies.
|
|
109
110
|
- **Quality gates are always last** — code review and security review run after all implementation, specs, and documentation are complete.
|
|
111
|
+
- **Cap local parallelism.** Delegated streams share this machine: limit each build and spec run (`dotnet -m:2`, `vitest --maxWorkers=2`), run one heavy phase at a time, and stagger parallel agents' builds so the machine stays responsive (see `verification-discipline.md`).
|
|
110
112
|
- **Independent features** (no shared events) can be implemented in parallel via separate `planner` or `coordinator` invocations.
|
|
111
113
|
|
|
112
114
|
---
|
|
@@ -94,7 +94,7 @@ public class and_all_information_is_valid : Specification
|
|
|
94
94
|
|
|
95
95
|
### What to specify
|
|
96
96
|
|
|
97
|
-
0. **Every contract specification first** — one spec each, named after it, using the contract's example values. Then add the code-derived cases below that the contract lacks and report them as proposals for the contract (the `.play` model when one covers the slice, otherwise the agreed outline); never present them as contract coverage. A `.play` specification maps to a plain-call spec for a pure decision, with a scenario added only for the composition
|
|
97
|
+
0. **Every contract specification first** — one spec each, named after it, using the contract's example values. Then add the code-derived cases below that the contract lacks and report them as proposals for the contract (the `.play` model when one covers the slice, otherwise the agreed outline); never present them as contract coverage. A `.play` specification maps to a plain-call spec for a pure decision, with a scenario added only for the pipeline composition it proves (never a simulated race); never edit, skip or delete a spec derived from the contract to make code pass — change the code or return an edit request.
|
|
98
98
|
1. **Happy path** — succeeds, correct event(s) appended.
|
|
99
99
|
2. **Each validation failure** — call the validator directly with supplied state; pipeline validation specs assert **both** `ShouldNotBeSuccessful()` and `ShouldHaveValidationErrors()`. Do not assert on message strings by default; assert exact text only when that wording is the specified behavior, and name that behavior in the fact. Violate **only** the rule the spec is named after (build the command valid in every other respect), or a neighbouring rule makes it pass.
|
|
100
100
|
3. **Business-rule violations** — call `Handle()` or the validator directly with the required model state and assert each rejection. Arc/Chronicle specs alone prove platform concurrency, conflict refusal and isolation. The application's only decision-read spec obligation is the single cheap shape-admission spec in `specs.scenarios.csharp.md`; do not repeat guard scenarios per decision.
|
|
@@ -74,7 +74,7 @@ Tagged **[contract]** (framework-enforced) or **[convention]** (house default).
|
|
|
74
74
|
3. **Code level** — infrastructure (hosting, DI composition, identity wiring, CI, deployment), clients, Screenplay code attachments and handlers, adapters in the render's customization area, and scope Stage cannot render yet (the model remains the contract). Framework repositories and brownfield work that is not opted in also stay code-first. Only the entry-point session may propose a model, at most once per session and never for trivial, bug-fix, infrastructure, client, framework or brownfield-maintenance work; if declined, do not ask again. Confirm Module/Feature, slice name, slice type and domain requirements as before; for new behavior or unclear event vocabulary run **cratis-chronicle-event-modeling** first, and record the agreed outline (fields, events, rules, scenarios) where the team tracks work, if anywhere. If you write code first where a model exists, say the model now lags.
|
|
75
75
|
4. **Trivial changes** keep the proportional-delegation policy; Phases 1–3 below apply to code you write at either level.
|
|
76
76
|
- **Phase 1 — Backend.** Implement a coherent slice change. **Gate:** incremental Debug build of the affected project (regenerates proxies, compiles `#if DEBUG` spec code).
|
|
77
|
-
- **Phase 2 — Specs.** Mandatory for every slice type. Start with plain calls for pure command/validator/reducer decisions with supplied read-model state; add scenarios only for pipeline/authorization wiring, constraints
|
|
77
|
+
- **Phase 2 — Specs.** Mandatory for every slice type. Start with plain calls for pure command/validator/reducer decisions with supplied read-model state; add scenarios only for pipeline/authorization wiring, constraints or declarative mapping. Follow [specs.scenarios.csharp.md](./specs.scenarios.csharp.instructions.md) for shared setup and cost budgets. **Gate:** tests pass.
|
|
78
78
|
- **Phase 3 — Frontend.** Build from the generated proxies, register in the composition page, wire routing. **Gate:** lint, conditional test, build.
|
|
79
79
|
|
|
80
80
|
**Backend before frontend, always** — the frontend depends on proxies that exist only after a successful build. Generate proxies from the **Debug** build (house convention); verify Release without re-running the generator: `dotnet build -c Release -p:CratisProxiesOutputPath=`. Why that property, and what to do when nothing is generated: the **cratis-arc-command** skill's proxy-generation reference.
|
|
@@ -50,6 +50,7 @@ Repo conventions follow from this: `Source/DotNET` + `Source/JavaScript` for dua
|
|
|
50
50
|
- **Backward compatibility is a contract.** A change to a public type, attribute, interface, or generated-proxy shape is a breaking change for every downstream app — label PRs by semver impact (`major`/`minor`/`patch`) and treat removals/renames of public surface as `major`.
|
|
51
51
|
- **Convention discovery is built here.** `IInstancesOf<T>` / `IImplementationsOf<T>`, attribute-based discovery, and source generation are the mechanisms the framework *provides*; use them internally too rather than hand-registration where a convention fits. A Fundamentals project reference does not carry the type-discovery analyzer like its NuGet package does: reference `Fundamentals.TypeDiscovery.Generator` explicitly, or your project's types may be absent from the generated universe.
|
|
52
52
|
- **Source generators / analyzers** (Arc's proxy generator, Fundamentals) follow Roslyn conventions; their output is consumed verbatim by apps, so treat generated shape as public API.
|
|
53
|
+
- **Analyzers and generators are written for speed** (fast feedback is a product requirement): incremental generators only; a syntactic prefilter (name or kind) before any semantic bind; compute shared evidence once per compilation, never once per analyzer or per symbol; touch it only after cheap relevance checks; never rebind every call site of the compilation. Each expensive analyzer gets a performance spec.
|
|
53
54
|
- **Orleans grains** in the Chronicle kernel follow `orleans.md`.
|
|
54
55
|
- **An alternate implementation of an interface must match the primary one's *semantics*, not just its signature.** Chronicle ships several implementations of the same storage interfaces (MongoDB, SQL, in-memory) and the in-memory ones exist precisely so the real kernel code paths can run without infrastructure. When you touch one, **diff it against the persistent implementations** — the signature tells you nothing about the contract. The specific trap: query criteria carry **sentinels meaning "do not narrow"** (`EventSourceId.Unspecified`, `EventSourceType.Unspecified`/`Default`, `EventStreamType.All`, `EventStreamId.Default`, an empty event-type set). Callers asking for "everything" pass those sentinels, never `null`, so a plain `is not null` check narrows every row away and the read silently returns nothing. A divergence here does not fail — it makes specs pass vacuously, which is worse.
|
|
55
56
|
- **A stub that silently succeeds is a bug, not a placeholder.** An unimplemented method returning `Task.CompletedTask`/an empty result lets a spec assert on work that never happened. Implement it, or make it fail loudly — never leave it quietly lying.
|
|
@@ -34,3 +34,4 @@ applyTo: "**/*"
|
|
|
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
35
|
- Run the affected-project gates before marking work ready (`dotnet build`/`dotnet test` with zero warnings, `yarn lint`, `npx tsc -b`), 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
|
+
- 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`.
|
|
@@ -12,7 +12,7 @@ Extends the base [specs.md](./specs.instructions.md) (folder structure, naming,
|
|
|
12
12
|
|
|
13
13
|
> **Which spec surface?**
|
|
14
14
|
> - **Framework / library code** (Chronicle kernel, Arc pipeline, source generators, Fundamentals): the `Specification` base + NSubstitute in this file is the dominant mode — unit-test the classes under test in isolation. Reach for a `*Scenario` helper (in [specs.scenarios.csharp.md](./specs.scenarios.csharp.instructions.md)) **only** when testing the very engine your repo provides — Arc → `CommandScenario`, Chronicle → the event/projection/reactor scenarios. The **cratis-application-slice-specifications** skill is application-oriented, not for general framework specs.
|
|
15
|
-
> - **Event-sourced applications on Cratis** (commands, projections, reducers, reactors, constraints): use this base plus a direct call by default for pure `Handle()`, validator and reducer decisions with supplied read-model state; add scenarios only for pipeline/authorization wiring, constraints
|
|
15
|
+
> - **Event-sourced applications on Cratis** (commands, projections, reducers, reactors, constraints): use this base plus a direct call by default for pure `Handle()`, validator and reducer decisions with supplied read-model state; add scenarios only for pipeline/authorization wiring, constraints or declarative projections — see **[specs.scenarios.csharp.md](./specs.scenarios.csharp.instructions.md)** (`profile: application`) and the **cratis-application-slice-specifications** skill.
|
|
16
16
|
|
|
17
17
|
`Cratis.Specifications` keeps the approach of Machine.Specifications (MSpec): `Establish → Because → should_` maps to "Given → When → Then" and keeps each spec focused on *one setup, one action, one set of assertions*.
|
|
18
18
|
|
package/package/corpus/harnesses/copilot/instructions/specs.scenarios.csharp.instructions.md
CHANGED
|
@@ -15,16 +15,16 @@ Specs are **mandatory for every slice type**, including reactors.
|
|
|
15
15
|
|
|
16
16
|
## Start with the plain call; add a scenario where it adds proof
|
|
17
17
|
|
|
18
|
-
**Judgment-shaped convention:** call pure `Handle()`, validators, reducers and reactor decisions directly with their inputs, including read-model state. Add a scenario only for pipeline/authorization wiring, constraints
|
|
18
|
+
**Judgment-shaped convention:** call pure `Handle()`, validators, reducers and reactor decisions directly with their inputs, including read-model state. Add a scenario only for pipeline/authorization wiring, constraints or declarative projection mapping. Do not repeat every decision through the pipeline; name the extra behavior each scenario proves.
|
|
19
19
|
|
|
20
|
-
**Application specs supply state, not decision-read infrastructure.** Call `Handle()` or the validator directly with supplied read-model state. Never call `UseDecisionReads`, configure protection modes, seed events solely for infrastructure, or re-prove the platform's concurrency, conflict-refusal or isolation matrix; Arc/Chronicle specs own it. The application's **only decision-read spec obligation** is one cheap assembly-level shape-admission spec: `DecisionReadAdmissions.ShouldAdmitDecisionReadsIn(assembly)` (`Cratis.Arc.Chronicle.Testing.Commands`). It checks the application's own models/projections without executing commands or running Chronicle, not the platform guards.
|
|
20
|
+
**Application specs supply state, not decision-read infrastructure.** Call `Handle()` or the validator directly with supplied read-model state. Never call `UseDecisionReads`, configure protection modes, seed events solely for infrastructure, or re-prove the platform's concurrency, conflict-refusal or isolation matrix; Arc/Chronicle specs own it. The application's **only decision-read spec obligation** is one cheap assembly-level shape-admission spec: `DecisionReadAdmissions.ShouldAdmitDecisionReadsIn(assembly)` (`Cratis.Arc.Chronicle.Testing.Commands`). It checks the application's own models/projections without executing commands or running Chronicle, not the platform guards. Never simulate competing appends either (`AppendConcurrently` or any hand-built interleaving): concurrency is a framework concern a developer should not think about in tests, and Arc and Chronicle specs prove it. A rule that must hold under races is expressed in production by taking the read model as a `Handle` parameter under `[ReadProtection(On)]`; the spec gives that read model's state and asserts the outcome. Report harness state gaps upstream; never weaken production guards for speed. `AppendConcurrently` is an advanced framework-verification API: use only for an explicit need. Direction, no release claim: Arc will obsolete `UseDecisionReads`.
|
|
21
21
|
|
|
22
22
|
**Share setup and budget cost (judgment-shaped).** Keep shared lifecycle on; use `[PerFactSpecificationLifecycle]` only on a class whose facts genuinely mutate shared state and cannot move that mutation into `Because`. Plain decision specs should take roughly milliseconds; measure scenario facts and justify seconds by the extra behavior they prove. Compare TRX durations and suite wall time with unchanged concurrency; see [running-specs.md](../../../skills/cratis-specifications-csharp/references/running-specs.md). Do not multiply scenario startup by splitting assertions into classes or opting the project out of shared lifecycle.
|
|
23
23
|
|
|
24
24
|
| Tool | Tests | Use when |
|
|
25
25
|
|---|---|---|
|
|
26
26
|
| `Specification` (plain call) | `Handle()`, `Handle(providedValue)`, validator/reducer logic or a reactor's decision as a method call; or an isolated class with mocked collaborators | **default** for a decision that is a pure function of its arguments |
|
|
27
|
-
| `CommandScenario<TCommand>` | the real Arc command pipeline — authorization + validators + `Provide()` + `Handle()` + appended events | pipeline wiring, authorization
|
|
27
|
+
| `CommandScenario<TCommand>` | the real Arc command pipeline — authorization + validators + `Provide()` + `Handle()` + appended events | pipeline wiring, authorization or constraints adds proof |
|
|
28
28
|
| `QueryScenario<TReadModel>` | query pipeline: argument conversion, authorization, validation, interceptors; `Observe` buffers emissions | query composition matters; real MongoDB observations still need infrastructure |
|
|
29
29
|
| `EventScenario` | Chronicle-level append semantics, no command pipeline | constraint violations, raw stream sequencing/concurrency |
|
|
30
30
|
| `ReadModelScenario<TReadModel>` | projection/reducer state from a sequence of events (auto-detects model-bound / fluent / reducer) | one class per read model, many read-only assertions on shared setup |
|
|
@@ -121,7 +121,7 @@ arguments?, paging?, sorting?)`; `Observe(...)` returns `QueryObservation.Initia
|
|
|
121
121
|
and buffered `Next()`. Configure principal/policies in `Services`; schemes fail
|
|
122
122
|
closed without HTTP. Chronicle query `Given` can seed keyed models/events.
|
|
123
123
|
|
|
124
|
-
For query setup
|
|
124
|
+
For query setup, see **cratis-application-slice-specifications**,
|
|
125
125
|
`references/query-and-decision-scenarios.md`. Framework read-protection guards are not application spec obligations.
|
|
126
126
|
|
|
127
127
|
### `EventScenario` — constraints & append semantics
|
package/package/corpus/harnesses/copilot/instructions/verification-discipline.instructions.md
CHANGED
|
@@ -12,8 +12,10 @@ authored a file or preserve a chain of evidence about how it arrived.
|
|
|
12
12
|
|
|
13
13
|
- Run the narrowest relevant build, type check, lint, and specifications while iterating; explain when a wider gate is required before completion or push/PR.
|
|
14
14
|
- Run one phase per command with its real exit status. Budget targeted checks around 120 seconds and build/test phases around 300 seconds; explain any longer budget first, and obtain explicit approval before a phase exceeds 600 seconds. Stop on a failure; do not blindly retry or repeat passing tests on unchanged inputs without a flaky-test hypothesis or required matrix.
|
|
15
|
+
- CI is not a feedback loop: run every gate locally before pushing. On a shared machine cap parallelism, one heavy phase at once (`cratis-engineering-ci-gates`).
|
|
15
16
|
- Separate status/fetch from builds, Debug from Release, each test project, and frontend lint/compile/test/build. Do not combine these into an opaque command with a large outer timeout. Expose progress and cancellation; report the precise failed or timed-out phase and do not continue dependent phases after failure.
|
|
16
17
|
- Never use `build/test | grep | sort/head/tail` as gate evidence. Capture the producer's exit status before summarising output; `pipefail` alone is insufficient with early-closing consumers such as `head`. Printed zero-error counts are not proof of success. Preserve needed full diagnostics in task-scoped `.ai-work/` logs rather than hiding them in `/tmp`.
|
|
18
|
+
- Fast feedback is a product requirement: a spec takes milliseconds, the suite seconds; specs share setup and run in parallel; analyzers must not halt builds. CI builds the spec path without analyzers and enforces them, warnings as errors, in a parallel required job; the pre-push gate runs them. A slowdown is a defect.
|
|
17
19
|
- Add a focused specification for every behavior or rejection rule you change.
|
|
18
20
|
- Keep each check deterministic and runnable locally and in CI.
|
|
19
21
|
- Never replace a real behavior check with a checksum, inventory, generated
|
|
@@ -21,7 +21,7 @@ This file is the reference for *what* goes in each part of a slice. Layout, slic
|
|
|
21
21
|
|
|
22
22
|
- .NET / C# (ASP.NET Core) — **Cratis Arc** for CQRS / model-bound commands and queries, **Cratis Chronicle** for event sourcing, MongoDB or EF Core for read models.
|
|
23
23
|
- React + TypeScript (Vite) — Cratis Components 4.x + Arc-generated proxies, MVVM. Vitest + Mocha/Chai/Sinon for frontend specs.
|
|
24
|
-
- xUnit + Cratis.Specifications + NSubstitute for C# specs (`Specification` plus a direct call for pure command/validator/reducer decisions with supplied state; add scenarios only for pipeline/authorization wiring, constraints
|
|
24
|
+
- xUnit + Cratis.Specifications + NSubstitute for C# specs (`Specification` plus a direct call for pure command/validator/reducer decisions with supplied state; add scenarios only for pipeline/authorization wiring, constraints or declarative projections — see [specs.md](./specs.instructions.md)).
|
|
25
25
|
|
|
26
26
|
## Proxy generation — the build dependency
|
|
27
27
|
|
|
@@ -93,7 +93,8 @@ When you receive a goal:
|
|
|
93
93
|
6. **Output a team plan** — always as a structured markdown checklist with agent assignments and phase labels.
|
|
94
94
|
7. **Return or execute the plan** — default to a parent handoff; delegate only under the explicit large-scope contract.
|
|
95
95
|
8. **Track overall progress** — after each phase, report what was completed and what remains.
|
|
96
|
-
9. **
|
|
96
|
+
9. **Open the PR yourself, once** — sub-agents deliver verified branches and never open or push to PRs. Verify locally first, then open one PR for the whole scope with `--assignee @me`; do not open it early or keep pushing to it (see `pull-requests.md`).
|
|
97
|
+
10. **Enforce scoped quality gates** — require relevant changed-lane evidence, not an unrelated full-code matrix.
|
|
97
98
|
|
|
98
99
|
---
|
|
99
100
|
|
|
@@ -103,6 +104,7 @@ When you receive a goal:
|
|
|
103
104
|
- **Implementation before documentation** — documentation of new features must wait until the implementation is complete and reviewed.
|
|
104
105
|
- **Build is a synchronisation point** — `dotnet build` must succeed before any frontend, spec, or documentation work that references generated proxies.
|
|
105
106
|
- **Quality gates are always last** — code review and security review run after all implementation, specs, and documentation are complete.
|
|
107
|
+
- **Cap local parallelism.** Delegated streams share this machine: limit each build and spec run (`dotnet -m:2`, `vitest --maxWorkers=2`), run one heavy phase at a time, and stagger parallel agents' builds so the machine stays responsive (see `verification-discipline.md`).
|
|
106
108
|
- **Independent features** (no shared events) can be implemented in parallel via separate `planner` or `coordinator` invocations.
|
|
107
109
|
|
|
108
110
|
---
|
|
@@ -89,7 +89,7 @@ public class and_all_information_is_valid : Specification
|
|
|
89
89
|
|
|
90
90
|
### What to specify
|
|
91
91
|
|
|
92
|
-
0. **Every contract specification first** — one spec each, named after it, using the contract's example values. Then add the code-derived cases below that the contract lacks and report them as proposals for the contract (the `.play` model when one covers the slice, otherwise the agreed outline); never present them as contract coverage. A `.play` specification maps to a plain-call spec for a pure decision, with a scenario added only for the composition
|
|
92
|
+
0. **Every contract specification first** — one spec each, named after it, using the contract's example values. Then add the code-derived cases below that the contract lacks and report them as proposals for the contract (the `.play` model when one covers the slice, otherwise the agreed outline); never present them as contract coverage. A `.play` specification maps to a plain-call spec for a pure decision, with a scenario added only for the pipeline composition it proves (never a simulated race); never edit, skip or delete a spec derived from the contract to make code pass — change the code or return an edit request.
|
|
93
93
|
1. **Happy path** — succeeds, correct event(s) appended.
|
|
94
94
|
2. **Each validation failure** — call the validator directly with supplied state; pipeline validation specs assert **both** `ShouldNotBeSuccessful()` and `ShouldHaveValidationErrors()`. Do not assert on message strings by default; assert exact text only when that wording is the specified behavior, and name that behavior in the fact. Violate **only** the rule the spec is named after (build the command valid in every other respect), or a neighbouring rule makes it pass.
|
|
95
95
|
3. **Business-rule violations** — call `Handle()` or the validator directly with the required model state and assert each rejection. Arc/Chronicle specs alone prove platform concurrency, conflict refusal and isolation. The application's only decision-read spec obligation is the single cheap shape-admission spec in `specs.scenarios.csharp.md`; do not repeat guard scenarios per decision.
|
|
@@ -14,7 +14,7 @@ branch → commits → PR → merge → issue disposition → cleanup workflow.
|
|
|
14
14
|
## Inputs
|
|
15
15
|
|
|
16
16
|
- **What changed** — brief description of the work (used for branch name and PR title)
|
|
17
|
-
- **Label** — exactly one of `no-release`, `patch`, `minor`, or `major`, selected from the repository's release contract and applied in `gh pr create --label <intent
|
|
17
|
+
- **Label** — exactly one of `no-release`, `patch`, `minor`, or `major`, selected from the repository's release contract and applied in `gh pr create --label <intent> --assignee @me`
|
|
18
18
|
- **Related issue** — optional exact repository and issue number; if unknown, search read-only first. Comment on or close it only when the user's request includes that effect; otherwise prepare the disposition as a proposal. In repositories released by `cratis/release-action`, a delivered issue is closed by release-action through `(#n)` in the description, but release-action does not run for a `no-release` PR, so `(#n)` closes nothing there; elsewhere follow the repository's own release and issue-closing process. Keep the issue current and close it with a reason per `cratis-engineering-issue-hygiene`.
|
|
19
19
|
|
|
20
20
|
Invoking this prompt is direct authority for the standard branch, commit, push, pull-request,
|
|
@@ -41,6 +41,12 @@ another. The method is in the `cratis-engineering-release-trains` skill.
|
|
|
41
41
|
|
|
42
42
|
## Waiting on checks and merging
|
|
43
43
|
|
|
44
|
+
Verify locally and open the PR once: CI is the final confirmation, not a feedback loop, so every
|
|
45
|
+
gate runs on this machine first, with parallelism capped when other agents or builds share it
|
|
46
|
+
(see `verification-discipline.md`). Do not open the PR early or keep pushing to it; each push
|
|
47
|
+
starts checks on shared runners. Assign the PR to the user you run for with `--assignee @me`.
|
|
48
|
+
When this prompt is run by an orchestrator or for sub-agent deliveries, the orchestrator opens the one PR.
|
|
49
|
+
|
|
44
50
|
Push only when the ship bar is met: root cause understood, specs added, local gate green,
|
|
45
51
|
review passed, issue and PR re-read, and no overlap with main. Then watch the exact run once
|
|
46
52
|
instead of polling it. Merge only after required checks pass. The method is in the
|
|
@@ -73,7 +73,7 @@ Tagged **[contract]** (framework-enforced) or **[convention]** (house default).
|
|
|
73
73
|
3. **Code level** — infrastructure (hosting, DI composition, identity wiring, CI, deployment), clients, Screenplay code attachments and handlers, adapters in the render's customization area, and scope Stage cannot render yet (the model remains the contract). Framework repositories and brownfield work that is not opted in also stay code-first. Only the entry-point session may propose a model, at most once per session and never for trivial, bug-fix, infrastructure, client, framework or brownfield-maintenance work; if declined, do not ask again. Confirm Module/Feature, slice name, slice type and domain requirements as before; for new behavior or unclear event vocabulary run **cratis-chronicle-event-modeling** first, and record the agreed outline (fields, events, rules, scenarios) where the team tracks work, if anywhere. If you write code first where a model exists, say the model now lags.
|
|
74
74
|
4. **Trivial changes** keep the proportional-delegation policy; Phases 1–3 below apply to code you write at either level.
|
|
75
75
|
- **Phase 1 — Backend.** Implement a coherent slice change. **Gate:** incremental Debug build of the affected project (regenerates proxies, compiles `#if DEBUG` spec code).
|
|
76
|
-
- **Phase 2 — Specs.** Mandatory for every slice type. Start with plain calls for pure command/validator/reducer decisions with supplied read-model state; add scenarios only for pipeline/authorization wiring, constraints
|
|
76
|
+
- **Phase 2 — Specs.** Mandatory for every slice type. Start with plain calls for pure command/validator/reducer decisions with supplied read-model state; add scenarios only for pipeline/authorization wiring, constraints or declarative mapping. Follow [specs.scenarios.csharp.md](./specs.scenarios.csharp.md) for shared setup and cost budgets. **Gate:** tests pass.
|
|
77
77
|
- **Phase 3 — Frontend.** Build from the generated proxies, register in the composition page, wire routing. **Gate:** lint, conditional test, build.
|
|
78
78
|
|
|
79
79
|
**Backend before frontend, always** — the frontend depends on proxies that exist only after a successful build. Generate proxies from the **Debug** build (house convention); verify Release without re-running the generator: `dotnet build -c Release -p:CratisProxiesOutputPath=`. Why that property, and what to do when nothing is generated: the **cratis-arc-command** skill's proxy-generation reference.
|
|
@@ -49,6 +49,7 @@ Repo conventions follow from this: `Source/DotNET` + `Source/JavaScript` for dua
|
|
|
49
49
|
- **Backward compatibility is a contract.** A change to a public type, attribute, interface, or generated-proxy shape is a breaking change for every downstream app — label PRs by semver impact (`major`/`minor`/`patch`) and treat removals/renames of public surface as `major`.
|
|
50
50
|
- **Convention discovery is built here.** `IInstancesOf<T>` / `IImplementationsOf<T>`, attribute-based discovery, and source generation are the mechanisms the framework *provides*; use them internally too rather than hand-registration where a convention fits. A Fundamentals project reference does not carry the type-discovery analyzer like its NuGet package does: reference `Fundamentals.TypeDiscovery.Generator` explicitly, or your project's types may be absent from the generated universe.
|
|
51
51
|
- **Source generators / analyzers** (Arc's proxy generator, Fundamentals) follow Roslyn conventions; their output is consumed verbatim by apps, so treat generated shape as public API.
|
|
52
|
+
- **Analyzers and generators are written for speed** (fast feedback is a product requirement): incremental generators only; a syntactic prefilter (name or kind) before any semantic bind; compute shared evidence once per compilation, never once per analyzer or per symbol; touch it only after cheap relevance checks; never rebind every call site of the compilation. Each expensive analyzer gets a performance spec.
|
|
52
53
|
- **Orleans grains** in the Chronicle kernel follow `orleans.md`.
|
|
53
54
|
- **An alternate implementation of an interface must match the primary one's *semantics*, not just its signature.** Chronicle ships several implementations of the same storage interfaces (MongoDB, SQL, in-memory) and the in-memory ones exist precisely so the real kernel code paths can run without infrastructure. When you touch one, **diff it against the persistent implementations** — the signature tells you nothing about the contract. The specific trap: query criteria carry **sentinels meaning "do not narrow"** (`EventSourceId.Unspecified`, `EventSourceType.Unspecified`/`Default`, `EventStreamType.All`, `EventStreamId.Default`, an empty event-type set). Callers asking for "everything" pass those sentinels, never `null`, so a plain `is not null` check narrows every row away and the read silently returns nothing. A divergence here does not fail — it makes specs pass vacuously, which is worse.
|
|
54
55
|
- **A stub that silently succeeds is a bug, not a placeholder.** An unimplemented method returning `Task.CompletedTask`/an empty result lets a spec assert on work that never happened. Implement it, or make it fail loudly — never leave it quietly lying.
|
|
@@ -13,7 +13,7 @@ Profile-specific rules declare a **`profile:`** in their frontmatter (`applicati
|
|
|
13
13
|
|
|
14
14
|
> **Arc is a standalone CQRS framework — not bound to event sourcing.** Even within the application profile, Arc provides model-bound commands/queries, validation, authorization, and full-stack proxy generation, and works **without** Chronicle (Arc.Core does not depend on Chronicle). A `[Command]` `Handle()` does not *have* to append events — it can return a response, return `void`, or work through injected services. The event-sourcing behavior (a returned event gets appended; `EventForEventSourceId`; "never inject `IEventLog`") comes from the **Arc + Chronicle** integration. This application is event-sourced, so the slice guidance assumes event-sourced commands — read the event-centric rules as the *house default for this app*, not universal Arc laws.
|
|
15
15
|
|
|
16
|
-
The framework is convention-over-configuration. **Idiomatic Cratis is the goal — not custom abstractions over it.** When something is unclear, prefer the Cratis convention; do not invent. The rules and skills under `.cratis/ai/` are the authoritative answer — if your question is not answered there, ask rather than inferring framework behavior from package internals.
|
|
16
|
+
The framework is convention-over-configuration. **Idiomatic Cratis is the goal — not custom abstractions over it.** Always recommend the idiomatic way unless explicitly needed otherwise. When something is unclear, prefer the Cratis convention; do not invent. The rules and skills under `.cratis/ai/` are the authoritative answer — if your question is not answered there, ask rather than inferring framework behavior from package internals.
|
|
17
17
|
|
|
18
18
|
## Project Philosophy
|
|
19
19
|
|
|
@@ -52,6 +52,7 @@ obtaining credentials, and other local conventions ("Product policy" above).
|
|
|
52
52
|
- Project context may explain which approved secret mechanism or local setup to
|
|
53
53
|
use, but it must never contain credential values, tokens, keys, passwords, or
|
|
54
54
|
other secrets.
|
|
55
|
+
- A repository's accepted decision records (`decisions/`) and project rules bind AI work: read those matching your paths, follow them, never work around one.
|
|
55
56
|
- Project-specific guidance wins when it deliberately narrows shared behavior,
|
|
56
57
|
but it may not weaken organization security, authorization, or required
|
|
57
58
|
quality gates.
|
|
@@ -10,3 +10,5 @@ unassigned. Never guess an issue/repository, replace an assignee or reopen a
|
|
|
10
10
|
closed issue. Report assignment failures and continue. The request to work on
|
|
11
11
|
the issue authorizes this claim only, not comments, labels or closure; follow
|
|
12
12
|
[pull-requests.md](./pull-requests.md) and the user's request for those.
|
|
13
|
+
|
|
14
|
+
Assign each PR you open to the same user: `gh pr create --assignee @me`.
|
|
@@ -33,3 +33,4 @@ applyTo: "**/*"
|
|
|
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
34
|
- Run the affected-project gates before marking work ready (`dotnet build`/`dotnet test` with zero warnings, `yarn lint`, `npx tsc -b`), 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
|
+
- 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`.
|
|
@@ -11,7 +11,7 @@ Extends the base [specs.md](./specs.md) (folder structure, naming, philosophy) w
|
|
|
11
11
|
|
|
12
12
|
> **Which spec surface?**
|
|
13
13
|
> - **Framework / library code** (Chronicle kernel, Arc pipeline, source generators, Fundamentals): the `Specification` base + NSubstitute in this file is the dominant mode — unit-test the classes under test in isolation. Reach for a `*Scenario` helper (in [specs.scenarios.csharp.md](./specs.scenarios.csharp.md)) **only** when testing the very engine your repo provides — Arc → `CommandScenario`, Chronicle → the event/projection/reactor scenarios. The **cratis-application-slice-specifications** skill is application-oriented, not for general framework specs.
|
|
14
|
-
> - **Event-sourced applications on Cratis** (commands, projections, reducers, reactors, constraints): use this base plus a direct call by default for pure `Handle()`, validator and reducer decisions with supplied read-model state; add scenarios only for pipeline/authorization wiring, constraints
|
|
14
|
+
> - **Event-sourced applications on Cratis** (commands, projections, reducers, reactors, constraints): use this base plus a direct call by default for pure `Handle()`, validator and reducer decisions with supplied read-model state; add scenarios only for pipeline/authorization wiring, constraints or declarative projections — see **[specs.scenarios.csharp.md](./specs.scenarios.csharp.md)** (`profile: application`) and the **cratis-application-slice-specifications** skill.
|
|
15
15
|
|
|
16
16
|
`Cratis.Specifications` keeps the approach of Machine.Specifications (MSpec): `Establish → Because → should_` maps to "Given → When → Then" and keeps each spec focused on *one setup, one action, one set of assertions*.
|
|
17
17
|
|
|
@@ -14,16 +14,16 @@ Specs are **mandatory for every slice type**, including reactors.
|
|
|
14
14
|
|
|
15
15
|
## Start with the plain call; add a scenario where it adds proof
|
|
16
16
|
|
|
17
|
-
**Judgment-shaped convention:** call pure `Handle()`, validators, reducers and reactor decisions directly with their inputs, including read-model state. Add a scenario only for pipeline/authorization wiring, constraints
|
|
17
|
+
**Judgment-shaped convention:** call pure `Handle()`, validators, reducers and reactor decisions directly with their inputs, including read-model state. Add a scenario only for pipeline/authorization wiring, constraints or declarative projection mapping. Do not repeat every decision through the pipeline; name the extra behavior each scenario proves.
|
|
18
18
|
|
|
19
|
-
**Application specs supply state, not decision-read infrastructure.** Call `Handle()` or the validator directly with supplied read-model state. Never call `UseDecisionReads`, configure protection modes, seed events solely for infrastructure, or re-prove the platform's concurrency, conflict-refusal or isolation matrix; Arc/Chronicle specs own it. The application's **only decision-read spec obligation** is one cheap assembly-level shape-admission spec: `DecisionReadAdmissions.ShouldAdmitDecisionReadsIn(assembly)` (`Cratis.Arc.Chronicle.Testing.Commands`). It checks the application's own models/projections without executing commands or running Chronicle, not the platform guards.
|
|
19
|
+
**Application specs supply state, not decision-read infrastructure.** Call `Handle()` or the validator directly with supplied read-model state. Never call `UseDecisionReads`, configure protection modes, seed events solely for infrastructure, or re-prove the platform's concurrency, conflict-refusal or isolation matrix; Arc/Chronicle specs own it. The application's **only decision-read spec obligation** is one cheap assembly-level shape-admission spec: `DecisionReadAdmissions.ShouldAdmitDecisionReadsIn(assembly)` (`Cratis.Arc.Chronicle.Testing.Commands`). It checks the application's own models/projections without executing commands or running Chronicle, not the platform guards. Never simulate competing appends either (`AppendConcurrently` or any hand-built interleaving): concurrency is a framework concern a developer should not think about in tests, and Arc and Chronicle specs prove it. A rule that must hold under races is expressed in production by taking the read model as a `Handle` parameter under `[ReadProtection(On)]`; the spec gives that read model's state and asserts the outcome. Report harness state gaps upstream; never weaken production guards for speed. `AppendConcurrently` is an advanced framework-verification API: use only for an explicit need. Direction, no release claim: Arc will obsolete `UseDecisionReads`.
|
|
20
20
|
|
|
21
21
|
**Share setup and budget cost (judgment-shaped).** Keep shared lifecycle on; use `[PerFactSpecificationLifecycle]` only on a class whose facts genuinely mutate shared state and cannot move that mutation into `Because`. Plain decision specs should take roughly milliseconds; measure scenario facts and justify seconds by the extra behavior they prove. Compare TRX durations and suite wall time with unchanged concurrency; see [running-specs.md](../skills/cratis-specifications-csharp/references/running-specs.md). Do not multiply scenario startup by splitting assertions into classes or opting the project out of shared lifecycle.
|
|
22
22
|
|
|
23
23
|
| Tool | Tests | Use when |
|
|
24
24
|
|---|---|---|
|
|
25
25
|
| `Specification` (plain call) | `Handle()`, `Handle(providedValue)`, validator/reducer logic or a reactor's decision as a method call; or an isolated class with mocked collaborators | **default** for a decision that is a pure function of its arguments |
|
|
26
|
-
| `CommandScenario<TCommand>` | the real Arc command pipeline — authorization + validators + `Provide()` + `Handle()` + appended events | pipeline wiring, authorization
|
|
26
|
+
| `CommandScenario<TCommand>` | the real Arc command pipeline — authorization + validators + `Provide()` + `Handle()` + appended events | pipeline wiring, authorization or constraints adds proof |
|
|
27
27
|
| `QueryScenario<TReadModel>` | query pipeline: argument conversion, authorization, validation, interceptors; `Observe` buffers emissions | query composition matters; real MongoDB observations still need infrastructure |
|
|
28
28
|
| `EventScenario` | Chronicle-level append semantics, no command pipeline | constraint violations, raw stream sequencing/concurrency |
|
|
29
29
|
| `ReadModelScenario<TReadModel>` | projection/reducer state from a sequence of events (auto-detects model-bound / fluent / reducer) | one class per read model, many read-only assertions on shared setup |
|
|
@@ -120,7 +120,7 @@ arguments?, paging?, sorting?)`; `Observe(...)` returns `QueryObservation.Initia
|
|
|
120
120
|
and buffered `Next()`. Configure principal/policies in `Services`; schemes fail
|
|
121
121
|
closed without HTTP. Chronicle query `Given` can seed keyed models/events.
|
|
122
122
|
|
|
123
|
-
For query setup
|
|
123
|
+
For query setup, see **cratis-application-slice-specifications**,
|
|
124
124
|
`references/query-and-decision-scenarios.md`. Framework read-protection guards are not application spec obligations.
|
|
125
125
|
|
|
126
126
|
### `EventScenario` — constraints & append semantics
|
|
@@ -11,8 +11,10 @@ authored a file or preserve a chain of evidence about how it arrived.
|
|
|
11
11
|
|
|
12
12
|
- Run the narrowest relevant build, type check, lint, and specifications while iterating; explain when a wider gate is required before completion or push/PR.
|
|
13
13
|
- Run one phase per command with its real exit status. Budget targeted checks around 120 seconds and build/test phases around 300 seconds; explain any longer budget first, and obtain explicit approval before a phase exceeds 600 seconds. Stop on a failure; do not blindly retry or repeat passing tests on unchanged inputs without a flaky-test hypothesis or required matrix.
|
|
14
|
+
- CI is not a feedback loop: run every gate locally before pushing. On a shared machine cap parallelism, one heavy phase at once (`cratis-engineering-ci-gates`).
|
|
14
15
|
- Separate status/fetch from builds, Debug from Release, each test project, and frontend lint/compile/test/build. Do not combine these into an opaque command with a large outer timeout. Expose progress and cancellation; report the precise failed or timed-out phase and do not continue dependent phases after failure.
|
|
15
16
|
- Never use `build/test | grep | sort/head/tail` as gate evidence. Capture the producer's exit status before summarising output; `pipefail` alone is insufficient with early-closing consumers such as `head`. Printed zero-error counts are not proof of success. Preserve needed full diagnostics in task-scoped `.ai-work/` logs rather than hiding them in `/tmp`.
|
|
17
|
+
- Fast feedback is a product requirement: a spec takes milliseconds, the suite seconds; specs share setup and run in parallel; analyzers must not halt builds. CI builds the spec path without analyzers and enforces them, warnings as errors, in a parallel required job; the pre-push gate runs them. A slowdown is a defect.
|
|
16
18
|
- Add a focused specification for every behavior or rejection rule you change.
|
|
17
19
|
- Keep each check deterministic and runnable locally and in CI.
|
|
18
20
|
- Never replace a real behavior check with a checksum, inventory, generated
|
|
@@ -20,7 +20,7 @@ This file is the reference for *what* goes in each part of a slice. Layout, slic
|
|
|
20
20
|
|
|
21
21
|
- .NET / C# (ASP.NET Core) — **Cratis Arc** for CQRS / model-bound commands and queries, **Cratis Chronicle** for event sourcing, MongoDB or EF Core for read models.
|
|
22
22
|
- React + TypeScript (Vite) — Cratis Components 4.x + Arc-generated proxies, MVVM. Vitest + Mocha/Chai/Sinon for frontend specs.
|
|
23
|
-
- xUnit + Cratis.Specifications + NSubstitute for C# specs (`Specification` plus a direct call for pure command/validator/reducer decisions with supplied state; add scenarios only for pipeline/authorization wiring, constraints
|
|
23
|
+
- xUnit + Cratis.Specifications + NSubstitute for C# specs (`Specification` plus a direct call for pure command/validator/reducer decisions with supplied state; add scenarios only for pipeline/authorization wiring, constraints or declarative projections — see [specs.md](./specs.md)).
|
|
24
24
|
|
|
25
25
|
## Proxy generation — the build dependency
|
|
26
26
|
|
|
@@ -12,7 +12,7 @@ Start a pure decision with a plain method call: `Handle()`,
|
|
|
12
12
|
`Handle(providedValue)`, reducer logic or a reactor's decision needs no host,
|
|
13
13
|
services or harness, including direct validator calls with supplied read-model state.
|
|
14
14
|
Add scenarios only for pipeline/authorization wiring, constraints, declarative
|
|
15
|
-
mapping
|
|
15
|
+
mapping; follow the
|
|
16
16
|
[scenario selection and cost rule](../../rules/specs.scenarios.csharp.md). The scenario family
|
|
17
17
|
exercises the real Arc and Chronicle code paths in-process — no HTTP, no fixture,
|
|
18
18
|
no server.
|
|
@@ -207,14 +207,15 @@ do not replay a projection merely to feed a pure command decision.
|
|
|
207
207
|
Both builder methods return `void`; there is nothing to await.
|
|
208
208
|
|
|
209
209
|
Read protection is invisible to application spec authors. Never configure modes,
|
|
210
|
-
call `UseDecisionReads`,
|
|
211
|
-
the platform concurrency/guard
|
|
210
|
+
call `UseDecisionReads`, simulate competing appends (`AppendConcurrently`), seed
|
|
211
|
+
events solely for infrastructure, or re-prove the platform concurrency/guard
|
|
212
|
+
matrix: give state, assert the outcome. Keep one cheap assembly-level
|
|
212
213
|
`DecisionReadAdmissions.ShouldAdmitDecisionReadsIn(assembly)` spec for the
|
|
213
214
|
application's own model/projection shapes: its only decision-read spec obligation.
|
|
214
215
|
If the harness cannot accept required state, report the upstream gap; never weaken
|
|
215
216
|
production guards for test speed. Read
|
|
216
217
|
[query and decision scenarios](references/query-and-decision-scenarios.md) for
|
|
217
|
-
query pipelines
|
|
218
|
+
query pipelines.
|
|
218
219
|
|
|
219
220
|
Validator and `Provide()` dependencies are registered in `_scenario.Services`;
|
|
220
221
|
the concrete validator itself is discovered automatically.
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
## Contents
|
|
4
4
|
|
|
5
5
|
- Query pipeline
|
|
6
|
-
-
|
|
6
|
+
- Decision specifications
|
|
7
7
|
- Sources
|
|
8
8
|
|
|
9
9
|
<!-- Copyright (c) Cratis. All rights reserved. -->
|
|
@@ -67,7 +67,7 @@ execution runs the query through Arc's hosted query pipeline and establishes con
|
|
|
67
67
|
before `Provide`/`Handle` on the command path. A direct static query call does not
|
|
68
68
|
cover those pipeline hooks.
|
|
69
69
|
|
|
70
|
-
##
|
|
70
|
+
## Decision specifications
|
|
71
71
|
|
|
72
72
|
Start with a direct decision call supplied with read-model state. Follow the
|
|
73
73
|
[scenario rule](../../../rules/specs.scenarios.csharp.md): application authors do
|
|
@@ -89,22 +89,20 @@ method bodies are not statically discovered. If the harness cannot accept
|
|
|
89
89
|
required state for a business decision, report the upstream gap; never weaken
|
|
90
90
|
production guards or invent guard doubles.
|
|
91
91
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
and the
|
|
95
|
-
|
|
92
|
+
Do not add a scenario to prove a race. A rule such as "two callers reserving the last
|
|
93
|
+
seat yield one reservation" is specified from state: supply a read model with no seats
|
|
94
|
+
left and assert the rejection, then supply one seat and assert the reservation.
|
|
95
|
+
Simulating competing appends is a framework concern a developer should not think
|
|
96
|
+
about in tests; Arc and Chronicle prove it. `AppendConcurrently` stays a public but
|
|
97
|
+
advanced framework-verification API (hidden from IntelliSense), outside application
|
|
98
|
+
testing guidance; use it only for a specific, explicit need. Production expresses
|
|
99
|
+
the guarantee with the read model as a `Handle` parameter under
|
|
100
|
+
`[ReadProtection(On)]`. Direction, not a release claim: Arc will obsolete
|
|
101
|
+
`UseDecisionReads`; do not adopt it.
|
|
102
|
+
`ShouldHaveCompletedStream(ClosedStreamScope)` may assert that a decision completed a
|
|
103
|
+
stream at the exact source and route (`Cratis.Arc.Chronicle.Testing.Commands`).
|
|
96
104
|
Use event history only when it is part of the domain example.
|
|
97
105
|
|
|
98
|
-
For an application-owned race/retry policy only, `AppendConcurrently(id, events...)`
|
|
99
|
-
(or its routed overload) can supply controlled interference. It is not required
|
|
100
|
-
for every guarded decision. Requires Arc 22.92.0 without explicit decision-read
|
|
101
|
-
setup; older limitations are upgrade/report concerns, not application setup
|
|
102
|
-
instructions. A competing append alone proves no policy: assert the intended
|
|
103
|
-
business outcome and ensure the decision would otherwise append.
|
|
104
|
-
`ShouldHaveCompletedStream(ClosedStreamScope)` can assert an application-owned
|
|
105
|
-
completion outcome at the exact source and route. These APIs are in
|
|
106
|
-
`Cratis.Arc.Chronicle.Testing.Commands`.
|
|
107
|
-
|
|
108
106
|
The Chronicle-backed `CommandScenario` discovers constraints automatically.
|
|
109
107
|
Assert domain constraint refusals instead of disabling them; use `EventScenario`
|
|
110
108
|
for append-time uniqueness examples. Do not subclass or substitute its engine.
|
|
@@ -276,7 +276,7 @@ Components guidance, not to this skill.
|
|
|
276
276
|
|
|
277
277
|
Start pure `Handle()` and validator decisions with direct calls and supplied
|
|
278
278
|
read-model state. Add scenarios only for pipeline/authorization wiring,
|
|
279
|
-
constraints
|
|
279
|
+
constraints, never read-protection plumbing or simulated concurrency;
|
|
280
280
|
follow the [scenario selection and cost rule](../../rules/specs.scenarios.csharp.md).
|
|
281
281
|
|
|
282
282
|
- The command is a `record`, carries `[Command]`, and declares a public instance
|
|
@@ -15,6 +15,13 @@ Source: Arc. These features require `Cratis.Arc.Chronicle`.
|
|
|
15
15
|
|
|
16
16
|
## Pick the guarded read
|
|
17
17
|
|
|
18
|
+
**Idiomatic default:** a state-dependent rule takes the read model as a `Handle()`
|
|
19
|
+
(or validator-constructor) parameter, with `[ReadProtection(On)]` where it must hold
|
|
20
|
+
under concurrent writers. Do not take `IDecisionReads` in `Handle()`: it is not
|
|
21
|
+
recommended with Arc and is not an investment target. A computed key stays in
|
|
22
|
+
`Provide()` until a read-model parameter covers it. Direction, not a release claim:
|
|
23
|
+
Arc will pin protected parameters so the idiomatic shape needs no further ceremony.
|
|
24
|
+
|
|
18
25
|
Under read protection `On` (`<CratisReadProtection>On</CratisReadProtection>`, or
|
|
19
26
|
`[ReadProtection(ReadProtectionMode.On)]` on a command), a read model that is a
|
|
20
27
|
parameter of `Handle()` or of a `CommandValidator<T>` constructor is read fresh from
|
|
@@ -178,19 +185,18 @@ source id/type and stream route; reactor tuples/collections cannot mix it with e
|
|
|
178
185
|
Call `Handle()` and validators directly with read-model state for pure business
|
|
179
186
|
decisions. Follow the [scenario rule](../../../rules/specs.scenarios.csharp.md):
|
|
180
187
|
read-protection plumbing is invisible to application spec authors. They never
|
|
181
|
-
call `UseDecisionReads`, configure modes,
|
|
182
|
-
or re-prove the platform concurrency, conflict-refusal or isolation matrix;
|
|
188
|
+
call `UseDecisionReads`, configure modes, simulate competing appends
|
|
189
|
+
(`AppendConcurrently`), seed events solely for infrastructure, or re-prove the platform concurrency, conflict-refusal or isolation matrix;
|
|
183
190
|
Arc/Chronicle specs own it. The application's only decision-read spec obligation
|
|
184
191
|
is one cheap assembly-level shape-admission spec from that rule.
|
|
185
192
|
Never weaken production guards for test speed. Report a harness state-setup gap
|
|
186
193
|
upstream instead of working around it in application specs.
|
|
187
194
|
|
|
188
|
-
Add scenarios for pipeline/authorization wiring
|
|
189
|
-
|
|
190
|
-
|
|
195
|
+
Add scenarios for pipeline/authorization wiring or constraints. Never simulate
|
|
196
|
+
competing appends: assert the business outcome from supplied state (for example, no
|
|
197
|
+
copies left rejects). Read
|
|
191
198
|
[query and decision scenarios](../../cratis-application-slice-specifications/references/query-and-decision-scenarios.md)
|
|
192
|
-
for
|
|
193
|
-
and measure the added cost.
|
|
199
|
+
for the query and decision setup. Keep shared lifecycle on and measure the added cost.
|
|
194
200
|
|
|
195
201
|
## Sources
|
|
196
202
|
|
|
@@ -268,10 +268,10 @@ authorization and camelCase member paths are separate contracts.
|
|
|
268
268
|
|
|
269
269
|
Every rule gets a failure specification: instantiate the validator with its
|
|
270
270
|
read-model state and validate directly, asserting the specific rejection. Add
|
|
271
|
-
`CommandScenario<TCommand>` only for pipeline/authorization wiring, constraints
|
|
272
|
-
|
|
271
|
+
`CommandScenario<TCommand>` only for pipeline/authorization wiring, constraints.
|
|
272
|
+
Follow the
|
|
273
273
|
[scenario rule](../../rules/specs.scenarios.csharp.md): application specs never
|
|
274
|
-
configure read-protection modes, call `UseDecisionReads`, seed events solely for
|
|
274
|
+
configure read-protection modes, call `UseDecisionReads`, simulate competing appends, seed events solely for
|
|
275
275
|
infrastructure, or re-prove platform guards. Keep the single cheap assembly-level
|
|
276
276
|
application-shape admission spec specified by that rule; it is the application's
|
|
277
277
|
only decision-read spec obligation. Report harness gaps upstream; never weaken
|
|
@@ -199,5 +199,5 @@ deciding writer is guarded or the rule is a constraint.
|
|
|
199
199
|
changes, absence guards, empty checked appends, isolation and commit lifecycle.
|
|
200
200
|
Their real-client/kernel integration proves the boundary; a default
|
|
201
201
|
`EventScenario` scope strategy returning `None` is not concurrency evidence.
|
|
202
|
-
-
|
|
203
|
-
|
|
202
|
+
- Application specs never simulate competing appends or repeat that matrix.
|
|
203
|
+
Never weaken production guards for spec speed.
|
|
@@ -316,12 +316,11 @@ assembly-level `DecisionReadAdmissions.ShouldAdmitDecisionReadsIn(assembly)`
|
|
|
316
316
|
check of its own models/projections, not per-decision scenarios. Production
|
|
317
317
|
protection stays unchanged regardless of spec cost.
|
|
318
318
|
|
|
319
|
-
|
|
320
|
-
borrowers competing for the last copy
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
the upstream gap rather than adding infrastructure setup to application specs.
|
|
319
|
+
Do not simulate competing appends in an application spec, even for a rule such as
|
|
320
|
+
two borrowers competing for the last copy. Give the state (no copies left) and assert
|
|
321
|
+
the domain outcome (rejected); the guarantee that only one wins is proven by Arc and
|
|
322
|
+
Chronicle. If the harness cannot accept required state, report the upstream gap
|
|
323
|
+
rather than adding infrastructure setup to application specs.
|
|
325
324
|
|
|
326
325
|
## Costs
|
|
327
326
|
|
|
@@ -144,10 +144,14 @@ handle it. Pitfall: without `merge_group` the required check never reports in th
|
|
|
144
144
|
queue. Read `references/required-checks-and-path-filters.md`.
|
|
145
145
|
|
|
146
146
|
**Compile once, analyze once.** Fits any workflow where one push compiles the same
|
|
147
|
-
code several times. Default: build
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
147
|
+
code several times. Default: build the spec path without analyzers
|
|
148
|
+
(`-p:RunAnalyzers=false`) and reuse the output; enforce every analyzer with warnings
|
|
149
|
+
as errors in one parallel **required** job that fails early on compile and analyzer
|
|
150
|
+
errors, while the local fast loop may skip analyzers and the pre-push gate runs them.
|
|
151
|
+
Pitfall: dropping analyzers from the only build that consumers enforce, or leaving
|
|
152
|
+
the analyzer job out of the required checks. Measure analyzer cost per rule before
|
|
153
|
+
and after (binlog analyzer timings), and fix a slow analyzer at its source rather
|
|
154
|
+
than switching it off. Read `references/test-setup-cost.md`.
|
|
151
155
|
|
|
152
156
|
**Cores per job before job count.** Fits uniformly slow jobs. Default: check `nproc`
|
|
153
157
|
and the runner's resources before sharding; undersized runners make every job slow.
|
|
@@ -11,6 +11,7 @@ a suite re-tests a dependency, or when compile errors surface late.
|
|
|
11
11
|
- Test each guarantee where it can break
|
|
12
12
|
- Surface compile errors early
|
|
13
13
|
- Count compiles per push
|
|
14
|
+
- Analyzer cost
|
|
14
15
|
|
|
15
16
|
## Time hidden outside per-test timing
|
|
16
17
|
|
|
@@ -80,3 +81,17 @@ Each extra compile is avoidable: build once, reuse the output (see
|
|
|
80
81
|
`build-once-and-shard.md`). Analyzers can roughly double compile time; run them once
|
|
81
82
|
in a parallel lint job and disable them in the shared build, while keeping the
|
|
82
83
|
strictest configuration that consumers enforce somewhere on the required path.
|
|
84
|
+
|
|
85
|
+
## Analyzer cost
|
|
86
|
+
|
|
87
|
+
Analyzers that run in the spec path stall every build. Take per-analyzer timings
|
|
88
|
+
from a binlog of the slow project, with the same inputs and concurrency before and
|
|
89
|
+
after. Rank by cumulative time per rule, not by assembly. Three results are
|
|
90
|
+
typical: rules that cannot apply to the repository (switch them off; a bulk
|
|
91
|
+
severity setting can run an analyzer whose own rules are `none`), an analyzer that
|
|
92
|
+
rebinds the whole compilation (fix it upstream: syntactic prefilter, evidence
|
|
93
|
+
computed once per compilation, touched only after cheap relevance checks), and
|
|
94
|
+
generators, which are rarely the cost. In one measured application, compiling with
|
|
95
|
+
analyzers took 395 s, 180 s after removing inapplicable rules, and 90 s with
|
|
96
|
+
analyzers off. Pass means the spec-path build skips analyzers, the parallel
|
|
97
|
+
required job still fails on any analyzer warning, and both timings are recorded.
|
package/package/corpus/skills/cratis-commits-and-pull-requests/references/pr-labels-and-release.md
CHANGED
|
@@ -17,7 +17,7 @@ See [commits.md](./commits.md) for logical grouping, message format and staging
|
|
|
17
17
|
|
|
18
18
|
Confirm the current repository workflow contract before selecting release intent because release-intent labels can trigger publication. A direct request to ship with a named label authorizes applying that label and completing the repository's standard pull-request workflow, including the release it normally triggers. Do not ask for separate authorization at each step. If the user did not request shipping or publication, a proposed semantic label describes impact but does not grant authority.
|
|
19
19
|
|
|
20
|
-
- Exactly one of `major`/`minor`/`patch`/`no-release`, set in the creating command (`gh pr create --label patch`), in every repository, including samples, docs and tooling repositories (`no-release` when nothing is shipped). To change intent, swap labels in one command: `gh pr edit <n> --remove-label minor --add-label patch`. Never add a second: with more than one of them, release-action releases nothing and reports `reason=error`. Re-running a `pull_request` workflow replays the original label payload, so fix a label mistake by editing the PR or pushing; a `workflow_dispatch` run needs an explicit `version` and the PR description as `release-notes`, and without notes it closes no issues.
|
|
20
|
+
- Exactly one of `major`/`minor`/`patch`/`no-release`, set in the creating command (`gh pr create --label patch --assignee @me`), in every repository, including samples, docs and tooling repositories (`no-release` when nothing is shipped). To change intent, swap labels in one command: `gh pr edit <n> --remove-label minor --add-label patch`. Never add a second: with more than one of them, release-action releases nothing and reports `reason=error`. Re-running a `pull_request` workflow replays the original label payload, so fix a label mistake by editing the PR or pushing; a `workflow_dispatch` run needs an explicit `version` and the PR description as `release-notes`, and without notes it closes no issues.
|
|
21
21
|
- Dependabot PRs carry only `no-release`. release-action never releases them, and the `major`/`minor`/`patch` Dependabot adds describe the dependency's version, not this product's.
|
|
22
22
|
- Label the PR according to semantic versioning impact:
|
|
23
23
|
- **major**: breaking changes to public APIs
|
|
@@ -72,6 +72,23 @@ do not run dependent phases or hide a producer's exit status behind a filter.
|
|
|
72
72
|
Report the exact command and result. Put verification and deferred coverage in
|
|
73
73
|
reviewer comments, not the release-note description.
|
|
74
74
|
|
|
75
|
+
## Local first, and resource-aware
|
|
76
|
+
|
|
77
|
+
CI is the final confirmation before merge and deploy, never a feedback loop.
|
|
78
|
+
Run build, specifications, lint and frontend gates locally until green, then
|
|
79
|
+
push. Do not push to see whether something compiles or passes, and do not use
|
|
80
|
+
a red run to discover the next failure.
|
|
81
|
+
|
|
82
|
+
Several agents, worktrees or builds often share one machine. Keep it responsive:
|
|
83
|
+
|
|
84
|
+
- Cap parallelism, for example `dotnet build -m:2`, `dotnet test -m:2` with the
|
|
85
|
+
spec runner's thread limit, and `vitest run --maxWorkers=2`.
|
|
86
|
+
- Run one heavy phase at a time (build, then specs, then frontend lint and
|
|
87
|
+
tests), never several at once.
|
|
88
|
+
- Do not start a heavy phase while another agent's runs in the same machine's
|
|
89
|
+
checkout; wait or lower the cap, and do not retry a starved or timed-out phase
|
|
90
|
+
at full parallelism.
|
|
91
|
+
|
|
75
92
|
## Wait without polling
|
|
76
93
|
|
|
77
94
|
After an authorized push, capture the full head SHA and discover the run for the
|
|
@@ -38,6 +38,9 @@ Before starting, read the issue, comments, assignees and any status block. Follo
|
|
|
38
38
|
- Do this once, at the start before the first edit, not on every turn. If it
|
|
39
39
|
fails (permissions or authentication), report it and continue with the work.
|
|
40
40
|
|
|
41
|
+
Assign each PR you open the same way: `gh pr create --assignee @me`, or
|
|
42
|
+
`gh pr edit <n> --add-assignee @me` afterwards.
|
|
43
|
+
|
|
41
44
|
The request to work on the issue authorizes this assignment only, not comments,
|
|
42
45
|
labels or closure. If another writer is active, coordinate rather than starting
|
|
43
46
|
a parallel edit. Delegated workers do not claim or mutate the issue.
|
|
@@ -34,6 +34,16 @@ Use `cratis-engineering-consolidation-guard` when folding existing PRs to prove
|
|
|
34
34
|
nothing was dropped. Use `cratis-engineering-ci-gates` for gate selection and
|
|
35
35
|
run handling, and `cratis-engineering-review-rounds` for proportionate review.
|
|
36
36
|
|
|
37
|
+
## Open the PR once
|
|
38
|
+
|
|
39
|
+
Each push to an open PR starts checks on shared runners. Push the branch for
|
|
40
|
+
backup or hand-off if needed, but open the PR only once, when the work is
|
|
41
|
+
verified locally and ready. Push to it again only for a correction that review
|
|
42
|
+
or CI found. Do not open a draft PR to see what CI says. Related work goes into
|
|
43
|
+
one PR (see below and `cratis-engineering-consolidation-guard`). An orchestrator
|
|
44
|
+
opens the one PR; a sub-agent delivers a verified branch and does not open or
|
|
45
|
+
push to a PR unless the request says so. Pass `--assignee @me` when creating it.
|
|
46
|
+
|
|
37
47
|
## Choose the candidate before creating a PR
|
|
38
48
|
|
|
39
49
|
1. Inspect the repository's worktrees, finished branches, and open PRs:
|
|
@@ -13,7 +13,7 @@ of contents, and each file states one setup, one action, and one or more
|
|
|
13
13
|
focused assertions.
|
|
14
14
|
|
|
15
15
|
Read [query and decision scenarios](../cratis-application-slice-specifications/references/query-and-decision-scenarios.md)
|
|
16
|
-
when specifying query emissions
|
|
16
|
+
when specifying query emissions.
|
|
17
17
|
Follow the [scenario selection and cost rule](../../rules/specs.scenarios.csharp.md):
|
|
18
18
|
application specs supply read-model state and test business decisions, never
|
|
19
19
|
read-protection plumbing. `Perform`/`Observe` need configured services/principal;
|
|
@@ -90,8 +90,7 @@ before changing runner or package family.
|
|
|
90
90
|
The plain `Specification` base is the universal foundation and the dominant mode
|
|
91
91
|
in library and framework code. In applications, start pure decisions with a
|
|
92
92
|
plain call, including direct validator calls, and add scenarios only for
|
|
93
|
-
pipeline/authorization wiring, constraints, declarative mapping
|
|
94
|
-
race policies. Keep shared lifecycle on; measure scenario cost using
|
|
93
|
+
pipeline/authorization wiring, constraints, or declarative mapping. Keep shared lifecycle on; measure scenario cost using
|
|
95
94
|
[running-specs.md](references/running-specs.md). Read
|
|
96
95
|
[application-scenarios.md](references/application-scenarios.md) before using
|
|
97
96
|
one. Out-of-process integration specifications are an advanced case reserved for
|
package/package/corpus/skills/cratis-specifications-csharp/references/application-scenarios.md
CHANGED
|
@@ -10,18 +10,18 @@
|
|
|
10
10
|
|
|
11
11
|
The four scenario helpers exercise the real Arc and Chronicle pipelines
|
|
12
12
|
in-process. Follow the [scenario selection and cost rule](../../../rules/specs.scenarios.csharp.md):
|
|
13
|
-
use them for pipeline/authorization wiring, constraints, declarative mapping
|
|
14
|
-
|
|
13
|
+
use them for pipeline/authorization wiring, constraints, or declarative mapping;
|
|
14
|
+
specify pure `Handle()`, validator, reducer and
|
|
15
15
|
reactor decisions first as plain calls with supplied read-model state. A library or framework repository reaches for a scenario only to test the
|
|
16
16
|
very engine it provides.
|
|
17
17
|
|
|
18
18
|
Read [query and decision scenarios](../../cratis-application-slice-specifications/references/query-and-decision-scenarios.md)
|
|
19
|
-
when using `QueryScenario<T>`, buffered emissions
|
|
19
|
+
when using `QueryScenario<T>`, or buffered emissions.
|
|
20
20
|
Read-protection plumbing is the harness's responsibility, never application setup.
|
|
21
21
|
|
|
22
22
|
| Helper | Exercises | Use for |
|
|
23
23
|
| --- | --- | --- |
|
|
24
|
-
| `CommandScenario<TCommand>` | Authorization, validators, `Provide()`, `Handle()`, appended events | Pipeline wiring, authorization, domain constraints
|
|
24
|
+
| `CommandScenario<TCommand>` | Authorization, validators, `Provide()`, `Handle()`, appended events | Pipeline wiring, authorization, domain constraints |
|
|
25
25
|
| `QueryScenario<TReadModel>` | Argument conversion, authorization, validation, interceptors and buffered observations | Query pipeline behavior |
|
|
26
26
|
| `EventScenario` | Chronicle append semantics without the command pipeline | Domain constraints; raw engine guards belong in framework specs |
|
|
27
27
|
| `ReadModelScenario<TReadModel>` | Projection or reducer state from a sequence of events | Declarative mapping/wiring, one class per model |
|
|
@@ -63,7 +63,7 @@ project on its own; `dotnet test` on the whole solution does not work there.
|
|
|
63
63
|
Apply the [scenario cost budget](../../../rules/specs.scenarios.csharp.md): plain
|
|
64
64
|
decision specs should take roughly milliseconds, not seconds. Measure scenario
|
|
65
65
|
facts and justify their cost by pipeline/authorization wiring, constraints,
|
|
66
|
-
declarative mapping
|
|
66
|
+
or declarative mapping that a plain call cannot
|
|
67
67
|
prove. Prefer fewer startups, not fewer assertions or weaker production guards.
|
|
68
68
|
|
|
69
69
|
Capture TRX for the affected project before and after the change. With VSTest,
|