@cratis/pi 7.34.0 → 7.35.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/security-reviewer.md +1 -0
- package/package/corpus/agents/spec-writer.md +1 -1
- package/package/corpus/harnesses/pi/extensions/shared/rules.ts +3 -1
- package/package/corpus/hooks/scripts/cratis-nuget-pins.txt +7 -6
- package/package/corpus/hooks/scripts/cratis-release-notes-reviewed.cjs +7 -6
- package/package/corpus/hooks/scripts/cratis-store-mutations.json +7 -3
- package/package/corpus/product-sync.json +896 -0
- package/package/corpus/prompts/add-business-rule.prompt.md +1 -1
- package/package/corpus/prompts/ship-changes.prompt.md +2 -2
- package/package/corpus/rules/ai-distribution.md +31 -3
- package/package/corpus/rules/application-profile.md +2 -1
- package/package/corpus/rules/components.md +66 -7
- package/package/corpus/rules/concepts.md +11 -3
- package/package/corpus/rules/csharp.md +3 -1
- package/package/corpus/rules/dialogs.md +9 -0
- package/package/corpus/rules/efcore.md +1 -1
- package/package/corpus/rules/elixir.md +49 -0
- package/package/corpus/rules/framework.md +5 -3
- package/package/corpus/rules/general.md +1 -0
- package/package/corpus/rules/glossary.md +4 -4
- package/package/corpus/rules/go-engineering.md +60 -0
- package/package/corpus/rules/go.md +115 -0
- package/package/corpus/rules/java.md +5 -2
- package/package/corpus/rules/kotlin.md +7 -5
- package/package/corpus/rules/orleans.md +65 -9
- package/package/corpus/rules/profiles.md +43 -6
- package/package/corpus/rules/pull-requests.md +3 -3
- package/package/corpus/rules/react.md +8 -1
- package/package/corpus/rules/reactors.md +27 -3
- package/package/corpus/rules/specs.csharp.md +11 -4
- package/package/corpus/rules/specs.scenarios.csharp.md +35 -4
- package/package/corpus/rules/specs.typescript.md +2 -1
- package/package/corpus/rules/storybook.md +1 -1
- package/package/corpus/rules/typescript.md +1 -1
- package/package/corpus/rules/vertical-slices.md +37 -5
- package/package/corpus/skills/cratis-application-react-specifications/SKILL.md +4 -2
- package/package/corpus/skills/cratis-application-slice-specifications/SKILL.md +18 -8
- package/package/corpus/skills/cratis-application-slice-specifications/references/query-and-decision-scenarios.md +65 -0
- package/package/corpus/skills/cratis-arc-authentication-authorization-and-identity/SKILL.md +53 -57
- package/package/corpus/skills/cratis-arc-authentication-authorization-and-identity/references/authentication.md +38 -42
- package/package/corpus/skills/cratis-arc-authentication-authorization-and-identity/references/authorization.md +18 -7
- package/package/corpus/skills/cratis-arc-authentication-authorization-and-identity/references/authproxy.md +30 -0
- package/package/corpus/skills/cratis-arc-authentication-authorization-and-identity/references/frontend.md +12 -9
- package/package/corpus/skills/cratis-arc-authentication-authorization-and-identity/references/local-development.md +9 -9
- package/package/corpus/skills/cratis-arc-authentication-authorization-and-identity/references/observable-emission-guards.md +8 -5
- package/package/corpus/skills/cratis-arc-authentication-authorization-and-identity/references/tenancy.md +20 -4
- package/package/corpus/skills/cratis-arc-command/SKILL.md +32 -10
- package/package/corpus/skills/cratis-arc-command/references/command-result.md +12 -5
- package/package/corpus/skills/cratis-arc-command/references/decisions-and-routing.md +95 -0
- package/package/corpus/skills/cratis-arc-command/references/generated-values.md +3 -2
- package/package/corpus/skills/cratis-arc-command/references/handler-shapes.md +8 -8
- package/package/corpus/skills/cratis-arc-command/references/proxy-generation.md +22 -3
- package/package/corpus/skills/cratis-arc-command/references/read-model-injection.md +13 -1
- package/package/corpus/skills/cratis-arc-command-execution/SKILL.md +19 -9
- package/package/corpus/skills/cratis-arc-command-kotlin/SKILL.md +44 -18
- package/package/corpus/skills/cratis-arc-command-kotlin/references/read-model-naming.md +29 -0
- package/package/corpus/skills/cratis-arc-command-operation/SKILL.md +10 -9
- package/package/corpus/skills/cratis-arc-command-operation/references/execution-and-recovery.md +2 -2
- package/package/corpus/skills/cratis-arc-command-operation/references/testing.md +4 -3
- package/package/corpus/skills/cratis-arc-command-typescript/SKILL.md +42 -22
- package/package/corpus/skills/cratis-arc-command-typescript/references/chronicle-events.md +36 -5
- package/package/corpus/skills/cratis-arc-command-typescript/references/command-operations.md +114 -0
- package/package/corpus/skills/cratis-arc-command-typescript/references/hosting-and-storage.md +37 -16
- package/package/corpus/skills/cratis-arc-command-typescript/references/identity-and-introspection.md +88 -0
- package/package/corpus/skills/cratis-arc-command-typescript/references/observability-and-host-scopes.md +25 -0
- package/package/corpus/skills/cratis-arc-command-typescript/references/proxy-generation.md +35 -4
- package/package/corpus/skills/cratis-arc-command-typescript/references/slice-layout.md +11 -0
- package/package/corpus/skills/cratis-arc-command-typescript/verification.json +8 -1
- package/package/corpus/skills/cratis-arc-command-validation/SKILL.md +49 -19
- package/package/corpus/skills/cratis-arc-ef-core-migration/SKILL.md +12 -6
- package/package/corpus/skills/cratis-arc-go/SKILL.md +148 -0
- package/package/corpus/skills/cratis-arc-go/references/queries.md +80 -0
- package/package/corpus/skills/cratis-arc-hosting/SKILL.md +96 -0
- package/package/corpus/skills/cratis-arc-hosting/references/integrations-and-publish.md +80 -0
- package/package/corpus/skills/cratis-arc-identity-and-tenancy-kotlin/SKILL.md +137 -0
- package/package/corpus/skills/cratis-arc-observable-query-http/SKILL.md +20 -2
- package/package/corpus/skills/cratis-arc-query-kotlin/SKILL.md +26 -6
- package/package/corpus/skills/cratis-arc-query-paging/SKILL.md +25 -20
- package/package/corpus/skills/cratis-arc-query-typescript/SKILL.md +32 -6
- package/package/corpus/skills/cratis-arc-query-typescript/references/storage-observation-and-compliance.md +66 -0
- package/package/corpus/skills/cratis-arc-query-typescript/verification.json +5 -1
- package/package/corpus/skills/cratis-arc-react-page/SKILL.md +24 -13
- package/package/corpus/skills/cratis-arc-react-page/references/data-page.md +20 -10
- package/package/corpus/skills/cratis-arc-react-page/references/data-tables.md +17 -3
- package/package/corpus/skills/cratis-arc-react-page/references/dialogs.md +14 -3
- package/package/corpus/skills/cratis-arc-react-page/references/from-screenplay.md +6 -1
- package/package/corpus/skills/cratis-arc-react-page/references/provenance.md +1 -1
- package/package/corpus/skills/cratis-arc-react-page/references/queries-and-commands.md +11 -1
- package/package/corpus/skills/cratis-arc-react-page/verification.json +6 -1
- package/package/corpus/skills/cratis-arc-spring-data-kotlin/SKILL.md +163 -0
- package/package/corpus/skills/cratis-arc-testing-kotlin/SKILL.md +131 -0
- package/package/corpus/skills/cratis-arc-validation-kotlin/SKILL.md +44 -11
- package/package/corpus/skills/cratis-arc-validation-typescript/SKILL.md +5 -3
- package/package/corpus/skills/cratis-chronicle-cli-operations/SKILL.md +79 -25
- package/package/corpus/skills/cratis-chronicle-cli-operations/references/command-effects.md +57 -0
- package/package/corpus/skills/cratis-chronicle-client-dotnet/SKILL.md +87 -99
- package/package/corpus/skills/cratis-chronicle-client-dotnet/references/additional-surfaces.md +65 -0
- package/package/corpus/skills/cratis-chronicle-client-dotnet/references/client-construction.md +42 -0
- package/package/corpus/skills/cratis-chronicle-client-dotnet/references/compatibility-check.md +12 -0
- package/package/corpus/skills/cratis-chronicle-client-dotnet/references/discovery.md +43 -19
- package/package/corpus/skills/cratis-chronicle-client-dotnet/references/hosting.md +29 -1
- package/package/corpus/skills/cratis-chronicle-client-elixir/SKILL.md +158 -162
- package/package/corpus/skills/cratis-chronicle-client-elixir/references/append-api.md +36 -15
- package/package/corpus/skills/cratis-chronicle-client-elixir/references/compliance.md +32 -0
- package/package/corpus/skills/cratis-chronicle-client-elixir/references/connections.md +56 -0
- package/package/corpus/skills/cratis-chronicle-client-elixir/references/event-sources.md +64 -0
- package/package/corpus/skills/cratis-chronicle-client-elixir/references/pitfalls.md +25 -0
- package/package/corpus/skills/cratis-chronicle-client-elixir/references/projections.md +48 -0
- package/package/corpus/skills/cratis-chronicle-client-elixir/references/upgrading.md +34 -0
- package/package/corpus/skills/cratis-chronicle-client-elixir/references/variants.md +13 -5
- package/package/corpus/skills/cratis-chronicle-client-elixir/verification.json +23 -0
- package/package/corpus/skills/cratis-chronicle-client-go/SKILL.md +162 -0
- package/package/corpus/skills/cratis-chronicle-client-go/references/projections.md +73 -0
- package/package/corpus/skills/cratis-chronicle-client-kotlin/SKILL.md +87 -88
- package/package/corpus/skills/cratis-chronicle-client-kotlin/references/connection-lifecycle.md +13 -0
- package/package/corpus/skills/cratis-chronicle-client-kotlin/references/discovery-and-registration.md +14 -4
- package/package/corpus/skills/cratis-chronicle-client-kotlin/references/event-sources.md +65 -0
- package/package/corpus/skills/cratis-chronicle-client-kotlin/references/options.md +29 -0
- package/package/corpus/skills/cratis-chronicle-client-kotlin/references/spring-boot.md +13 -0
- package/package/corpus/skills/cratis-chronicle-client-kotlin/references/variants.md +5 -4
- package/package/corpus/skills/cratis-chronicle-client-typescript/SKILL.md +165 -156
- package/package/corpus/skills/cratis-chronicle-client-typescript/references/read-models-and-projections.md +54 -11
- package/package/corpus/skills/cratis-chronicle-client-typescript/references/testing.md +126 -0
- package/package/corpus/skills/cratis-chronicle-client-typescript/references/variants.md +3 -5
- package/package/corpus/skills/cratis-chronicle-client-typescript/verification.json +19 -0
- package/package/corpus/skills/cratis-chronicle-compliance/SKILL.md +36 -13
- package/package/corpus/skills/cratis-chronicle-decision-reads/SKILL.md +110 -0
- package/package/corpus/skills/cratis-chronicle-decision-reads/references/admission-and-ownership.md +57 -0
- package/package/corpus/skills/cratis-chronicle-decision-reads/verification.json +12 -0
- package/package/corpus/skills/cratis-chronicle-event-constraints/SKILL.md +58 -19
- package/package/corpus/skills/cratis-chronicle-event-constraints/references/closing-streams.md +73 -0
- package/package/corpus/skills/cratis-chronicle-event-modeling/SKILL.md +32 -3
- package/package/corpus/skills/cratis-chronicle-event-specifications/SKILL.md +18 -5
- package/package/corpus/skills/cratis-chronicle-event-type-migration/SKILL.md +32 -2
- package/package/corpus/skills/cratis-chronicle-hosting/SKILL.md +134 -0
- package/package/corpus/skills/cratis-chronicle-hosting/references/operations.md +89 -0
- package/package/corpus/skills/cratis-chronicle-hosting/verification.json +14 -0
- package/package/corpus/skills/cratis-chronicle-mcp-inspection/SKILL.md +93 -66
- package/package/corpus/skills/cratis-chronicle-mcp-inspection/references/blocked-tools.md +21 -7
- package/package/corpus/skills/cratis-chronicle-mcp-inspection/references/deployment.md +77 -0
- package/package/corpus/skills/cratis-chronicle-mcp-inspection/references/observational-tools.md +46 -4
- package/package/corpus/skills/cratis-chronicle-multi-tenancy/SKILL.md +15 -1
- package/package/corpus/skills/cratis-chronicle-projection/SKILL.md +44 -10
- package/package/corpus/skills/cratis-chronicle-projection/references/fluent-builder.md +7 -1
- package/package/corpus/skills/cratis-chronicle-projection/references/model-bound-attributes.md +8 -0
- package/package/corpus/skills/cratis-chronicle-reactor/SKILL.md +85 -105
- package/package/corpus/skills/cratis-chronicle-reactor/references/slice-delivery-checklist.md +1 -1
- package/package/corpus/skills/cratis-chronicle-reactor/references/specifications.md +20 -1
- package/package/corpus/skills/cratis-chronicle-read-model/SKILL.md +2 -2
- package/package/corpus/skills/cratis-chronicle-read-model/references/queries.md +35 -16
- package/package/corpus/skills/cratis-chronicle-read-model-specifications/SKILL.md +15 -3
- package/package/corpus/skills/cratis-chronicle-reducer/SKILL.md +23 -4
- package/package/corpus/skills/cratis-chronicle-web-workbench/SKILL.md +40 -15
- package/package/corpus/skills/cratis-cli-terminal-workbench/SKILL.md +20 -6
- package/package/corpus/skills/cratis-code-review/SKILL.md +25 -3
- package/package/corpus/skills/cratis-components-accessibility/SKILL.md +20 -4
- package/package/corpus/skills/cratis-components-schema-editor/SKILL.md +40 -28
- package/package/corpus/skills/cratis-components-schema-editor/references/tree-layout.md +62 -0
- package/package/corpus/skills/cratis-components-schema-editor/verification.json +14 -0
- package/package/corpus/skills/cratis-components-stepper-command-dialog/SKILL.md +16 -8
- package/package/corpus/skills/cratis-components-styling/SKILL.md +57 -20
- package/package/corpus/skills/cratis-components-styling/verification.json +13 -0
- package/package/corpus/skills/cratis-components-toolbar/SKILL.md +37 -7
- package/package/corpus/skills/cratis-components-toolbar/verification.json +12 -0
- package/package/corpus/skills/cratis-engineering-csharp-conventions/SKILL.md +6 -0
- package/package/corpus/skills/cratis-engineering-csharp-conventions/references/exceptions-logging-and-di.md +5 -3
- package/package/corpus/skills/cratis-fundamentals-concept/SKILL.md +19 -6
- package/package/corpus/skills/cratis-fundamentals-concept/references/typescript-concepts.md +97 -0
- package/package/corpus/skills/cratis-fundamentals-concept/verification.json +4 -1
- package/package/corpus/skills/cratis-fundamentals-concept-go/SKILL.md +112 -0
- package/package/corpus/skills/cratis-fundamentals-type-discovery/SKILL.md +54 -17
- package/package/corpus/skills/cratis-fundamentals-type-discovery/verification.json +14 -0
- package/package/corpus/skills/cratis-lens-browser-extension/SKILL.md +55 -28
- package/package/corpus/skills/cratis-performance-review/SKILL.md +5 -2
- package/package/corpus/skills/cratis-release-notes/SKILL.md +3 -1
- package/package/corpus/skills/cratis-screenplay-automations-and-translations/SKILL.md +5 -4
- package/package/corpus/skills/cratis-screenplay-automations-and-translations/references/realization-and-gap-fill.md +1 -1
- package/package/corpus/skills/cratis-screenplay-captures-and-reactions/SKILL.md +1 -1
- package/package/corpus/skills/cratis-screenplay-command-surface/SKILL.md +5 -6
- package/package/corpus/skills/cratis-screenplay-command-surface/references/compliance.md +25 -7
- package/package/corpus/skills/cratis-screenplay-command-surface/references/enum-numbers.md +4 -2
- package/package/corpus/skills/cratis-screenplay-command-surface/references/generated-values-and-responses.md +4 -1
- package/package/corpus/skills/cratis-screenplay-event-modeling/SKILL.md +4 -3
- package/package/corpus/skills/cratis-screenplay-event-modeling/references/nine-steps.md +1 -1
- package/package/corpus/skills/cratis-screenplay-event-modeling/references/parsed-not-runnable.md +2 -2
- package/package/corpus/skills/cratis-screenplay-legacy-extraction/SKILL.md +3 -2
- package/package/corpus/skills/cratis-screenplay-legacy-extraction/references/generate-notes.md +34 -4
- package/package/corpus/skills/cratis-screenplay-model-authoring/SKILL.md +5 -3
- package/package/corpus/skills/cratis-screenplay-model-authoring/references/language-reference.md +1 -1
- package/package/corpus/skills/cratis-screenplay-model-authoring/references/mcp-tools.md +4 -2
- package/package/corpus/skills/cratis-screenplay-model-authoring/references/property-links.md +42 -3
- package/package/corpus/skills/cratis-screenplay-model-authoring/verification.json +3 -1
- package/package/corpus/skills/cratis-screenplay-modeling-lifecycle/references/vocabulary-map.md +2 -2
- package/package/corpus/skills/cratis-screenplay-render-and-gap-fill/SKILL.md +6 -6
- package/package/corpus/skills/cratis-screenplay-render-and-gap-fill/references/drift-and-ledger.md +1 -1
- package/package/corpus/skills/cratis-screenplay-render-and-gap-fill/references/gap-fill-handoff.md +6 -4
- package/package/corpus/skills/cratis-screenplay-render-and-gap-fill/references/renderability-gate.md +1 -1
- package/package/corpus/skills/cratis-screenplay-scenario-coverage/SKILL.md +3 -1
- package/package/corpus/skills/cratis-screenplay-scenario-coverage/references/invoicing-dues-design.md +1 -1
- package/package/corpus/skills/cratis-screenplay-slice-design/SKILL.md +1 -1
- package/package/corpus/skills/cratis-screenplay-slice-design/references/rule-layers.md +2 -2
- package/package/corpus/skills/cratis-screenplay-slice-design/references/worked-example.md +1 -1
- package/package/corpus/skills/cratis-screenplay-specifications/references/examples-and-routes.md +48 -0
- package/package/corpus/skills/cratis-screenplay-specifications/verification.json +3 -1
- package/package/corpus/skills/cratis-screenplay-streams-and-consistency/SKILL.md +7 -5
- package/package/corpus/skills/cratis-screenplay-streams-and-consistency/references/chronicle-boundaries.md +2 -2
- package/package/corpus/skills/cratis-screenplay-streams-and-consistency/references/consistency-and-concurrency.md +2 -2
- package/package/corpus/skills/cratis-screenplay-streams-and-consistency/references/streams-example.md +5 -4
- package/package/corpus/skills/cratis-screenplay-toolchain/SKILL.md +8 -6
- package/package/corpus/skills/cratis-screenplay-toolchain/references/cheat-sheet-example.md +2 -2
- package/package/corpus/skills/cratis-screenplay-toolchain/references/diagnostics.md +4 -2
- package/package/corpus/skills/cratis-screenplay-toolchain/references/doc-contradictions.md +1 -1
- package/package/corpus/skills/cratis-screenplay-toolchain/references/executable-subset.md +16 -11
- package/package/corpus/skills/cratis-screenplay-toolchain/references/renderable-subset.md +8 -5
- package/package/corpus/skills/cratis-screenplay-toolchain/references/screenplay-contract.json +1329 -32
- package/package/corpus/skills/cratis-screenplay-toolchain/references/screenplay-contract.version +1 -1
- package/package/corpus/skills/cratis-screenplay-toolchain/references/verdicts.md +2 -2
- package/package/corpus/skills/cratis-screenplay-toolchain/references/versions.md +23 -7
- package/package/corpus/skills/cratis-screenplay-toolchain/verification.json +1 -1
- package/package/corpus/skills/cratis-screenplay-ui-composition/SKILL.md +2 -0
- package/package/corpus/skills/cratis-screenplay-ui-composition/references/screen-composition-contract.md +27 -9
- package/package/corpus/skills/cratis-security-review/SKILL.md +9 -3
- package/package/corpus/skills/cratis-security-review/references/arc-boundaries.md +59 -0
- package/package/corpus/skills/cratis-specification-by-example/SKILL.md +7 -0
- package/package/corpus/skills/cratis-specifications-csharp/SKILL.md +43 -11
- package/package/corpus/skills/cratis-specifications-csharp/references/application-scenarios.md +16 -4
- package/package/corpus/skills/cratis-specifications-csharp/references/csharp-patterns.md +18 -5
- package/package/corpus/skills/cratis-specifications-csharp/references/integration-specs.md +21 -0
- package/package/corpus/skills/cratis-specifications-csharp/references/shared-lifecycle.md +34 -0
- package/package/corpus/skills/cratis-specifications-csharp/verification.json +13 -0
- package/package/corpus/skills/cratis-specifications-typescript/SKILL.md +14 -5
- package/package/corpus/skills/cratis-specifications-typescript/verification.json +12 -0
- package/package/corpus/skills/cratis-stage-rendering-and-sandbox/SKILL.md +11 -5
- package/package/corpus/skills/cratis-stage-rendering-and-sandbox/references/admission.md +7 -4
- package/package/corpus/skills/cratis-stage-rendering-and-sandbox/references/rendered-application.md +10 -1
- package/package/corpus/skills/cratis-stage-rendering-and-sandbox/references/scene-runtime.md +75 -0
- package/package/corpus/skills/cratis-stage-rendering-and-sandbox/verification.json +6 -1
- package/package/corpus/skills/cratis-studio-mcp-safety-guidance/SKILL.md +14 -1
- package/package/profile-catalog.json +68 -1
- package/package.json +1 -1
- package/src/index.ts +3 -1
|
@@ -16,7 +16,7 @@ Enforce a new rule on an existing command. Invoke the **cratis-arc-command-valid
|
|
|
16
16
|
- Reusable value invariant → `ConceptValidator<T>`.
|
|
17
17
|
- Command-input / cross-field / pre-handler rule → `CommandValidator<T>`.
|
|
18
18
|
- Handler needs fetched data first → `Provide()`.
|
|
19
|
-
- State rule that must hold **under concurrency** →
|
|
19
|
+
- State rule that must hold **under concurrency** → enroll a stream decision with `IStreamReads`/`StreamDecision`, or use `[ProtectedDecision]` with an admitted `DecisionRead<T>`; plain read-model injection and `Result<TEvent, ValidationResult>` alone add no guard. Specify the race with `UseDecisionReads()` and seeded events, not pinned models.
|
|
20
20
|
- Uniqueness → `[Unique]` / `IConstraint`.
|
|
21
21
|
|
|
22
22
|
> **Never throw for normal business rejection** — a throw is HTTP 500, not a validation error. Recoverable rejection is a `ValidationResult` / `Result<,>`. Add a spec for the failure case (assert both not-successful and has-validation-errors). The skill carries the detail; don't duplicate it here.
|
|
@@ -45,8 +45,8 @@ The description is published verbatim as the release notes, so it follows the co
|
|
|
45
45
|
- No development write-up: no Overview/Verification/Test plan headings (only a first `## Summary`
|
|
46
46
|
is allowed), no review, testing or provenance notes. Those go in a PR comment.
|
|
47
47
|
- `(#n)` ends the bullet that delivers an issue and `(part of #n)` marks anything that stays open;
|
|
48
|
-
never `Closes`/`Fixes`/`Refs` before a number, and never an issue reference inside an HTML comment
|
|
49
|
-
|
|
48
|
+
never `Closes`/`Fixes`/`Refs` before a number, and never an issue reference inside an HTML comment
|
|
49
|
+
(release-action removes comments, so it would close nothing).
|
|
50
50
|
- Links are absolute `https://` URLs, never relative paths.
|
|
51
51
|
- Post reviewer notes (checks run, what was not verified, review provenance, stacking, merge or
|
|
52
52
|
deploy order) right after creating the PR with `gh pr comment <n> --body-file .ai-work/pr-notes.md`.
|
|
@@ -15,7 +15,7 @@ Do not copy or synchronize shared `.cratis/ai`, `.agents`, `.claude`, `.github`,
|
|
|
15
15
|
never become an accidental source that republishes its local AI corpus.
|
|
16
16
|
|
|
17
17
|
Shared Cratis capabilities are authored and reviewed in `Cratis/AI` and reach a
|
|
18
|
-
repository through
|
|
18
|
+
repository through these channels, each with its own version semantics:
|
|
19
19
|
|
|
20
20
|
- **`cratis ai install` / `cratis ai update`** copy the corpus into `.cratis/ai/`
|
|
21
21
|
from the current `main` of `Cratis/AI` (or an explicit `--source` path), record
|
|
@@ -25,11 +25,32 @@ repository through one of three channels, each with its own version semantics:
|
|
|
25
25
|
prompts, and hooks are always installed; rules are filtered by profile and
|
|
26
26
|
language; skills by the profile catalog; `harnesses/<harness>/` only for the
|
|
27
27
|
harnesses selected.
|
|
28
|
-
- **`@cratis/pi`** is
|
|
28
|
+
- **`@cratis/pi`** is a versioned channel: an npm package cut per release,
|
|
29
29
|
pinned and rolled back by package version. It yields to a managed install when
|
|
30
30
|
`.cratis/ai.manifest.json` exists.
|
|
31
31
|
- **Native plugin marketplaces** (Claude Code, Codex, Copilot, Cursor) expose the
|
|
32
|
-
skills only, from the unpinned GitHub source.
|
|
32
|
+
skills only, from the unpinned `Cratis/AI` GitHub source.
|
|
33
|
+
- **`Cratis/AI.Distribution`** is a separate tag-versioned, deny-by-default public
|
|
34
|
+
evaluation marketplace. At **v0.3.0** it contains 29 skills and is explicitly
|
|
35
|
+
unsupported `0.x`, not a supported installation channel. Codex and Gemini
|
|
36
|
+
accept `--ref v0.3.0`; Pi accepts
|
|
37
|
+
`git:github.com/Cratis/AI.Distribution@v0.3.0`. Its documented Claude Code and
|
|
38
|
+
Copilot marketplace-add commands carry no ref. Live Chronicle CLI operations
|
|
39
|
+
(`cratis-chronicle-cli-operations`) and both Chronicle/Studio MCP skills remain
|
|
40
|
+
excluded, as do command execution, EF Core/event-type migration and reactors.
|
|
41
|
+
Sources: [v0.3.0 README](https://github.com/Cratis/AI.Distribution/blob/v0.3.0/README.md),
|
|
42
|
+
[release manifest](https://github.com/Cratis/AI.Distribution/blob/v0.3.0/marketplace-release.json)
|
|
43
|
+
and [exclusions](https://github.com/Cratis/AI.Distribution/blob/v0.3.0/provenance.json).
|
|
44
|
+
|
|
45
|
+
At CLI **v3.53.1**, install/update/uninstall support `--dry-run`; `--source`
|
|
46
|
+
or `CRATIS_AI_SOURCE` supplies a local corpus. Otherwise the CLI shallow-clones
|
|
47
|
+
Cratis/AI's default branch and deletes the download after the run. `status`
|
|
48
|
+
exits non-zero on local modifications; `--force` does not remove changed owned
|
|
49
|
+
MCP entries on uninstall. Consumer extension sections in `.cratis/ai.json` and
|
|
50
|
+
hook shebang/execute bits are preserved. Installation creates no model folder.
|
|
51
|
+
Sources: [AiCorpusSource.cs](https://github.com/Cratis/cli/blob/v3.53.1/Source/Cli/Commands/Ai/AiCorpusSource.cs)
|
|
52
|
+
and [AI commands](https://github.com/Cratis/cli/blob/v3.53.1/Documentation/ai/index.md)
|
|
53
|
+
(the latter's older model-directory claim does not override current behavior).
|
|
33
54
|
|
|
34
55
|
## Profile-selected MCP servers
|
|
35
56
|
|
|
@@ -44,6 +65,13 @@ servers, settings and comments, detect conflicts, support dry-run/status, and
|
|
|
44
65
|
remove only unchanged owned entries on uninstall. Unsupported adapters must be
|
|
45
66
|
reported explicitly rather than presented as configured.
|
|
46
67
|
|
|
68
|
+
At CLI v3.53.1 only Screenplay is registered: `.mcp.json` for Claude (with
|
|
69
|
+
`--project-root-env CLAUDE_PROJECT_DIR`), `.vscode/mcp.json` for Copilot,
|
|
70
|
+
`.cursor/mcp.json`, `.codex/config.toml` and OpenCode's config. Pi uses the
|
|
71
|
+
`cratis-mcp` harness extension rather than a config file. CodeScene's `cs-mcp`
|
|
72
|
+
is never registered by the CLI; neither Chronicle nor Studio MCP is registered
|
|
73
|
+
by the corpus. Source: [AiMcpHarnesses.cs](https://github.com/Cratis/cli/blob/v3.53.1/Source/Cli/Commands/Ai/AiMcpHarnesses.cs).
|
|
74
|
+
|
|
47
75
|
Project model roots and opt-outs are consumer-owned configuration. Guidance
|
|
48
76
|
installation never creates or manages a model directory: the Screenplay MCP locates the model
|
|
49
77
|
itself (existing `.play` files, else `Source/` or `src/`, else a new `Screenplay/` folder). Ordinary
|
|
@@ -31,7 +31,7 @@ Commands are imperative intents (`Register`, `Create`); the slice folder is the
|
|
|
31
31
|
Tagged **[contract]** (framework-enforced) or **[convention]** (house default). Mechanics and examples live in `vertical-slices.md`.
|
|
32
32
|
|
|
33
33
|
1. **[contract] Model-bound — no controllers.** Commands are `[Command]` records with a public instance `Handle()` (Arc analyzers enforce this); queries are `static` methods on `[ReadModel]` records; projections/constraints/authorization use attributes. Arc generates the HTTP surface. Drop to fluent (`IProjectionFor<T>`, `IConstraint`) only when model-bound can't express the rule.
|
|
34
|
-
2. **[contract] Command validation & data flow.** Put command rejection in `CommandValidator<T>`, global value invariants in `ConceptValidator<T>`, and fetched/computed handler data in **`Provide()`** (runs after validation/authorization; may short-circuit with `ValidationResult.Error` / `Result<TProvided, ValidationResult>`). Keep `Handle()` focused on event construction. For a state-dependent rule that must hold **under concurrency**,
|
|
34
|
+
2. **[contract] Command validation & data flow.** Put command rejection in `CommandValidator<T>`, global value invariants in `ConceptValidator<T>`, and fetched/computed handler data in **`Provide()`** (runs after validation/authorization; may short-circuit with `ValidationResult.Error` / `Result<TProvided, ValidationResult>`). Keep `Handle()` focused on event construction. For a state-dependent rule that must hold **under concurrency**, enroll a guarded stream decision (`IStreamReads`/`StreamDecision`) or use `[ProtectedDecision]` with an admitted `DecisionRead<T>`; plain injected models remain advisory. Return a typed rejection via `Result<TEvent, ValidationResult>` where needed; the result alone adds no guard. **Throwing from `Provide()`/`Handle()` is an exception (HTTP 500), not a validation rejection** — throw only for genuinely exceptional conditions, never for normal business rejection.
|
|
35
35
|
3. **[contract] Event-source id resolution:** `ICanProvideEventSourceId` first; else the first qualifying property in declaration order — an `EventSourceId`/`EventSourceId<T>`-derived value *or* a `[Key]` property (no priority between them; two candidates is `ARCCHR0002`); else Arc generates one. A value actually used as a Chronicle stream identity derives from `EventSourceId<T>` with the underlying `IComparable` primitive — never `ConceptAs<Guid>` for that stream identity. `NotSet`, `New()`, and primitive→derived-id operators are optional domain/API conveniences, not Chronicle requirements; typed empty/zero values are real specified stream IDs, not `EventSourceId.Unspecified`.
|
|
36
36
|
4. **[contract] Events never carry the event-source id** — it is implicit in the event context.
|
|
37
37
|
5. **[contract] `[Key]` / `[Subject]` are distinct.** `[Key]` is for event-source/read-model/projection key resolution; `[Subject]` is compliance identity only. Don't put either on an `EventSourceId<T>` value (it already is both); use them only for non-`EventSourceId<T>` values.
|
|
@@ -52,6 +52,7 @@ Tagged **[contract]** (framework-enforced) or **[convention]** (house default).
|
|
|
52
52
|
|
|
53
53
|
## Implementation Workflow
|
|
54
54
|
|
|
55
|
+
- **Starting a brand-new application:** scaffold it instead of hand-writing the skeleton: `dotnet new install Cratis.Templates`, then `dotnet new cratis -n MyApp -o MyApp` (`--language Kotlin|Java`, `--Database MongoDB|PostgreSQL|MsSql|SQLite`; `cratis-aspire` for Aspire; `cratis-chronicle-console` or `cratis-chronicle-web` for a Chronicle client only). Non-interactive runs need `--allow-scripts yes`; the .NET templates target `net10.0`. The template writes `.cratis/ai.json`; run `cratis ai update` afterwards. Its `SomeModule/SomeFeature/Registration/` slice is the house shape. There is no Go, Python or Elixir template (verified at Cratis.Templates `v1.7.4`).
|
|
55
56
|
- **Phase 0 — Find the contract / choose the level.** Before writing slice code, find what the code must match, and choose the level once for the whole scope.
|
|
56
57
|
1. **Look for a Screenplay model** under the model root (the folder holding the project's `.play` files, or the root set by `mcpServers.screenplay.root` in `.cratis/ai.json`; search `**/*.play`) for the slice, command, event and read-model names. A `.play` file outside the root, an untracked or uncommitted draft, an empty directory, or an installed profile or skill is not opt-in; the repository is opted in only when the root holds a committed `.play` file (`git ls-tree -r --name-only HEAD` lists a `.play` file there, narrowed to `-- <root>` when a root is configured) or the project set that root explicitly (master definition: **cratis-screenplay-modeling-lifecycle**, "Decide the level first").
|
|
57
58
|
2. **Model level** — an accepted model under the root covers the scope, or the repository is opted in and this scope has no model yet. The `.play` slice and its specs are the contract: change the model first (new behavior starts in discovery), verify it (V1–V3), get an independent review, then render with Stage or gap-fill by hand only what the renderer rejects. Hand-written code stays checked against the model (**cratis-application-slice-conformance**). Never edit Stage-managed output, never implement behavior the model does not state, never change the model to match existing code, never weaken protection to make it compile or render. Start with **cratis-screenplay-event-modeling** (decision rule), then **cratis-screenplay-modeling-lifecycle**. If the Screenplay skills are not installed, say so; do not author `.play` from memory.
|
|
@@ -16,7 +16,7 @@ The package root exports **only** setup (`CratisComponentsProvider`, configurati
|
|
|
16
16
|
| Need | Use | Subpath |
|
|
17
17
|
|---|---|---|
|
|
18
18
|
| App root | `CratisComponentsProvider` | `@cratis/components` |
|
|
19
|
-
| Page chrome, buttons, basic controls | `Page`, `Button`, `IconButton`, `TextInput`, `TextArea`, `NumberInput`, `Checkbox`, `Radio`, `Switch`, `Tooltip`, `ErrorBoundary`, `FormElement`, `ComboBox`
|
|
19
|
+
| Page chrome, buttons, basic controls | `Page`, `Button`, `IconButton`, `TextInput`, `TextArea`, `NumberInput`, `Checkbox`, `Radio`, `Switch`, `Tooltip`, `ErrorBoundary`, `FormElement`, `ComboBox`, `ToggleGroup`, `Tabs`, `TagGroup`, `Breadcrumbs`, `DatePickerInput`, `ActionMenubar`, `ToolbarFocusMode`, `Surface` | `@cratis/components/Common` |
|
|
20
20
|
| Icon | `Icon` (type) / `IconDisplay` | `@cratis/components/Common` |
|
|
21
21
|
| Query list page | `DataPage`, `MenuItem`, `Column` | `@cratis/components/DataPage` |
|
|
22
22
|
| Standalone query table | `DataTableForQuery` / `DataTableForObservableQuery`, `Column` | `@cratis/components/DataTables` |
|
|
@@ -28,8 +28,35 @@ The package root exports **only** setup (`CratisComponentsProvider`, configurati
|
|
|
28
28
|
| Notifications | `Toaster`, `toast`, `toastCommandResult` | `@cratis/components/Notifications` |
|
|
29
29
|
| Status & display | `Tag`, `Badge`, `Chip`, `Skeleton`, `Avatar`, `ProgressBar`, `ProgressSpinner`, `Message` | `@cratis/components/Display` |
|
|
30
30
|
| Canvas tool palette | `Toolbar`, `ToolbarButton`, … | `@cratis/components/Toolbar` |
|
|
31
|
+
| Schema structure / object content | `SchemaEditor` / `ObjectContentEditor` / `ObjectNavigationalBar` | `@cratis/components/SchemaEditor`, `/ObjectContentEditor`, `/ObjectNavigationalBar` |
|
|
32
|
+
| Spatial canvas / pivot data | `Canvas` / `PivotViewer` | `@cratis/components/Canvas`, `/PivotViewer` |
|
|
33
|
+
| Chat | `Chat` | `@cratis/components/Chat` |
|
|
34
|
+
| Ordered configuration | `OrderedItemEditor`, `PropertyControls` | `@cratis/components/ConfigurationEditor` |
|
|
35
|
+
| Filter panel | `FilterPanel` | `@cratis/components/Filter` |
|
|
36
|
+
| Icon / Markdown editing | `IconPicker` / `MarkdownEditor` | `@cratis/components/IconPicker`, `/MarkdownEditor` |
|
|
37
|
+
| Time navigation | `TimeMachine` | `@cratis/components/TimeMachine` |
|
|
38
|
+
| Renderer contracts / built-in | renderer exports | `@cratis/components/renderer`, `/renderer/builtin` |
|
|
39
|
+
| CSS foundation / area sheets | layer order / structural CSS | `@cratis/components/styles/base`, `<subpath>/styles` |
|
|
31
40
|
| Shared types | `JsonSchema`, `Json`, … | `@cratis/components/types` |
|
|
32
41
|
|
|
42
|
+
At Components 4.26.4, React and React DOM are `^19.0.0`, Arc and Arc React are
|
|
43
|
+
`>=20.3.1 <23`, Fundamentals is `^7.10.3`, and `reflect-metadata` `0.2.2` is required
|
|
44
|
+
(import it at the entry point). `tsyringe` `4.10.0` is optional for Components;
|
|
45
|
+
Arc React installs it. `Canvas` and `PivotViewer` need the optional `pixi.js ^8.20.0`
|
|
46
|
+
peer; ordinary pages do not. No `motion-dom` or `motion-utils` resolution pin is needed.
|
|
47
|
+
|
|
48
|
+
### Common controls
|
|
49
|
+
|
|
50
|
+
All import from `@cratis/components/Common`:
|
|
51
|
+
|
|
52
|
+
| Control | Main props / choice |
|
|
53
|
+
| --- | --- |
|
|
54
|
+
| `ComboBox` | `options`, `value: string \| null`, `onChange(key)`, `filter`, `openOnFocus`, `loading`, `emptyMessage`, `failure`, `action`, `optionLayout` — a single-select entity picker |
|
|
55
|
+
| `ToggleGroup` | `options`, `value`, `onChange` — choose a value; radiogroup semantics with one Tab stop |
|
|
56
|
+
| `Tabs` | `tabs`, `value`, `onChange` — choose a panel, not a domain value |
|
|
57
|
+
| `TagGroup` | `value: string[]`, `onChange`, `editable`, `separators`, `allowDuplicates`, `removeIcon` |
|
|
58
|
+
| `Breadcrumbs` | `items`, `separator` — last item is `aria-current='page'` |
|
|
59
|
+
|
|
33
60
|
Use `Dropdown` from `@cratis/components/Dropdown`, never a vendor select: it renders through the Components overlay environment, so it stacks correctly above dialogs, and it follows the WAI-ARIA button/listbox (or combobox, when `filter` is on) pattern. Its `onChange` receives the **value**, not an event — as do every CommandForm field's.
|
|
34
61
|
|
|
35
62
|
### Notifications — feedback for commands run outside a dialog
|
|
@@ -46,6 +73,14 @@ const result = await command.execute();
|
|
|
46
73
|
if (toastCommandResult(result, { successTitle: 'Author registered' })) refresh();
|
|
47
74
|
```
|
|
48
75
|
|
|
76
|
+
Without a mounted toaster, neither `toast` nor `toastCommandResult` displays anything.
|
|
77
|
+
Mount **one**, not both: two toasters show every toast twice. The provider has no
|
|
78
|
+
Arc dependency; its position relative to `<Arc>` is not what enables notifications.
|
|
79
|
+
|
|
80
|
+
`ErrorBoundary` (`Common`) contains a failing section with a neutral message, never
|
|
81
|
+
exception text. Supply `fallback` (a node or `(reset) => node`), `onError`, and
|
|
82
|
+
`onReset` when needed; retry remounts only the protected section.
|
|
83
|
+
|
|
49
84
|
For ad-hoc notifications, call the imperative `toast.success/info/warn/error(...)` — each takes an
|
|
50
85
|
**options object**, not a bare string: `toast.info({ title: 'Saved', description: '…' })`.
|
|
51
86
|
|
|
@@ -65,7 +100,12 @@ Required props: `title`, `query` (`Constructor<TQuery>`; snapshot and observable
|
|
|
65
100
|
auto-detected), `emptyMessage`, and `children`. Other props: `queryArguments`, `dataKey` (pass
|
|
66
101
|
whenever the read model has an identity), `selection` / `onSelectionChange`, `globalFilterFields` /
|
|
67
102
|
`defaultFilters`, `detailsComponent` (`React.FC<IDetailsComponentProps<T>>` = `{ item, onRefresh? }`),
|
|
68
|
-
`onRefresh
|
|
103
|
+
`onRefresh` (forwarded unchanged to the details component; it never refetches the list),
|
|
104
|
+
`selectionMode='multiple'` with `selectedItems` / `onSelectedItemsChange`, and
|
|
105
|
+
`loadingMessage` / `failureMessage` / `unauthorizedMessage` for query-state rows.
|
|
106
|
+
Use an observable query for a live list; DataPage exposes no snapshot refresh handle.
|
|
107
|
+
Global search uses `globalSearchPlaceholder` / `globalSearchAriaLabel`; paginator
|
|
108
|
+
styling and labels use `paginatorClassName` / `paginatorAriaLabels`. The Cratis part props are `tablePt: DataTableParts` / `paginatorPt: TablePaginatorParts`
|
|
69
109
|
/ `menubarPt: ButtonParts` (plus `tableClassName` / `menubarClassName`).
|
|
70
110
|
|
|
71
111
|
Columns and toolbar actions are compositional children:
|
|
@@ -123,15 +163,28 @@ An app does three things, once, at its root — or the components render unstyle
|
|
|
123
163
|
|
|
124
164
|
1. **Import the stylesheets, in this order** — components do not import their own CSS:
|
|
125
165
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
import '@cratis/components/
|
|
166
|
+
In `index.css`, imported once by the entry point with `import './index.css'`:
|
|
167
|
+
|
|
168
|
+
```css
|
|
169
|
+
@import '@cratis/components/tokens';
|
|
170
|
+
@import '@cratis/components/styles';
|
|
171
|
+
@import '@cratis/components/theme'; /* optional baseline light/dark look */
|
|
130
172
|
```
|
|
131
173
|
|
|
174
|
+
Direct CSS subpath imports from TypeScript need ambient declarations on TypeScript 6
|
|
175
|
+
(otherwise TS2882). To reduce the roughly 32 KiB gzip aggregate, replace `styles`
|
|
176
|
+
with `styles/base` plus the needed `<subpath>/styles` sheets. Area order does not matter.
|
|
177
|
+
|
|
132
178
|
A product with its own design system omits `theme`, defines the `--cratis-*` variables itself, and imports those values *after* the two Components entries so they win the cascade.
|
|
133
179
|
|
|
134
|
-
2. **Mount `CratisComponentsProvider`** (from the package root) around the app. Its `value` carries `locale` (BCP 47 — drives dates, numbers, keyboard behavior and announcements) and `messages` (the Components-owned labels for `paginator`, `datePicker`, `dropdown`, `dialog`, `stepper`, `notifications`, `dataTable`, `columnFilter`, `toolbar`); `
|
|
180
|
+
2. **Mount `CratisComponentsProvider`** (from the package root) around the app. Its `value` carries `locale` (BCP 47 — drives dates, numbers, keyboard behavior and announcements) and `messages` (the Components-owned labels for `paginator`, `datePicker`, `dropdown`, `dialog`, `stepper`, `notifications`, `dataTable`, `filter`, `columnFilter`, `toolbar`); `icons` replaces the
|
|
181
|
+
product-wide glyphs (`close`, `remove`, `expand`, `sortAscending`, `sortDescending`,
|
|
182
|
+
`previous`, `next`, `clear`). Resolution is component prop → provider → built-in;
|
|
183
|
+
`null` hides only the glyph. `useCratisIcon()` (package root) resolves this vocabulary.
|
|
184
|
+
`locales` is deprecated; use `messages`. `toaster` accepts `boolean | ToasterProps`
|
|
185
|
+
and mounts the toast region. Provider props also include `overlayEnvironment`,
|
|
186
|
+
`rendererSetup` (non-secret booleans), experimental `libraryMode` (`strict` / `degrade`)
|
|
187
|
+
and `rendererFallback` (`core` / `throw`). Renderer keys from Components 3 — `license`, `theme`, `pt`, `ripple`, `unstyled`, z-index — are a **type error**, on purpose. Keep the `value` object stable when it carries a large message catalog.
|
|
135
188
|
|
|
136
189
|
```tsx
|
|
137
190
|
import { CratisComponentsProvider } from '@cratis/components';
|
|
@@ -143,6 +196,9 @@ An app does three things, once, at its root — or the components render unstyle
|
|
|
143
196
|
);
|
|
144
197
|
```
|
|
145
198
|
|
|
199
|
+
Components 4.22.1+ with `theme` imported maps Arc's `--color-error` and
|
|
200
|
+
`--color-error-bg` in dark schemes; a product theme omitting it must define both.
|
|
201
|
+
|
|
146
202
|
3. **Install nothing else.** No PrimeReact, no PrimeIcons, no theme preset, no vendor provider. Only if the product wants a vendor's *look* on the nine primitive slots does it install one adapter package and pass its manifest to the provider's `library` prop — and the vendor's own provider, theme and license then stay the application's, outside Components.
|
|
147
203
|
|
|
148
204
|
### Writing styles
|
|
@@ -178,6 +234,9 @@ See [dialogs.md](./dialogs.md) for the full dialog guide.
|
|
|
178
234
|
|
|
179
235
|
Components accepts an **`Icon`** (`@cratis/components/Common`) wherever a control takes an icon: either a React node — preferred — or a complete, consumer-owned icon-font class string. Components installs **no icon font**: a string is rendered on an `<i>` unchanged, so the product must load that stylesheet itself. `react-icons` is a Components dependency and the natural source of React icon nodes (`<FaHouse aria-hidden="true" />`). Not every `icon` prop has that shape — `DataPage.MenuItem.icon` is a React component *type* because the page instantiates it; follow the exported prop type.
|
|
180
236
|
|
|
237
|
+
Use provider `value.icons` for Components' own glyphs across the product;
|
|
238
|
+
`Dialog.closeIcon`, `TagGroup.removeIcon`, and other component props still win at one site.
|
|
239
|
+
|
|
181
240
|
For the application's own SVG icons:
|
|
182
241
|
|
|
183
242
|
- **Distinguish icons from status/interactive components.** A pure SVG icon is a simple presentational element. A component that wraps an icon with interactive behavior (e.g. a dropdown, tooltip, or complex state) is a _component_, not an icon — name it accordingly (e.g. `SliceStatus`, not `SliceStatusIcon`).
|
|
@@ -84,8 +84,11 @@ public record AuthorId(Guid Value) : EventSourceId<Guid>(Value), IGeneratable<Au
|
|
|
84
84
|
- The exact `EventSourceId<T>` base supports conversions among its underlying
|
|
85
85
|
`T`, string, typed ID, and untyped `EventSourceId`, but those operators do not
|
|
86
86
|
construct your derived domain record from every source form.
|
|
87
|
-
- String and Guid
|
|
88
|
-
|
|
87
|
+
- String and Guid remain the safest stream-id primitives. Chronicle v19.50.0
|
|
88
|
+
uses invariant numeric conversion, `"O"` for date/time values and `"c"` for
|
|
89
|
+
TimeSpan (since 19.37.3; `Source/Clients/DotNET/Events/EventSourceId.cs:148-174`).
|
|
90
|
+
Preserve the old untyped id for streams written under legacy date/time or
|
|
91
|
+
decimal-comma culture formats; the new conversion can otherwise open a new stream.
|
|
89
92
|
- Pass the identity explicitly to Chronicle append/read operations. Declaring an
|
|
90
93
|
`EventSourceId<T>` property does not select the stream.
|
|
91
94
|
- Do not put `[Key]` or `[Subject]` on an `EventSourceId<T>`-derived member;
|
|
@@ -126,4 +129,9 @@ Use GeoJSON types from `Cratis.Geospatial`: `Point` for a location,
|
|
|
126
129
|
`LineString` for a route, and `Polygon` for an area. Do not use the removed
|
|
127
130
|
experimental `Coordinate` type. Model geospatial absence according to the
|
|
128
131
|
owning domain contract; do not invent a nullable event payload that conflicts
|
|
129
|
-
with Chronicle event rules.
|
|
132
|
+
with Chronicle event rules. TypeScript imports `Point`, `LineString`, `LinearRing`,
|
|
133
|
+
and `Polygon` from `@cratis/fundamentals/geospatial` (verified at 7.23.0).
|
|
134
|
+
The wire shape is GeoJSON, for example
|
|
135
|
+
`{ "type": "Point", "coordinates": [longitude, latitude] }`: longitude first.
|
|
136
|
+
The removal of `Coordinate` in 7.15.1 is a stored-data compatibility break;
|
|
137
|
+
plan a migration rather than assuming the old shape deserializes as GeoJSON.
|
|
@@ -53,6 +53,8 @@ Every rule here reduces noise. `var` avoids redundant type repetition. Expressio
|
|
|
53
53
|
- Prefer LINQ (`.Where`, `.Any`, `.Select`, `.FirstOrDefault`) over a `foreach` that filters inside its body with an `if`/`continue` or an early `return` — put the filter in the query so the intent is explicit (`items.Where(predicate)`, `return items.Any(predicate);`). Reserve `foreach` for genuine iteration with side effects. (Filtering inside a loop is what the analyzers flag as a "missed opportunity to use Where".)
|
|
54
54
|
- Don't use regions — they hide code instead of organizing it. If a file needs regions, it needs refactoring.
|
|
55
55
|
- Never add postfixes like `Async`, `Impl`, `Service` to class names — they add noise without information.
|
|
56
|
+
- Name a method without the `Async` suffix unless a synchronous method of the same name also exists, never write an explicit `private` modifier (property setters excepted), and never put a `.Features.` segment in a namespace.
|
|
57
|
+
- The `Cratis.Architecture.CodeAnalysis` analyzer package (26 diagnostics, `CRARCH0001`–`CRARCH0026`; verified at `v1.0.2`) enforces these and others: `CRARCH0003` postfixes, `0004` `.Features.` namespaces, `0005` regions, `0006`/`0024` `LoggerMessage`, `0007` `IServiceProvider` injection, `0008` `is null`, `0017` namespace matches folder, `0019` `Async` suffix, `0022` explicit `private`, `0023` typed logger category; `0012` (`async void`) and `0014` (test types in production) are errors. When a repository has the package, a `CRARCH` warning is the house convention, not noise.
|
|
56
58
|
- For types with no implementation body, omit the braces (e.g. `public interface IMyInterface;`).
|
|
57
59
|
- Prefer `record` types for immutable data structures (events, commands, read models, concepts) — they give you value equality, immutability, and concise syntax for free.
|
|
58
60
|
|
|
@@ -306,7 +308,7 @@ public class ReactorSideEffectHandlers(IInstancesOf<IReactorSideEffectHandler> h
|
|
|
306
308
|
|
|
307
309
|
- Never inject `IEnumerable<TInterface>` to enumerate implementations of an abstraction. That signature only works if every implementation is hand-registered, which defeats convention-based discovery. Use `IInstancesOf<TInterface>` instead.
|
|
308
310
|
- Never write `services.AddSingleton<TInterface, Impl>()` or `services.AddTransient<TInterface, Impl>()` for a type that exists to be discovered. Mark the implementation with `[Singleton]` (for singletons) or rely on the `IFoo → Foo` convention (for transients) and remove the registration line.
|
|
309
|
-
- `IInstancesOf<T>`
|
|
311
|
+
- `IInstancesOf<T>` fixes its type set at construction and resolves instances on each enumeration through the consumer's service provider (Fundamentals 7.23.0). It does not discover late-loaded implementations on access. A singleton consumer captures the root provider; it must not enumerate scoped implementations. Resolve a scoped or transient consumer inside a scope when any implementation is scoped.
|
|
310
312
|
- `IEnumerable<T>` is still the right type to **return** from a method that yields a sequence of values. The rule applies only when the goal is to enumerate **implementations** of an abstraction.
|
|
311
313
|
|
|
312
314
|
## Logging
|
|
@@ -250,6 +250,9 @@ Use `buttons={null}` for dialogs that contain their own internal actions (e.g. a
|
|
|
250
250
|
| Prop | Type | Notes |
|
|
251
251
|
|---|---|---|
|
|
252
252
|
| `title` | `string` | Header text |
|
|
253
|
+
| `subtitle` | `ReactNode` | Secondary header content |
|
|
254
|
+
| `placement` | `'center' \| 'start' \| 'end'` | Defaults to center; start/end are RTL-aware side sheets |
|
|
255
|
+
| `closeIcon` | `ReactNode` | Header dismissal glyph; `null` hides only the glyph |
|
|
253
256
|
| `visible` | `boolean` | Controlled open state; defaults to `true` |
|
|
254
257
|
| `buttons` | `DialogButtons \| ReactNode \| null` | Prefer `DialogButtons` enum; `null` for no footer |
|
|
255
258
|
| `isValid` | `boolean` | Disables the confirm button when `false` |
|
|
@@ -265,4 +268,10 @@ Use `buttons={null}` for dialogs that contain their own internal actions (e.g. a
|
|
|
265
268
|
| `style` / `contentStyle` / `className` | | Modal-root and content-region styling |
|
|
266
269
|
| `pt` | `DialogParts` | Per-part attributes: `backdrop`, `positioner`, `root`, `header`, `title`, `close`, `content`, `footer`, `confirm`, `cancel` |
|
|
267
270
|
|
|
271
|
+
`CommandDialog` forwards these Dialog presentation props (since Components 4.14.1).
|
|
272
|
+
It also accepts `confirmBeforeExecute(values) => boolean | Promise<boolean>`:
|
|
273
|
+
after validation and `onBeforeExecute`, only `true` executes. Fields are disabled
|
|
274
|
+
while confirmation is pending; changed command values discard approval without executing.
|
|
275
|
+
This is a pre-execution gate, unlike the post-success `onConfirm` close gate.
|
|
276
|
+
|
|
268
277
|
`resizable`, `ptOptions` and `unstyled` are accepted for source compatibility and do nothing. There is no `modal`, `draggable`, `footer` or `onHide` — the dialog is always modal, the footer comes from `buttons`, and closing is reported through `onCancel`/`onClose`. Style the dialog through its parts (`pt`, or `[data-cratis-part='root']` selectors), never through React Aria class names.
|
|
@@ -75,7 +75,7 @@ Where a repository organizes its migrations (a dedicated project, a versioned fi
|
|
|
75
75
|
|
|
76
76
|
## Observation **[contract]**
|
|
77
77
|
|
|
78
|
-
An EF Core read model can back an observable query: `dbSet.Observe(...)`, `ObserveById(...)` and `ObserveSingle(...)` (extension methods declared in the `Microsoft.EntityFrameworkCore` namespace, so they are in scope wherever the `DbSet` is) push changes through the provider's change notifier — see the skill for what each provider supports.
|
|
78
|
+
An EF Core read model can back an observable query: `dbSet.Observe(...)`, `ObserveById(...)` and `ObserveSingle(...)` (extension methods declared in the `Microsoft.EntityFrameworkCore` namespace, so they are in scope wherever the `DbSet` is) push changes through the provider's change notifier — see the skill for what each provider supports. At Arc v22.75.0 auxiliary sources support `ignoreQueryContext: true`; single-instance observations emit `default` on absence/deletion/filter exit. Indexer-property keys are supported; composite/shadow-only keys are refused at setup.
|
|
79
79
|
|
|
80
80
|
## See also
|
|
81
81
|
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
---
|
|
2
|
+
applyTo: "**/*.ex,**/*.exs"
|
|
3
|
+
paths:
|
|
4
|
+
- "**/*.ex"
|
|
5
|
+
- "**/*.exs"
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
<!-- Copyright (c) Cratis. All rights reserved. -->
|
|
9
|
+
<!-- Licensed under the MIT license. See LICENSE file in the project root for full license information. -->
|
|
10
|
+
|
|
11
|
+
# Elixir Conventions
|
|
12
|
+
|
|
13
|
+
Use Elixir and OTP idioms, not translated C# or JVM shapes. These conventions
|
|
14
|
+
are grounded in `Cratis/Chronicle.Elixir v3.10.2` (`Source/chronicle/mix.exs`,
|
|
15
|
+
`.formatter.exs`, and `lib/chronicle/`). Client-specific APIs belong in the
|
|
16
|
+
**cratis-chronicle-client-elixir** skill.
|
|
17
|
+
|
|
18
|
+
## Build and format
|
|
19
|
+
|
|
20
|
+
- For Chronicle 3.10.x use Elixir 1.18 or later (`~> 1.18`).
|
|
21
|
+
- Run `mix compile --warnings-as-errors`, `mix test`, and
|
|
22
|
+
`mix format --check-formatted` with the project's formatter inputs.
|
|
23
|
+
- Use two-space indentation and let `mix format` own layout.
|
|
24
|
+
- Chronicle exports no `locals_without_parens` formatter configuration. Accept
|
|
25
|
+
parentheses around its DSL calls; do not assume `import_deps` supplies them.
|
|
26
|
+
|
|
27
|
+
## Code shape
|
|
28
|
+
|
|
29
|
+
- PascalCase module names; snake_case functions, variables and struct fields.
|
|
30
|
+
- Use structs for event/read-model data and pattern-matching clauses for
|
|
31
|
+
dispatch. Schema-bearing structs need typed defaults; `nil` is not a type
|
|
32
|
+
declaration and registers as string in this client.
|
|
33
|
+
- Preserve tagged results such as `:ok`, `{:ok, value}`, and `{:error, reason}`.
|
|
34
|
+
Handle expected remote failures explicitly rather than using a success-only
|
|
35
|
+
match in a long-lived process.
|
|
36
|
+
- Put long-lived processes under the application's supervision tree. Wait for
|
|
37
|
+
actual client readiness, not merely a successful supervisor start.
|
|
38
|
+
- Process-local context is not inherited by `Task` processes; pass required
|
|
39
|
+
context explicitly at that boundary.
|
|
40
|
+
- Document public APIs with `@moduledoc`, `@doc`, and `@spec`; use `Logger` for
|
|
41
|
+
operational logging and keep credentials out of messages and crash reports.
|
|
42
|
+
- Use American English in identifiers, comments and documentation.
|
|
43
|
+
|
|
44
|
+
Every `.ex` and `.exs` source file starts with:
|
|
45
|
+
|
|
46
|
+
```elixir
|
|
47
|
+
# Copyright (c) Cratis. All rights reserved.
|
|
48
|
+
# Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
49
|
+
```
|
|
@@ -21,9 +21,11 @@ Skip these `profile: application` rules entirely when in a framework repo: `vert
|
|
|
21
21
|
|
|
22
22
|
Each framework repo is organized by what it builds, not by feature slices:
|
|
23
23
|
|
|
24
|
-
- **Fundamentals** — the base library. `ConceptAs<T>`, type discovery (`IInstancesOf<T>` / `IImplementationsOf<T>`), serialization, common primitives. `Source/DotNET` (
|
|
24
|
+
- **Fundamentals** — the base library. `ConceptAs<T>`, type discovery (`IInstancesOf<T>` / `IImplementationsOf<T>`), serialization, common primitives. `Source/DotNET` includes `Fundamentals.TypeDiscovery.Generator`, `Metrics.Roslyn` (`Cratis.Metrics.Roslyn`) and `OpenTelemetry` (`Cratis.OpenTelemetry`); `Source/JavaScript` publishes `@cratis/fundamentals`, and `Source/ESLintConfig` publishes `@cratis/eslint-config` (verified at v7.23.0).
|
|
25
|
+
- **Specifications** — BDD lifecycle, assertions and analyzers. `Source/Specifications` supplies common helpers, `Source/XUnit` and `Source/NUnit` supply runner-specific bases/assertions, and `Source/CodeAnalysis` supplies the bundled analyzers (v4.1.1).
|
|
26
|
+
- **Orleans** — shared silo hosting, grain serializers, jobs and jobs storage (MongoDB/SQL/in-memory), in `Cratis.Orleans*` packages (v1.16.3). The core does not require Chronicle; the optional `.Chronicle` adapter does.
|
|
25
27
|
- **Arc** — the CQRS + model-binding + proxy-generation engine. `Source/DotNET` (the command/query pipeline, validation, authorization, identity, the Roslyn **proxy generator**) + `Source/JavaScript` (`@cratis/arc`, `@cratis/arc.react`, `@cratis/arc.react.mvvm`). Arc.Core does **not** depend on Chronicle.
|
|
26
|
-
- **Chronicle** — the event-sourcing engine. `Source/Kernel` (the engine: **Orleans grains**, event sequences, observers/projections/reducers, storage providers — MongoDB and others), `Source/Clients` (the client SDKs incl. `DotNET` and `Testing`), `Infrastructure`, `Tools`, `Workbench`. The kernel is the deep, performance- and consistency-critical core.
|
|
28
|
+
- **Chronicle** — the event-sourcing engine. `Source/Kernel` (the engine: **Orleans grains**, event sequences, observers/projections/reducers, storage providers — MongoDB and others), `Source/Clients` (the client SDKs incl. `DotNET` and `Testing`), `Infrastructure`, `Tools`, `Workbench`. The kernel is the deep, performance- and consistency-critical core. Its shared job engine, jobs storage, serializers and reusable silo hosting now come from the separate **Orleans** repo, not Chronicle-owned jobs code (Chronicle v19.50.0).
|
|
27
29
|
- **Components** — the React component library (Components-owned markup and styling contract; React Aria internally; optional PrimeReact/MUI presentation adapters under `Adapters/`). `Source/<Component>/` folder per component (`CommandDialog`, `DataPage`, `DataTables`, …) with Storybook stories; published as `@cratis/components`. (Application rules *consume* these components; here you *build* them.)
|
|
28
30
|
|
|
29
31
|
Repo conventions follow from this: `Source/DotNET` + `Source/JavaScript` for dual-stack libraries; `Kernel` vs `Clients` for Chronicle; a folder-per-component library layout for Components. Match the structure of the area you are editing — do not introduce app-style layouts.
|
|
@@ -32,7 +34,7 @@ Repo conventions follow from this: `Source/DotNET` + `Source/JavaScript` for dua
|
|
|
32
34
|
|
|
33
35
|
- **Public API design is the product.** These libraries are consumed by every Cratis app, so the **Lovable APIs** value (`general.md`) is paramount: sane defaults, convention over configuration, extensible/overridable, minimal boilerplate. Design the API the app developer will love before the implementation.
|
|
34
36
|
- **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`.
|
|
35
|
-
- **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.
|
|
37
|
+
- **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.
|
|
36
38
|
- **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.
|
|
37
39
|
- **Orleans grains** in the Chronicle kernel follow `orleans.md`.
|
|
38
40
|
- **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.
|
|
@@ -130,6 +130,7 @@ A claim is only as good as the signal behind it — a build result, a test run,
|
|
|
130
130
|
| **Contributing to a Cratis framework repo** (framework profile) | `framework.md`; creating a repository in the Cratis organization: `new-repository-intake.md` |
|
|
131
131
|
| Slice anatomy (commands, `Provide()`, validators, events, projections, read models, reactors, constraints, compliance, cross-slice) | `vertical-slices.md` |
|
|
132
132
|
| C# / TypeScript style | `csharp.md`, `typescript.md` |
|
|
133
|
+
| Go style, source and module files | `go.md`; framework contributors also read `go-engineering.md`; product APIs use `cratis-chronicle-client-go`, `cratis-arc-go` and `cratis-fundamentals-concept-go` |
|
|
133
134
|
| Service lifetimes — why anything taking a scoped dependency is scoped or transient, never a singleton | `csharp.md` |
|
|
134
135
|
| React + Arc + Cratis Components + MVVM + dialogs | `react.md`, `components.md`, `dialogs.md` |
|
|
135
136
|
| Frontend engineering quality & testing | `frontend-quality.md`, `frontend-testing.md`, `storybook.md` |
|
|
@@ -23,7 +23,7 @@ One precise line per load-bearing term, so the same word means the same thing ev
|
|
|
23
23
|
- **Projection** — declares how a read model is built by consuming **events** (model-bound attributes, or fluent `IProjectionFor<T>`); pure events→state, no side effects, never reads other read models.
|
|
24
24
|
- **Reducer** — `IReducerFor<T>`; a "current state + event → next state" read-model builder; the last-resort escape hatch when projections can't express the transition.
|
|
25
25
|
- **Reactor** — `IReactor`; observes events and produces **side effects** (notifications, commands, follow-up events). The "if this then that".
|
|
26
|
-
- **Observer** — Chronicle's umbrella for anything consuming an event sequence (projection, reducer, reactor); carries subscription / replay / **quarantine** state.
|
|
26
|
+
- **Observer** — Chronicle's umbrella for anything consuming an event sequence (projection, reducer, reactor); carries subscription / replay / **quarantine** state. Projection replay and catch-up each walk the sequence in one globally ordered job step; a new catch-up failure stops that step. Full replay is inactive and completion does not resume a quarantined observer (Chronicle v19.50.1, `Documentation/concepts/observers.mdx`, `Observation/Jobs/{CatchUpObserver,ReplayObserver}.cs` under `Source/Kernel/Core/`).
|
|
27
27
|
- **Sink** — where a read model is persisted (MongoDB, EF Core).
|
|
28
28
|
- **AutoMap** — Chronicle's on-by-default mapping of matching event→read-model property names; **never call `.AutoMap()`**.
|
|
29
29
|
- **Query** — a `static` method on a `[ReadModel]`; returns derived state, **snapshot** (one-shot) or **observable** (live).
|
|
@@ -34,8 +34,8 @@ One precise line per load-bearing term, so the same word means the same thing ev
|
|
|
34
34
|
- **Provide()** — the command method that fetches/computes data after validation/authorization and before `Handle()`; may short-circuit with a `ValidationResult`.
|
|
35
35
|
- **Causation chain** — the ordered links saying how an append came about (root process → command → …), each carrying properties. A command records its **name and its property values** there, so an event says what the command was asked to do; the chain lives in the event log and is as permanent as the events.
|
|
36
36
|
- **Constraint** — `IConstraint`; an **append-time** invariant (uniqueness / concurrency) enforced at the event-store level.
|
|
37
|
-
- **DCB (Dynamic Consistency Boundary)** — enforcing a state-dependent rule
|
|
38
|
-
- **Consistency boundary** — the scope within which an invariant holds atomically (an event source, or the
|
|
37
|
+
- **DCB (Dynamic Consistency Boundary)** — enforcing a state-dependent rule under concurrency over explicitly enrolled event-state reads: stream decisions/exact scopes or protected, admitted projection decision reads. Plain injected models and `Result<TEvent, ValidationResult>` alone are advisory, not a guard.
|
|
38
|
+
- **Consistency boundary** — the scope within which an invariant holds atomically (an event source, a routed stream, or the event state enrolled by an admitted protected decision read).
|
|
39
39
|
- **EventForEventSourceId** — self-describing wrapper to append an event to a **specific** (cross-stream) event source, from a command `Handle()` or from a reactor handler (reactor support has shipped since Chronicle 15.35). It carries the event stream type and id, source type, subject, occurred time, tags and causation, so it is also how a reactor sets those explicitly.
|
|
40
40
|
- **ReactorDelivery** — the identity of one delivery of one event to one reactor partition; declare it as a handler parameter and Chronicle passes it in. Stable across a replay and across recovering a failed partition, so a receipt kept under its `Id` is what makes a side effect survive re-delivery. An identity, not a guarantee — Chronicle does not know whether the effect ran.
|
|
41
41
|
|
|
@@ -53,7 +53,7 @@ One precise line per load-bearing term, so the same word means the same thing ev
|
|
|
53
53
|
- **`[PII]`** — marks an inherently personal value so Chronicle can manage/erase it.
|
|
54
54
|
- **`[NotAudited]`** — an **Arc** marking (`Cratis.Arc.Chronicle.Commands`, not a Chronicle type) for a value that is secret but *not* personal data (password, token, API key), so it is never written to the causation chain. Withholds only; it does not encrypt the value, so pair it with `[Encrypted]` for an operational secret. It never enrolls a value in erasure the way Chronicle's `[PII]` does.
|
|
55
55
|
- **`[Encrypted]`** — a Chronicle marking (`Cratis.Chronicle.ProtectedValues`, Chronicle 19.32.0+) that encrypts an **operational secret** (API key, token, a company's bank account number) at rest on the event, without erasure. It does not keep a command input off the causation chain, so a secret gets `[Encrypted]` **plus** `[NotAudited]`. Never combine it with `[PII]` (`CHR0053`); never put it on an event source id (`CHR0052`).
|
|
56
|
-
- **`[OnceOnly]`** — marks a reactor handler (or the whole reactor class) as non-replayable: Chronicle skips it for every event arriving as part of a **replay** — observer rewind, redaction, revision. Replay-exclusion only, not exactly-once
|
|
56
|
+
- **`[OnceOnly]`** — marks a reactor handler (or the whole reactor class) as non-replayable: Chronicle skips it for every event arriving as part of a **replay** — observer rewind, redaction, revision. Replay-exclusion only, not exactly-once, not a per-event-source run limit or deduplication; ordinary catch-up, crash redelivery and failed-partition recovery can run the handler again (Chronicle v19.50.1, `Documentation/code-analysis/CHR0022.mdx`). Use a `ReactorDelivery` receipt for that case.
|
|
57
57
|
- **Namespace / tenant** — Chronicle isolates tenants by **namespace**; each namespace has its own events, observers, and read models.
|
|
58
58
|
|
|
59
59
|
## Profiles
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
---
|
|
2
|
+
profile: framework
|
|
3
|
+
applyTo: "**/*.go,go.mod,go.sum,**/go.mod,**/go.sum"
|
|
4
|
+
paths:
|
|
5
|
+
- "**/*.go"
|
|
6
|
+
- "go.mod"
|
|
7
|
+
- "go.sum"
|
|
8
|
+
- "**/go.mod"
|
|
9
|
+
- "**/go.sum"
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
<!-- Copyright (c) Cratis. All rights reserved. -->
|
|
13
|
+
<!-- Licensed under the MIT license. See LICENSE file in the project root for full license information. -->
|
|
14
|
+
|
|
15
|
+
# Go framework parity and module releases
|
|
16
|
+
|
|
17
|
+
`cratis/engineering/go` composes the Go language profile. Repository-owned
|
|
18
|
+
context, not this rule, defines module paths, layout, quality-gate commands,
|
|
19
|
+
release configuration and the exact C# parity target.
|
|
20
|
+
|
|
21
|
+
## Preserve the product contract
|
|
22
|
+
|
|
23
|
+
Before changing a Go port, inspect its owning C# API, implementation and tests
|
|
24
|
+
at the parity target revision. Translate concepts idiomatically, not literally:
|
|
25
|
+
context plus errors, constructors/options, explicit registration, named values
|
|
26
|
+
and deliberate stream lifetimes. Do not change sibling implementations to
|
|
27
|
+
accommodate the port.
|
|
28
|
+
|
|
29
|
+
Preserve routes, verbs, camelCase JSON where contracted, envelopes, UUID byte
|
|
30
|
+
order/encoding, protobuf fields and RPCs, tenancy, event ordering, retry and
|
|
31
|
+
checkpoint semantics. Record each deliberate divergence in repository-owned
|
|
32
|
+
parity documentation with source path/revision, Go surface, status, executable
|
|
33
|
+
evidence and caller migration implications. A compilation check is not wire,
|
|
34
|
+
streaming or lifecycle parity. Unsupported behavior fails explicitly, never as
|
|
35
|
+
no-op success. Keep a limited conformance result limited; do not claim whole-product parity.
|
|
36
|
+
|
|
37
|
+
## Release compatibility
|
|
38
|
+
|
|
39
|
+
- Review signatures, interface growth, public struct comparability, wrapped
|
|
40
|
+
errors, defaults and wire behavior. API-diff tools supplement consumer tests.
|
|
41
|
+
- Experimental v0 breaking APIs require a **minor** bump and migration notes,
|
|
42
|
+
not a patch. From v1, incompatible APIs need a planned major version.
|
|
43
|
+
- Apply exactly one release-intent label under the repository's PR policy.
|
|
44
|
+
Check how its configured `Cratis/release-action` maps v0 changes before release.
|
|
45
|
+
- Root modules use immutable `vX.Y.Z` tags created through the configured
|
|
46
|
+
release-action workflow. Do not create duplicate manual releases or move tags.
|
|
47
|
+
Nested modules need their own explicitly reviewed tag policy.
|
|
48
|
+
- Plan `/v2` migrations across the module directive, imports, examples, consumers
|
|
49
|
+
and parallel support. Neither v0 nor v1 gets a `/v0` or `/v1` suffix.
|
|
50
|
+
- Correct a bad release with a new release and, when appropriate, documented
|
|
51
|
+
retractions in a newer published version. Retraction does not erase downloads
|
|
52
|
+
or prohibit an explicit request for the old version.
|
|
53
|
+
- Verify release consumption without local workspace/replacement assistance.
|
|
54
|
+
Source/tag availability, module download, consumer compilation and proxy/pkg.go.dev
|
|
55
|
+
indexing are separate results. Indexing delay never justifies retagging.
|
|
56
|
+
|
|
57
|
+
Adapted from the repository-owned
|
|
58
|
+
[Chronicle.Go parity rule](https://github.com/Cratis/Chronicle.Go/blob/v0.9.1/.cratis/ai/rules/go-cratis-parity.md)
|
|
59
|
+
and [repository-owned module release guidance](https://github.com/Cratis/Chronicle.Go/tree/v0.9.1/.cratis/ai/skills),
|
|
60
|
+
with repository-specific paths and commands removed.
|